/*
 * UUpwr_PsuCommObj.c
 *
 *  Created on: 2022�~3��30��
 *      Author: 7564
 */

#include "UUpwr_PsuCommObj.h"

//================================================
// Callback function
//================================================
void RefreshStatus(void *func)
{
	return_status = func;
}

void RefreshModuleCount(void *func)
{
	return_module_count = func;
}

void RefreshAvailableCap(void *func)
{
	return_available_cap = func;
}

void RefreshFwVersion(void *func)
{
	return_fw_version = func;
}

void RefreshInputVol(void *func)
{
	return_input_vol = func;
}

void RefreshGetOutput(void *func)
{
	return_get_output = func;
}

void RefreshGetOutputF(void *func)
{
	return_get_output_float = func;
}

void RefreshMisInfo(void *func)
{
	return_mis_info = func;
}

void RefreshIavailable(void *func)
{
	return_iavail_info = func;
}

void AutoMode_RefreshOutputAndTemp(void *func)
{
	return_output_temp = func;
}

void AutoMode_RefreshModuleStatus(void *func)
{
	return_module_status = func;
}

void AutoMode_RefreshModuleInput(void *func)
{
	return_module_input = func;
}

//================================================
// Private Function
//================================================
int UU_GetTimeoutValue(struct timespec *startTime)
{
	struct timespec endTime;

	clock_gettime(CLOCK_MONOTONIC_COARSE, &endTime);
	return (endTime.tv_nsec - startTime->tv_nsec) / 1000000;
}

void UU_GetTimespecFunc(struct timespec *time)
{
	clock_gettime(CLOCK_MONOTONIC_COARSE, time);
}

void SendCmdToPsu(int cmd, byte *data, byte dataLen)
{
    PwrFrame PwrFrameMsg;
    struct can_frame frame;

    //�]�w CANBSU 2.0B ���ʥ]
    PwrFrameMsg.PwrMessage = cmd | 0x80000000;

    frame.can_id = PwrFrameMsg.PwrMessage;
    frame.can_dlc = dataLen;
    memcpy(frame.data, data, dataLen);

    write(CanFd, &frame, sizeof(struct can_frame));
}

int InitCanBus()
{
	int 					s0,nbytes;
	struct timeval			tv;
	struct ifreq 			ifr0;
	struct sockaddr_can		addr0;
	//struct can_filter 		rfilter[2];

	system("/sbin/ip link set can1 down");
	system("/sbin/ip link set can1 type can bitrate 500000 restart-ms 100");
	system("/sbin/ip link set can1 up");

	s0 = socket(PF_CAN, SOCK_RAW, CAN_RAW);

	tv.tv_sec = 0;
	tv.tv_usec = 10000;
   	if (setsockopt(s0, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(struct	timeval)) < 0)
	{
		#ifdef SystemLogMessage
   		PRINTF_LIB_FUNC("Set SO_RCVTIMEO NG");
		#endif
	}
	nbytes=40960;
	if (setsockopt(s0, SOL_SOCKET,  SO_RCVBUF, &nbytes, sizeof(int)) < 0)
	{
		#ifdef SystemLogMessage
		PRINTF_LIB_FUNC("Set SO_RCVBUF NG");
		#endif
	}
	nbytes=40960;
	if (setsockopt(s0, SOL_SOCKET, SO_SNDBUF, &nbytes, sizeof(int)) < 0)
	{
		#ifdef SystemLogMessage
		PRINTF_LIB_FUNC("Set SO_SNDBUF NG");
		#endif
	}
	nbytes=40960;

   	strcpy(ifr0.ifr_name, "can1" );
	ioctl(s0, SIOCGIFINDEX, &ifr0); /* ifr.ifr_ifindex gets filled with that device's index */
	addr0.can_family = AF_CAN;
	addr0.can_ifindex = ifr0.ifr_ifindex;
	bind(s0, (struct sockaddr *)&addr0, sizeof(addr0));
	return s0;
}

void SetOutputVoltage(byte group, int voltage)
{
	byte data[8];
	PwrFrame PwrFrameMsg;
	PwrFrameMsg.PwrMessage = 0;

	PwrFrameMsg.UUBits.Protocol = 0x01;
	PwrFrameMsg.UUBits.MonitorAddress = PSU_MONITOR_DEFAULT;
	// module id
	if (group == SYSTEM_CMD)
		PwrFrameMsg.UUBits.ModuleAddress = PSU_MODULE_BROADCAST;
	else
		PwrFrameMsg.UUBits.ModuleAddress = group;

	memset(data, 0x00, ARRAY_SIZE(data));
	// Group
	if (group == SYSTEM_CMD)
		data[0] = 0x00;
	else
		data[0] = group + 1;
	// Message Type
	data[0] = data[0] << 4;
	data[0] |= PSU_MSG_CMD_SET_PARAM;
	// Command Type
	data[1] = PSU_W_OUTPUT_VOL;
	// Command Data
	data[4] = (voltage >> 24) & 0xFF;
	data[5] = (voltage >> 16) & 0xFF;
	data[6] = (voltage >> 8) & 0xFF;
	data[7] = voltage & 0xFF;

	SendCmdToPsu(PwrFrameMsg.PwrMessage, data, sizeof(data));
}

void SetOutputCurrent(byte group, int current)
{
	byte data[8];
	PwrFrame PwrFrameMsg;
	PwrFrameMsg.PwrMessage = 0;

	PwrFrameMsg.UUBits.Protocol = 0x01;
	PwrFrameMsg.UUBits.MonitorAddress = PSU_MONITOR_DEFAULT;
	// module id
	if (group == SYSTEM_CMD)
		PwrFrameMsg.UUBits.ModuleAddress = PSU_MODULE_BROADCAST;
	else
		PwrFrameMsg.UUBits.ModuleAddress = group;

	memset(data, 0x00, ARRAY_SIZE(data));
	// Group
	if (group == SYSTEM_CMD)
		data[0] = 0x00;
	else
		data[0] = group + 1;
	// Message Type
	data[0] = data[0] << 4;
	data[0] |= PSU_MSG_CMD_SET_PARAM;
	// Command Type
	data[1] = PSU_W_OUTPUT_CUR;
	// Command Data
	data[4] = (current >> 24) & 0xFF;
	data[5] = (current >> 16) & 0xFF;
	data[6] = (current >> 8) & 0xFF;
	data[7] = current & 0xFF;

	SendCmdToPsu(PwrFrameMsg.PwrMessage, data, sizeof(data));
}

