#include 	<sys/time.h>
#include 	<sys/timeb.h>
#include    <sys/types.h>
#include    <sys/stat.h>
#include 	<sys/types.h>
#include 	<sys/ioctl.h>
#include 	<sys/socket.h>
#include 	<sys/ipc.h>
#include 	<sys/shm.h>
#include 	<sys/shm.h>
#include 	<sys/mman.h>
#include 	<linux/wireless.h>
#include 	<arpa/inet.h>
#include 	<netinet/in.h>

#include 	<unistd.h>
#include 	<stdarg.h>
#include    <stdio.h>      /*�зǿ�J��X�w�q*/
#include    <stdlib.h>     /*�зǨ�Ʈw�w�q*/
#include    <unistd.h>     /*Unix �зǨ�Ʃw�q*/
#include    <fcntl.h>      /*�ɱ���w�q*/
#include    <termios.h>    /*PPSIX �׺ݱ���w�q*/
#include    <errno.h>      /*���~���w�q*/
#include 	<errno.h>
#include 	<string.h>
#include	<time.h>
#include	<ctype.h>
#include 	<ifaddrs.h>
#include 	<math.h>
#include	"../../define.h"
#include	"internalComm.h"
#include 	<stdbool.h>

#define ARRAY_SIZE(A)		(sizeof(A) / sizeof(A[0]))
#define PASS				1
#define FAIL				-1
#define YES					1
#define NO					0
#define TEN_MINUTES			600
#define ENV_TEMP_MIN		45
#define ENV_TEMP_MAX		50
#define DEFAULT_AC_INDEX	2

struct SysConfigAndInfo			*ShmSysConfigAndInfo;
struct StatusCodeData 			*ShmStatusCodeData;
struct FanModuleData			*ShmFanModuleData;
struct RelayModuleData			*ShmRelayModuleData;
struct CHAdeMOData				*ShmCHAdeMOData;
struct CcsData					*ShmCcsData;
struct PsuData 					*ShmPsuData;

#define VIN_MAX_VOLTAGE_IEC		296	// �j��ӭ� : OVP
#define VIN_MIN_VOLTAGE_IEC		166	// �p��ӭ� : UVP
#define VIN_MAX_VOLTAGE_UL		305	// �j��ӭ� : OVP
#define VIN_MIN_VOLTAGE_UL		215	// �p��ӭ� : UVP

#define VIN_DROP_VOLTAGE	150	// �p��ӭ� : ac drop

#define VOUT_MAX_VOLTAGE	995
#define VOUT_MIN_VOLTAGE	150
#define IOUT_MAX_CURRENT	50

#define MAX_FAN_SPEED		13500
#define MIN_FAN_SPEED		3000
#define NORMAL_FAN_SPEED	7000

// GFD Status
#define GFD_IDLE			0
#define GFD_CABLECHK		1
#define GFD_PRECHARGE		2
#define GFD_CHARGING		3

// �̤p���� Relay �q��
#define SELF_TO_CHANGE_RELAY_STATUS			600
// �z�L�q���T�{ Relay �O�_�f�W���̾ڹq��
#define CHECK_RELAY_STATUS					300
#define CHECK_RELAY_STATUS_GAP				100
// �w���b����R�q�{�Ǥ��_�} Relay ���q�y
#define SEFETY_SWITCH_RELAY_CUR				20
// �T�{ Relay Welding �q��
#define RELAY_WELDING_DET					300

byte gunCount;
byte acgunCount;
// �j��T
struct ChargingInfoData *_chargingData[CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY];
struct ChargingInfoData *ac_chargingInfo[AC_QUANTITY];

bool _isOutputNoneMatch[CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY];
struct timeval _checkOutputNoneMatchTimer[CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY];

bool _isRelayWelding[CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY];
struct timeval _checkRelayWeldingTimer[CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY];

bool FindChargingInfoData(byte target, struct ChargingInfoData **chargingData);

int Uart5Fd;
char *relayRs485PortName = "/dev/ttyS5";
unsigned short fanSpeedSmoothValue = 500;

bool isStopChargingCount = false;
struct timeval _close_ac_contactor;

struct timeval _priority_time;

struct timeval	_ac_charging_comp;
struct timeval	_ac_preparing;
struct timeb 	_ac_startChargingTime;
struct timeb 	_ac_endChargingTime;

unsigned short _setFanSpeed = 0;

Ver ver;
PresentInputVoltage inputVoltage;
PresentOutputVoltage outputVoltage;
FanSpeed fanSpeed;
Temperature temperature;
AuxPower auxPower;
Gfd gfd_adc;
Gfd_config gfd_config;
Gpio_in gpio_in;
Gpio_out gpio_out;
Relay outputRelay;
Relay regRelay;
Rtc rtc;

Ac_Status acStatus;
Ac_Led_Status ledStatus;
Ac_Alarm_code acAlarmCode;
Ac_Charging_energy acChargingEnergy;
Ac_Charging_current acChargingCurrent;

#define AC_OVP						1
#define AC_UVP						2
#define AC_OCP						4
#define AC_OTP						8
#define AC_GMI_FAULT				16
#define AC_CP_ERROR					32
#define AC_AC_LEAKAGE				64
#define AC_DC_LEAKAGE				128
#define AC_SYSTEM_SELFTEST_FAULT	256
#define AC_HANDSHAKE_TIMEOUT		512
#define AC_EMC_STOP					1024
#define AC_RELAY_WELDING			2048
#define AC_GF_MODULE_FAULT			4096
#define AC_SHUTTER_FAULT			8192
#define AC_LOCKER_FAULT				16384
#define AC_POWER_DROP				32768
#define AC_CIRCUIT_SHORT			65536
#define AC_ROTARY_SWITCH_FAULT		131072
#define AC_RELAY_DRIVE_FAULT		262144

int _alarm_code[] = {AC_OVP, AC_UVP, AC_OCP, AC_OTP, AC_GMI_FAULT, AC_CP_ERROR, AC_AC_LEAKAGE
		, AC_DC_LEAKAGE, AC_SYSTEM_SELFTEST_FAULT, AC_HANDSHAKE_TIMEOUT, AC_EMC_STOP, AC_RELAY_WELDING
		, AC_GF_MODULE_FAULT, AC_SHUTTER_FAULT, AC_LOCKER_FAULT, AC_POWER_DROP, AC_CIRCUIT_SHORT
		, AC_ROTARY_SWITCH_FAULT, AC_RELAY_DRIVE_FAULT};

void PRINTF_FUNC(char *string, ...);

int StoreLogMsg(const char *fmt, ...);
unsigned long GetTimeoutValue(struct timeval _sour_time);

#define DEBUG_INFO(format, args...) StoreLogMsg("[%s:%d][%s][Info] "format, __FILE__, __LINE__, __FUNCTION__, ##args)
#define DEBUG_WARN(format, args...) StoreLogMsg("[%s:%d][%s][Warn] "format, __FILE__, __LINE__, __FUNCTION__, ##args)
#define DEBUG_ERROR(format, args...) StoreLogMsg("[%s:%d][%s][Error] "format, __FILE__, __LINE__, __FUNCTION__, ##args)

unsigned long GetTimeoutValue(struct timeval _sour_time)
{
	struct timeval _end_time;
	gettimeofday(&_end_time, NULL);

	return 1000000 * (_end_time.tv_sec - _sour_time.tv_sec) + _end_time.tv_usec - _sour_time.tv_usec;
}

int StoreLogMsg(const char *fmt, ...)
{
	char Buf[4096+256];
	char buffer[4096];
	time_t CurrentTime;
	struct tm *tm;
	va_list args;

	va_start(args, fmt);
	int rc = vsnprintf(buffer, sizeof(buffer), fmt, args);
	va_end(args);

	memset(Buf,0,sizeof(Buf));
	CurrentTime = time(NULL);
	tm=localtime(&CurrentTime);
	sprintf(Buf,"echo \"%04d-%02d-%02d %02d:%02d:%02d - %s\" >> /Storage/SystemLog/[%04d.%02d]SystemLog",
			tm->tm_year+1900,tm->tm_mon+1,tm->tm_mday,tm->tm_hour,tm->tm_min,tm->tm_sec,
			buffer,
			tm->tm_year+1900,tm->tm_mon+1);
	system(Buf);

	return rc;
}

int DiffTimeb(struct timeb ST, struct timeb ET)
{
	//return milli-second
	unsigned int StartTime, StopTime;

	StartTime = (unsigned int) ST.time;
	StopTime = (unsigned int) ET.time;
	//return (StopTime-StartTime)*1000+ET.millitm-ST.millitm;
	return (StopTime - StartTime);
}

unsigned short MaxValue(unsigned short value1, unsigned short value2)
{
	return value1 >= value2 ? value1 : value2;
}

void PRINTF_FUNC(char *string, ...)
{
	va_list args;
	char buffer[4096];
	va_start(args, string);
	vsnprintf(buffer, sizeof(buffer), string, args);
	va_end(args);

	if (ShmSysConfigAndInfo->SysConfig.SwitchDebugFlag == YES)
		printf("%s \n", buffer);
	else
		DEBUG_INFO("%s \n", buffer);
}

//==========================================
// Communication Function
//==========================================
void GetFwAndHwVersion_Fan()
{
	if(Query_FW_Ver(Uart5Fd, Addr.Fan, &ver) == PASS)
	{
		// FanModuleData
		strcpy((char *) ShmFanModuleData->version, ver.Version_FW);
		// SystemInfo
		strcpy((char *) ShmSysConfigAndInfo->SysInfo.FanModuleFwRev, ver.Version_FW);
		//PRINTF_FUNC("GetFwAndHwVersion_Fan s1 = %s \n", ver.Version_FW);
	}

	if (Query_HW_Ver(Uart5Fd, Addr.Fan, &ver) == PASS)
	{
		// SystemInfo
		strcpy((char *) ShmSysConfigAndInfo->SysInfo.FanModuleHwRev, ver.Version_FW);
		//PRINTF_FUNC("GetFwAndHwVersion_Fan s2 = %s \n", ver.Version_HW);
	}
}

void GetFwAndHwVersion_Relay()
{
	if (Query_FW_Ver(Uart5Fd, Addr.Relay, &ver) == PASS)
	{
		// FanModuleData
		strcpy((char *) ShmRelayModuleData->version, ver.Version_FW);
		// SystemInfo
		strcpy((char *) ShmSysConfigAndInfo->SysInfo.RelayModuleFwRev, ver.Version_FW);
		//PRINTF_FUNC("GetFwAndHwVersion_Relay s1 = %s \n", ver.Version_FW);
	}

	if (Query_HW_Ver(Uart5Fd, Addr.Relay, &ver) == PASS)
	{
		// SystemInfo
		strcpy((char *) ShmSysConfigAndInfo->SysInfo.RelayModuleHwRev, ver.Version_FW);
		//PRINTF_FUNC("GetFwAndHwVersion_Relay s2 = %s \n", ver.Version_HW);
	}
}

void GetFwVersion_AC()
{
	if (Query_FW_Ver(Uart5Fd, Addr.AcPlug, &ver) == PASS)
	{
		ac_chargingInfo[0]->SelfTest_Comp = YES;
		strcpy((char *) ac_chargingInfo[0]->version, ver.Version_FW);
	}
}