void GetFastOutputVol(byte group)
{
	byte data[8];
	PwrFrame PwrFrameMsg;
	PwrFrameMsg.PwrMessage = 0;
	PwrFrameMsg.UUBits.Protocol = 0x01;
	PwrFrameMsg.UUBits.MonitorAddress = PSU_MONITOR_DEFAULT;
	// module id
	//if (group == SYSTEM_CMD)
		PwrFrameMsg.UUBits.ModuleAddress = PSU_MODULE_BROADCAST;
	//else
	//	PwrFrameMsg.UUBits.ModuleAddress = group;

	memset(data, 0x00, ARRAY_SIZE(data));
	// Group
	if (group == SYSTEM_CMD)
		data[0] = 0x00;
	else
		data[0] = group + 1;
	// Message Type
	data[0] = data[0] << 4;
	data[0] |= PSU_MSG_CMD_READ_MSG;
	// Command Type
	data[1] = PSU_R_FAST_OUTPUT_VOL;

	SendCmdToPsu(PwrFrameMsg.PwrMessage, data, sizeof(data));
}

void GetFastOutputCur(byte group)
{
	byte data[8];
	PwrFrame PwrFrameMsg;
	PwrFrameMsg.PwrMessage = 0;
	PwrFrameMsg.UUBits.Protocol = 0x01;
	PwrFrameMsg.UUBits.MonitorAddress = PSU_MONITOR_DEFAULT;
	// module id
	//if (group == SYSTEM_CMD)
		PwrFrameMsg.UUBits.ModuleAddress = PSU_MODULE_BROADCAST;
	//else
	//	PwrFrameMsg.UUBits.ModuleAddress = group;

	memset(data, 0x00, ARRAY_SIZE(data));
	// Group
	if (group == SYSTEM_CMD)
		data[0] = 0x00;
	else
		data[0] = group + 1;
	// Message Type
	data[0] = data[0] << 4;
	data[0] |= PSU_MSG_CMD_READ_MSG;
	// Command Type
	data[1] = PSU_R_FAST_OUTPUT_CUR;

	SendCmdToPsu(PwrFrameMsg.PwrMessage, data, sizeof(data));
}

void GetOutputPowCap(byte group)
{
	byte data[8];
	PwrFrame PwrFrameMsg;
	PwrFrameMsg.PwrMessage = 0;

	PwrFrameMsg.UUBits.Protocol = 0x01;
	PwrFrameMsg.UUBits.MonitorAddress = PSU_MONITOR_DEFAULT;
	// module id
	//if (group == SYSTEM_CMD)
		PwrFrameMsg.UUBits.ModuleAddress = PSU_MODULE_BROADCAST;
	//else
	//	PwrFrameMsg.UUBits.ModuleAddress = group;

	memset(data, 0x00, ARRAY_SIZE(data));
	// Group
	if (group == SYSTEM_CMD)
		data[0] = 0x00;
	else
		data[0] = group + 1;
	// Message Type
	data[0] = data[0] << 4;
	data[0] |= PSU_MSG_CMD_READ_MSG;
	// Command Type
	data[1] = PSU_R_OUTPUT_POW_CAP;

	SendCmdToPsu(PwrFrameMsg.PwrMessage, data, sizeof(data));
}

void GetOutputCurCap(byte group)
{
	byte data[8];
	PwrFrame PwrFrameMsg;
	PwrFrameMsg.PwrMessage = 0;

	PwrFrameMsg.UUBits.Protocol = 0x01;
	PwrFrameMsg.UUBits.MonitorAddress = PSU_MONITOR_DEFAULT;
	// module id
	if (group == SYSTEM_CMD)
		PwrFrameMsg.UUBits.ModuleAddress = PSU_MODULE_BROADCAST;
	else
		PwrFrameMsg.UUBits.ModuleAddress = group;

	memset(data, 0x00, ARRAY_SIZE(data));
	// Group
	if (group == SYSTEM_CMD)
		data[0] = 0x00;
	else
		data[0] = group + 1;
	// Message Type
	data[0] = data[0] << 4;
	data[0] |= PSU_MSG_CMD_READ_MSG;
	// Command Type
	data[1] = PSU_R_OUTPUT_CUR_CAP;

	SendCmdToPsu(PwrFrameMsg.PwrMessage, data, sizeof(data));
}

void GetPsuMaxVoltage(byte group)
{
	byte data[8];
	PwrFrame PwrFrameMsg;
	PwrFrameMsg.PwrMessage = 0;
	PwrFrameMsg.UUBits.Protocol = 0x01;
	PwrFrameMsg.UUBits.MonitorAddress = PSU_MONITOR_DEFAULT;
	// module id
	//if (group == SYSTEM_CMD)
	PwrFrameMsg.UUBits.ModuleAddress = PSU_MODULE_BROADCAST;
	//else
	//	PwrFrameMsg.UUBits.ModuleAddress = group;

	memset(data, 0x00, ARRAY_SIZE(data));
	// Group
	if (group == SYSTEM_CMD)
		data[0] = 0x00;
	else
		data[0] = group + 1;
	// Message Type
	data[0] = data[0] << 4;
	data[0] |= PSU_MSG_CMD_READ_MSG;
	// Command Type
	data[1] = PSU_R_MAX_VOL;

	SendCmdToPsu(PwrFrameMsg.PwrMessage, data, sizeof(data));
}

void GetTemperature(byte group, byte type)
{
	byte data[8];
	PwrFrame PwrFrameMsg;
	PwrFrameMsg.PwrMessage = 0;

	PwrFrameMsg.UUBits.Protocol = 0x01;
	PwrFrameMsg.UUBits.MonitorAddress = PSU_MONITOR_DEFAULT;
	// module id
	if (group == SYSTEM_CMD)
		PwrFrameMsg.UUBits.ModuleAddress = PSU_MODULE_BROADCAST;
	else
		PwrFrameMsg.UUBits.ModuleAddress = group;

	memset(data, 0x00, ARRAY_SIZE(data));
	// Group
	if (group == SYSTEM_CMD)
		data[0] = 0x00;
	else
		data[0] = group + 1;
	// Message Type
	data[0] = data[0] << 4;
	data[0] |= PSU_MSG_CMD_READ_MSG;
	// Command Type
	if (type == UU_MODULE_TEMP_ENV)
		data[1] = PSU_R_IN_TEMP;
	else if (type == UU_MODULE_TEMP_DD)
		data[1] = PSU_R_PFC_TEMP;

	SendCmdToPsu(PwrFrameMsg.PwrMessage, data, sizeof(data));
}

void GetInputVoltageL12(byte group)
{
	byte data[8];
	PwrFrame PwrFrameMsg;
	PwrFrameMsg.PwrMessage = 0;

	PwrFrameMsg.UUBits.Protocol = 0x01;
	PwrFrameMsg.UUBits.MonitorAddress = PSU_MONITOR_DEFAULT;
	// module id
	if (group == SYSTEM_CMD)
		PwrFrameMsg.UUBits.ModuleAddress = PSU_MODULE_BROADCAST;
	else
		PwrFrameMsg.UUBits.ModuleAddress = group;

	memset(data, 0x00, ARRAY_SIZE(data));
	// Group
	if (group == SYSTEM_CMD)
		data[0] = 0x00;
	else
		data[0] = group + 1;
	// Message Type
	data[0] = data[0] << 4;
	data[0] |= PSU_MSG_CMD_READ_MSG;
	// Command Type
	data[1] = PSU_R_VIN_L12;

	SendCmdToPsu(PwrFrameMsg.PwrMessage, data, sizeof(data));
}

void GetInputVoltageL23(byte group)
{
	byte data [8];
	PwrFrame PwrFrameMsg;
	PwrFrameMsg.PwrMessage = 0;

	PwrFrameMsg.UUBits.Protocol = 0x01;
	PwrFrameMsg.UUBits.MonitorAddress = PSU_MONITOR_DEFAULT;
	// module id
	if (group == SYSTEM_CMD)
		PwrFrameMsg.UUBits.ModuleAddress = PSU_MODULE_BROADCAST;
	else
		PwrFrameMsg.UUBits.ModuleAddress = group;

	memset ( data, 0x00, ARRAY_SIZE( data ) );
	// Group
	if (group == SYSTEM_CMD)
		data [0] = 0x00;
	else
		data [0] = group + 1;
	// Message Type
	data [0] = data [0] << 4;
	data [0] |= PSU_MSG_CMD_READ_MSG;
	// Command Type
	data [1] = PSU_R_VIN_L23;

	SendCmdToPsu ( PwrFrameMsg.PwrMessage, data, sizeof(data) );
}

void GetInputVoltageL31(byte group)
{
	byte data [8];
	PwrFrame PwrFrameMsg;
	PwrFrameMsg.PwrMessage = 0;

	PwrFrameMsg.UUBits.Protocol = 0x01;
	PwrFrameMsg.UUBits.MonitorAddress = PSU_MONITOR_DEFAULT;
	// module id
	if (group == SYSTEM_CMD)
		PwrFrameMsg.UUBits.ModuleAddress = PSU_MODULE_BROADCAST;
	else
		PwrFrameMsg.UUBits.ModuleAddress = group;

	memset ( data, 0x00, ARRAY_SIZE( data ) );
	// Group
	if (group == SYSTEM_CMD)
		data [0] = 0x00;
	else
		data [0] = group + 1;
	// Message Type
	data [0] = data [0] << 4;
	data [0] |= PSU_MSG_CMD_READ_MSG;
	// Command Type
	data [1] = PSU_R_VIN_L31;

	SendCmdToPsu ( PwrFrameMsg.PwrMessage, data, sizeof(data) );
}

void GetDc2DcVersion(byte group)
{
	byte data[8];
	PwrFrame PwrFrameMsg;
	PwrFrameMsg.PwrMessage = 0;
	PwrFrameMsg.UUBits.Protocol = 0x01;
	PwrFrameMsg.UUBits.MonitorAddress = PSU_MONITOR_DEFAULT;
	// module id
	//if (group == SYSTEM_CMD)
	PwrFrameMsg.UUBits.ModuleAddress = PSU_MODULE_BROADCAST;
	//else
	//	PwrFrameMsg.UUBits.ModuleAddress = group;

	memset(data, 0x00, ARRAY_SIZE(data));
	// Group
	if (group == SYSTEM_CMD)
		data[0] = 0x00;
	else
		data[0] = group + 1;
	// Message Type
	data[0] = data[0] << 4;
	data[0] |= PSU_MSG_CMD_READ_MSG;
	// Command Type
	data[1] = PSU_R_DD_VERSION;

	SendCmdToPsu(PwrFrameMsg.PwrMessage, data, sizeof(data));
}

void GetPfcVersion(byte group)
{
	byte data[8];
	PwrFrame PwrFrameMsg;
	PwrFrameMsg.PwrMessage = 0;
	PwrFrameMsg.UUBits.Protocol = 0x01;
	PwrFrameMsg.UUBits.MonitorAddress = PSU_MONITOR_DEFAULT;
	// module id
	//if (group == SYSTEM_CMD)
	PwrFrameMsg.UUBits.ModuleAddress = PSU_MODULE_BROADCAST;
	//else
	//	PwrFrameMsg.UUBits.ModuleAddress = group;

	memset(data, 0x00, ARRAY_SIZE(data));
	// Group
	if (group == SYSTEM_CMD)
		data[0] = 0x00;
	else
		data[0] = group + 1;
	// Message Type
	data[0] = data[0] << 4;
	data[0] |= PSU_MSG_CMD_READ_MSG;
	// Command Type
	data[1] = PSU_R_PFC_VERSION;

	SendCmdToPsu(PwrFrameMsg.PwrMessage, data, sizeof(data));
}