void SetRtcData_Relay()
{
	struct timeb csuTime;
	struct tm *tmCSU;

	ftime(&csuTime);
	tmCSU = localtime(&csuTime.time);
	//	PRINTF_FUNC("Time : %04d-%02d-%02d %02d:%02d:%02d \n", tmCSU->tm_year + 1900,
	//			tmCSU->tm_mon + 1, tmCSU->tm_mday, tmCSU->tm_hour, tmCSU->tm_min,
	//			tmCSU->tm_sec);

	rtc.RtcData[0] = '0' + (tmCSU->tm_year + 1900) / 1000 % 10;
	rtc.RtcData[1] = '0' + (tmCSU->tm_year + 1900) / 100 % 10;
	rtc.RtcData[2] = '0' + (tmCSU->tm_year + 1900) / 10 % 10;
	rtc.RtcData[3] = '0' + (tmCSU->tm_year + 1900) / 1 % 10;

	rtc.RtcData[4] = '0' + (tmCSU->tm_mon + 1) / 10 % 10;
	rtc.RtcData[5] = '0' + (tmCSU->tm_mon + 1) / 1 % 10;

	rtc.RtcData[6] = '0' + (tmCSU->tm_mday) / 10 % 10;
	rtc.RtcData[7] = '0' + (tmCSU->tm_mday) / 1 % 10;

	rtc.RtcData[8] = '0' + (tmCSU->tm_hour) / 10 % 10;
	rtc.RtcData[9] = '0' + (tmCSU->tm_hour) / 1 % 10;

	rtc.RtcData[10] = '0' + (tmCSU->tm_min) / 10 % 10;
	rtc.RtcData[11] = '0' + (tmCSU->tm_min) / 1 % 10;

	rtc.RtcData[12] = '0' + (tmCSU->tm_sec) / 10 % 10;
	rtc.RtcData[13] = '0' + (tmCSU->tm_sec) / 1 % 10;

	if (Config_Rtc_Data(Uart5Fd, Addr.Relay, &rtc) == PASS)
	{
		//PRINTF_FUNC("SetRtc (RB) sucessfully. \n");
	}
}

void SetRtcData_Fan()
{
	struct timeb csuTime;
	struct tm *tmCSU;

	ftime(&csuTime);
	tmCSU = localtime(&csuTime.time);
	//	PRINTF_FUNC("Time : %04d-%02d-%02d %02d:%02d:%02d \n", tmCSU->tm_year + 1900,
	//			tmCSU->tm_mon + 1, tmCSU->tm_mday, tmCSU->tm_hour, tmCSU->tm_min,
	//			tmCSU->tm_sec);

	rtc.RtcData[0] = '0' + (tmCSU->tm_year + 1900) / 1000 % 10;
	rtc.RtcData[1] = '0' + (tmCSU->tm_year + 1900) / 100 % 10;
	rtc.RtcData[2] = '0' + (tmCSU->tm_year + 1900) / 10 % 10;
	rtc.RtcData[3] = '0' + (tmCSU->tm_year + 1900) / 1 % 10;

	rtc.RtcData[4] = '0' + (tmCSU->tm_mon + 1) / 10 % 10;
	rtc.RtcData[5] = '0' + (tmCSU->tm_mon + 1) / 1 % 10;

	rtc.RtcData[6] = '0' + (tmCSU->tm_mday) / 10 % 10;
	rtc.RtcData[7] = '0' + (tmCSU->tm_mday) / 1 % 10;

	rtc.RtcData[8] = '0' + (tmCSU->tm_hour) / 10 % 10;
	rtc.RtcData[9] = '0' + (tmCSU->tm_hour) / 1 % 10;

	rtc.RtcData[10] = '0' + (tmCSU->tm_min) / 10 % 10;
	rtc.RtcData[11] = '0' + (tmCSU->tm_min) / 1 % 10;

	rtc.RtcData[12] = '0' + (tmCSU->tm_sec) / 10 % 10;
	rtc.RtcData[13] = '0' + (tmCSU->tm_sec) / 1 % 10;

	if (Config_Rtc_Data(Uart5Fd, Addr.Fan, &rtc) == PASS)
	{
		//PRINTF_FUNC("SetRtc (FB) sucessfully. \n");
	}
}

void SetModelName_Fan()
{
	if (Config_Model_Name(Uart5Fd, Addr.Fan, ShmSysConfigAndInfo->SysConfig.ModelName) == PASS)
	{
		PRINTF_FUNC("Set Model name PASS = %s \n", ShmSysConfigAndInfo->SysConfig.ModelName);
	}
}

// AC �T�ۿ�J�q��
void GetPresentInputVol()
{
	if (Query_Present_InputVoltage(Uart5Fd, Addr.Relay, &inputVoltage) == PASS)
	{
		// resolution : 0.1
		ShmSysConfigAndInfo->SysInfo.InputVoltageR = ShmRelayModuleData->InputL1Volt = inputVoltage.L1N_L12;
		ShmSysConfigAndInfo->SysInfo.InputVoltageS = ShmRelayModuleData->InputL2Volt = inputVoltage.L2N_L23;
		ShmSysConfigAndInfo->SysInfo.InputVoltageT = ShmRelayModuleData->InputL3Volt = inputVoltage.L3N_L31;

		//********************************************************************************************************//
		// Vin (UVP)
		if (ShmSysConfigAndInfo->SysInfo.ChargerType == _CHARGER_TYPE_IEC)
		{
			if (inputVoltage.L1N_L12 < VIN_MIN_VOLTAGE_IEC)
				ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL1InputUVP = YES;
			else
				ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL1InputUVP = NO;

			if (inputVoltage.L2N_L23 < VIN_MIN_VOLTAGE_IEC)
				ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL2InputUVP = YES;
			else
				ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL2InputUVP = NO;

			if (inputVoltage.L3N_L31 < VIN_MIN_VOLTAGE_IEC)
				ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL3InputUVP = YES;
			else
				ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL3InputUVP = NO;
		}
		else if (ShmSysConfigAndInfo->SysInfo.ChargerType == _CHARGER_TYPE_UL)
		{
			if (inputVoltage.L1N_L12 < VIN_MIN_VOLTAGE_UL)
				ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL1InputUVP = YES;
			else
				ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL1InputUVP = NO;

			if (inputVoltage.L2N_L23 < VIN_MIN_VOLTAGE_UL)
				ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL2InputUVP = YES;
			else
				ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL2InputUVP = NO;

			if (inputVoltage.L3N_L31 < VIN_MIN_VOLTAGE_UL)
				ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL3InputUVP = YES;
			else
				ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL3InputUVP = NO;
		}
		//********************************************************************************************************//
		// Vin (OVP)
		if (ShmSysConfigAndInfo->SysInfo.ChargerType == _CHARGER_TYPE_IEC)
		{
			if (inputVoltage.L1N_L12 > VIN_MAX_VOLTAGE_IEC)
				ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL1InputOVP = YES;
			else
				ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL1InputOVP = NO;

			if (inputVoltage.L2N_L23 > VIN_MAX_VOLTAGE_IEC)
				ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL2InputOVP = YES;
			else
				ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL2InputOVP = NO;

			if (inputVoltage.L3N_L31 > VIN_MAX_VOLTAGE_IEC)
				ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL3InputOVP = YES;
			else
				ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL3InputOVP = NO;
		}
		else if (ShmSysConfigAndInfo->SysInfo.ChargerType == _CHARGER_TYPE_UL)
		{
			if (inputVoltage.L1N_L12 > VIN_MAX_VOLTAGE_UL)
				ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL1InputOVP = YES;
			else
				ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL1InputOVP = NO;

			if (inputVoltage.L2N_L23 > VIN_MAX_VOLTAGE_UL)
				ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL2InputOVP = YES;
			else
				ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL2InputOVP = NO;

			if (inputVoltage.L3N_L31 > VIN_MAX_VOLTAGE_UL)
				ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL3InputOVP = YES;
			else
				ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL3InputOVP = NO;
		}
	}
}

// ���k�j�� Relay �e�᪺��X�q��
void GetPersentOutputVol()
{
	if (Query_Present_OutputVoltage(Uart5Fd, Addr.Relay, &outputVoltage) == PASS)
	{
//		PRINTF_FUNC("Conn1 fuse 1 = %f \n", outputVoltage.behindFuse_Voltage_C1);
//		PRINTF_FUNC("Conn1 relay 1 = %f \n", outputVoltage.behindRelay_Voltage_C1);
//		PRINTF_FUNC("Conn2 fuse 2 = %f \n", outputVoltage.behindFuse_Voltage_C2);
//		PRINTF_FUNC("Conn2 relay 2 = %f \n", outputVoltage.behindRelay_Voltage_C2);

		//PRINTF_FUNC("outputVoltage.behindFuse_Voltage_C1 = %f \n", outputVoltage.behindFuse_Voltage_C1);
		//PRINTF_FUNC("outputVoltage.behindFuse_Voltage_C2 = %f \n", outputVoltage.behindFuse_Voltage_C2);

		ShmRelayModuleData->Gun1FuseOutputVolt = outputVoltage.behindFuse_Voltage_C1;
		ShmRelayModuleData->Gun1RelayOutputVolt = outputVoltage.behindRelay_Voltage_C1;
		ShmRelayModuleData->Gun2FuseOutputVolt = outputVoltage.behindFuse_Voltage_C2;
		ShmRelayModuleData->Gun2RelayOutputVolt = outputVoltage.behindRelay_Voltage_C2;

		for (int index = 0; index < gunCount; index++)
		{
			if (index == 0)
			{
				if (_chargingData[index]->Evboard_id == 0x01)
				{
					_chargingData[index]->FuseChargingVoltage = ShmRelayModuleData->Gun1FuseOutputVolt;
					_chargingData[index]->FireChargingVoltage = ShmRelayModuleData->Gun1RelayOutputVolt;
				}
				else if (_chargingData[index]->Evboard_id == 0x02)
				{
					_chargingData[index]->FuseChargingVoltage = ShmRelayModuleData->Gun2FuseOutputVolt;
					_chargingData[index]->FireChargingVoltage = ShmRelayModuleData->Gun2RelayOutputVolt;
				}
			}
			else if (index == 1)
			{
				_chargingData[index]->FuseChargingVoltage = ShmRelayModuleData->Gun2FuseOutputVolt;
				_chargingData[index]->FireChargingVoltage = ShmRelayModuleData->Gun2RelayOutputVolt;
			}

			//unsigned short Ovp = 0;
			//unsigned short Ocp = 0;
			//Ovp = MIN [VOUT_MAX_VOLTAGE, EV_BATTERY_VOLTAGE] 	// �̤j��X�q���P�q���q���̤j��
			//Ocp = MIN [IOUT_MAX_CURRENT, EV_CURRENT_REQ]		// �̤j��X�q�y�P�ݨD�q�y�̤p��
			if (_chargingData[index]->Type == _Type_Chademo)
			{
				//Ovp = MaxValue(_chargingData[index]->MaximumChargingVoltage, _chargingData[index]->EvBatteryMaxVoltage);
				//Ocp = MaxValue(_chargingData[index]->PresentChargingCurrent, ShmCHAdeMOData->ev[_chargingData[index]->type_index].ChargingCurrentRequest);
			}
			else if (_chargingData[index]->Type == _Type_CCS_2)
			{

			}
		}
	}
}