//================================================
// Receive data from CANBUS Function
//================================================
void SendCallback()
{
	int _passTime = UU_GetTimeoutValue ( & ShmTimelineData._getCount_time );
	if (_passTime < 0)
		UU_GetTimespecFunc(&ShmTimelineData._getCount_time);
	else if (ShmTimelineData._getCountChk && _passTime > 200)
	{
		ShmUuPowerData.totalPsuCount = 0;
		for (byte i = 0; i < 2; i ++)
		{
			if (ShmUuPowerData.uu_pow_info [i].psuCount > 0)
			{
				return_module_count ( i, ShmUuPowerData.uu_pow_info [i].psuCount );
				ShmUuPowerData.totalPsuCount += ShmUuPowerData.uu_pow_info [i].psuCount;
			}
		}

		return_module_count (SYSTEM_CMD, ShmUuPowerData.totalPsuCount);
		ShmTimelineData._getCountChk = LIB_STOP;
		ShmUuPowerData._getCountIndexComp = LIB_START;
	}
}

void ReceiveDataFromCanBus()
{
	int nbytes;
	struct can_frame frame;
	PwrFrame *PwrFrameMsg;
	byte group;

	memset(&ShmUuPowerData, 0, sizeof(struct UuPowerInformation));
	memset(&ShmTimelineData, 0, sizeof(struct TimelineInfor));

	while(1)
	{
		SendCallback();

		memset(&frame, 0, sizeof(struct can_frame));
		nbytes = read(CanFd, &frame, sizeof(struct can_frame));

		if (nbytes > 0)
		{
            PwrFrameMsg = (PwrFrame *)&frame.can_id;
            //byte protocol = PwrFrameMsg->UUBits.Protocol;
            byte moduleAddr = PwrFrameMsg->UUBits.ModuleAddress;
            //byte monitorAddr = PwrFrameMsg->UUBits.MonitorAddress;

            // Group �q0�}�l~ �� UU �q 1 �}�l~
            group = ((frame.data[0] & 0xF0) >> 4) - 1;
			//printf("group = %d \n", group);
			//printf("moduleAddr = %d \n", moduleAddr);
			//printf("monitorAddr = %d \n", monitorAddr);
//			printf("data[0] = %d, data[1] = %d, data[2] = %d, data[3] = %d, data[4] = %d, data[5] = %d, data[6] = %d, data[7] = %d \n",
//					frame.data[0], frame.data[1], frame.data[2], frame.data[3],
//					frame.data[4], frame.data[5], frame.data[6], frame.data[7]);

            switch (frame.data[1])
            {
            	case PSU_R_MODULE_COUNT:
            	{
            		//printf("----------PSU_R_GET_COUNT---------- \n");
            	    bool isFind = false;
            	    for (byte i = 0; i < ShmUuPowerData.uu_pow_info[group].psuCount; i++)
            	    {
            	    	if (ShmUuPowerData.uu_pow_info[group].psuInfo[i].targetNumber == moduleAddr)
            	    		isFind = true;
            	    }

            	    if (!isFind)
            	    {
            	    	ShmUuPowerData.uu_pow_info[group].psuInfo[ShmUuPowerData.uu_pow_info[group].psuCount].targetNumber = moduleAddr;
            	        ShmUuPowerData.uu_pow_info[group].psuCount++;
            	    }

            	    if (ShmTimelineData._getCountChk == LIB_STOP)
            	    {
            	    	ShmTimelineData._getCountChk = LIB_START;
            	    	UU_GetTimespecFunc(&ShmTimelineData._getCount_time);
            	    }
            	}
            	break;
            }

            if (ShmUuPowerData._getCountIndexComp)
            {
				switch (frame.data[1])
				{
					case PSU_R_FAST_OUTPUT_VOL:
					{
						//printf("----------PSU_R_FAST_OUTPUT_VOL---------- \n");
						float _vol = 0, _cur = 0;
						for(byte count = 0; count < ShmUuPowerData.uu_pow_info[group].psuCount; count++)
						{
							if (ShmUuPowerData.uu_pow_info[group].psuInfo[count].targetNumber == moduleAddr)
							{
								ShmUuPowerData.uu_pow_info[group].psuInfo[count].outputVol =
										((frame.data[4] << 24 | frame.data[5] << 16 | frame.data[6] << 8 | frame.data[7])) / 100;
							}

							if (ShmUuPowerData.uu_pow_info[group].psuInfo[count].outputVol > 0)
							{
								if (_vol == 0 || ShmUuPowerData.uu_pow_info[group].psuInfo[count].outputVol < _vol)
									_vol = ShmUuPowerData.uu_pow_info[group].psuInfo[count].outputVol;
							}

							_cur += ShmUuPowerData.uu_pow_info[group].psuInfo[count].outputCur;
						}

						ShmUuPowerData.uu_pow_info[group].presentVol = _vol;
						ShmUuPowerData.uu_pow_info[group].presentCur = _cur;

						return_get_output_float(group,
								ShmUuPowerData.uu_pow_info [group].presentVol,
								ShmUuPowerData.uu_pow_info [group].presentCur,
								PSU_PROTOCOL_TYPE );
					}
						break;
					case PSU_R_FAST_OUTPUT_CUR:
					{
						//printf("----------PSU_R_OUTPUT_CUR---------- \n");
						for(byte count = 0; count < ShmUuPowerData.uu_pow_info[group].psuCount; count++)
						{
							if (ShmUuPowerData.uu_pow_info[group].psuInfo[count].targetNumber == moduleAddr)
							{
								ShmUuPowerData.uu_pow_info[group].psuInfo[count].outputCur =
										((frame.data[4] << 24 | frame.data[5] << 16 | frame.data[6] << 8 | frame.data[7])) / 100;
								break;
							}
						}
	//
	//					ShmUuPowerData.uu_pow_info[group].presentCur = ((frame.data[4] << 24 | frame.data[5] << 16 | frame.data[6] << 8 | frame.data[7])) / 100;
	//					return_get_output_float(group,
	//					    ShmUuPowerData.uu_pow_info[group].presentVol,
	//						ShmUuPowerData.uu_pow_info[group].presentCur,
	//						PSU_PROTOCOL_TYPE);
					}
						break;
					case PSU_R_DD_VERSION:
					{
						//printf("----------PSU_R_DD_VERSION---------- \n");
						for(byte count = 0; count < ShmUuPowerData.uu_pow_info[group].psuCount; count++)
						{
							if (ShmUuPowerData.uu_pow_info[group].psuInfo[count].targetNumber == moduleAddr)
							{
								ShmUuPowerData.uu_pow_info[group].psuInfo[count].dc2dcVersion =
										((frame.data[6] << 8) + frame.data[7]);

								byte psuIndexAddr = moduleAddr;
								if (group > 0)
								{
									psuIndexAddr = moduleAddr + ShmUuPowerData.uu_pow_info[group - 1].psuCount;
								}
								return_fw_version(psuIndexAddr,
										ShmUuPowerData.uu_pow_info[group].psuInfo[count].dc2dcVersion,
										ShmUuPowerData.uu_pow_info[group].psuInfo[count].pfcVersion,
										LIB_UU_HW_VERSIION,
										PSU_PROTOCOL_TYPE);
								break;
							}
						}
					}
						break;
					case PSU_R_PFC_VERSION:
					{
						//printf("----------PSU_R_PFC_VERSION---------- \n");
						for(byte count = 0; count < ShmUuPowerData.uu_pow_info[group].psuCount; count++)
						{
							if (ShmUuPowerData.uu_pow_info[group].psuInfo[count].targetNumber == moduleAddr)
							{
								ShmUuPowerData.uu_pow_info[group].psuInfo[count].pfcVersion =
										((frame.data[6] << 8) + frame.data[7]);

								byte psuIndexAddr = moduleAddr;
								if (group > 0)
								{
									psuIndexAddr = moduleAddr + ShmUuPowerData.uu_pow_info[group - 1].psuCount;
								}
								return_fw_version(psuIndexAddr,
										ShmUuPowerData.uu_pow_info[group].psuInfo[count].dc2dcVersion,
										ShmUuPowerData.uu_pow_info[group].psuInfo[count].pfcVersion,
										LIB_UU_HW_VERSIION,
										PSU_PROTOCOL_TYPE);
								break;
							}
						}
					}
						break;
					case PSU_R_IAVAILABLE:
					{
						//printf("----------PSU_R_IAVAILABLE---------- \n");
	//					printf("Group = %d, moduleAddr = %d, data[4] = %d, data[5] = %d, data[6] = %d, data[7] = %d \n",
	//							group, moduleAddr,
	//							frame.data[4], frame.data[5], frame.data[6], frame.data[7]);
						for(byte count = 0; count < ShmUuPowerData.uu_pow_info[group].psuCount; count++)
						{
							if (ShmUuPowerData.uu_pow_info[group].psuInfo[count].targetNumber == moduleAddr)
							{
								byte psuIndexAddr = moduleAddr;
								if (group > 0)
								{
									psuIndexAddr = moduleAddr + ShmUuPowerData.uu_pow_info[group - 1].psuCount;
								}

								return_iavail_info(psuIndexAddr, ((frame.data[6] << 8) + frame.data[7]) / 1, LIB_NO_USE);
								break;
							}
						}
					}
						break;
					case PSU_W_OUTPUT_VOL:
					{
						printf("----------PSU_W_OUTPUT_VOL_CAP---------- \n");
					}
						break;
					case PSU_W_OUTPUT_CUR:
					{
						printf("----------PSU_W_OUTPUT_CUR_CAP---------- \n");
					}
						break;
					case PSU_R_SERIAL_NUM:
					{
						printf("----------PSU_R_SERIAL_NUM---------- \n");
					}
						break;
					case PSU_R_STATUS:
					{
						//printf("----------PSU_R_STATUS---------- \n");
						byte psuIndexAddr = moduleAddr;
						if (group > 0)
						{
							psuIndexAddr = moduleAddr + ShmUuPowerData.uu_pow_info[group - 1].psuCount;
						}

						return_status(group, psuIndexAddr, LIB_NO_USE, LIB_NO_USE, PSU_PROTOCOL_TYPE,
								frame.data[4], frame.data[5], frame.data[6], frame.data[7]);
					}
						break;
					case PSU_R_OUTPUT_POW_CAP:
					{
						int pow = (frame.data[4] << 24 | frame.data[5] << 16 | frame.data[6] << 8 | frame.data[7]) / 10000;

						if ((pow += 5) > 180)
							pow = 180;

						for(byte count = 0; count < ShmUuPowerData.uu_pow_info[group].psuCount; count++)
						{
							if (ShmUuPowerData.uu_pow_info[group].psuInfo[count].targetNumber == moduleAddr)
							{
								ShmUuPowerData.uu_pow_info[group].psuInfo[count].powerCap = pow;

								byte psuIndexAddr = moduleAddr;
								if (group > 0)
								{
									 psuIndexAddr = moduleAddr + ShmUuPowerData.uu_pow_info[group - 1].psuCount;
								}

								return_available_cap(psuIndexAddr,
										LIB_PSU_MAX_VOL,
										LIB_PSU_MIN_VOL,
										LIB_PSU_MAX_CUR,
										ShmUuPowerData.uu_pow_info[group].psuInfo[count].powerCap);
								break;
							}
						}
					}
						break;
					case PSU_R_OUTPUT_CUR_CAP:
					{
						// �]�����C���]�w�����D~�ӫ��O�L�k���`���O
						int cur = (frame.data[4] << 24 | frame.data[5] << 16 | frame.data[6] << 8 | frame.data[7]) / 1000;

						for(byte count = 0; count < ShmUuPowerData.uu_pow_info[group].psuCount; count++)
						{
							if (ShmUuPowerData.uu_pow_info[group].psuInfo[count].targetNumber == moduleAddr)
							{
								ShmUuPowerData.uu_pow_info[group].psuInfo[count].currentCap = cur;
								break;
							}
						}
					}
						break;
					case PSU_R_MAX_VOL:
					{
						// �]�����C���]�w�����D~�ӫ��O�L�k���`���O
						int maxVol = ((frame.data[4] << 24 | frame.data[5] << 16 | frame.data[6] << 8 | frame.data[7]) / 100000) * 1000;

						for(byte count = 0; count < ShmUuPowerData.uu_pow_info[group].psuCount; count++)
						{
							if (ShmUuPowerData.uu_pow_info[group].psuInfo[count].targetNumber == moduleAddr)
							{
								ShmUuPowerData.uu_pow_info[group].psuInfo[count].maxVoltage = maxVol;
								break;
							}
						}
					}
						break;
					case PSU_R_VIN_L12:
					{
						//printf("----------PSU_R_VIN_L12---------- \n");
						for(byte count = 0; count < ShmUuPowerData.uu_pow_info[group].psuCount; count++)
						{
							if (ShmUuPowerData.uu_pow_info[group].psuInfo[count].targetNumber == moduleAddr)
							{
								ShmUuPowerData.uu_pow_info[group].psuInfo[count].inputVolL12 =
										((frame.data[4] << 24 | frame.data[5] << 16 | frame.data[6] << 8 | frame.data[7])) / 1000;
								break;
							}
						}
					}
						break;
					case PSU_R_VIN_L23:
					{
						//printf("----------PSU_R_VIN_L23---------- \n");
						for(byte count = 0; count < ShmUuPowerData.uu_pow_info[group].psuCount; count++)
						{
							if (ShmUuPowerData.uu_pow_info[group].psuInfo[count].targetNumber == moduleAddr)
							{
								ShmUuPowerData.uu_pow_info[group].psuInfo[count].inputVolL23 =
										((frame.data[4] << 24 | frame.data[5] << 16 | frame.data[6] << 8 | frame.data[7])) / 1000;
								break;
							 }
						 }
					}
						break;
					case PSU_R_VIN_L31:
					{
						//printf("----------PSU_R_VIN_L31---------- \n");
						for(byte count = 0; count < ShmUuPowerData.uu_pow_info[group].psuCount; count++)
						{
							if (ShmUuPowerData.uu_pow_info[group].psuInfo[count].targetNumber == moduleAddr)
							{
								ShmUuPowerData.uu_pow_info[group].psuInfo[count].inputVolL31 =
										((frame.data[4] << 24 | frame.data[5] << 16 | frame.data[6] << 8 | frame.data[7])) / 1000;

								byte psuIndexAddr = moduleAddr;
								if (group > 0)
								{
									psuIndexAddr = moduleAddr + ShmUuPowerData.uu_pow_info[group - 1].psuCount;
								}

								return_input_vol(psuIndexAddr,
										ShmUuPowerData.uu_pow_info[group].psuInfo[count].inputVolL12,
										ShmUuPowerData.uu_pow_info[group].psuInfo[count].inputVolL23,
										ShmUuPowerData.uu_pow_info[group].psuInfo[count].inputVolL31);
								break;
							}
						}
					}
						break;
					case PSU_R_IN_TEMP:
					{
						byte psuIndexAddr = moduleAddr;
						unsigned char ReturnValue = ((frame.data[4] << 24 | frame.data[5] << 16 | frame.data[6] << 8 | frame.data[7])) / 1000;

						if (group > 0)
						{
							psuIndexAddr = moduleAddr + ShmUuPowerData.uu_pow_info[group - 1].psuCount;
						}

						// Env Temp
						return_output_temp(psuIndexAddr, LIB_NO_USE, LIB_NO_USE, LIB_NO_USE, ReturnValue, PSU_PROTOCOL_TYPE);
					}
						break;
					case PSU_R_PFC_TEMP:
					case PSU_R_DD2_TEMP:
					case PSU_R_DD3_TEMP:
					{
						byte psuIndexAddr = moduleAddr;
						float ReturnValue = ((frame.data[4] << 24 | frame.data[5] << 16 | frame.data[6] << 8 | frame.data[7])) / 1000;

						if (group > 0)
						{
							psuIndexAddr = moduleAddr + ShmUuPowerData.uu_pow_info[group - 1].psuCount;
						}

						// DD Temp
						return_mis_info(psuIndexAddr, ReturnValue, 2);
						//printf("temp = %02d \n", ((frame.data[4] << 24 | frame.data[5] << 16 | frame.data[6] << 8 | frame.data[7])) / 1000);
					}
						break;
					case PSU_RW_GROUP:
					{
						printf("PSU_RW_GROUP : address = %d, group = %d \n",  moduleAddr, group);
					}
						break;
					case PSU_W_HIGH_LOW_VOL_MODE:
					{
						//printf("----------PSU_W_HIGH_LOW_VOL_MODE---------- \n");
					}
						break;
					case PSU_R_HIGH_LOW_VOL_MODE:
					{
						//printf("----------PSU_R_HIGH_LOW_VOL_MODE---------- \n");
						printf("PSU_R_HIGH_LOW_VOL_MODE : G : %d, value : %d \n", group, frame.data[7]);
					}
						break;
				}
            }
		}
		else
			usleep(10000);
	}
}

//================================================
// Public Function
//================================================
bool InitialCommunication()
{
	CanFd = InitCanBus();

	if(CanFd < 0)
	{
		printf("Init can bus fail.... \n");
		return false;
	}

    recFork = fork();
    if(recFork == 0)
    {
    	ReceiveDataFromCanBus();
	}

//  callbackFunc = fork();
//	if (callbackFunc == 0)
//	{
//		SendCallback();
//	}

    return true;
}

/*
 * Data :
 * byte 0 =>
 	0 ~ 3 bit : MessageType
 	4 ~ 7 bit : Group Address (1 ~ 15)
 * byte 1 =>
 	Command Type
 * byte 2�B3 =>
 	Reserved
 * byte 4 ~ 7 =>
	Command Data
 */
/**********************************************************************************/
/***                                                                            ***/
/***                                   Get                                      ***/
/***                                                                            ***/
/**********************************************************************************/
void GetGroup(byte address)
{
	byte data[8];
    PwrFrame PwrFrameMsg;
    PwrFrameMsg.PwrMessage = 0;

    PwrFrameMsg.UUBits.Protocol = 0x01;
	PwrFrameMsg.UUBits.MonitorAddress = PSU_MONITOR_DEFAULT;
	// module id
    PwrFrameMsg.UUBits.ModuleAddress = 0x04;

	memset(data, 0x00, ARRAY_SIZE(data));
	// Group
	data[0] = 0x01;
	// Message Type
	data[0] = data[0] << 4;
	data[0] |= PSU_MSG_CMD_READ_MSG;
	// Command Type
	data[1] = PSU_RW_GROUP;
	// Reserved
	data[2] = 0x00;
	data[3] = 0x00;
	// Command Data
	data[4] = 0x00;
	data[5] = 0x00;
	data[6] = 0x00;
	data[7] = 0x00;

	SendCmdToPsu(PwrFrameMsg.PwrMessage, data, sizeof(data));
}