// �����t��
void GetFanSpeed()
{
	//PRINTF_FUNC("Get fan board speed \n");
	if (Query_Fan_Speed(Uart5Fd, Addr.Fan, &fanSpeed) == PASS)
	{
		ShmFanModuleData->PresentFan1Speed = fanSpeed.speed[0];
		ShmFanModuleData->PresentFan2Speed = fanSpeed.speed[1];
		ShmFanModuleData->PresentFan3Speed = fanSpeed.speed[2];
		ShmFanModuleData->PresentFan4Speed = fanSpeed.speed[3];
//		PRINTF_FUNC("SystemFanRotaSpeed_1 = %d \n", fanSpeed.speed[0]);
//		PRINTF_FUNC("SystemFanRotaSpeed_2 = %d \n", fanSpeed.speed[1]);
//		PRINTF_FUNC("SystemFanRotaSpeed_3 = %d \n", fanSpeed.speed[2]);
//		PRINTF_FUNC("SystemFanRotaSpeed_4 = %d \n", fanSpeed.speed[3]);
		// Config_Fan_Speed(Uart5Fd, Addr.Fan, &fanSpeed[0]);
		//SysInfoData (SystemFanRotaSpeed)
	}
}

// Ū�� Relay ���A
void GetRelayOutputStatus()
{
	if (Query_Relay_Output(Uart5Fd, Addr.Relay, &regRelay) == PASS)
	{
		regRelay.relay_event.bits.AC_Contactor = ShmSysConfigAndInfo->SysInfo.AcContactorStatus;
	}
}

// �T�{ K1 K2 relay �����A
void CheckK1K2RelayOutput(byte index)
{
	if (index == 0)
	{
		if (_chargingData[index]->Evboard_id == 0x01)
		{
			if (regRelay.relay_event.bits.Gun1_N == YES && regRelay.relay_event.bits.Gun1_P == YES)
				_chargingData[index]->RelayK1K2Status = YES;
			else
				_chargingData[index]->RelayK1K2Status = NO;

			if(_chargingData[index]->Type == _Type_CCS_2)
			{
				if (regRelay.relay_event.bits.Gun1_N == YES	&& regRelay.relay_event.bits.CCS_Precharge == YES)
					_chargingData[index]->RelayKPK2Status = YES;
				else
					_chargingData[index]->RelayKPK2Status = NO;
			}
		}
		else if (_chargingData[index]->Evboard_id == 0x02)
		{
			if (regRelay.relay_event.bits.Gun2_N == YES && regRelay.relay_event.bits.Gun2_P == YES)
				_chargingData[index]->RelayK1K2Status = YES;
			else
				_chargingData[index]->RelayK1K2Status = NO;

			if(_chargingData[index]->Type == _Type_CCS_2)
			{
				if (regRelay.relay_event.bits.Gun2_N == YES	&& regRelay.relay_event.bits.CCS_Precharge == YES)
					_chargingData[index]->RelayKPK2Status = YES;
				else
					_chargingData[index]->RelayKPK2Status = NO;
			}
		}
	}
	else if (index == 1)
	{
		if (regRelay.relay_event.bits.Gun2_N == YES && regRelay.relay_event.bits.Gun2_P == YES)
			_chargingData[index]->RelayK1K2Status = YES;
		else
			_chargingData[index]->RelayK1K2Status = NO;

		if(_chargingData[index]->Type == _Type_CCS_2)
		{
			if (regRelay.relay_event.bits.Gun2_N == YES && regRelay.relay_event.bits.CCS_Precharge == YES)
				_chargingData[index]->RelayKPK2Status = YES;
			else
				_chargingData[index]->RelayKPK2Status = NO;
		}
	}

	if (regRelay.relay_event.bits.Gun1_Parallel_N == YES && regRelay.relay_event.bits.Gun1_Parallel_P == YES)
		ShmSysConfigAndInfo->SysInfo.BridgeRelayStatus = YES;
	else
		ShmSysConfigAndInfo->SysInfo.BridgeRelayStatus = NO;

//	PRINTF_FUNC("Check Relay Output. index = %d, RelayKPK2Status = %d, BridgeRelayStatus = %d \n",
//			index, _chargingData[index]->RelayKPK2Status, ShmSysConfigAndInfo->SysInfo.BridgeRelayStatus);
}

void GetGfdAdc()
{
	// define : �C 0.2 ~ 1 ���@��
	// occur : <= 75k �کi @ 150 - 750 Vdc
	// warning : >= 100 �کi && <= 500 �کi @ 150-750 Vdc
	if (Query_Gfd_Adc(Uart5Fd, Addr.Relay, &gfd_adc) == PASS)
	{
		for (int i = 0; i < gunCount; i++)
		{
			if (_chargingData[i]->Type == 0x09 && !ShmSysConfigAndInfo->SysConfig.AlwaysGfdFlag)
			{
				if ((_chargingData[i]->PresentChargingVoltage * 10) >= VOUT_MIN_VOLTAGE)
					_chargingData[i]->GroundFaultStatus = GFD_PASS;
				continue;
			}

			if (i == 0)
			{
				_chargingData[i]->GroundFaultStatus = gfd_adc.result_conn1;
				if (_chargingData[i]->GroundFaultStatus == GFD_FAIL)
				{
					PRINTF_FUNC("GFD Fail. index = %d, Step = %d, R = %d, Vol = %d \n",
							i, gfd_adc.rb_step_1, gfd_adc.Resister_conn1, gfd_adc.voltage_conn1);
				}
				else if (_chargingData[i]->GroundFaultStatus == GFD_PASS ||
						_chargingData[i]->GroundFaultStatus == GFD_WARNING)
				{
//					PRINTF_FUNC("GFD Result. index = %d, Result = %d, R = %d, Vol = %d \n",
//						i, _chargingData[i]->GroundFaultStatus, gfd_adc.Resister_conn1, gfd_adc.voltage_conn1);
				}
			}
			else if (i == 1)
			{
				_chargingData[i]->GroundFaultStatus = gfd_adc.result_conn2;
				if (_chargingData[i]->GroundFaultStatus == GFD_FAIL)
				{
					PRINTF_FUNC("GFD Fail. index = %d, Step = %d, R = %d, Vol = %d \n",
							i, gfd_adc.rb_step_2, gfd_adc.Resister_conn2, gfd_adc.voltage_conn2);
				}
				else if (_chargingData[i]->GroundFaultStatus == GFD_PASS ||
						_chargingData[i]->GroundFaultStatus == GFD_WARNING)
				{
//					PRINTF_FUNC("GFD Result. index = %d, Result = %d, R = %d, Vol = %d \n",
//						i, _chargingData[i]->GroundFaultStatus, gfd_adc.Resister_conn2, gfd_adc.voltage_conn2);
				}
			}
		}
	}
}

void GetGpioInput()
{
	if (Query_Gpio_Input(Uart5Fd, Addr.Aux, &gpio_in) == PASS)
	{
		// AC Contactor Status
		if (gpio_in.AC_MainBreaker == 1)
		{
			// AC Main Breaker ON
			PRINTF_FUNC("RB AC Main Breaker. \n");
		}

		if (gpio_in.SPD == 1)
		{
			// SPD (�p���O�@) ON
			PRINTF_FUNC("RB SPD. \n");
		}

		if (gpio_in.Door_Open == 1)
		{
			// Door Open
			PRINTF_FUNC("RB Door Open. \n");
		}

		if (gpio_in.GFD[0] == 1)
		{
			// GFD_1 Trigger
		}

		if (gpio_in.GFD[1] == 1)
		{
			// GFD_2 Trigger
		}

		if (gpio_in.AC_Drop == 1)
		{
			// AC Drop
			PRINTF_FUNC("RB AC Drop. \n");
		}

		if (gpio_in.Emergency_IO == 1)
		{
			// Emergency IO ON
			PRINTF_FUNC("RB Emergency IO ON. \n");
		}

		if (gpio_in.Button_Emergency_Press == 1)
		{
			// Emergency button Press
		}

		if (gpio_in.Button_On_Press == 1)
		{
			// On button Press
		}

		if (gpio_in.Button_Off_Press == 1)
		{
			// Off button Press
		}

		if (gpio_in.Key_1_Press == 1)
		{
			// key 1 press
		}

		if (gpio_in.Key_2_Press == 1)
		{
			// key 2 press
		}

		if (gpio_in.Key_3_Press == 1)
		{
			// key 3 press
		}

		if (gpio_in.Key_4_Press == 1)
		{
			// key 4 press
		}
	}
}

// 5V 12V 24V 48V
void GetAuxPower()
{
	if (Query_Aux_PowerVoltage(Uart5Fd, Addr.Fan, &auxPower) == PASS)
	{
		ShmSysConfigAndInfo->SysInfo.AuxPower48V = auxPower.voltage[0];
		ShmSysConfigAndInfo->SysInfo.AuxPower24V = auxPower.voltage[1];
		//ShmSysConfigAndInfo->SysInfo.AuxPower12V = auxPower.voltage[4];
		//ShmSysConfigAndInfo->SysInfo.AuxPower5V = auxPower.voltage[6];
		// aux power voltage
		//PRINTF_FUNC("aux1 = %x, \n", auxPower.voltage[0]);
		//PRINTF_FUNC("aux2 = %x, \n", auxPower.voltage[1]);
	}
}

void SetFanModuleSpeed()
{
	// �վ㭷���t�׭n���i�� : 500 rpm/p
//	if (ShmFanModuleData->PresentFan1Speed != ShmFanModuleData->SetFan1Speed ||
//			ShmFanModuleData->PresentFan2Speed != ShmFanModuleData->SetFan2Speed ||
//			ShmFanModuleData->PresentFan3Speed != ShmFanModuleData->SetFan3Speed ||
//			ShmFanModuleData->PresentFan4Speed != ShmFanModuleData->SetFan4Speed)
	{
		//printf("ShmFanModuleData->SetFan1Speed = %d \n", ShmFanModuleData->SetFan1Speed);

		FanSpeed _fanSpeed;

		//unsigned short speed = ShmFanModuleData->PresentFan1Speed + fanSpeedSmoothValue;
		_setFanSpeed += fanSpeedSmoothValue;

		//if (speed >= ShmFanModuleData->SetFan1Speed)
		//	speed = ShmFanModuleData->SetFan1Speed;
		if (_setFanSpeed >= ShmFanModuleData->SetFan1Speed)
			_setFanSpeed = ShmFanModuleData->SetFan1Speed;
		_fanSpeed.speed[0] = _setFanSpeed;

		//speed = ShmFanModuleData->PresentFan2Speed + fanSpeedSmoothValue;
		//if (speed >= ShmFanModuleData->SetFan2Speed)
		//	speed = ShmFanModuleData->SetFan2Speed;
		_fanSpeed.speed[1] = _setFanSpeed;

		//speed = ShmFanModuleData->PresentFan3Speed + fanSpeedSmoothValue;
		//if (speed >= ShmFanModuleData->SetFan3Speed)
		//	speed = ShmFanModuleData->SetFan3Speed;
		_fanSpeed.speed[2] = _setFanSpeed;

		//speed = ShmFanModuleData->PresentFan4Speed + fanSpeedSmoothValue;
		//if (speed >= ShmFanModuleData->SetFan4Speed)
		//	speed = ShmFanModuleData->SetFan4Speed;
		_fanSpeed.speed[3] = _setFanSpeed;

		if (Config_Fan_Speed(Uart5Fd, Addr.Fan, &_fanSpeed) == PASS)
		{
			//PRINTF_FUNC("successfully Fan\n");
		}
	}
}