void GetStatus(byte group, byte param)
{
	if (param == LIB_NO_USE)
		return;

	byte data[8];
    PwrFrame PwrFrameMsg;
    PwrFrameMsg.PwrMessage = 0;

    PwrFrameMsg.UUBits.Protocol = 0x01;
	PwrFrameMsg.UUBits.MonitorAddress = PSU_MONITOR_DEFAULT;
	// module id - ���ޭ��@�s~ ���O��Ӹs���s�o�ʰ�
	PwrFrameMsg.UUBits.ModuleAddress = PSU_MODULE_BROADCAST;

	memset(data, 0x00, ARRAY_SIZE(data));
	// Group
	if (group == SYSTEM_CMD)
		data[0] = 0x00;
	else
		data[0] = group + 1;
	// Message Type
	data[0] = data[0] << 4;
	data[0] |= PSU_MSG_CMD_READ_MSG;
	// Command Type
	data[1] = PSU_R_STATUS;

	SendCmdToPsu(PwrFrameMsg.PwrMessage, data, sizeof(data));
}

void GetModuleVoltageMode(byte group)
{
	byte data[8];
	PwrFrame PwrFrameMsg;
	PwrFrameMsg.PwrMessage = 0;

	PwrFrameMsg.UUBits.Protocol = 0x01;
	PwrFrameMsg.UUBits.MonitorAddress = PSU_MONITOR_DEFAULT;
	// module id - �s�o
	if (group == SYSTEM_CMD)
		PwrFrameMsg.UUBits.ModuleAddress = PSU_MODULE_BROADCAST;
	else
		PwrFrameMsg.UUBits.ModuleAddress = group;

	memset(data, 0x00, ARRAY_SIZE(data));
	// Group
	if (group == SYSTEM_CMD)
		data[0] = 0x00;
	else
		data[0] = group + 1;
	// Message Type
	data[0] = data[0] << 4;
	data[0] |= PSU_MSG_CMD_READ_MSG;
	// Command Type
	data[1] = PSU_R_HIGH_LOW_VOL_MODE;

	SendCmdToPsu(PwrFrameMsg.PwrMessage, data, sizeof(data));
}

/**********************************************************************************/
/***                                                                            ***/
/***                                   Set                                      ***/
/***                                                                            ***/
/**********************************************************************************/
void SetGroup(byte group, byte sourceAddr, byte targetAddr)
{
	byte data[8];
	PwrFrame PwrFrameMsg;
	PwrFrameMsg.PwrMessage = 0;

	PwrFrameMsg.UUBits.Protocol = 0x01;
	PwrFrameMsg.UUBits.MonitorAddress = PSU_MONITOR_DEFAULT;
	// module id
	PwrFrameMsg.UUBits.ModuleAddress = sourceAddr;

	memset(data, 0x00, ARRAY_SIZE(data));
	// Group
	data[0] = group + 1;
	// Message Type
	data[0] = data[0] << 4;
	data[0] |= PSU_MSG_CMD_SET_PARAM;
	// Command Type
	data[1] = PSU_RW_GROUP;
	// Reserved
	data[2] = 0x00;
	data[3] = 0x00;
	// Command Data
	data[7] = targetAddr;

	SendCmdToPsu(PwrFrameMsg.PwrMessage, data, sizeof(data));
}

void SetModuleVoltageMode(byte group, byte value)
{
	byte data[8];
	PwrFrame PwrFrameMsg;
	PwrFrameMsg.PwrMessage = 0;

	PwrFrameMsg.UUBits.Protocol = 0x01;
	PwrFrameMsg.UUBits.MonitorAddress = PSU_MONITOR_DEFAULT;
	// module id
	if (group == SYSTEM_CMD)
		PwrFrameMsg.UUBits.ModuleAddress = PSU_MODULE_BROADCAST;
	else
		PwrFrameMsg.UUBits.ModuleAddress = group;

	memset(data, 0x00, ARRAY_SIZE(data));
	// Group
	if (group == SYSTEM_CMD)
		data[0] = 0x00;
	else
		data[0] = group + 1;
	// Message Type
	data[0] = data[0] << 4;
	data[0] |= PSU_MSG_CMD_SET_PARAM;
	// Command Type
	data[1] = PSU_W_HIGH_LOW_VOL_MODE;
	// Command Data
	data[4] = 0x00;
	data[5] = 0x00;
	data[6] = 0x00;
	data[7] = value;

	SendCmdToPsu(PwrFrameMsg.PwrMessage, data, sizeof(data));
}