//==========================================
// Common Function
//==========================================
void SetK1K2RelayStatus(byte index)
{
	if (_chargingData[index]->SystemStatus < S_PREPARING_FOR_EVSE)
	{
		if (_chargingData[index]->Evboard_id == 0x01)
		{
			if(regRelay.relay_event.bits.Gun1_P == YES)
				outputRelay.relay_event.bits.Gun1_P = NO;
			else if (regRelay.relay_event.bits.Gun1_N == YES)
				outputRelay.relay_event.bits.Gun1_N = NO;

			if (_chargingData[index]->Type == _Type_CCS_2)
			{
				if(regRelay.relay_event.bits.CCS_Precharge == YES)
					outputRelay.relay_event.bits.CCS_Precharge = NO;
			}
		}
		else if (_chargingData[index]->Evboard_id == 0x02)
		{
			if(regRelay.relay_event.bits.Gun2_P == YES)
				outputRelay.relay_event.bits.Gun2_P = NO;
			else if (regRelay.relay_event.bits.Gun2_N == YES)
				outputRelay.relay_event.bits.Gun2_N = NO;

			if (_chargingData[index]->Type == _Type_CCS_2)
			{
				if(regRelay.relay_event.bits.CCS_Precharge == YES)
					outputRelay.relay_event.bits.CCS_Precharge = NO;
			}
		}
	}
	else if ((_chargingData[index]->SystemStatus >= S_PREPARING_FOR_EVSE &&
			_chargingData[index]->SystemStatus <= S_CHARGING))
	{
		if (_chargingData[index]->RelayWeldingCheck == YES)
		{
			if (_chargingData[index]->Evboard_id == 0x01)
			{
				if(regRelay.relay_event.bits.Gun1_N == NO)
					outputRelay.relay_event.bits.Gun1_N = YES;
				else if (regRelay.relay_event.bits.Gun1_P == NO)
					outputRelay.relay_event.bits.Gun1_P = YES;
			}
			else if (_chargingData[index]->Evboard_id == 0x02)
			{
				if(regRelay.relay_event.bits.Gun2_N == NO)
					outputRelay.relay_event.bits.Gun2_N = YES;
				else if (regRelay.relay_event.bits.Gun2_P == NO)
					outputRelay.relay_event.bits.Gun2_P = YES;
			}
		}
	}
	else if ((_chargingData[index]->SystemStatus >= S_TERMINATING &&
			_chargingData[index]->SystemStatus <= S_COMPLETE))
	{
		if ((_chargingData[index]->PresentChargingCurrent * 10) <= SEFETY_SWITCH_RELAY_CUR)
		{
			if (_chargingData[index]->Evboard_id == 0x01)
			{
				if(regRelay.relay_event.bits.Gun1_P == YES)
					outputRelay.relay_event.bits.Gun1_P = NO;
				else if (regRelay.relay_event.bits.Gun1_N == YES)
					outputRelay.relay_event.bits.Gun1_N = NO;
			}
			else if (_chargingData[index]->Evboard_id == 0x02)
			{
				if(regRelay.relay_event.bits.Gun2_P == YES)
					outputRelay.relay_event.bits.Gun2_P = NO;
				else if (regRelay.relay_event.bits.Gun2_N == YES)
					outputRelay.relay_event.bits.Gun2_N = NO;
			}
		}
	}
	else if (_chargingData[index]->SystemStatus == S_CCS_PRECHARGE_ST0)
	{
		if (_chargingData[index]->Evboard_id == 0x01)
		{
			if (_chargingData[index]->Type == _Type_CCS_2)
			{
				if (regRelay.relay_event.bits.CCS_Precharge == NO)
					outputRelay.relay_event.bits.CCS_Precharge = YES;
				else if (regRelay.relay_event.bits.CCS_Precharge == YES)
					outputRelay.relay_event.bits.Gun1_P = NO;
			}
		}
		else if (_chargingData[index]->Evboard_id == 0x02)
		{
			if (_chargingData[index]->Type == _Type_CCS_2)
			{
				if (regRelay.relay_event.bits.CCS_Precharge == NO)
					outputRelay.relay_event.bits.CCS_Precharge = YES;
				else if (regRelay.relay_event.bits.CCS_Precharge == YES)
					outputRelay.relay_event.bits.Gun2_P = NO;
			}
		}
	}
	else if (_chargingData[index]->SystemStatus == S_CCS_PRECHARGE_ST1)
	{
		if (_chargingData[index]->Evboard_id == 0x01)
		{
			if (_chargingData[index]->Type == _Type_CCS_2)
			{
				if (regRelay.relay_event.bits.Gun1_P == NO)
					outputRelay.relay_event.bits.Gun1_P = YES;
				else if(regRelay.relay_event.bits.Gun1_P == YES)
					outputRelay.relay_event.bits.CCS_Precharge = NO;
			}
		}
		else if (_chargingData[index]->Evboard_id == 0x02)
		{
			if (_chargingData[index]->Type == _Type_CCS_2)
			{
				if (regRelay.relay_event.bits.Gun2_P == NO)
					outputRelay.relay_event.bits.Gun2_P = YES;
				else if(regRelay.relay_event.bits.Gun2_P == YES)
					outputRelay.relay_event.bits.CCS_Precharge = NO;
			}
		}
	}
}

void CheckAcInputOvpStatus(byte index)
{
	if (ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL1InputOVP == YES ||
			ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL2InputOVP == YES ||
			ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL3InputOVP == YES)
	{
		_chargingData[index]->StopChargeFlag = YES;
	}
}

void CheckPhaseLossStatus(byte index)
{
	if (ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL1InputUVP == YES ||
			ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL2InputUVP == YES ||
			ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL3InputUVP == YES)
	{
		_chargingData[index]->StopChargeFlag = YES;
	}
}

void SetParalleRelayStatus()
{
	if (gunCount >= 2 && ShmSysConfigAndInfo->SysInfo.IsAlternatvieConf == NO)
	{
		if (_chargingData[0]->SystemStatus == S_BOOTING || _chargingData[1]->SystemStatus == S_BOOTING ||
				(_chargingData[0]->SystemStatus == S_IDLE && _chargingData[1]->SystemStatus == S_IDLE))
		{
			// ��l��~ ���f����
			if (regRelay.relay_event.bits.Gun1_Parallel_P == YES)
				outputRelay.relay_event.bits.Gun1_Parallel_P = NO;
			else if (regRelay.relay_event.bits.Gun1_Parallel_N == YES)
				outputRelay.relay_event.bits.Gun1_Parallel_N = NO;
		}
		else
		{
			if (_chargingData[0]->IsReadyToCharging == YES ||
					_chargingData[1]->IsReadyToCharging == YES)
			{
				// ************�ݦҼ{�b������ - ���} relay �P�f�^ relay ���ɾ��I************
				if (ShmSysConfigAndInfo->SysInfo.MainChargingMode == _MAIN_CHARGING_MODE_MAX)
				{
					if (ShmSysConfigAndInfo->SysInfo.ReAssignedFlag < _REASSIGNED_RELAY_M_TO_A)
					{
						// �̤j�R - �f�W����
						if (regRelay.relay_event.bits.Gun1_Parallel_N == NO)
							outputRelay.relay_event.bits.Gun1_Parallel_N = YES;
						else if (regRelay.relay_event.bits.Gun1_Parallel_P == NO)
							outputRelay.relay_event.bits.Gun1_Parallel_P = YES;
					}
					else
					{
						// �����R - ���f
						if (regRelay.relay_event.bits.Gun1_Parallel_P == YES)
							outputRelay.relay_event.bits.Gun1_Parallel_P = NO;
						else if (regRelay.relay_event.bits.Gun1_Parallel_N == YES)
							outputRelay.relay_event.bits.Gun1_Parallel_N = NO;
					}
				}
				else if (ShmSysConfigAndInfo->SysInfo.MainChargingMode == _MAIN_CHARGING_MODE_AVER)
				{
					if (ShmSysConfigAndInfo->SysInfo.ReAssignedFlag < _REASSIGNED_RELAY_A_TO_M)
					{
						// �����R - ���f
						if (regRelay.relay_event.bits.Gun1_Parallel_P == YES)
							outputRelay.relay_event.bits.Gun1_Parallel_P = NO;
						else if (regRelay.relay_event.bits.Gun1_Parallel_N == YES)
							outputRelay.relay_event.bits.Gun1_Parallel_N = NO;
					}
					else
					{
						// �̤j�R - �f�W����
						if (regRelay.relay_event.bits.Gun1_Parallel_N == NO)
							outputRelay.relay_event.bits.Gun1_Parallel_N = YES;
						else if (regRelay.relay_event.bits.Gun1_Parallel_P == NO)
							outputRelay.relay_event.bits.Gun1_Parallel_P = YES;
					}
				}
			}
		}
	}
}