/**********************************************************************************/
/***                                                                            ***/
/***                                   sdlu                                     ***/
/***                                                                            ***/
/**********************************************************************************/
void SwitchPower(byte group, byte value)
{
	byte data[8];
	PwrFrame PwrFrameMsg;
	PwrFrameMsg.PwrMessage = 0;

	PwrFrameMsg.UUBits.Protocol = 0x01;
	PwrFrameMsg.UUBits.MonitorAddress = PSU_MONITOR_DEFAULT;
	// module id
	if (group == SYSTEM_CMD)
		PwrFrameMsg.UUBits.ModuleAddress = PSU_MODULE_BROADCAST;
	else
		PwrFrameMsg.UUBits.ModuleAddress = group;

	memset(data, 0x00, ARRAY_SIZE(data));
	// 1 : ����
	// 0 : �}��
	// Group
	if (group == SYSTEM_CMD)
		data[0] = 0x00;
	else
		data[0] = group + 1;
	// Message Type
	data[0] = data[0] << 4;
	data[0] |= PSU_MSG_CMD_SET_PARAM;
	// Command Type
	data[1] = PSU_W_SWITCH_POW;
	// Command Data
	data[4] = 0x00;
	data[5] = 0x00;
	data[6] = 0x00;
	data[7] = value;

	SendCmdToPsu(PwrFrameMsg.PwrMessage, data, sizeof(data));
}

void GetModuleCount(byte group)
{
	byte data[8];
    PwrFrame PwrFrameMsg;
    PwrFrameMsg.PwrMessage = 0;
    PwrFrameMsg.UUBits.Protocol = 0x01;
    PwrFrameMsg.UUBits.MonitorAddress = PSU_MONITOR_DEFAULT;
    // module id - �s�o
    if (group == SYSTEM_CMD)
    	PwrFrameMsg.UUBits.ModuleAddress = PSU_MODULE_BROADCAST;
    else
    {
    	PwrFrameMsg.UUBits.ModuleAddress = group;
    }

    memset(data, 0x00, ARRAY_SIZE(data));
	if (group == SYSTEM_CMD)
	{
		// Group
		data[0] = 0x01;
		// Message Type
		data[0] = data[0] << 4;
		data[0] |= PSU_MSG_CMD_READ_MSG;
		// Command Type
		data[1] = PSU_R_MODULE_COUNT;

		SendCmdToPsu(PwrFrameMsg.PwrMessage, data, sizeof(data));

		// Group
		data[0] = 0x02;
		SendCmdToPsu(PwrFrameMsg.PwrMessage, data, sizeof(data));
	}
	else
	{
		// Group
		data[0] = group + 1;
		// Message Type
		data[0] = data[0] << 4;
		data[0] |= PSU_MSG_CMD_READ_MSG;
		// Command Type
		data[1] = PSU_R_MODULE_COUNT;

		SendCmdToPsu(PwrFrameMsg.PwrMessage, data, sizeof(data));
	}
}

void GetModuleCap(byte group)
{
	GetOutputPowCap(group);
	//GetOutputCurCap(group);
	//GetPsuMaxVoltage(group);
}

void GetModuleIavailable(byte group)
{
	byte data[8];
	PwrFrame PwrFrameMsg;
	PwrFrameMsg.PwrMessage = 0;

	PwrFrameMsg.UUBits.Protocol = 0x01;
	PwrFrameMsg.UUBits.MonitorAddress = PSU_MONITOR_DEFAULT;
	// module id
	//if (group == SYSTEM_CMD)
		PwrFrameMsg.UUBits.ModuleAddress = PSU_MODULE_BROADCAST;
	//else
	//	PwrFrameMsg.UUBits.ModuleAddress = group;

	memset(data, 0x00, ARRAY_SIZE(data));
	// Group
	if (group == SYSTEM_CMD)
		data[0] = 0x00;
	else
		data[0] = group + 1;
	// Message Type
	data[0] = data[0] << 4;
	data[0] |= PSU_MSG_CMD_READ_MSG;
	// Command Type
	data[1] = PSU_R_IAVAILABLE;

	SendCmdToPsu(PwrFrameMsg.PwrMessage, data, sizeof(data));
}

void GetModuleOutputF(byte group)
{
	GetFastOutputVol(group);
	GetFastOutputCur(group);
}

void GetDcTemperature(byte group)
{
	GetTemperature(group, UU_MODULE_TEMP_ENV);
	GetTemperature(group, UU_MODULE_TEMP_DD);
	GetInputVoltageL12(group);
	GetInputVoltageL23(group);
	GetInputVoltageL31(group);
}

void PresentOutputVol(byte group, int voltage, int current, byte psuCount)
{
	voltage *= 100;
	SetOutputVoltage ( group, voltage );

	current *= 100;
	if (psuCount > 0)
		current /= psuCount;
	else
		current = LIB_PSU_MIN_CUR;
	SetOutputCurrent ( group, current );
	if (current == 0 && voltage == 0)
		SwitchPower(group, PSU_POWER_OFF);
}

void GetModuleVer(byte group)
{
	GetDc2DcVersion(group);
	GetPfcVersion(group);
}

void SetWalkInConfig(byte group, byte enable, byte sec)
{
	// �o���q�i�H���Ҷ����C���]�w�B��l�Ƥ@�dz]�w
	ShmUuPowerData._getCountIndexComp = LIB_STOP;
	SetModuleVoltageMode(group, PSU_VOLTAGE_LOW);
}

void FlashLed(byte group, byte value)
{
	// none use
}

void SetDirModulePresentOutput(byte group, int voltage, int current, byte _switch, byte _interRelay)
{
	// none use
}