void CheckAlarmOccur()
{
	bool isErr = false;
	for(byte count = 0; count < sizeof(_alarm_code)/sizeof(_alarm_code[0]); count++)
	{
		if (acAlarmCode.AcAlarmCode & _alarm_code[count])
		{
			isErr = true;
			switch(_alarm_code[count])
			{
			case AC_OVP: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.AcSystemInputOVP = YES; break;
			case AC_UVP: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.AcSystemInputUVP = YES; break;
			case AC_OCP: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemAcOutputOCP = YES; break;
			case AC_OTP: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemAmbientOTP = YES; break;
			case AC_GMI_FAULT: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.AcGroundfaultFail = YES; break;
			case AC_CP_ERROR: ShmStatusCodeData->InfoCode.InfoEvents.bits.PilotFault = YES; break;
			case AC_AC_LEAKAGE: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.RcdTrip = YES; break;
			case AC_DC_LEAKAGE: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.RcdTrip = YES; break;
			case AC_SYSTEM_SELFTEST_FAULT: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.McuSelftestFail = YES; break;
			case AC_HANDSHAKE_TIMEOUT: break;
			case AC_EMC_STOP: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.EmergencyStopTrip = YES; break;
			case AC_RELAY_WELDING: ShmStatusCodeData->FaultCode.FaultEvents.bits.AcOutputRelayWelding = YES; break;
			case AC_GF_MODULE_FAULT: ShmStatusCodeData->FaultCode.FaultEvents.bits.RcdSelfTestFail = YES; break;
			case AC_SHUTTER_FAULT: break;
			case AC_LOCKER_FAULT: ShmStatusCodeData->FaultCode.FaultEvents.bits.AcConnectorLockFail = YES; break;
			case AC_POWER_DROP: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL1InputDrop = YES; break;
			case AC_CIRCUIT_SHORT: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.CircuitShort = YES; break;
			case AC_ROTARY_SWITCH_FAULT: break;
			case AC_RELAY_DRIVE_FAULT: ShmStatusCodeData->FaultCode.FaultEvents.bits.AcOutputRelayDrivingFault = YES; break;
			}
		}
		else
		{
			switch(_alarm_code[count])
			{
			case AC_OVP: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.AcSystemInputOVP = NO; break;
			case AC_UVP: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.AcSystemInputUVP = NO; break;
			case AC_OCP: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemAcOutputOCP = NO; break;
			case AC_OTP: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemAmbientOTP = NO; break;
			case AC_GMI_FAULT: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.AcGroundfaultFail = NO; break;
			case AC_CP_ERROR: ShmStatusCodeData->InfoCode.InfoEvents.bits.PilotFault = NO; break;
			case AC_AC_LEAKAGE: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.RcdTrip = NO; break;
			case AC_DC_LEAKAGE: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.RcdTrip = NO; break;
			case AC_SYSTEM_SELFTEST_FAULT: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.McuSelftestFail = NO; break;
			case AC_HANDSHAKE_TIMEOUT: break;
			case AC_EMC_STOP: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.EmergencyStopTrip = NO; break;
			case AC_RELAY_WELDING: ShmStatusCodeData->FaultCode.FaultEvents.bits.AcOutputRelayWelding = NO; break;
			case AC_GF_MODULE_FAULT: ShmStatusCodeData->FaultCode.FaultEvents.bits.RcdSelfTestFail = NO; break;
			case AC_SHUTTER_FAULT: break;
			case AC_LOCKER_FAULT: ShmStatusCodeData->FaultCode.FaultEvents.bits.AcConnectorLockFail = NO; break;
			case AC_POWER_DROP: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL1InputDrop = NO; break;
			case AC_CIRCUIT_SHORT: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.CircuitShort = NO; break;
			case AC_ROTARY_SWITCH_FAULT:  break;
			case AC_RELAY_DRIVE_FAULT: ShmStatusCodeData->FaultCode.FaultEvents.bits.AcOutputRelayDrivingFault = NO; break;
			}
		}
	}

	ac_chargingInfo[0]->IsErrorOccur = isErr;
}

//==========================================
// Init all share memory
//==========================================
int InitShareMemory()
{
	int result = PASS;
	int MeterSMId;

	//creat ShmSysConfigAndInfo
	if ((MeterSMId = shmget(ShmSysConfigAndInfoKey, sizeof(struct SysConfigAndInfo),  0777)) < 0)
	{
		#ifdef SystemLogMessage
		DEBUG_ERROR("shmget ShmSysConfigAndInfo NG\n");
		#endif
		result = FAIL;
	}
	else if ((ShmSysConfigAndInfo = shmat(MeterSMId, NULL, 0)) == (void *) -1)
	{
		#ifdef SystemLogMessage
		DEBUG_ERROR("[shmat ShmSysConfigAndInfo NG\n");
		#endif
		result = FAIL;
	 }
	 //creat ShmStatusCodeData
	if ((MeterSMId = shmget(ShmStatusCodeKey, sizeof(struct StatusCodeData),  0777)) < 0)
	{
		#ifdef SystemLogMessage
		DEBUG_ERROR("shmget ShmStatusCodeData NG\n");
		#endif
		result = FAIL;
	}
	else if ((ShmStatusCodeData = shmat(MeterSMId, NULL, 0)) == (void *) -1)
	{
		#ifdef SystemLogMessage
		DEBUG_ERROR("shmat ShmStatusCodeData NG\n");
		#endif
		result = FAIL;
	}

	//creat ShmFanModuleData
	if ((MeterSMId = shmget(ShmFanBdKey, sizeof(struct FanModuleData),  0777)) < 0)
	{
		#ifdef SystemLogMessage
		DEBUG_ERROR("shmget ShmFanModuleData NG\n");
		#endif
		result = FAIL;
	}
	else if ((ShmFanModuleData = shmat(MeterSMId, NULL, 0)) == (void *) -1)
	{
		#ifdef SystemLogMessage
		DEBUG_ERROR("shmat ShmFanModuleData NG\n");
		#endif
		result = FAIL;
	 }
	 memset(ShmFanModuleData,0,sizeof(struct FanModuleData));
	 //creat ShmRelayModuleData
	if ((MeterSMId = shmget(ShmRelayBdKey, sizeof(struct RelayModuleData),  0777)) < 0)
	{
		#ifdef SystemLogMessage
		DEBUG_ERROR("shmget ShmRelayModuleData NG\n");
		#endif
		result = FAIL;
	}
	else if ((ShmRelayModuleData = shmat(MeterSMId, NULL, 0)) == (void *) -1)
	{
		#ifdef SystemLogMessage
		DEBUG_ERROR("shmat ShmRelayModuleData NG\n");
		#endif
		result = FAIL;
	}

	//creat ShmPsuData
	if ((MeterSMId = shmget(ShmPsuKey, sizeof(struct PsuData),  0777)) < 0)
	{
		#ifdef SystemLogMessage
		DEBUG_ERROR("shmget ShmPsuData NG \n");
		#endif
		result = FAIL;
	}
	else if ((ShmPsuData = shmat(MeterSMId, NULL, 0)) == (void *) -1)
	{
		#ifdef SystemLogMessage
		DEBUG_ERROR("shmat ShmPsuData NG \n");
		#endif
		result = FAIL;
	}
	memset(ShmPsuData,0,sizeof(struct PsuData));

	if(CHAdeMO_QUANTITY > 0)
	{
		if ((MeterSMId = shmget(ShmCHAdeMOCommKey, sizeof(struct CHAdeMOData),	IPC_CREAT | 0777)) < 0)
		{
			#ifdef SystemLogMessage
			DEBUG_ERROR("[shmget ShmCHAdeMOData NG \n");
			#endif
			return FAIL;
		}
		else if ((ShmCHAdeMOData = shmat(MeterSMId, NULL, 0)) == (void *) -1) {
			#ifdef SystemLogMessage
			DEBUG_ERROR("shmat ShmCHAdeMOData NG \n");
			#endif
			return FAIL;
		}
	}

	if(CCS_QUANTITY > 0)
	{
		if ((MeterSMId = shmget(ShmCcsCommKey, sizeof(struct CcsData),	IPC_CREAT | 0777)) < 0)
		{
			#ifdef SystemLogMessage
			DEBUG_ERROR("shmget ShmCcsData NG \n");
			#endif
			return FAIL;
		}
		else if ((ShmCcsData = shmat(MeterSMId, NULL, 0)) == (void *) -1)
		{
			#ifdef SystemLogMessage
		   	DEBUG_ERROR("shmat ShmCcsData NG \n");
			#endif
			return FAIL;
		}
	}


	return result;
}

int InitComPort()
{
	int fd;
	struct termios tios;

	fd = open(relayRs485PortName, O_RDWR);
	if(fd <= 0)
	{
		#ifdef SystemLogMessage
		DEBUG_ERROR("Module_InternalComm. InitComPort NG\n");
		#endif
		if(ShmStatusCodeData!=NULL)
		{
			ShmStatusCodeData->AlarmCode.AlarmEvents.bits.CsuInitFailed=1;
		}
		sleep(5);
		return -1;
	}
	ioctl (fd, TCGETS, &tios);
	tios.c_cflag = B115200 | CS8 | CLOCAL | CREAD;
	tios.c_lflag = 0;
	tios.c_iflag = 0;
	tios.c_oflag = 0;
	tios.c_cc[VMIN]=0;
	tios.c_cc[VTIME]=(byte)0;		// timeout 0.5 second
	tios.c_lflag=0;
	tcflush(fd, TCIFLUSH);
	ioctl (fd, TCSETS, &tios);

	return fd;
}

//================================================
// Main process
//================================================
bool FindChargingInfoData(byte target, struct ChargingInfoData **chargingData)
{
	for (byte index = 0; index < CHAdeMO_QUANTITY; index++) {
		if (ShmSysConfigAndInfo->SysInfo.ChademoChargingData[index].Index
				== target) {
			chargingData[target] =
					&ShmSysConfigAndInfo->SysInfo.ChademoChargingData[index];
			return true;
		}
	}

	for (byte index = 0; index < CCS_QUANTITY; index++) {
		if (ShmSysConfigAndInfo->SysInfo.CcsChargingData[index].Index
				== target) {
			chargingData[target] =
					&ShmSysConfigAndInfo->SysInfo.CcsChargingData[index];
			return true;
		}
	}

	for (byte index = 0; index < GB_QUANTITY; index++) {
		if (ShmSysConfigAndInfo->SysInfo.GbChargingData[index].Index
				== target) {
			chargingData[target] =
					&ShmSysConfigAndInfo->SysInfo.GbChargingData[index];
			return true;
		}
	}

	return false;
}

bool FindAcChargingInfoData(byte target, struct ChargingInfoData **acChargingData)
{
	if (target < AC_QUANTITY)
	{
		acChargingData[target] = &ShmSysConfigAndInfo->SysInfo.AcChargingData[target];
		return true;
	}

	return false;
}

void Initialization()
{
	bool isPass = false;

	for (byte index = 0; index < ARRAY_SIZE(outputRelay.relay_event.relay_status); index++)
	{
		outputRelay.relay_event.relay_status[index] = 0x00;
	}

	while(!isPass)
	{
		isPass = true;
		for (byte _index = 0; _index < gunCount; _index++)
		{
			if (!FindChargingInfoData(_index, &_chargingData[0]))
			{
				DEBUG_ERROR("EvComm : FindChargingInfoData false \n");
				isPass = false;
				break;
			}
		}
	}

	isPass = false;

	if (acgunCount > 0)
	{
		while(!isPass)
		{
			isPass = true;
			for (byte _index = 0; _index < acgunCount; _index++)
			{
				if (!FindAcChargingInfoData(_index, &ac_chargingInfo[0]))
				{
					DEBUG_ERROR("EvComm : FindAcChargingInfoData false \n");
					isPass = false;
					break;
				}
			}
		}
	}
}

bool IsNoneMatchRelayStatus()
{
	bool result = false;

	if ((regRelay.relay_event.bits.AC_Contactor != outputRelay.relay_event.bits.AC_Contactor) ||
		(regRelay.relay_event.bits.CCS_Precharge != outputRelay.relay_event.bits.CCS_Precharge) ||
		(regRelay.relay_event.bits.Gun1_P != outputRelay.relay_event.bits.Gun1_P) ||
		(regRelay.relay_event.bits.Gun1_N != outputRelay.relay_event.bits.Gun1_N) ||
		(regRelay.relay_event.bits.Gun2_P != outputRelay.relay_event.bits.Gun2_P) ||
		(regRelay.relay_event.bits.Gun2_N != outputRelay.relay_event.bits.Gun2_N) ||
		(regRelay.relay_event.bits.Gun1_Parallel_P != outputRelay.relay_event.bits.Gun1_Parallel_P) ||
		(regRelay.relay_event.bits.Gun1_Parallel_N != outputRelay.relay_event.bits.Gun1_Parallel_N))
	{
		if (regRelay.relay_event.bits.AC_Contactor != outputRelay.relay_event.bits.AC_Contactor)
			PRINTF_FUNC("AC Contact Relay none match. \n");
		if (regRelay.relay_event.bits.CCS_Precharge != outputRelay.relay_event.bits.CCS_Precharge)
			PRINTF_FUNC("CCS Precharge Relay none match. \n");
		if (regRelay.relay_event.bits.Gun1_P != outputRelay.relay_event.bits.Gun1_P)
			PRINTF_FUNC("SMR1:D+ Relay none match. \n");
		if (regRelay.relay_event.bits.Gun1_N != outputRelay.relay_event.bits.Gun1_N)
			PRINTF_FUNC("SMR1:D- Relay none match. \n");
		if (regRelay.relay_event.bits.Gun2_P != outputRelay.relay_event.bits.Gun2_P)
			PRINTF_FUNC("SMR2:D+ Relay none match. \n");
		if (regRelay.relay_event.bits.Gun2_N != outputRelay.relay_event.bits.Gun2_N)
			PRINTF_FUNC("SMR2:D- Relay none match. \n");
		if (regRelay.relay_event.bits.Gun1_Parallel_P != outputRelay.relay_event.bits.Gun1_Parallel_P)
			PRINTF_FUNC("Parallel:D+ Relay none match. \n");
		if (regRelay.relay_event.bits.Gun1_Parallel_N != outputRelay.relay_event.bits.Gun1_Parallel_N)
			PRINTF_FUNC("Parallel:D- Relay none match. \n");

		result = true;
	}

	return result;
}

void MatchRelayStatus()
{
	// �]�� AC Contactor �S�� Feedback�A�ҥH�Ȯɥ��o�˳B�z
	//regRelay.relay_event.bits.AC_Contactor = outputRelay.relay_event.bits.AC_Contactor;
	ShmSysConfigAndInfo->SysInfo.AcContactorStatus  = regRelay.relay_event.bits.AC_Contactor = outputRelay.relay_event.bits.AC_Contactor;
	regRelay.relay_event.bits.CCS_Precharge = outputRelay.relay_event.bits.CCS_Precharge;
	regRelay.relay_event.bits.Gun1_P = outputRelay.relay_event.bits.Gun1_P;
	regRelay.relay_event.bits.Gun1_N = outputRelay.relay_event.bits.Gun1_N;
	regRelay.relay_event.bits.Gun2_P = outputRelay.relay_event.bits.Gun2_P;
	regRelay.relay_event.bits.Gun2_N = outputRelay.relay_event.bits.Gun2_N;
	regRelay.relay_event.bits.Gun1_Parallel_P = outputRelay.relay_event.bits.Gun1_Parallel_P;
	regRelay.relay_event.bits.Gun1_Parallel_N = outputRelay.relay_event.bits.Gun1_Parallel_N;
}

void CheckRelayStatusByADC()
{
	if (ShmRelayModuleData->Gun1FuseOutputVolt > 0 && ShmRelayModuleData->Gun1RelayOutputVolt > 0 &&
			(ShmRelayModuleData->Gun1FuseOutputVolt == ShmRelayModuleData->Gun1RelayOutputVolt))
	{
		// Relay �e��q���@�P
		_chargingData[0]->RelayK1K2Status = 0x01;
	}
	else
		_chargingData[0]->RelayK1K2Status = 0x00;

	if (ShmRelayModuleData->Gun2FuseOutputVolt > 0 && ShmRelayModuleData->Gun2RelayOutputVolt > 0 &&
				(ShmRelayModuleData->Gun2FuseOutputVolt == ShmRelayModuleData->Gun2RelayOutputVolt))
	{
		// Relay �e��q���@�P
		_chargingData[1]->RelayK1K2Status = 0x01;
	}
	else
		_chargingData[1]->RelayK1K2Status = 0x00;
}

void SetGfdConfig(byte index, byte resister)
{
	gfd_config.index = index;
	gfd_config.state = resister;

	//PRINTF_FUNC("************************GFD Vol = %d, GFD Res = %d \n", gfd_config.reqVol, gfd_config.resister);
	if (Config_Gfd_Value(Uart5Fd, Addr.Relay, &gfd_config) == PASS)
	{
//		PRINTF_FUNC("Set reqVol = %f, resister = %d \n",
//				gfd_config.reqVol,
//				gfd_config.resister);
	}
}

void CableCheckDetected(byte index)
{
	// Cable Check
	// �����u�W���q�� = ���ݭn�D���q���q�y
	// _chargingData[targetGun]->EvBatterytargetVoltage
	// �~�i�H�}�l���� 1s
	// Warning : Rgfd <= 150 ��/V ���]�q���� 500V �h~ Rgfd <= 75000 ��
	// Pre-Warning : 150 ��/V < Rgfd <= 500 ��/V ���]�q���� 500V �h 75000 �� < Rgfd <= 250000
	// SO Normal : Rgfd > 500 ��/V ���]�q���� 500 V �h Rgfd > 250000 ��
	if ((_chargingData[index]->Type >= _Type_Chademo && _chargingData[index]->Type <= _Type_GB) ||
			(_chargingData[index]->Type == 0x09 && ShmSysConfigAndInfo->SysConfig.AlwaysGfdFlag))
	{
		if ((_chargingData[index]->SystemStatus >= S_PREPARING_FOR_EVSE && _chargingData[index]->SystemStatus <= S_CHARGING) ||
			(_chargingData[index]->SystemStatus >= S_CCS_PRECHARGE_ST0 && _chargingData[index]->SystemStatus <= S_CCS_PRECHARGE_ST1))
		{
			if (_chargingData[index]->SystemStatus == S_PREPARING_FOR_EVSE &&
					_chargingData[index]->RelayWeldingCheck == YES)
			{
				SetGfdConfig(index, GFD_CABLECHK);
			}
			else if (_chargingData[index]->SystemStatus >= S_CCS_PRECHARGE_ST0 &&
					_chargingData[index]->SystemStatus <= S_CCS_PRECHARGE_ST1)
			{
				SetGfdConfig(index, GFD_PRECHARGE);
			}
			else if (_chargingData[index]->SystemStatus <= S_CHARGING)
			{
				if (_chargingData[index]->Type == _Type_GB)
					SetGfdConfig(index, GFD_IDLE);
				else
					SetGfdConfig(index, GFD_CHARGING);
			}
		}
		else if(_chargingData[index]->SystemStatus == S_COMPLETE || _chargingData[index]->SystemStatus == S_PREPARNING
				|| _chargingData[index]->SystemStatus == S_IDLE)
		{
			SetGfdConfig(index, GFD_IDLE);
		}
	}
}

void CheckOutputPowerOverCarReq(byte index)
{
	float fireV = _chargingData[index]->FireChargingVoltage;
	float carV = _chargingData[index]->EvBatterytargetVoltage;

	if (_chargingData[index]->EvBatterytargetVoltage > 1500 &&
			(_chargingData[index]->Type == _Type_Chademo ||
				_chargingData[index]->Type == _Type_CCS_2 ||
				_chargingData[index]->Type == _Type_GB))
	{
		if (fireV >= (carV + (carV * 0.1)))
		{
			PRINTF_FUNC("[Module_InternalComm]CheckOutputPowerOverCarReq NG : fire = %f, battery = %f \n",
					_chargingData[index]->FireChargingVoltage, _chargingData[index]->EvBatterytargetVoltage);
			DEBUG_ERROR("[Module_InternalComm]CheckOutputPowerOverCarReq NG : fire = %f, battery = %f \n",
					_chargingData[index]->FireChargingVoltage, _chargingData[index]->EvBatterytargetVoltage);
			_chargingData[index]->StopChargeFlag = YES;
		}
	}
}

void CheckOutputVolNoneMatchFire(byte index)
{
	if (_chargingData[index]->EvBatterytargetVoltage > 1500 &&
			(_chargingData[index]->Type == _Type_Chademo ||
					_chargingData[index]->Type == _Type_CCS_2 ||
					_chargingData[index]->Type == _Type_GB))
	{
		if (((_chargingData[index]->PresentChargingVoltage * 10) < _chargingData[index]->FireChargingVoltage - 300) ||
				((_chargingData[index]->PresentChargingVoltage * 10) > _chargingData[index]->FireChargingVoltage + 300))
		{
			if (!_isOutputNoneMatch[index])
			{
				_isOutputNoneMatch[index] = YES;
				gettimeofday(&_checkOutputNoneMatchTimer[index], NULL);
			}
			else
			{
				if ((GetTimeoutValue(_checkOutputNoneMatchTimer[index]) / 1000) >= 5000)
				{
					PRINTF_FUNC("[Module_InternalComm]CheckOutputVolNoneMatchFire NG (%d) : pre = %f, fire = %f \n",
							index, (_chargingData[index]->PresentChargingVoltage * 10), _chargingData[index]->FireChargingVoltage);
					DEBUG_ERROR("[Module_InternalComm]CheckOutputVolNoneMatchFire NG (%d): pre = %f, fire = %f \n",
							index, (_chargingData[index]->PresentChargingVoltage * 10), _chargingData[index]->FireChargingVoltage);
					_chargingData[index]->StopChargeFlag = YES;
				}
			}
		}
		else
			_isOutputNoneMatch[index] = NO;
	}
}

void CheckRelayWeldingStatus(byte index)
{
	if (!_isRelayWelding[index])
	{
		if ((_chargingData[index]->PresentChargingVoltage * 10) >= VOUT_MIN_VOLTAGE * 10)
		{
			gettimeofday(&_checkRelayWeldingTimer[index], NULL);
			_isRelayWelding[index] = YES;
		}
	}
	else
	{
		if ((GetTimeoutValue(_checkRelayWeldingTimer[index]) / 1000) >= 1000)
		{
			_chargingData[index]->RelayWeldingCheck = YES;
			return;
		}

		if (_chargingData[index]->FireChargingVoltage >= VOUT_MIN_VOLTAGE)
		{
			if (_chargingData[index]->Type == _Type_Chademo)
				ShmStatusCodeData->FaultCode.FaultEvents.bits.ChademoOutputRelayWelding = YES;
			else if (_chargingData[index]->Type == _Type_GB)
				ShmStatusCodeData->FaultCode.FaultEvents.bits.GbOutputRelayWelding = YES;
			else if (_chargingData[index]->Type == _Type_CCS_2)
				ShmStatusCodeData->FaultCode.FaultEvents.bits.CcsOutputRelayWelding = YES;

			PRINTF_FUNC("CheckRelayWeldingStatus : fail \n");
			_chargingData[index]->StopChargeFlag = YES;
		}
	}
}

void GetPsuTempForFanSpeed()
{
	char temp = 0;
	for (byte index = 0; index < ShmPsuData->GroupCount; index++)
	{
		for (byte count = 0; count < ShmPsuData->PsuGroup[index].GroupPresentPsuQuantity; count++)
		{
			if (temp < ShmPsuData->PsuGroup[index].PsuModule[count].ExletTemp)
				temp = ShmPsuData->PsuGroup[index].PsuModule[count].ExletTemp;
		}
	}

	if (ShmSysConfigAndInfo->SysConfig.SwitchDebugFlag == NO)
	{
		if (ShmFanModuleData->TestFanSpeed == NORMAL_FAN_SPEED)
		{
			if (temp >= ENV_TEMP_MAX)
				ShmFanModuleData->TestFanSpeed = MAX_FAN_SPEED;
		}
		else if (ShmFanModuleData->TestFanSpeed == MAX_FAN_SPEED)
		{
			if (temp <= ENV_TEMP_MIN)
				ShmFanModuleData->TestFanSpeed = NORMAL_FAN_SPEED;
		}
		else
			ShmFanModuleData->TestFanSpeed = NORMAL_FAN_SPEED;
	}
}

void GetAcStatus()
{
	if (Query_AC_Status(Uart5Fd, Addr.AcPlug, &acStatus) == PASS)
	{
	//				printf("CpStatus = %d \n", acStatus.CpStatus);
	//				printf("CurLimit = %d \n", acStatus.CurLimit);
	//				printf("PilotVol_P = %d \n", acStatus.PilotVol_P);
	//				printf("PilotVol_N = %d \n", acStatus.PilotVol_N);
	//				printf("LockStatus = %d \n", acStatus.LockStatus);
	//				printf("RelayStatus = %d \n", acStatus.RelayStatus);
	//				printf("ShutterStatus = %d \n", acStatus.ShutterStatus);
	//				printf("MeterStatus = %d \n", acStatus.MeterStatus);
	//				printf("PpStatus = %d \n", acStatus.PpStatus);
	//				printf("MaxCurrent = %d \n", acStatus.MaxCurrent);
	//				printf("RotateSwitchStatus = %d \n", acStatus.RelayStatus);
	//				printf("============================== \n");
	//
	//				ac_chargingInfo[0]->SystemStatus = acStatus.CpStatus;
	}
}

void GetAcAlarmCode()
{
	if (Query_AC_Alarm_Code(Uart5Fd, Addr.AcPlug, &acAlarmCode) == PASS)
	{
		CheckAlarmOccur();
	}
}

unsigned char GetChargingEnergy()
{
	return Query_Charging_Energy(Uart5Fd, Addr.AcPlug, &acChargingEnergy);
}

unsigned char GetChargingCurrent()
{
	return Query_Charging_Current(Uart5Fd, Addr.AcPlug, &acChargingCurrent);
}

void ChangeLedStatus()
{
	if (ac_chargingInfo[0]->SystemStatus == S_IDLE)
		ledStatus.ActionMode = 1;
	else if (ac_chargingInfo[0]->SystemStatus == S_PREPARNING)
		ledStatus.ActionMode = 3;
	else if (ac_chargingInfo[0]->SystemStatus == S_CHARGING)
		ledStatus.ActionMode = 4;

	Config_LED_Status(Uart5Fd, Addr.AcPlug, &ledStatus);
}

void SetLegacyReq(byte _switch)
{
	Config_Legacy_Req(Uart5Fd, Addr.AcPlug, _switch);
}

void SetCpDuty(byte _value)
{
	Config_Ac_Duty(Uart5Fd, Addr.AcPlug, _value);
}

void ChangeToCsuMode()
{
	ac_chargingInfo[0]->IsModeChagned = Config_CSU_Mode(Uart5Fd, Addr.AcPlug);

//	if (ac_chargingInfo[0]->IsModeChagned == PASS)
//	{
//		Config_Reset_MCU(Uart5Fd, Addr.AcPlug);
//	}
}

void AcChargeTypeProcess()
{
	if (acgunCount > 0)
	{
		if (ac_chargingInfo[0]->SelfTest_Comp == NO)
		{
			ac_chargingInfo[0]->IsModeChagned = NO;
			GetFwVersion_AC();
		}
		else if (ac_chargingInfo[0]->SelfTest_Comp == YES)
		{
			if (ac_chargingInfo[0]->IsModeChagned != PASS)
			{
				ChangeToCsuMode();
				return;
			}

			GetAcStatus();
			GetAcAlarmCode();

			byte _status = S_NONE;
			bool _isStatusChanged = false;

			if (acStatus.CpStatus == AC_SYS_A || ac_chargingInfo[0]->IsErrorOccur)
			{
				if (ac_chargingInfo[0]->SystemStatus == S_CHARGING)
					_status = S_TERMINATING;
				else if (ac_chargingInfo[0]->SystemStatus >= S_TERMINATING)
				{
					if (GetTimeoutValue(_ac_charging_comp) >= 10000000)
						_status = S_IDLE;
				}
				else
					_status = S_IDLE;
			}
			else if (ac_chargingInfo[0]->SystemStatus >= S_PREPARNING &&
					ac_chargingInfo[0]->SystemStatus < S_CHARGING)
			{
				if (acStatus.CpStatus == AC_SYS_C && acStatus.RelayStatus == YES)
					_status = S_CHARGING;
				else if (GetTimeoutValue(_ac_preparing) >= 30000000)
					_status = S_IDLE;
			}
			else if (acStatus.CpStatus == AC_SYS_B &&
					ac_chargingInfo[0]->IsAvailable &&
					!ac_chargingInfo[0]->IsErrorOccur &&
					(ShmSysConfigAndInfo->SysInfo.WaitForPlugit == YES ||
						ShmSysConfigAndInfo->SysConfig.AuthorisationMode == AUTH_MODE_DISABLE))
			{
				PRINTF_FUNC("** UserId = %s \n", ShmSysConfigAndInfo->SysConfig.UserId);
				strcpy((char *)ac_chargingInfo[0]->StartUserId, (char *)ShmSysConfigAndInfo->SysConfig.UserId);
				PRINTF_FUNC("** CardNumber = %s \n", ac_chargingInfo[0]->StartUserId);
				strcpy((char *)ShmSysConfigAndInfo->SysConfig.UserId, "");
				ShmSysConfigAndInfo->SysInfo.WaitForPlugit = NO;
				_status = S_PREPARNING;
			}

			//printf("_status = %d \n", _status);

			if (_status != S_NONE && ac_chargingInfo[0]->SystemStatus != _status)
			{
				_isStatusChanged = true;
				ac_chargingInfo[0]->SystemStatus = _status;
			}

			// �]�w����̤j�R�q�q�y >= 6 ~ <= 32
			switch(ac_chargingInfo[0]->SystemStatus)
			{
				case S_IDLE:
				{
					if (_isStatusChanged)
					{
						ac_chargingInfo[0]->PresentChargedEnergy = 0.0;
					}

					ChangeLedStatus();
				}
					break;
				case S_PREPARNING:
				{
					if (_isStatusChanged)
					{
						ShmSysConfigAndInfo->SysInfo.SystemPage = _LCM_NONE;
						ShmSysConfigAndInfo->SysInfo.CurGunSelectedByAc = DEFAULT_AC_INDEX;
						gettimeofday(&_ac_preparing, NULL);
					}

					if (GetChargingEnergy() == PASS)
					{
						ac_chargingInfo[0]->PresentChargedEnergy = acChargingEnergy.Energy / 100;
					}

					SetLegacyReq(YES);
					ChangeLedStatus();
				}
					break;
				case S_CHARGING:
				{
					if (_isStatusChanged)
					{
						ftime(&_ac_startChargingTime);
						ShmSysConfigAndInfo->SysInfo.CurGunSelectedByAc = DEFAULT_AC_INDEX;
					}

					if (GetChargingEnergy() == PASS)
						ac_chargingInfo[0]->PresentChargedEnergy = acChargingEnergy.Energy / 100;

					if (GetChargingCurrent() == PASS)
						ac_chargingInfo[0]->PresentChargingPower = (220 * (acChargingCurrent.OuputCurrentL1 / 10)) / 1000;

					ftime(&_ac_endChargingTime);
					ac_chargingInfo[0]->RemainChargingDuration = DiffTimeb(_ac_startChargingTime, _ac_endChargingTime);

					// �ΥH�P�_�O�_���b��X
					ac_chargingInfo[0]->IsCharging = acStatus.RelayStatus;

					SetCpDuty(ShmSysConfigAndInfo->SysConfig.AcMaxChargingCurrent);
					ChangeLedStatus();
				}
					break;
				case S_TERMINATING:
				{
					if (_isStatusChanged)
					{
						gettimeofday(&_ac_charging_comp, NULL);
					}

					SetLegacyReq(NO);
					if (acStatus.RelayStatus == NO)
						ac_chargingInfo[0]->SystemStatus = S_COMPLETE;
				}
					break;
				case S_COMPLETE:
				{
					if (_isStatusChanged)
					{
						gettimeofday(&_ac_charging_comp, NULL);
						ftime(&_ac_endChargingTime);
						ac_chargingInfo[0]->RemainChargingDuration = DiffTimeb(_ac_startChargingTime, _ac_endChargingTime);
					}
				}
					break;
			}
		}
	}
}

int main(void)
{
	if(InitShareMemory() == FAIL)
	{
		#ifdef SystemLogMessage
		DEBUG_ERROR("InitShareMemory NG\n");
		#endif
		if(ShmStatusCodeData!=NULL)
		{
			ShmStatusCodeData->AlarmCode.AlarmEvents.bits.FailToCreateShareMemory=1;
		}
		sleep(5);
		return 0;
	}

	gunCount = ShmSysConfigAndInfo->SysConfig.TotalConnectorCount;
	acgunCount = ShmSysConfigAndInfo->SysConfig.AcConnectorCount;
	// Open Uart5 for RB
	Uart5Fd = InitComPort();
	Initialization();
	sleep(1);

	if(Uart5Fd < 0)
	{
		PRINTF_FUNC("(Internal) open port error. \n");
		return 0;
	}

	outputRelay.relay_event.bits.AC_Contactor = 0x00;
	outputRelay.relay_event.bits.CCS_Precharge = 0x00;
	outputRelay.relay_event.bits.Gun1_Parallel_P = 0x00;
	outputRelay.relay_event.bits.Gun1_Parallel_N = 0x00;
	outputRelay.relay_event.bits.Gun1_P = 0x00;
	outputRelay.relay_event.bits.Gun1_N = 0x00;
	outputRelay.relay_event.bits.Gun2_N = 0x00;
	outputRelay.relay_event.bits.Gun2_P = 0x00;
	if(Config_Relay_Output(Uart5Fd, Addr.Relay, &outputRelay) != PASS)
		PRINTF_FUNC("Config_Relay_Output fail \n");

	bool printRelayStatus = true;
	for(;;)
	{
		bool isCharging = false;
		// �{�Ƕ}�l���e~ �������T�w FW �����P�w�骩���A�T�{��!!~ �ӼҲդ~��O�u���� Initial Comp.
		if (ShmRelayModuleData->SelfTest_Comp == NO)
		{
			GetFwAndHwVersion_Relay();
			SetRtcData_Relay();
			sleep(1);
		}

		if (ShmFanModuleData->SelfTest_Comp == NO)
		{
			GetFwAndHwVersion_Fan();
			SetModelName_Fan();
			SetRtcData_Fan();
			sleep(1);
			gettimeofday(&_priority_time, NULL);
		}

		AcChargeTypeProcess();

		if (ShmRelayModuleData->SelfTest_Comp == YES)
		{
			// ==============�u���v�̰� 10 ms ==============
			// ��X�q��
			GetPersentOutputVol();

			// �T�ۿ�J�q��
			GetPresentInputVol();

			// Ū�����e AC relay ���A
			regRelay.relay_event.bits.AC_Contactor = ShmSysConfigAndInfo->SysInfo.AcContactorStatus;
			//GetRelayOutputStatus();

			for (int i = 0; i < gunCount; i++)
			{
				// Cable check (Set)
				CableCheckDetected(i);

				// check k1 k2 relay ���A
				CheckK1K2RelayOutput(i);

				// �̾ڷ��e�U�j�����A��� �f�W/��} Relay
				SetK1K2RelayStatus(i);

				if (ShmSysConfigAndInfo->SysConfig.PhaseLossPolicy == YES)
					CheckPhaseLossStatus(i);

				CheckAcInputOvpStatus(i);

				if (_chargingData[i]->SystemStatus == S_IDLE)
				{
					_chargingData[i]->RelayWeldingCheck = NO;
					_isRelayWelding[i] = NO;
				}

				if (_chargingData[i]->SystemStatus == S_BOOTING	||
					(_chargingData[i]->SystemStatus >= S_REASSIGN_CHECK && _chargingData[i]->SystemStatus <= S_COMPLETE) ||
					(_chargingData[i]->SystemStatus >= S_CCS_PRECHARGE_ST0 && _chargingData[i]->SystemStatus <= S_CCS_PRECHARGE_ST1) ||
					ShmSysConfigAndInfo->SysInfo.WaitForPlugit == YES ||
					(ShmSysConfigAndInfo->SysInfo.PageIndex >= _LCM_AUTHORIZING && ShmSysConfigAndInfo->SysInfo.PageIndex <= _LCM_WAIT_FOR_PLUG))
				{
					_chargingData[i]->IsReadyToCharging = YES;
					isCharging = true;

					// ���w�u���b�j���O�� GBT ���ɭԤ~�� relay welding ���P�_
					if (_chargingData[i]->Type == _Type_GB)
					{
						if (_chargingData[i]->SystemStatus >= S_PREPARING_FOR_EVSE &&
							_chargingData[i]->RelayWeldingCheck == NO)
							CheckRelayWeldingStatus(i);
					}
					else
						_chargingData[i]->RelayWeldingCheck = YES;

					if (_chargingData[i]->SystemStatus == S_CHARGING)
					{
						CheckOutputPowerOverCarReq(i);
						CheckOutputVolNoneMatchFire(i);
					}
					else
						_isOutputNoneMatch[i] = NO;
				}
				else
					_chargingData[i]->IsReadyToCharging = NO;
			}
			// Cable check (Get)
			GetGfdAdc();

			// ���� relay
			SetParalleRelayStatus();

			// �f�W AC Contactor
//			if (isCharging)
//				outputRelay.relay_event.bits.AC_Contactor = YES;
//			else
//				outputRelay.relay_event.bits.AC_Contactor = NO;

			if (isCharging)
			{
				isStopChargingCount = false;
				outputRelay.relay_event.bits.AC_Contactor = YES;
			}
			else
			{
				if (!isStopChargingCount)
				{
					gettimeofday(&_close_ac_contactor, NULL);
					isStopChargingCount = true;
				}
				else
				{
					if ((outputRelay.relay_event.bits.AC_Contactor == YES && GetTimeoutValue(_close_ac_contactor) / 1000 >= (TEN_MINUTES * 1000)))
						outputRelay.relay_event.bits.AC_Contactor = NO;
				}
			}

			// �f�W/�P�} Relay
			if(IsNoneMatchRelayStatus())
			{
				if (Config_Relay_Output(Uart5Fd, Addr.Relay, &outputRelay))
				{
					//regRelay.relay_event.bits.AC_Contactor = ShmSysConfigAndInfo->SysInfo.AcContactorStatus;
					regRelay.relay_event.bits.CCS_Precharge = outputRelay.relay_event.bits.CCS_Precharge;
					regRelay.relay_event.bits.Gun1_P = outputRelay.relay_event.bits.Gun1_P;
					regRelay.relay_event.bits.Gun1_N = outputRelay.relay_event.bits.Gun1_N;
					regRelay.relay_event.bits.Gun2_P = outputRelay.relay_event.bits.Gun2_P;
					regRelay.relay_event.bits.Gun2_N = outputRelay.relay_event.bits.Gun2_N;
					regRelay.relay_event.bits.Gun1_Parallel_P = outputRelay.relay_event.bits.Gun1_Parallel_P;
					regRelay.relay_event.bits.Gun1_Parallel_N = outputRelay.relay_event.bits.Gun1_Parallel_N;

					PRINTF_FUNC("Match Relay, AC = %x, g1_p = %x, g1_n = %x, g2_p = %x, g2_n = %x, pre = %x, bri_p = %x, bri_n = %x \n",
							regRelay.relay_event.bits.AC_Contactor,
							regRelay.relay_event.bits.Gun1_P,
							regRelay.relay_event.bits.Gun1_N,
							regRelay.relay_event.bits.Gun2_P,
							regRelay.relay_event.bits.Gun2_N,
							regRelay.relay_event.bits.CCS_Precharge,
							regRelay.relay_event.bits.Gun1_Parallel_P,
							regRelay.relay_event.bits.Gun1_Parallel_N);
				}
			}


//			if(IsNoneMatchRelayStatus())
//			{
//				if (printRelayStatus)
//				{
////					PRINTF_FUNC("Match Relay Target, AC = %x, g1_p = %x, g1_n = %x, g2_p = %x, g2_n = %x, pre = %x, bri_p = %x, bri_n = %x \n",
////							outputRelay.relay_event.bits.AC_Contactor,
////							outputRelay.relay_event.bits.Gun1_P,
////							outputRelay.relay_event.bits.Gun1_N,
////							outputRelay.relay_event.bits.Gun2_P,
////							outputRelay.relay_event.bits.Gun2_N,
////							outputRelay.relay_event.bits.CCS_Precharge,
////							outputRelay.relay_event.bits.Gun1_Parallel_P,
////							outputRelay.relay_event.bits.Gun1_Parallel_N);
//				}
//				printRelayStatus = false;
//				if (Config_Relay_Output(Uart5Fd, Addr.Relay, &outputRelay))
//				{
//					PRINTF_FUNC("Match Relay Target, AC = %x, g1_p = %x, g1_n = %x, g2_p = %x, g2_n = %x, pre = %x, bri_p = %x, bri_n = %x \n",
//							outputRelay.relay_event.bits.AC_Contactor,
//							outputRelay.relay_event.bits.Gun1_P,
//							outputRelay.relay_event.bits.Gun1_N,
//							outputRelay.relay_event.bits.Gun2_P,
//							outputRelay.relay_event.bits.Gun2_N,
//							outputRelay.relay_event.bits.CCS_Precharge,
//							outputRelay.relay_event.bits.Gun1_Parallel_P,
//							outputRelay.relay_event.bits.Gun1_Parallel_N);
//				}
//			}
//			else
//			{
//				if (!printRelayStatus)
//				{
//					PRINTF_FUNC("Match Relay, AC = %x, g1_p = %x, g1_n = %x, g2_p = %x, g2_n = %x, pre = %x, bri_p = %x, bri_n = %x \n",
//							regRelay.relay_event.bits.AC_Contactor,
//							regRelay.relay_event.bits.Gun1_P,
//							regRelay.relay_event.bits.Gun1_N,
//							regRelay.relay_event.bits.Gun2_P,
//							regRelay.relay_event.bits.Gun2_N,
//							regRelay.relay_event.bits.CCS_Precharge,
//							regRelay.relay_event.bits.Gun1_Parallel_P,
//							regRelay.relay_event.bits.Gun1_Parallel_N);
//				}
//				printRelayStatus = true;
//			}
		}

		if (ShmFanModuleData->SelfTest_Comp == YES)
		{
			if (GetTimeoutValue(_priority_time) / 1000 >= 1000)
			{
				GetPsuTempForFanSpeed();

				GetFanSpeed();
				ShmSysConfigAndInfo->SysInfo.SystemFanRotaSpeed = _setFanSpeed;

				gettimeofday(&_priority_time, NULL);
				if (isCharging)
				{
//					if (ShmFanModuleData->PresentFan1Speed < MAX_FAN_SPEED ||
//						ShmFanModuleData->PresentFan2Speed < MAX_FAN_SPEED ||
//						ShmFanModuleData->PresentFan3Speed < MAX_FAN_SPEED ||
//						ShmFanModuleData->PresentFan4Speed < MAX_FAN_SPEED)
//					{
//						ShmFanModuleData->SetFan1Speed = MAX_FAN_SPEED;
//						ShmFanModuleData->SetFan2Speed = MAX_FAN_SPEED;
//						ShmFanModuleData->SetFan3Speed = MAX_FAN_SPEED;
//						ShmFanModuleData->SetFan4Speed = MAX_FAN_SPEED;
//					}

					// �b�٨S�ݨ� PSU �ū�~ �٬O�n���ӳ̤p��t
					ShmFanModuleData->SetFan1Speed = MIN_FAN_SPEED;
					ShmFanModuleData->SetFan2Speed = MIN_FAN_SPEED;
					ShmFanModuleData->SetFan3Speed = MIN_FAN_SPEED;
					ShmFanModuleData->SetFan4Speed = MIN_FAN_SPEED;

					if (ShmFanModuleData->TestFanSpeed > 0)
					{
						ShmFanModuleData->SetFan1Speed = ShmFanModuleData->TestFanSpeed;
						ShmFanModuleData->SetFan2Speed = ShmFanModuleData->TestFanSpeed;
						ShmFanModuleData->SetFan3Speed = ShmFanModuleData->TestFanSpeed;
						ShmFanModuleData->SetFan4Speed = ShmFanModuleData->TestFanSpeed;
					}
				}
				else
				{
//					if (ShmFanModuleData->PresentFan1Speed > MIN_FAN_SPEED ||
//						ShmFanModuleData->PresentFan2Speed > MIN_FAN_SPEED ||
//						ShmFanModuleData->PresentFan3Speed > MIN_FAN_SPEED ||
//						ShmFanModuleData->PresentFan4Speed > MIN_FAN_SPEED)
//					{
						ShmFanModuleData->SetFan1Speed = MIN_FAN_SPEED;
						ShmFanModuleData->SetFan2Speed = MIN_FAN_SPEED;
						ShmFanModuleData->SetFan3Speed = MIN_FAN_SPEED;
						ShmFanModuleData->SetFan4Speed = MIN_FAN_SPEED;
//					}

					// ����ɡA�p�ū��٬O�ܰ��A�h�ݭn��������t����ū׭��C
					if (ShmFanModuleData->TestFanSpeed >= MAX_FAN_SPEED)
					{
						ShmFanModuleData->SetFan1Speed = ShmFanModuleData->TestFanSpeed;
						ShmFanModuleData->SetFan2Speed = ShmFanModuleData->TestFanSpeed;
						ShmFanModuleData->SetFan3Speed = ShmFanModuleData->TestFanSpeed;
						ShmFanModuleData->SetFan4Speed = ShmFanModuleData->TestFanSpeed;
					}
				}

				//PRINTF_FUNC("set fan = %d \n", ShmFanModuleData->SetFan1Speed);
				SetFanModuleSpeed();
			}
		}

		usleep(10000);
	}

	return FAIL;
}