/* USER CODE BEGIN Header */
/**
 ******************************************************************************
 * File Name          : freertos.c
 * Description        : Code for freertos applications
 ******************************************************************************
 * @attention
 *
 * <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
 * All rights reserved.</center></h2>
 *
 * This software component is licensed by ST under Ultimate Liberty license
 * SLA0044, the "License"; You may not use this file except in compliance with
 * the License. You may obtain a copy of the License at:
 *                             www.st.com/SLA0044
 *
 ******************************************************************************
 */
/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/
#include "FreeRTOS.h"
#include "task.h"
#include "main.h"
#include "cmsis_os.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include <stdlib.h>
#include "adc.h"
#include "crc.h"
#include "flash_if.h"
#include "sine.h"
#include "usart.h"
#include "tim.h"
#include "can.h"
#include "math.h"

/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define PROTOCOL_HEAD											0xaa
#define PROTOCOL_ADDR (nBoard_Addr) // 0x01:AUX PWR     0x02: FAN BD    0x03:RLY BD		0xff:Any
#define PROTOCOL_ADDR_BROADCAST 0xff

#define PROTOCOL_MESSAGE_QUERY_FW_VER							0x01
#define PROTOCOL_MESSAGE_QUERY_HW_VER 							0x02
#define PROTOCOL_MESSAGE_QUERY_PRESENT_INPUT_VOLTAGE			0x03
#define PROTOCOL_MESSAGE_QUERY_PRESENT_OUTPUT_VOLTAGE  			0x04
#define PROTOCOL_MESSAGE_QUERY_FAN_SPEED 						0x05
#define PROTOCOL_MESSAGE_QUERY_TEMPERATURE 						0x06
#define PROTOCOL_MESSAGE_QUERY_AUX_POWER_VOLTAGE				0x07
#define PROTOCOL_MESSAGE_QUERY_GFD_ADC_VALUE					0x09
#define PROTOCOL_MESSAGE_QUERY_INPUT_GPIO_STATUS 				0x0A
#define PROTOCOL_MESSAGE_QUERY_ALARM_LOG 						0x22
#define PROTOCOL_MESSAGE_QUERY_SN 								0x23
#define PROTOCOL_MESSAGE_QUERY_MODEL_NAME 						0x24
#define PROTOCOL_MESSAGE_QUERY_PARAMETER 						0x25
#define PROTOCOL_MESSAGE_QUERY_ALARM_CODE						0x29
#define PROTOCOL_MESSAGE_QUERY_BATTERY_VOLTAGE_IN    		    0x38 
#define PROTOCOL_MESSAGE_QUERY_OUTPUT_RELAY_OUTPUT_STATUS		0x3A
#define PROTOCOL_MESSAGE_QUERY_BRIDGE_RELAY_OUTPUT_STATUS		0x3B
#define PROTOCOL_MESSAGE_QUERY_SELF_TEST_STATUS					0x3C


#define PROTOCOL_MESSAGE_CONFIG_FAN_SPEED 						0x81
#define PROTOCOL_MESSAGE_CONFIG_SN 								0x82
#define PROTOCOL_MESSAGE_CONFIG_MODEL_NAME 						0x83
#define PROTOCOL_MESSAGE_CONFIG_PARAMETER 						0x84
#define PROTOCOL_MESSAGE_CONFIG_GPIO_OUTPUT 					0x86
#define PROTOCOL_MESSAGE_CONFIG_GFD_VALUE 						0x8B
#define PROTOCOL_MESSAGE_CONFIG_RUN_SELF_TEST					0x92
#define PROTOCOL_MESSAGE_CONFIG_OUTPUT_RELAY_OUTPUT				0x98
#define PROTOCOL_MESSAGE_CONFIG_BRIDGE_RELAY_OUTPUT				0x99
#define PROTOCOL_MESSAGE_CONFIG_GFD_MODE						0x9F


#define PROTOCOL_MESSAGE_UPGRADE_START 							0xe0
#define PROTOCOL_MESSAGE_UPGRADE_ABOARD							0xe1
#define PROTOCOL_MESSAGE_UPGRADE_TRANS 							0xe2
#define PROTOCOL_MESSAGE_UPGRADE_STOP 							0xe3

#define USER_MESSAGE_QUERY_SENSE_GFD							0xF1
#define USER_MESSAGE_QUERY_SENSE_DC_VOLTAGE						0xF2

#define Multi_Relay_Delay_Time 200	//unit:ms
#define WeldingCMDDelay 10			//unit:100ms

#define BridgeBoard		(nBoard_Addr == MainBridge1 || nBoard_Addr == MainBridge2 || nBoard_Addr == MainBridge3 || nBoard_Addr == MainBridge4)

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN Variables */

// RB v4.0
// const uint32_t  mem_def_data[20]={0xaf00984, 0x89807f9, 0x64005d5, 0xaf00989, 0x8980802, \
//	                          0x64005da, 0xaf00986, 0x8980800, 0x64005db, 0x251c2516,
//	                          0x5dc05e5, 0x251c250f,0x5dc05dd, 0x128e12c0, 0x3b604ae,
//	                          0x128e1284, 0x3b604a4, 0, 0, 0 };
// RB v4.0 (base on the situation of removing diode condition.)

//L1~L3 SMR1~SMR6 GFD-L~FGD-R
const uint32_t mem_def_data[27] = {0x0AEF0A2B, 0x08960800, 0x063F05D4, 						//L1 3 point
								   0x0AEF0A29, 0x089607FF, 0x063F05D3, 						//L2 3 point	
								   0x0AEF0A29, 0x08960802, 0x063F05D5, 						//L3 3 point
								   0x251C2505, 0x05DC05DD, 0x251C250F, 0x05DC05DB, 			//SMR1,SMR2 DCV 2 point
								   0x251C2505, 0x05DC05DD, 0x251C250F, 0x05DC05DB,			//SMR3,SMR4 DCV 2 point
								   0x251C2505, 0x05DC05DD, 0x251C250F, 0x05DC05DB,			//SMR5,SMR6 DCV 2 point
								   0x128E13E4, 0x03B604CF, 0x128E139D, 0x03B604D0, 			//LGFD,RGFD 2 point
								   0x251C2505, 0x05DC05DD									//DC IN 2 point
								  };

__IO uint32_t flashdestination;
__IO uint32_t newdestination;

//uint8_t test;
uint8_t test[8];
uint8_t CSRHB_VER;


/* USER CODE END Variables */
osThreadId defaultTaskHandle;
osThreadId uart1TaskHandle;
osThreadId adc1TaskHandle;
osThreadId adc2TaskHandle;
osThreadId adc3TaskHandle;
osThreadId gpioTaskHandle;
osThreadId memoryTaskHandle;
osThreadId InkeyTaskHandle;
osThreadId gfd_left_TaskHandle;
osThreadId gfd_right_TaskHandle;
osThreadId sf_test_TaskHandle;
osThreadId _ledTask_Handle;
osThreadId CANTaskHandle;

/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN FunctionPrototypes */
void CSRHB_Ver_Check(void);
uint8_t isValidCheckSum(void);
void CLC_Corr_Gain_Par(uint16_t SpecData_H, uint16_t SpecData_L, uint16_t MCUData_H, uint16_t MCUData_L, float *GainA, float *GainB);
uint16_t acVolCalWithGain(uint16_t orgValue, uint8_t phase);
void nTestIO(GPIO_TypeDef *GPIO_out_port, uint16_t GPIO_out_Pin, GPIO_TypeDef *GPIO_in_port, uint16_t GPIO_in_Pin, uint8_t nItem);
void nTestIO1(GPIO_TypeDef *GPIO_out_port, uint16_t GPIO_out_Pin, GPIO_TypeDef *GPIO_in_port, uint16_t GPIO_in_Pin, uint8_t nItem);
void nTestEXT_INT(GPIO_TypeDef *GPIO_out_port, uint16_t GPIO_out_Pin, uint8_t *flag, uint8_t nItem);

void nTestIO_2(GPIO_TypeDef *GPIO_out_port, uint16_t GPIO_out_Pin,
			   GPIO_TypeDef *GPIO_out2_port, uint16_t GPIO_out2_Pin, GPIO_TypeDef *GPIO_in_port, uint16_t GPIO_in_Pin, uint8_t nItem);
void IOdebug(void);		
void CalcuteGFDMaxMinValue(uint8_t gunindex);	
void SetGfdMode(void);	
void UartCMDtest(void);	   
/* USER CODE END FunctionPrototypes */

void StartDefaultTask(void const * argument);
void Uart1Task(void const * argument);
void Adc1Task(void const * argument);
void Adc2Task(void const * argument);
void Adc3Task(void const * argument);
void GpioTask(void const * argument);
void MemoryTask(void const * argument);
void Inkey_Task(void const * argument);
void Gfd_Left_Task(void const * argument);
void Gfd_Right_Task(void const * argument);
void SF_Test_Task(void const * argument);
void LedTask(void const * argument);
void canTask(void const * argument);

void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) */

/* GetIdleTaskMemory prototype (linked to static allocation support) */
void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize );

/* USER CODE BEGIN GET_IDLE_TASK_MEMORY */
static StaticTask_t xIdleTaskTCBBuffer;
static StackType_t xIdleStack[configMINIMAL_STACK_SIZE];

void vApplicationGetIdleTaskMemory(StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize)
{
	*ppxIdleTaskTCBBuffer = &xIdleTaskTCBBuffer;
	*ppxIdleTaskStackBuffer = &xIdleStack[0];
	*pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
	/* place for user code */
}
/* USER CODE END GET_IDLE_TASK_MEMORY */

/**
  * @brief  FreeRTOS initialization
  * @param  None
  * @retval None
  */
void MX_FREERTOS_Init(void) {
  /* USER CODE BEGIN Init */
	// Version info configuration
	memset(&Module_Info.Soft_Ver_Ptr[0], 0x00, ARRAY_SIZE(Module_Info.Soft_Ver_Ptr));
	memset(&Module_Info.Hard_Ver_Ptr[0], 0x00, ARRAY_SIZE(Module_Info.Hard_Ver_Ptr));

	sprintf((char *)Module_Info.Soft_Ver_Ptr, "T1.03.R3");			

	if(nBoard_Addr == MainRelay1){
		sprintf((char *)Module_Info.Hard_Ver_Ptr, "CSRHO_1 ");
	}else if(nBoard_Addr == MainRelay2){ 	
		sprintf((char *)Module_Info.Hard_Ver_Ptr, "CSRHO_2 ");	
	}else if(nBoard_Addr == GunRelay){ 	
		sprintf((char *)Module_Info.Hard_Ver_Ptr, "CSRHO_G ");
	}else if(nBoard_Addr == MainBridge1){ 	
		sprintf((char *)Module_Info.Hard_Ver_Ptr, "CSRHB_1 ");		
	}else if(nBoard_Addr == MainBridge2){ 	
		sprintf((char *)Module_Info.Hard_Ver_Ptr, "CSRHB_2 ");		
	}else if(nBoard_Addr == MainBridge3){ 	
		sprintf((char *)Module_Info.Hard_Ver_Ptr, "CSRHB_3 ");	
	}else if(nBoard_Addr == MainBridge4){ 	
		sprintf((char *)Module_Info.Hard_Ver_Ptr, "CSRHB_4 ");			
	}else{ 	
		sprintf((char *)Module_Info.Hard_Ver_Ptr, "Undefine");
	}	


  /* USER CODE END Init */

  /* USER CODE BEGIN RTOS_MUTEX */
	/* add mutexes, ... */
  /* USER CODE END RTOS_MUTEX */

  /* USER CODE BEGIN RTOS_SEMAPHORES */
	/* add semaphores, ... */
  /* USER CODE END RTOS_SEMAPHORES */

  /* USER CODE BEGIN RTOS_TIMERS */
	/* start timers, add new ones, ... */
  /* USER CODE END RTOS_TIMERS */

  /* USER CODE BEGIN RTOS_QUEUES */
	/* add queues, ... */
  /* USER CODE END RTOS_QUEUES */

  /* Create the thread(s) */
  /* definition and creation of defaultTask */
  osThreadDef(defaultTask, StartDefaultTask, osPriorityIdle, 0, 128);
  defaultTaskHandle = osThreadCreate(osThread(defaultTask), NULL);

  /* definition and creation of uart1Task */
  osThreadDef(uart1Task, Uart1Task, osPriorityAboveNormal, 0, 1024);
  uart1TaskHandle = osThreadCreate(osThread(uart1Task), NULL);

  /* definition and creation of adc1Task */
  osThreadDef(adc1Task, Adc1Task, osPriorityNormal, 0, 512);
  adc1TaskHandle = osThreadCreate(osThread(adc1Task), NULL);

  /* definition and creation of adc2Task */
  osThreadDef(adc2Task, Adc2Task, osPriorityNormal, 0, 1024);
  adc2TaskHandle = osThreadCreate(osThread(adc2Task), NULL);

  /* definition and creation of adc3Task */
  osThreadDef(adc3Task, Adc3Task, osPriorityNormal, 0, 256);
  adc3TaskHandle = osThreadCreate(osThread(adc3Task), NULL);

  /* definition and creation of gpioTask */
  osThreadDef(gpioTask, GpioTask, osPriorityNormal, 0, 256);
  gpioTaskHandle = osThreadCreate(osThread(gpioTask), NULL);

  /* definition and creation of memoryTask */
  osThreadDef(memoryTask, MemoryTask, osPriorityIdle, 0, 256);
  memoryTaskHandle = osThreadCreate(osThread(memoryTask), NULL);

  /* definition and creation of InkeyTask */
//   osThreadDef(InkeyTask, Inkey_Task, osPriorityAboveNormal, 0, 128);
//   InkeyTaskHandle = osThreadCreate(osThread(InkeyTask), NULL);

  /* definition and creation of gfd_left_Task */
  osThreadDef(gfd_left_Task, Gfd_Left_Task, osPriorityAboveNormal, 0, 256);
  gfd_left_TaskHandle = osThreadCreate(osThread(gfd_left_Task), NULL);

  /* definition and creation of gfd_right_Task */
  osThreadDef(gfd_right_Task, Gfd_Right_Task, osPriorityAboveNormal, 0, 256);
  gfd_right_TaskHandle = osThreadCreate(osThread(gfd_right_Task), NULL);

  /* definition and creation of sf_test_Task */
  osThreadDef(sf_test_Task, SF_Test_Task, osPriorityNormal, 0, 128);
  sf_test_TaskHandle = osThreadCreate(osThread(sf_test_Task), NULL);

  /* definition and creation of _ledTask_ */
  osThreadDef(_ledTask_, LedTask, osPriorityIdle, 0, 128);
  _ledTask_Handle = osThreadCreate(osThread(_ledTask_), NULL);

  /* definition and creation of CANTask */
  osThreadDef(CANTask, canTask, osPriorityAboveNormal, 0, 256);
  CANTaskHandle = osThreadCreate(osThread(CANTask), NULL);

  /* USER CODE BEGIN RTOS_THREADS */
	/* add threads, ... */
  /* USER CODE END RTOS_THREADS */

}

/* USER CODE BEGIN Header_StartDefaultTask */
/**
 * @brief  Function implementing the defaultTask thread.
 * @param  argument: Not used
 * @retval None
 */
/* USER CODE END Header_StartDefaultTask */
void StartDefaultTask(void const * argument)
{
  /* USER CODE BEGIN StartDefaultTask */
	/* Infinite loop */
	printf("FW Ver:%s\n\r", Module_Info.Soft_Ver_Ptr);
	printf("PCB Define:%s\n\r", Module_Info.Hard_Ver_Ptr);
	CSRHB_Ver_Check();
	Gfd.IsolationVoltage = 5000;
	printf("Initial IsolationVoltage:%dV\n\r",Gfd.IsolationVoltage/10);    
	for (;;)
	{		

		if (bRelayFeedback == 1)
		{
			bRelayFeedback = 0;
	
			Module_Info.Relay_Status.flags.SMR1_relay_n = ~HAL_GPIO_ReadPin(SMR1_Relay_n_Ret_GPIO_Port, SMR1_Relay_n_Ret_Pin);
			Module_Info.Relay_Status.flags.SMR1_relay_p = ~HAL_GPIO_ReadPin(SMR1_Relay_p_Ret_GPIO_Port, SMR1_Relay_p_Ret_Pin);
			Module_Info.Relay_Status.flags.SMR2_relay_n = ~HAL_GPIO_ReadPin(SMR2_Relay_n_Ret_GPIO_Port, SMR2_Relay_n_Ret_Pin);
			Module_Info.Relay_Status.flags.SMR2_relay_p = ~HAL_GPIO_ReadPin(SMR2_Relay_p_Ret_GPIO_Port, SMR2_Relay_p_Ret_Pin);
		}

#if (DEBUG_PRINTF == 1)		
			Module_Info.Relay_Status.flags.SMR1_relay_n = ~HAL_GPIO_ReadPin(SMR1_Relay_n_Ret_GPIO_Port, SMR1_Relay_n_Ret_Pin);
			Module_Info.Relay_Status.flags.SMR1_relay_p = ~HAL_GPIO_ReadPin(SMR1_Relay_p_Ret_GPIO_Port, SMR1_Relay_p_Ret_Pin);
			Module_Info.Relay_Status.flags.SMR2_relay_n = ~HAL_GPIO_ReadPin(SMR2_Relay_n_Ret_GPIO_Port, SMR2_Relay_n_Ret_Pin);
			Module_Info.Relay_Status.flags.SMR2_relay_p = ~HAL_GPIO_ReadPin(SMR2_Relay_p_Ret_GPIO_Port, SMR2_Relay_p_Ret_Pin);
			Module_Info.Relay_Status.flags.SMR3_relay_n = ~HAL_GPIO_ReadPin(SMR3_Relay_n_Ret_GPIO_Port, SMR3_Relay_n_Ret_Pin);
			Module_Info.Relay_Status.flags.SMR3_relay_p = ~HAL_GPIO_ReadPin(SMR3_Relay_p_Ret_GPIO_Port, SMR3_Relay_p_Ret_Pin);
			Module_Info.Relay_Status.flags.SMR4_relay_n = ~HAL_GPIO_ReadPin(SMR4_Relay_n_Ret_GPIO_Port, SMR4_Relay_n_Ret_Pin);
			Module_Info.Relay_Status.flags.SMR4_relay_p = ~HAL_GPIO_ReadPin(SMR4_Relay_p_Ret_GPIO_Port, SMR4_Relay_p_Ret_Pin);
			Module_Info.Relay_Status.flags.SMR5_relay_n = ~HAL_GPIO_ReadPin(SMR5_Relay_n_Ret_GPIO_Port, SMR5_Relay_n_Ret_Pin);
			Module_Info.Relay_Status.flags.SMR5_relay_p = ~HAL_GPIO_ReadPin(SMR5_Relay_p_Ret_GPIO_Port, SMR5_Relay_p_Ret_Pin);
			Module_Info.Relay_Status.flags.SMR6_relay_n = ~HAL_GPIO_ReadPin(SMR6_Relay_n_Ret_GPIO_Port, SMR6_Relay_n_Ret_Pin);
			Module_Info.Relay_Status.flags.SMR6_relay_p = ~HAL_GPIO_ReadPin(SMR6_Relay_p_Ret_GPIO_Port, SMR6_Relay_p_Ret_Pin);

			printf("Relay Set	    = %014llx \n\r",Module_Info.Relay_IO.All);
			printf("Relay Status = %014llx \n\r\n\r",Module_Info.Relay_Status.All);



		printf("Dip_Switch = %d \n\r", Module_Info.gfd_chk[1].R_GFD_v);
		
				printf(" ADC1 = %d ADC2 = %d ADC3 = %d ADC4 = %d ADC5 = %d \n\r", adc_value.ADC1_IN0.value,
						adc_value.ADC1_IN1.value,adc_value.ADC1_IN2.value,adc_value.ADC1_IN3.value,adc_value.ADC1_IN4.value);
				printf(" ADC6 = %d ADC7 = %d ADC8 = %d ADC9 = %d \n\r", adc_value.ADC1_IN5.value,
						adc_value.ADC1_IN6.value,adc_value.ADC1_IN7.value,adc_value.ADC1_IN8.value);

				printf("SMR6 = %d \n\r",Module_Info.SMR6_Relay_V);				

		printf(" CT1 = %d , CT2 = %d , ADC_1 = %f,  ADC_2 = %f \n\r", Module_Info.SMR1_Relay_C,
			   Module_Info.SMR2_Relay_C, c_vadc[0], c_vadc[1]); // 100A = 1000

		vTaskDelay(2000 / portTICK_RATE_MS);
#else

		osDelay(1);
#endif
	}

  /* USER CODE END StartDefaultTask */
}

/* USER CODE BEGIN Header_Uart1Task */
/**
 * @brief Function implementing the uart1Task thread.
 * @param argument: Not used
 * @retval None
 */
/* USER CODE END Header_Uart1Task */
void Uart1Task(void const * argument)
{
  /* USER CODE BEGIN Uart1Task */
	/* Infinite loop */
	uint8_t tx[UART_BUFFER_SIZE];
	uint8_t tx_len;
	uint8_t chksum = 0;
	uint8_t endFlag[4] = {0x55, 0xaa, 0x55, 0xaa};
	uint32_t flash, crc32;
	uint16_t temp;
	uint16_t nSMR1_Sense, nSMR2_Sense, nSMR3_Sense,nSMR4_Sense,nSMR5_Sense,nSMR6_Sense,nVer165, SMR1_Gfd_Sense, SMR2_Gfd_Sense;

	// uint16_t delay = 100;	
	for (;;)
	{		
	UartCMDtest();	

		
			if (uart_recv_end_flag == 1)
			{
				// printf(" %x %x %x %x %x %x\n\r", uart_rx_buffer[0],uart_rx_buffer[1],uart_rx_buffer[2],uart_rx_buffer[3],uart_rx_buffer[4],uart_rx_buffer[5]);
				chksum = 0;
				if ((uart_rx_buffer[2] == PROTOCOL_ADDR) || (uart_rx_buffer[2] == PROTOCOL_ADDR_BROADCAST))
				{
					if (isValidCheckSum() == ON)
					{						
						switch (uart_rx_buffer[3])
						{
						case USER_MESSAGE_QUERY_SENSE_DC_VOLTAGE:
							tx_len = 35;
							tx[0] = 0xaa;
							tx[1] = PROTOCOL_ADDR;
							tx[2] = uart_rx_buffer[1];
							tx[3] = USER_MESSAGE_QUERY_SENSE_DC_VOLTAGE;
							tx[4] = 28;
							tx[5] = 0;

							tx[6] = ((Module_Info.SMR1_Relay_C >> 0) & 0xff);
							tx[7] = ((Module_Info.SMR1_Relay_C >> 8) & 0xff);							
							tx[8] = ((Module_Info.SMR2_Relay_C >> 0) & 0xff);
							tx[9] = ((Module_Info.SMR2_Relay_C >> 8) & 0xff);
							tx[10] = ((Module_Info.SMR1_Relay_V >> 0) & 0xff);
							tx[11] = ((Module_Info.SMR1_Relay_V >> 8) & 0xff);
							tx[12] = ((Module_Info.SMR2_Relay_V >> 0) & 0xff);
							tx[13] = ((Module_Info.SMR2_Relay_V >> 8) & 0xff);		
							tx[14] = ((Module_Info.SMR3_Relay_V >> 0) & 0xff);
							tx[15] = ((Module_Info.SMR3_Relay_V >> 8) & 0xff);			
							tx[16] = ((Module_Info.SMR4_Relay_V >> 0) & 0xff);
							tx[17] = ((Module_Info.SMR4_Relay_V >> 8) & 0xff);			
							tx[18] = ((Module_Info.SMR5_Relay_V >> 0) & 0xff);
							tx[19] = ((Module_Info.SMR5_Relay_V >> 8) & 0xff);			
							tx[20] = ((Module_Info.SMR6_Relay_V >> 0) & 0xff);
							tx[21] = ((Module_Info.SMR6_Relay_V >> 8) & 0xff);								

							nSMR1_Sense = (uint16_t)adc_value.ADC1_IN0.value;
							nSMR2_Sense = (uint16_t)adc_value.ADC1_IN2.value;
							nSMR3_Sense = (uint16_t)adc_value.ADC1_IN5.value;
							nSMR4_Sense = (uint16_t)adc_value.ADC1_IN6.value;
							nSMR5_Sense = (uint16_t)adc_value.ADC1_IN7.value;
							nSMR6_Sense = (uint16_t)adc_value.ADC1_IN8.value;

							
							tx[22] = ((nSMR1_Sense >> 0) & 0xff);
							tx[23] = ((nSMR1_Sense >> 8) & 0xff);
							tx[24] = ((nSMR2_Sense >> 0) & 0xff);
							tx[25] = ((nSMR2_Sense >> 8) & 0xff);
							tx[26] = ((nSMR3_Sense >> 0) & 0xff);
							tx[27] = ((nSMR3_Sense >> 8) & 0xff);
							tx[28] = ((nSMR4_Sense >> 0) & 0xff);
							tx[29] = ((nSMR4_Sense >> 8) & 0xff);
							tx[30] = ((nSMR5_Sense >> 0) & 0xff);
							tx[31] = ((nSMR5_Sense >> 8) & 0xff);
							tx[32] = ((nSMR6_Sense >> 0) & 0xff);
							tx[33] = ((nSMR6_Sense >> 8) & 0xff);


							//tx[18] = ((Module_Info.BAT_Voltage >> 0) & 0xff);
							//tx[19] = ((Module_Info.BAT_Voltage >> 8) & 0xff);
							//tx[20] = ((nBat1_Sense >> 0) & 0xff);
							//tx[21] = ((nBat1_Sense >> 8) & 0xff);

							for (int idx = 0; idx < (tx[4] | (tx[5] << 8)); idx++)
							{
								chksum ^= tx[6 + idx];
							}
							tx[34] = chksum;
							break;

						case USER_MESSAGE_QUERY_SENSE_GFD:
							tx_len = 29;
							tx[0] = 0xaa;
							tx[1] = PROTOCOL_ADDR;
							tx[2] = uart_rx_buffer[1];
							tx[3] = USER_MESSAGE_QUERY_SENSE_GFD;
							tx[4] = 22;
							tx[5] = 0x00;
							
							if (Module_Info.gfd_chk[0].bResult_Gfd == GFD_FAIL)
							{
								tx[6] = (((Module_Info.gfd_chk[0].R_GFD_Fail / 1000) >> 0) & 0xff); // Gfd Resistor
								tx[7] = (((Module_Info.gfd_chk[0].R_GFD_Fail / 1000) >> 8) & 0xff);

								tx[8] = ((Module_Info.gfd_chk[0].SMR_Voltage_Fail >> 0) & 0xff);
								tx[9] = ((Module_Info.gfd_chk[0].SMR_Voltage_Fail >> 8) & 0xff);
								tx[11] = Module_Info.gfd_chk[0].Rfd_State_Fail;
							}
							else
							{
								tx[6] = (((Module_Info.gfd_chk[0].R_GFD_v / 1000) >> 0) & 0xff); // Gfd Resistor
								tx[7] = (((Module_Info.gfd_chk[0].R_GFD_v / 1000) >> 8) & 0xff);

								tx[8] = ((Module_Info.SMR1_Relay_V >> 0) & 0xff);
								tx[9] = ((Module_Info.SMR1_Relay_V >> 8) & 0xff);
								tx[11] = Module_Info.gfd_chk[0].Rfd_State;
							}

							tx[10] = Module_Info.gfd_chk[0].bResult_Gfd;
							
							if (Module_Info.gfd_chk[1].bResult_Gfd == GFD_FAIL)
							{
								tx[12] = (((Module_Info.gfd_chk[1].R_GFD_Fail / 1000) >> 0) & 0xff); // Gfd Resistor
								tx[13] = (((Module_Info.gfd_chk[1].R_GFD_Fail / 1000) >> 8) & 0xff);

								tx[14] = ((Module_Info.gfd_chk[1].SMR_Voltage_Fail >> 0) & 0xff);
								tx[15] = ((Module_Info.gfd_chk[1].SMR_Voltage_Fail >> 8) & 0xff);
								tx[17] = Module_Info.gfd_chk[1].Rfd_State_Fail;
							}
							else
							{
								tx[12] = (((Module_Info.gfd_chk[1].R_GFD_v / 1000) >> 0) & 0xff); // Gfd Resistor
								tx[13] = (((Module_Info.gfd_chk[1].R_GFD_v / 1000) >> 8) & 0xff);

								tx[14] = ((Module_Info.SMR2_Relay_V >> 0) & 0xff);
								tx[15] = ((Module_Info.SMR2_Relay_V >> 8) & 0xff);
								tx[17] = Module_Info.gfd_chk[1].Rfd_State;
							}

							tx[16] = Module_Info.gfd_chk[1].bResult_Gfd;

							//  Verf_165
							nVer165 = (uint16_t)(Module_Info.Vref_165 * 100.0);
							tx[18] = ((nVer165 >> 0) & 0xff);
							tx[19] = ((nVer165 >> 8) & 0xff);

							SMR1_Gfd_Sense = (uint16_t)(Module_Info.SMR_Gfd_Sense[0] * 100.0);
							SMR2_Gfd_Sense = (uint16_t)(Module_Info.SMR_Gfd_Sense[1] * 100.0);
							// SMR1_Gfd_Diff = (uint16_t)(Module_Info.SMR_Gfd_Diff[0] * 100.0);
							// SMR2_Gfd_Diff = (uint16_t)(Module_Info.SMR_Gfd_Diff[1] * 100.0);

							tx[20] = ((SMR1_Gfd_Sense >> 0) & 0xff);
							tx[21] = ((SMR1_Gfd_Sense >> 8) & 0xff);
							tx[22] = ((SMR2_Gfd_Sense >> 0) & 0xff);
							tx[23] = ((SMR2_Gfd_Sense >> 8) & 0xff);

							// tx[24] = ((SMR1_Gfd_Diff >> 0) & 0xff);
							// tx[25] = ((SMR1_Gfd_Diff >> 8) & 0xff);
							// tx[26] = ((SMR2_Gfd_Diff >> 0) & 0xff);
							// tx[27] = ((SMR2_Gfd_Diff >> 8) & 0xff);

							for (int idx = 0; idx < (tx[4] | (tx[5] << 8)); idx++)
							{
								chksum ^= tx[6 + idx];
							}
							tx[28] = chksum;

							break;

						case PROTOCOL_MESSAGE_QUERY_FW_VER:
							tx_len = 15;
							tx[0] = 0xaa;
							tx[1] = PROTOCOL_ADDR;
							tx[2] = uart_rx_buffer[1];
							tx[3] = PROTOCOL_MESSAGE_QUERY_FW_VER;
							tx[4] = 0x08;
							tx[5] = 0x00;

							for (int idx = 0; idx < 8; idx++)
								tx[(6 + idx)] = Module_Info.Soft_Ver_Ptr[idx];

							for (int idx = 0; idx < (tx[4] | (tx[5] << 8)); idx++)
								chksum ^= tx[(6 + idx)];

							tx[14] = chksum;
							break;

						case PROTOCOL_MESSAGE_QUERY_HW_VER:
							tx_len = 15;
							tx[0] = 0xaa;
							tx[1] = PROTOCOL_ADDR;
							tx[2] = uart_rx_buffer[1];
							tx[3] = PROTOCOL_MESSAGE_QUERY_HW_VER;
							tx[4] = 0x08;
							tx[5] = 0x00;

							for (int idx = 0; idx < 8; idx++)
								tx[(6 + idx)] = Module_Info.Hard_Ver_Ptr[idx];

							for (int idx = 0; idx < (tx[4] | (tx[5] << 8)); idx++)
								chksum ^= tx[(6 + idx)];

							tx[14] = chksum;

							break;
						case PROTOCOL_MESSAGE_QUERY_PRESENT_INPUT_VOLTAGE:
							tx_len = 14;
							tx[0] = 0xaa;
							tx[1] = PROTOCOL_ADDR;
							tx[2] = uart_rx_buffer[1];
							tx[3] = PROTOCOL_MESSAGE_QUERY_PRESENT_INPUT_VOLTAGE;
							tx[4] = 0x07;
							tx[5] = 0x00;
							tx[6] = 0;
							tx[7] = ((AC_Sine[0].Vrms_AVG >> 0) & 0xff);
							tx[8] = ((AC_Sine[0].Vrms_AVG >> 8) & 0xff);
							tx[9] = ((AC_Sine[1].Vrms_AVG >> 0) & 0xff);
							tx[10] = ((AC_Sine[1].Vrms_AVG >> 8) & 0xff);
							tx[11] = ((AC_Sine[2].Vrms_AVG >> 0) & 0xff);
							tx[12] = ((AC_Sine[2].Vrms_AVG >> 8) & 0xff);

							for (int idx = 0; idx < (tx[4] | (tx[5] << 8)); idx++)
								chksum ^= tx[6 + idx];
							tx[13] = chksum;
							break;			
						case PROTOCOL_MESSAGE_QUERY_BATTERY_VOLTAGE_IN:
							tx_len = 11;
							tx[0] = 0xaa;
							tx[1] = PROTOCOL_ADDR;
							tx[2] = uart_rx_buffer[1];
							tx[3] = PROTOCOL_MESSAGE_QUERY_BATTERY_VOLTAGE_IN;
							tx[4] = 0x04;
							tx[5] = 0x00;
							tx[6] = ((Module_Info.BAT_Voltage>>0) & 0xff);
							tx[7] = ((Module_Info.BAT_Voltage>>8) & 0xff);
							tx[8] = tx[9] = 0;
							
							for(int idx=0;idx<(tx[4] | (tx[5]<<8));idx++)
							{
								chksum ^= tx[6 + idx];
							}
							tx[10] = chksum;
							break;				
						case PROTOCOL_MESSAGE_QUERY_PRESENT_OUTPUT_VOLTAGE:
							tx_len = 23;
							tx[0] = 0xaa;
							tx[1] = PROTOCOL_ADDR;
							tx[2] = uart_rx_buffer[1];
							tx[3] = PROTOCOL_MESSAGE_QUERY_PRESENT_OUTPUT_VOLTAGE;
							tx[4] = 16;
							tx[5] = 0x00;
							tx[6] = ((Module_Info.SMR1_Relay_C >> 0) & 0xff);
							tx[7] = ((Module_Info.SMR1_Relay_C >> 8) & 0xff);
							tx[8] = ((Module_Info.SMR1_Relay_V >> 0) & 0xff);
							tx[9] = ((Module_Info.SMR1_Relay_V >> 8) & 0xff);
							tx[10] = ((Module_Info.SMR2_Relay_C >> 0) & 0xff);
							tx[11] = ((Module_Info.SMR2_Relay_C >> 8) & 0xff);
							tx[12] = ((Module_Info.SMR2_Relay_V >> 0) & 0xff);
							tx[13] = ((Module_Info.SMR2_Relay_V >> 8) & 0xff);							
							tx[14] = ((Module_Info.SMR3_Relay_V >> 0) & 0xff);
							tx[15] = ((Module_Info.SMR3_Relay_V >> 8) & 0xff);			
							tx[16] = ((Module_Info.SMR4_Relay_V >> 0) & 0xff);
							tx[17] = ((Module_Info.SMR4_Relay_V >> 8) & 0xff);			
							tx[18] = ((Module_Info.SMR5_Relay_V >> 0) & 0xff);
							tx[19] = ((Module_Info.SMR5_Relay_V >> 8) & 0xff);			
							tx[20] = ((Module_Info.SMR6_Relay_V >> 0) & 0xff);
							tx[21] = ((Module_Info.SMR6_Relay_V >> 8) & 0xff);	

							for (int idx = 0; idx < (tx[4] | (tx[5] << 8)); idx++)
							{
								chksum ^= tx[6 + idx];
							}
							tx[22] = chksum;

							break;
						case PROTOCOL_MESSAGE_QUERY_OUTPUT_RELAY_OUTPUT_STATUS:						
							tx_len = 14;
							tx[0] = 0xaa;
							tx[1] = PROTOCOL_ADDR;
							tx[2] = uart_rx_buffer[1];
							tx[3] = uart_rx_buffer[3];
							tx[4] = 7;
							tx[5] = 0;

							// Read Relay Feedback Pins ......	
							Module_Info.Relay_Status.flags.AC_Contactor = ~HAL_GPIO_ReadPin(AC_Contactor_Ret_GPIO_Port, AC_Contactor_Ret_Pin);
							Module_Info.Relay_Status.flags.Precharge1 = ~HAL_GPIO_ReadPin(Precharge1_Ret_GPIO_Port, Precharge1_Ret_Pin);
							Module_Info.Relay_Status.flags.Precharge2 = ~HAL_GPIO_ReadPin(Precharge2_Ret_GPIO_Port, Precharge2_Ret_Pin);

							Module_Info.Relay_Status.flags.SMR1_relay_n = ~HAL_GPIO_ReadPin(SMR1_Relay_n_Ret_GPIO_Port, SMR1_Relay_n_Ret_Pin);
							Module_Info.Relay_Status.flags.SMR1_relay_p = ~HAL_GPIO_ReadPin(SMR1_Relay_p_Ret_GPIO_Port, SMR1_Relay_p_Ret_Pin);
							Module_Info.Relay_Status.flags.SMR2_relay_n = ~HAL_GPIO_ReadPin(SMR2_Relay_n_Ret_GPIO_Port, SMR2_Relay_n_Ret_Pin);
							Module_Info.Relay_Status.flags.SMR2_relay_p = ~HAL_GPIO_ReadPin(SMR2_Relay_p_Ret_GPIO_Port, SMR2_Relay_p_Ret_Pin);
							Module_Info.Relay_Status.flags.SMR3_relay_n = ~HAL_GPIO_ReadPin(SMR3_Relay_n_Ret_GPIO_Port, SMR3_Relay_n_Ret_Pin);
							Module_Info.Relay_Status.flags.SMR3_relay_p = ~HAL_GPIO_ReadPin(SMR3_Relay_p_Ret_GPIO_Port, SMR3_Relay_p_Ret_Pin);
							Module_Info.Relay_Status.flags.SMR4_relay_n = ~HAL_GPIO_ReadPin(SMR4_Relay_n_Ret_GPIO_Port, SMR4_Relay_n_Ret_Pin);
							Module_Info.Relay_Status.flags.SMR4_relay_p = ~HAL_GPIO_ReadPin(SMR4_Relay_p_Ret_GPIO_Port, SMR4_Relay_p_Ret_Pin);
							Module_Info.Relay_Status.flags.SMR5_relay_n = ~HAL_GPIO_ReadPin(SMR5_Relay_n_Ret_GPIO_Port, SMR5_Relay_n_Ret_Pin);
							Module_Info.Relay_Status.flags.SMR5_relay_p = ~HAL_GPIO_ReadPin(SMR5_Relay_p_Ret_GPIO_Port, SMR5_Relay_p_Ret_Pin);
							Module_Info.Relay_Status.flags.SMR6_relay_n = ~HAL_GPIO_ReadPin(SMR6_Relay_n_Ret_GPIO_Port, SMR6_Relay_n_Ret_Pin);
							Module_Info.Relay_Status.flags.SMR6_relay_p = ~HAL_GPIO_ReadPin(SMR6_Relay_p_Ret_GPIO_Port, SMR6_Relay_p_Ret_Pin);		

							tx[6] = (Module_Info.Relay_Status.All & 0xff);
							tx[7] = (Module_Info.Relay_Status.All >> 8) & 0xff;							
							tx[8] = (Module_Info.Relay_Status.All >> 16) & 0xff;
							tx[9] = (Module_Info.Relay_Status.All >> 24) & 0xff;
							tx[10] = (Module_Info.Relay_Status.All >> 32) & 0xff;
							tx[11] = (Module_Info.Relay_Status.All >> 40) & 0xff;
							tx[12] = (Module_Info.Relay_Status.All >> 48) & 0xff;
							
								
							for (int idx = 0; idx < (tx[4] | (tx[5] << 8)); idx++)
							{
								chksum ^= tx[6 + idx];
							}
							tx[13] = chksum;
							break;
						case PROTOCOL_MESSAGE_QUERY_BRIDGE_RELAY_OUTPUT_STATUS:
							tx_len = 13;
							tx[0] = 0xaa;
							tx[1] = PROTOCOL_ADDR;
							tx[2] = uart_rx_buffer[1];
							tx[3] = uart_rx_buffer[3];
							tx[4] = 6;
							tx[5] = 0;

							// Read Relay Feedback Pins ......	
							Module_Info.Relay_Status.flags.AC_Contactor = ~HAL_GPIO_ReadPin(AC_Contactor_Ret_GPIO_Port, AC_Contactor_Ret_Pin);
							Module_Info.Relay_Status.flags.Precharge1 = ~HAL_GPIO_ReadPin(Precharge1_Ret_GPIO_Port, Precharge1_Ret_Pin);
							Module_Info.Relay_Status.flags.Precharge2 = ~HAL_GPIO_ReadPin(Precharge2_Ret_GPIO_Port, Precharge2_Ret_Pin);

							Module_Info.Relay_Status.flags.SMR1_relay_n = ~HAL_GPIO_ReadPin(SMR1_Relay_n_Ret_GPIO_Port, SMR1_Relay_n_Ret_Pin);
							Module_Info.Relay_Status.flags.SMR1_relay_p = ~HAL_GPIO_ReadPin(SMR1_Relay_p_Ret_GPIO_Port, SMR1_Relay_p_Ret_Pin);
							Module_Info.Relay_Status.flags.SMR2_relay_n = ~HAL_GPIO_ReadPin(SMR2_Relay_n_Ret_GPIO_Port, SMR2_Relay_n_Ret_Pin);
							Module_Info.Relay_Status.flags.SMR2_relay_p = ~HAL_GPIO_ReadPin(SMR2_Relay_p_Ret_GPIO_Port, SMR2_Relay_p_Ret_Pin);
							Module_Info.Relay_Status.flags.SMR3_relay_n = ~HAL_GPIO_ReadPin(SMR3_Relay_n_Ret_GPIO_Port, SMR3_Relay_n_Ret_Pin);
							Module_Info.Relay_Status.flags.SMR3_relay_p = ~HAL_GPIO_ReadPin(SMR3_Relay_p_Ret_GPIO_Port, SMR3_Relay_p_Ret_Pin);
							Module_Info.Relay_Status.flags.SMR4_relay_n = ~HAL_GPIO_ReadPin(SMR4_Relay_n_Ret_GPIO_Port, SMR4_Relay_n_Ret_Pin);
							Module_Info.Relay_Status.flags.SMR4_relay_p = ~HAL_GPIO_ReadPin(SMR4_Relay_p_Ret_GPIO_Port, SMR4_Relay_p_Ret_Pin);
							Module_Info.Relay_Status.flags.SMR5_relay_n = ~HAL_GPIO_ReadPin(SMR5_Relay_n_Ret_GPIO_Port, SMR5_Relay_n_Ret_Pin);
							Module_Info.Relay_Status.flags.SMR5_relay_p = ~HAL_GPIO_ReadPin(SMR5_Relay_p_Ret_GPIO_Port, SMR5_Relay_p_Ret_Pin);
							Module_Info.Relay_Status.flags.SMR6_relay_n = ~HAL_GPIO_ReadPin(SMR6_Relay_n_Ret_GPIO_Port, SMR6_Relay_n_Ret_Pin);
							Module_Info.Relay_Status.flags.SMR6_relay_p = ~HAL_GPIO_ReadPin(SMR6_Relay_p_Ret_GPIO_Port, SMR6_Relay_p_Ret_Pin);		

							tx[6] = (Module_Info.Relay_Status.All & 0xff);
							tx[7] = (Module_Info.Relay_Status.All >> 8) & 0xff;							
							tx[8] = (Module_Info.Relay_Status.All >> 16) & 0xff;
							tx[9] = (Module_Info.Relay_Status.All >> 24) & 0xff;
							tx[10] = (Module_Info.Relay_Status.All >> 32) & 0xff;
							tx[11] = (Module_Info.Relay_Status.All >> 40) & 0xff;	
								
							for (int idx = 0; idx < (tx[4] | (tx[5] << 8)); idx++)
							{
								chksum ^= tx[6 + idx];
							}
							tx[12] = chksum;
							break;	
						case PROTOCOL_MESSAGE_QUERY_GFD_ADC_VALUE:
							tx_len = 19;
							tx[0] = 0xaa;
							tx[1] = PROTOCOL_ADDR;
							tx[2] = uart_rx_buffer[1];
							tx[3] = PROTOCOL_MESSAGE_QUERY_GFD_ADC_VALUE;
							tx[4] = 12;
							tx[5] = 0x00;
							
							if (Module_Info.gfd_chk[0].bResult_Gfd == GFD_FAIL)
							{
								tx[6] = (((Module_Info.gfd_chk[0].R_GFD_Fail / 1000) >> 0) & 0xff); // Gfd Resistor
								tx[7] = (((Module_Info.gfd_chk[0].R_GFD_Fail / 1000) >> 8) & 0xff);

								tx[8] = ((Module_Info.gfd_chk[0].SMR_Voltage_Fail >> 0) & 0xff);
								tx[9] = ((Module_Info.gfd_chk[0].SMR_Voltage_Fail >> 8) & 0xff);
								tx[11] = Module_Info.gfd_chk[0].Rfd_State_Fail;
							}
							else
							{
								tx[6] = (((Module_Info.gfd_chk[0].R_GFD_v / 1000) >> 0) & 0xff); // Gfd Resistor
								tx[7] = (((Module_Info.gfd_chk[0].R_GFD_v / 1000) >> 8) & 0xff);

								tx[8] = ((Module_Info.SMR1_Relay_V >> 0) & 0xff);
								tx[9] = ((Module_Info.SMR1_Relay_V >> 8) & 0xff);
								tx[11] = Module_Info.gfd_chk[0].Rfd_State;
							}

							tx[10] = Module_Info.gfd_chk[0].bResult_Gfd;
							
							if (Module_Info.gfd_chk[1].bResult_Gfd == GFD_FAIL)
							{
								tx[12] = (((Module_Info.gfd_chk[1].R_GFD_Fail / 1000) >> 0) & 0xff); // Gfd Resistor
								tx[13] = (((Module_Info.gfd_chk[1].R_GFD_Fail / 1000) >> 8) & 0xff);

								tx[14] = ((Module_Info.gfd_chk[1].SMR_Voltage_Fail >> 0) & 0xff);
								tx[15] = ((Module_Info.gfd_chk[1].SMR_Voltage_Fail >> 8) & 0xff);
								tx[17] = Module_Info.gfd_chk[1].Rfd_State_Fail;
							}
							else
							{
								tx[12] = (((Module_Info.gfd_chk[1].R_GFD_v / 1000) >> 0) & 0xff); // Gfd Resistor
								tx[13] = (((Module_Info.gfd_chk[1].R_GFD_v / 1000) >> 8) & 0xff);

								tx[14] = ((Module_Info.SMR2_Relay_V >> 0) & 0xff);
								tx[15] = ((Module_Info.SMR2_Relay_V >> 8) & 0xff);
								tx[17] = Module_Info.gfd_chk[1].Rfd_State;
							}

							tx[16] = Module_Info.gfd_chk[1].bResult_Gfd;

							for (int idx = 0; idx < (tx[4] | (tx[5] << 8)); idx++)
							{
								chksum ^= tx[6 + idx];
							}
							tx[18] = chksum;

							break;
						case PROTOCOL_MESSAGE_QUERY_INPUT_GPIO_STATUS:
							tx_len = 8;
							tx[0] = 0xaa;
							tx[1] = PROTOCOL_ADDR;
							tx[2] = uart_rx_buffer[1];
							tx[3] = PROTOCOL_MESSAGE_QUERY_INPUT_GPIO_STATUS;
							tx[4] = 1;
							tx[5] = 0;
							tx[6] = Module_Info.Gpio_status.All;

							for (int idx = 0; idx < (tx[4] | (tx[5] << 8)); idx++)
							{
								chksum ^= tx[6 + idx];
							}
							tx[7] = chksum;

							break;
						case PROTOCOL_MESSAGE_QUERY_SN:
							tx_len = 27;
							tx[0] = 0xaa;
							tx[1] = PROTOCOL_ADDR;
							tx[2] = uart_rx_buffer[1];
							tx[3] = PROTOCOL_MESSAGE_QUERY_SN;
							tx[4] = 0x14;
							tx[5] = 0x00;

							memcpy(&tx[6], Module_Info.SN, 20);
							for (int idx = 0; idx < (tx[4] | (tx[5] << 8)); idx++)
							{
								chksum ^= tx[6 + idx];
							}
							tx[26] = chksum;

							break;

						case PROTOCOL_MESSAGE_QUERY_ALARM_CODE:
							tx_len = 13;
							tx[0] = 0xaa;
							tx[1] = PROTOCOL_ADDR;
							tx[2] = uart_rx_buffer[1];
							tx[3] = PROTOCOL_MESSAGE_QUERY_ALARM_CODE;
							tx[4] = 6;
							tx[5] = 0;
							// === Data ===
							tx[6] = 0;
							tx[7] = 0;
							tx[8] = 0;
							tx[9] = (Module_Info.Alarm_CSU.All) & 0xff;
							tx[10] = (Module_Info.Alarm_CSU.All >> 8) & 0xff;
							tx[11] = 0;

							for (int idx = 0; idx < (tx[4] | (tx[5] << 8)); idx++)
							{
								chksum ^= tx[6 + idx];
							}
							tx[12] = chksum;
							break;
						case PROTOCOL_MESSAGE_QUERY_SELF_TEST_STATUS:
							tx_len = 13;
							tx[0] = 0xaa;
							tx[1] = PROTOCOL_ADDR;
							tx[2] = uart_rx_buffer[1];
							tx[3] = PROTOCOL_MESSAGE_QUERY_SELF_TEST_STATUS;
							tx[4] = 6;
							tx[5] = 0;
							tx[6] = sf_t.SF_Config.SF_test_status;
							tx[7] = sf_t.SF_Config.data.value & 0xff;
							tx[8] = (sf_t.SF_Config.data.value >> 8) & 0xff;
							tx[9] = (sf_t.SF_Config.data.value >> 16) & 0xff;
							tx[10] = (sf_t.SF_Config.data.value >> 24) & 0xff;
							tx[11] = (sf_t.SF_Config.data.value >> 32) & 0xff;

							for (int idx = 0; idx < (tx[4] | (tx[5] << 8)); idx++)
							{
								chksum ^= tx[6 + idx];
							}
							tx[12] = chksum;
							break;

						case PROTOCOL_MESSAGE_QUERY_PARAMETER:
							tx_len = 11;
							tx[0] = 0xaa;
							tx[1] = PROTOCOL_ADDR;
							tx[2] = uart_rx_buffer[1];
							tx[3] = PROTOCOL_MESSAGE_QUERY_PARAMETER;
							tx[4] = 4;
							tx[5] = 0;

							tx[6] = uart_rx_buffer[6];
							tx[7] = uart_rx_buffer[7];

							// === Data ===

							switch (uart_rx_buffer[6])
							{
							case Input_L1_AC_voltage:
								switch (uart_rx_buffer[7])
								{
								case 1: // METER_DATA , MCU_DATA
									tx[8] = Module_Info.memory.Module_Config.data.item.Correction_Volt[0][METER_DATA] & 0xff;
									tx[9] = (Module_Info.memory.Module_Config.data.item.Correction_Volt[0][METER_DATA] >> 8) & 0xff;
									break;
								case 2:
									tx[8] = Module_Info.memory.Module_Config.data.item.Correction_Volt[1][METER_DATA] & 0xff;
									tx[9] = (Module_Info.memory.Module_Config.data.item.Correction_Volt[1][METER_DATA] >> 8) & 0xff;
									break;
								case 3:
									tx[8] = Module_Info.memory.Module_Config.data.item.Correction_Volt[2][METER_DATA] & 0xff;
									tx[9] = (Module_Info.memory.Module_Config.data.item.Correction_Volt[2][METER_DATA] >> 8) & 0xff;
									break;
								default:
									tx[8] = 0;
									tx[9] = 0;
									break;
								}
								break;
							case Input_L2_AC_voltage:
								switch (uart_rx_buffer[7])
								{
								case 1:
									tx[8] = Module_Info.memory.Module_Config.data.item.Correction_Volt[3][METER_DATA] & 0xff;
									tx[9] = (Module_Info.memory.Module_Config.data.item.Correction_Volt[3][METER_DATA] >> 8) & 0xff;
									break;
								case 2:
									tx[8] = Module_Info.memory.Module_Config.data.item.Correction_Volt[4][METER_DATA] & 0xff;
									tx[9] = (Module_Info.memory.Module_Config.data.item.Correction_Volt[4][METER_DATA] >> 8) & 0xff;
									break;
								case 3:
									tx[8] = Module_Info.memory.Module_Config.data.item.Correction_Volt[5][METER_DATA] & 0xff;
									tx[9] = (Module_Info.memory.Module_Config.data.item.Correction_Volt[5][METER_DATA] >> 8) & 0xff;
									break;
								default:
									break;
								}
								break;
							case Input_L3_AC_voltage:
								switch (uart_rx_buffer[7])
								{
								case 1:
									tx[8] = Module_Info.memory.Module_Config.data.item.Correction_Volt[6][METER_DATA] & 0xff;
									tx[9] = (Module_Info.memory.Module_Config.data.item.Correction_Volt[6][METER_DATA] >> 8) & 0xff;
									break;
								case 2:
									tx[8] = Module_Info.memory.Module_Config.data.item.Correction_Volt[7][METER_DATA] & 0xff;
									tx[9] = (Module_Info.memory.Module_Config.data.item.Correction_Volt[7][METER_DATA] >> 8) & 0xff;
									break;
								case 3:
									tx[8] = Module_Info.memory.Module_Config.data.item.Correction_Volt[8][METER_DATA] & 0xff;
									tx[9] = (Module_Info.memory.Module_Config.data.item.Correction_Volt[8][METER_DATA] >> 8) & 0xff;
									break;
								default:
									break;
								}
								break;
							case SMR1_output_voltage:
								switch (uart_rx_buffer[7])
								{
								case 1:
									tx[8] = Module_Info.memory.Module_Config.data.item.DC_Correction_Volt[0][METER_DATA] & 0xff;
									tx[9] = (Module_Info.memory.Module_Config.data.item.DC_Correction_Volt[0][METER_DATA] >> 8) & 0xff;
									break;
								case 2:
									tx[8] = Module_Info.memory.Module_Config.data.item.DC_Correction_Volt[1][METER_DATA] & 0xff;
									tx[9] = (Module_Info.memory.Module_Config.data.item.DC_Correction_Volt[1][METER_DATA] >> 8) & 0xff;
									break;
								default:
									break;
								}
								break;
							case SMR2_output_voltage:
								switch (uart_rx_buffer[7])
								{
								case 1:
									tx[8] = Module_Info.memory.Module_Config.data.item.DC_Correction_Volt[2][METER_DATA] & 0xff;
									tx[9] = (Module_Info.memory.Module_Config.data.item.DC_Correction_Volt[2][METER_DATA] >> 8) & 0xff;
									break;
								case 2:
									tx[8] = Module_Info.memory.Module_Config.data.item.DC_Correction_Volt[3][METER_DATA] & 0xff;
									tx[9] = (Module_Info.memory.Module_Config.data.item.DC_Correction_Volt[3][METER_DATA] >> 8) & 0xff;
									break;
								default:
									break;
								}
								break;
							case SMR3_output_voltage:
								switch (uart_rx_buffer[7])
								{
								case 1:
									tx[8] = Module_Info.memory.Module_Config.data.item.DC_Correction_Volt[4][METER_DATA] & 0xff;
									tx[9] = (Module_Info.memory.Module_Config.data.item.DC_Correction_Volt[4][METER_DATA] >> 8) & 0xff;
									break;
								case 2:
									tx[8] = Module_Info.memory.Module_Config.data.item.DC_Correction_Volt[5][METER_DATA] & 0xff;
									tx[9] = (Module_Info.memory.Module_Config.data.item.DC_Correction_Volt[5][METER_DATA] >> 8) & 0xff;
									break;
								default:
									break;
								}
								break;	
							case SMR4_output_voltage:
								switch (uart_rx_buffer[7])
								{
								case 1:
									tx[8] = Module_Info.memory.Module_Config.data.item.DC_Correction_Volt[6][METER_DATA] & 0xff;
									tx[9] = (Module_Info.memory.Module_Config.data.item.DC_Correction_Volt[6][METER_DATA] >> 8) & 0xff;
									break;
								case 2:
									tx[8] = Module_Info.memory.Module_Config.data.item.DC_Correction_Volt[7][METER_DATA] & 0xff;
									tx[9] = (Module_Info.memory.Module_Config.data.item.DC_Correction_Volt[7][METER_DATA] >> 8) & 0xff;
									break;
								default:
									break;
								}
								break;		
							case SMR5_output_voltage:
								switch (uart_rx_buffer[7])
								{
								case 1:
									tx[8] = Module_Info.memory.Module_Config.data.item.DC_Correction_Volt[8][METER_DATA] & 0xff;
									tx[9] = (Module_Info.memory.Module_Config.data.item.DC_Correction_Volt[8][METER_DATA] >> 8) & 0xff;
									break;
								case 2:
									tx[8] = Module_Info.memory.Module_Config.data.item.DC_Correction_Volt[9][METER_DATA] & 0xff;
									tx[9] = (Module_Info.memory.Module_Config.data.item.DC_Correction_Volt[9][METER_DATA] >> 8) & 0xff;
									break;
								default:
									break;
								}
								break;			
							case SMR6_output_voltage:
								switch (uart_rx_buffer[7])
								{
								case 1:
									tx[8] = Module_Info.memory.Module_Config.data.item.DC_Correction_Volt[10][METER_DATA] & 0xff;
									tx[9] = (Module_Info.memory.Module_Config.data.item.DC_Correction_Volt[10][METER_DATA] >> 8) & 0xff;
									break;
								case 2:
									tx[8] = Module_Info.memory.Module_Config.data.item.DC_Correction_Volt[11][METER_DATA] & 0xff;
									tx[9] = (Module_Info.memory.Module_Config.data.item.DC_Correction_Volt[11][METER_DATA] >> 8) & 0xff;
									break;
								default:
									break;
								}
								break;				
							case GFD_Resister_Left:
								switch (uart_rx_buffer[7])
								{
								case 1:
									tx[8] = Module_Info.memory.Module_Config.data.item.GFD_Correction_Resistor[0][METER_DATA] & 0xff;
									tx[9] = (Module_Info.memory.Module_Config.data.item.GFD_Correction_Resistor[0][METER_DATA] >> 8) & 0xff;
									break;
								case 2:
									tx[8] = Module_Info.memory.Module_Config.data.item.GFD_Correction_Resistor[1][METER_DATA] & 0xff;
									tx[9] = (Module_Info.memory.Module_Config.data.item.GFD_Correction_Resistor[1][METER_DATA] >> 8) & 0xff;
									break;
								default:
									break;
								}
								break;
							case GFD_Resister_Right:
								switch (uart_rx_buffer[7])
								{
								case 1:
									tx[8] = Module_Info.memory.Module_Config.data.item.GFD_Correction_Resistor[2][METER_DATA] & 0xff;
									tx[9] = (Module_Info.memory.Module_Config.data.item.GFD_Correction_Resistor[2][METER_DATA] >> 8) & 0xff;
									break;
								case 2:
									tx[8] = Module_Info.memory.Module_Config.data.item.GFD_Correction_Resistor[3][METER_DATA] & 0xff;
									tx[9] = (Module_Info.memory.Module_Config.data.item.GFD_Correction_Resistor[3][METER_DATA] >> 8) & 0xff;
									break;
								default:
									break;
								}
								break;							
							default:
								break;
							}

							for (int idx = 0; idx < (tx[4] | (tx[5] << 8)); idx++)
							{
								chksum ^= tx[(6 + idx)];
							}
							tx[10] = chksum;
							break;

						/*--------------------------------------------
							Config message
						--------------------------------------------*/
						case PROTOCOL_MESSAGE_CONFIG_MODEL_NAME:
							nGun = 0;
                        	    for (int i=7; i<=9; i++){
                        	    	if(uart_rx_buffer[(6+i)] != '0')
                        	    		nGun += 1;
                        	    }

								for (int i = 0;i<14;i++){
									ModelName[i] = uart_rx_buffer[(6+i)]; 
								}
								ModelName[14] = 0;
								
							
								if(memcmp(ModelName,Module_Info.memory.Module_Config.data.item.Modelname,14) != 0){									
									memcpy(Module_Info.memory.Module_Config.data.item.Modelname,ModelName,14);
									Module_Info.memory.Module_Config.op_bits.update = ON;
									Module_Info.memory.Module_Config.op_bits.modelname = ON;
								}	

							tx_len = 8;
							tx[0] = 0xaa;
							tx[1] = PROTOCOL_ADDR;
							tx[2] = uart_rx_buffer[1];
							tx[3] = PROTOCOL_MESSAGE_CONFIG_MODEL_NAME;
							tx[4] = 0x01;
							tx[5] = 0x00;
							tx[6] = 0x01;
							tx[7] = 0x01;
							break;

						case PROTOCOL_MESSAGE_CONFIG_OUTPUT_RELAY_OUTPUT:						
							Module_Info.Relay_IO.All = (((uint64_t)uart_rx_buffer[12] << 48) | ((uint64_t)uart_rx_buffer[11] << 40) | ((uint64_t)uart_rx_buffer[10]<< 32) |
														((uint64_t)uart_rx_buffer[9] << 24) | ((uint64_t)uart_rx_buffer[8] << 16) | ((uint64_t)uart_rx_buffer[7]<< 8)	| 
														((uint64_t)uart_rx_buffer[6] )) ;
							tx_len = 8;		
							tx[0] = 0xaa;
							tx[1] = PROTOCOL_ADDR;
							tx[2] = uart_rx_buffer[1];
							tx[3] = uart_rx_buffer[3];
							tx[4] = 0x01;
							tx[5] = 0x00;
							tx[6] = 0x01;
							tx[7] = 0x01;
							OpFlag.bRelay_Config_Change = ON;
							break;
							
						case PROTOCOL_MESSAGE_CONFIG_BRIDGE_RELAY_OUTPUT:
							Module_Info.Relay_IO.All = (((uint64_t)uart_rx_buffer[11] << 40) | ((uint64_t)uart_rx_buffer[10] << 32) | ((uint64_t)uart_rx_buffer[9]<< 24) |
														((uint64_t)uart_rx_buffer[8] << 16)  | ((uint64_t)uart_rx_buffer[7] << 8)   | ((uint64_t)uart_rx_buffer[6])); 														
							tx_len = 8;		
							tx[0] = 0xaa;
							tx[1] = PROTOCOL_ADDR;
							tx[2] = uart_rx_buffer[1];
							tx[3] = uart_rx_buffer[3];
							tx[4] = 0x01;
							tx[5] = 0x00;
							tx[6] = 0x01;
							tx[7] = 0x01;
							OpFlag.bRelay_Config_Change = ON;
							break;	
						case PROTOCOL_MESSAGE_CONFIG_GPIO_OUTPUT:
							Module_Info.Gpio_status.All = uart_rx_buffer[6];
							tx_len = 8;
							tx[0] = 0xaa;
							tx[1] = PROTOCOL_ADDR;
							tx[2] = uart_rx_buffer[1];
							tx[3] = PROTOCOL_MESSAGE_CONFIG_GPIO_OUTPUT;
							tx[4] = 0x01;
							tx[5] = 0x00;
							tx[6] = 0x01;
							tx[7] = 0x01;

							break;
						case PROTOCOL_MESSAGE_CONFIG_SN:
							for (int idx = 0; idx < ((uart_rx_buffer[4] | uart_rx_buffer[5] << 8) >> 1); idx++)
								Module_Info.SN[idx] = uart_rx_buffer[(idx + 6)];

							tx_len = 8;
							tx[0] = 0xaa;
							tx[1] = PROTOCOL_ADDR;
							tx[2] = uart_rx_buffer[1];
							tx[3] = PROTOCOL_MESSAGE_CONFIG_SN;
							tx[4] = 0x01;
							tx[5] = 0x00;
							tx[6] = 0x01;
							tx[7] = 0x01;

							break;
						case PROTOCOL_MESSAGE_CONFIG_GFD_VALUE:
							tx_len = 8;
							tx[0] = 0xaa;
							tx[1] = PROTOCOL_ADDR;
							tx[2] = uart_rx_buffer[1];
							tx[3] = PROTOCOL_MESSAGE_CONFIG_GFD_VALUE;
							tx[4] = 0x01;
							tx[5] = 0x00;
							tx[6] = 0x01;
							switch (uart_rx_buffer[6])
							{
							case 0: // Left gun
								Module_Info.gfd_chk[0].Csu_State = uart_rx_buffer[7];
								tx[7] = 0x01;
								break;
							case 1: // Right gun
								Module_Info.gfd_chk[1].Csu_State = uart_rx_buffer[7];
								tx[7] = 0x01;
								break;
							default:
								Module_Info.gfd_chk[0].Csu_State = 0;
								Module_Info.gfd_chk[1].Csu_State = 0;
								tx[7] = 0x00;
								break;
							}
							break;
						case PROTOCOL_MESSAGE_CONFIG_GFD_MODE:                                                                                                                                        
            	                tx_len = 8;            
            	                tx[0] = 0xaa;
            	                tx[1] = PROTOCOL_ADDR;
            	                tx[2] = uart_rx_buffer[1];
            	                tx[3] = PROTOCOL_MESSAGE_CONFIG_GFD_MODE;
            	                tx[4] = 0x01;
            	                tx[5] = 0x00;
            	                tx[6] = 0x01;
            	                switch(uart_rx_buffer[6])
            	                {
            	                    case 0:			// Left gun
            	                        Gfd.GfdMode[0] = uart_rx_buffer[7];
            	                        tx[7] = 0x01;
										if(Gfd.GfdOldMode[0] != Gfd.GfdMode[0]){
											Gfd.GfdOldMode[0] = Gfd.GfdMode[0];

											if(Gfd.GfdMode[0] !=0){
												printf("Set SMR1 GFD Mode : %s\n\r", Gfd.GfdMode[0] == GFD_BALANCE ? "Balance" : "Unbalance");
											}else{
												printf("Set SMR1 GFD Mode : OFF\n\r");	
											}
										}	
            	                        break;
            	                    case 1:			// Right gun
            	                        Gfd.GfdMode[1] = uart_rx_buffer[7];
            	                        tx[7] = 0x01;

										if(Gfd.GfdOldMode[1] != Gfd.GfdMode[1]){
											Gfd.GfdOldMode[1] = Gfd.GfdMode[1];

											if(Gfd.GfdMode[1] !=0){
												printf("Set SMR2 GFD Mode : %s\n\r", Gfd.GfdMode[1] == GFD_BALANCE ? "Balance" : "Unbalance");
											}else{
												printf("Set SMR2 GFD Mode : OFF\n\r");	
											}
										}	
            	                        break;
            	                    default:
            	                        Module_Info.gfd_chk[0].Csu_State = 0;
            	                        Module_Info.gfd_chk[1].Csu_State = 0;
            	                        tx[7] = 0x00;
            	                        break;
            	                }
            	                break;		
						case PROTOCOL_MESSAGE_CONFIG_RUN_SELF_TEST:
							tx_len = 8;
							tx[0] = 0xaa;
							tx[1] = PROTOCOL_ADDR;
							tx[2] = uart_rx_buffer[1];
							tx[3] = PROTOCOL_MESSAGE_CONFIG_RUN_SELF_TEST;
							tx[4] = 1;
							tx[5] = 0;
							tx[6] = sf_t.SF_Config.SF_Act = 1;
							tx[7] = 1;

							sf_t.SF_Config.SF_State = 0;
							sf_t.SF_Config.data.value = 0;
							sf_t.SF_Config.SF_test_status = 2; // Unknow
							break;
						case PROTOCOL_MESSAGE_CONFIG_PARAMETER:
							tx_len = 8;
							tx[0] = 0xaa;
							tx[1] = PROTOCOL_ADDR;
							tx[2] = uart_rx_buffer[1];
							tx[3] = PROTOCOL_MESSAGE_CONFIG_PARAMETER;
							tx[4] = 0x01;
							tx[5] = 0x00;
							tx[6] = 0x01;

							// Default the result.

							tx[7] = 0x01;
							temp = uart_rx_buffer[8] | (uart_rx_buffer[9] << 8);

							switch (uart_rx_buffer[6])
							{
							case Input_L1_AC_voltage:
								switch (uart_rx_buffer[7])
								{
								case 1:
									Module_Info.memory.Module_Config.data.item.Correction_Volt[0][METER_DATA] = temp;
									Module_Info.memory.Module_Config.data.item.Correction_Volt[0][MCU_DATA] = adc_value.ADC2_IN0.value / 10;
									break;
								case 2:
									Module_Info.memory.Module_Config.data.item.Correction_Volt[1][METER_DATA] = temp;
									Module_Info.memory.Module_Config.data.item.Correction_Volt[1][MCU_DATA] = adc_value.ADC2_IN0.value / 10;
									break;
								case 3:
									Module_Info.memory.Module_Config.data.item.Correction_Volt[2][METER_DATA] = temp;
									Module_Info.memory.Module_Config.data.item.Correction_Volt[2][MCU_DATA] = adc_value.ADC2_IN0.value / 10;
									break;									
								case 10:
									Module_Info.memory.Module_Config.op_bits.read = ON;
									break;
								default:
									break;
								}
								break;
							case Input_L2_AC_voltage:
								switch (uart_rx_buffer[7])
								{
								case 1:
									Module_Info.memory.Module_Config.data.item.Correction_Volt[3][METER_DATA] = temp;
									Module_Info.memory.Module_Config.data.item.Correction_Volt[3][MCU_DATA] = adc_value.ADC2_IN1.value / 10;
									break;
								case 2:
									Module_Info.memory.Module_Config.data.item.Correction_Volt[4][METER_DATA] = temp;
									Module_Info.memory.Module_Config.data.item.Correction_Volt[4][MCU_DATA] = adc_value.ADC2_IN1.value / 10;
									break;
								case 3:
									Module_Info.memory.Module_Config.data.item.Correction_Volt[5][METER_DATA] = temp;
									Module_Info.memory.Module_Config.data.item.Correction_Volt[5][MCU_DATA] = adc_value.ADC2_IN1.value / 10;
									break;
								default:
									break;
								}
								break;
							case Input_L3_AC_voltage:
								switch (uart_rx_buffer[7])
								{
								case 1:
									Module_Info.memory.Module_Config.data.item.Correction_Volt[6][METER_DATA] = temp;
									Module_Info.memory.Module_Config.data.item.Correction_Volt[6][MCU_DATA] = adc_value.ADC2_IN2.value / 10;
									break;
								case 2:
									Module_Info.memory.Module_Config.data.item.Correction_Volt[7][METER_DATA] = temp;
									Module_Info.memory.Module_Config.data.item.Correction_Volt[7][MCU_DATA] = adc_value.ADC2_IN2.value / 10;
									break;
								case 3:
									Module_Info.memory.Module_Config.data.item.Correction_Volt[8][METER_DATA] = temp;
									Module_Info.memory.Module_Config.data.item.Correction_Volt[8][MCU_DATA] = adc_value.ADC2_IN2.value / 10;
									break;
								default:
									break;
								}
								break;
								
							case SMR1_output_voltage:
								switch (uart_rx_buffer[7])
								{
								case 1:
									Module_Info.memory.Module_Config.data.item.DC_Correction_Volt[0][METER_DATA] = temp;
									Module_Info.memory.Module_Config.data.item.DC_Correction_Volt[0][MCU_DATA] = (uint16_t)((double)adc_value.ADC1_IN0.value * vsense1 / 10.0);
									break;
								case 2:
									Module_Info.memory.Module_Config.data.item.DC_Correction_Volt[1][METER_DATA] = temp;
									Module_Info.memory.Module_Config.data.item.DC_Correction_Volt[1][MCU_DATA] = (uint16_t)((double)adc_value.ADC1_IN0.value * vsense1 / 10.0);
									break;
								// reset coefficient to orginal.
								case 9:		
									Module_Info.DCVcoeff[0].gain_volt = 1;
									Module_Info.DCVcoeff[0].offset_volt = 0;
									break;
								case 10:
									Module_Info.memory.Module_Config.op_bits.read = ON;
									break;
								default:
									break;
								}
								break;
							case SMR2_output_voltage:
								switch (uart_rx_buffer[7])
								{
								case 1:
									Module_Info.memory.Module_Config.data.item.DC_Correction_Volt[2][METER_DATA] = temp;
									Module_Info.memory.Module_Config.data.item.DC_Correction_Volt[2][MCU_DATA] = (uint16_t)((double)adc_value.ADC1_IN2.value * vsense1 / 10.0);
									break;
								case 2:
									Module_Info.memory.Module_Config.data.item.DC_Correction_Volt[3][METER_DATA] = temp;
									Module_Info.memory.Module_Config.data.item.DC_Correction_Volt[3][MCU_DATA] = (uint16_t)((double)adc_value.ADC1_IN2.value * vsense1 / 10.0);
									break;
								// reset coefficient to orginal.
								case 9:
									Module_Info.DCVcoeff[1].gain_volt = 1;
									Module_Info.DCVcoeff[1].offset_volt = 0;
									break;
								case 10:
									Module_Info.memory.Module_Config.op_bits.read = ON;
									break;
								default:
									break;
								}
								break;
							case SMR3_output_voltage:
								switch (uart_rx_buffer[7])
								{
								case 1:
									Module_Info.memory.Module_Config.data.item.DC_Correction_Volt[4][METER_DATA] = temp;
									Module_Info.memory.Module_Config.data.item.DC_Correction_Volt[4][MCU_DATA] = (uint16_t)((double)adc_value.ADC1_IN5.value * vsense1 / 10.0);
									break;
								case 2:
									Module_Info.memory.Module_Config.data.item.DC_Correction_Volt[5][METER_DATA] = temp;
									Module_Info.memory.Module_Config.data.item.DC_Correction_Volt[5][MCU_DATA] = (uint16_t)((double)adc_value.ADC1_IN5.value * vsense1 / 10.0);
									break;
								// reset coefficient to orginal.
								case 9:
									Module_Info.DCVcoeff[2].gain_volt = 1;
									Module_Info.DCVcoeff[2].offset_volt = 0;
									break;
								case 10:
									Module_Info.memory.Module_Config.op_bits.read = ON;
									break;
								default:
									break;
								}
								break;	
							case SMR4_output_voltage:
								switch (uart_rx_buffer[7])
								{
								case 1:
									Module_Info.memory.Module_Config.data.item.DC_Correction_Volt[6][METER_DATA] = temp;
									Module_Info.memory.Module_Config.data.item.DC_Correction_Volt[6][MCU_DATA] = (uint16_t)((double)adc_value.ADC1_IN6.value * vsense1 / 10.0);
									break;
								case 2:
									Module_Info.memory.Module_Config.data.item.DC_Correction_Volt[7][METER_DATA] = temp;
									Module_Info.memory.Module_Config.data.item.DC_Correction_Volt[7][MCU_DATA] = (uint16_t)((double)adc_value.ADC1_IN6.value * vsense1 / 10.0);
									break;
								// reset coefficient to orginal.
								case 9:
									Module_Info.DCVcoeff[3].gain_volt = 1;
									Module_Info.DCVcoeff[3].offset_volt = 0;
									break;
								case 10:
									Module_Info.memory.Module_Config.op_bits.read = ON;
									break;
								default:
									break;
								}
								break;	
							case SMR5_output_voltage:
								switch (uart_rx_buffer[7])
								{
								case 1:
									Module_Info.memory.Module_Config.data.item.DC_Correction_Volt[8][METER_DATA] = temp;
									Module_Info.memory.Module_Config.data.item.DC_Correction_Volt[8][MCU_DATA] = (uint16_t)((double)adc_value.ADC1_IN7.value * vsense1 / 10.0);
									break;
								case 2:
									Module_Info.memory.Module_Config.data.item.DC_Correction_Volt[9][METER_DATA] = temp;
									Module_Info.memory.Module_Config.data.item.DC_Correction_Volt[9][MCU_DATA] = (uint16_t)((double)adc_value.ADC1_IN7.value * vsense1 / 10.0);
									break;
								// reset coefficient to orginal.
								case 9:
									Module_Info.DCVcoeff[4].gain_volt = 1;
									Module_Info.DCVcoeff[4].offset_volt = 0;
									break;
								case 10:
									Module_Info.memory.Module_Config.op_bits.read = ON;
									break;
								default:
									break;
								}
								break;	
							case SMR6_output_voltage:
								switch (uart_rx_buffer[7])
								{
								case 1:
									Module_Info.memory.Module_Config.data.item.DC_Correction_Volt[10][METER_DATA] = temp;
									Module_Info.memory.Module_Config.data.item.DC_Correction_Volt[10][MCU_DATA] = (uint16_t)((double)adc_value.ADC1_IN8.value * vsense1 / 10.0);
									break;
								case 2:
									Module_Info.memory.Module_Config.data.item.DC_Correction_Volt[11][METER_DATA] = temp;
									Module_Info.memory.Module_Config.data.item.DC_Correction_Volt[11][MCU_DATA] = (uint16_t)((double)adc_value.ADC1_IN8.value * vsense1 / 10.0);
									break;
								// reset coefficient to orginal.
								case 9:
									Module_Info.DCVcoeff[5].gain_volt = 1;
									Module_Info.DCVcoeff[5].offset_volt = 0;
									break;
								case 10:
									Module_Info.memory.Module_Config.op_bits.read = ON;
									break;
								default:
									break;
								}
								break;	
							case GFD_Resister_Left:
								switch (uart_rx_buffer[7])
								{
								case 1:
									Module_Info.memory.Module_Config.data.item.GFD_Correction_Resistor[0][METER_DATA] = temp;
									Module_Info.memory.Module_Config.data.item.GFD_Correction_Resistor[0][MCU_DATA] = Module_Info.gfd_chk[0].R_GFD_v / 100;
									break;
								case 2:
									Module_Info.memory.Module_Config.data.item.GFD_Correction_Resistor[1][METER_DATA] = temp;
									Module_Info.memory.Module_Config.data.item.GFD_Correction_Resistor[1][MCU_DATA] = Module_Info.gfd_chk[0].R_GFD_v / 100;
									break;
								case 9:									
									bGfd_Correct[0] = 1;
									Module_Info.GFDcoeff[0].gain_volt = 1;
									Module_Info.GFDcoeff[0].offset_volt = 0;
									break;
								case 10:
									Module_Info.memory.Module_Config.op_bits.read = ON;
									break;
								case 11:
									bGfd_Correct[0] = 1;
									break;
								default:
									break;
								}
								break;
							case GFD_Resister_Right:
								switch (uart_rx_buffer[7])
								{
								case 1:
									Module_Info.memory.Module_Config.data.item.GFD_Correction_Resistor[2][METER_DATA] = temp;
									Module_Info.memory.Module_Config.data.item.GFD_Correction_Resistor[2][MCU_DATA] = Module_Info.gfd_chk[1].R_GFD_v / 100;
									break;
								case 2:
									Module_Info.memory.Module_Config.data.item.GFD_Correction_Resistor[3][METER_DATA] = temp;
									Module_Info.memory.Module_Config.data.item.GFD_Correction_Resistor[3][MCU_DATA] = Module_Info.gfd_chk[1].R_GFD_v / 100;
									break;
								case 9:
									bGfd_Correct[1] = 1;
									Module_Info.GFDcoeff[1].gain_volt = 1;
									Module_Info.GFDcoeff[1].offset_volt = 0;
									break;
								case 10:
									Module_Info.memory.Module_Config.op_bits.read = ON;
									break;
								case 11:
									bGfd_Correct[1] = 1;
									break;
								default:
									break;
								}
								break;		
							case Battery1_input_voltage:
								switch(uart_rx_buffer[7])
								{								
									
									case 1:
										Module_Info.memory.Module_Config.data.item.DCIn_Correction_Volt[0][METER_DATA] = temp;
										Module_Info.memory.Module_Config.data.item.DCIn_Correction_Volt[0][MCU_DATA] = (uint16_t) ((double)adc_value.ADC3_IN8.value * vsense1 / 10.0);
										break;
									case 2:
										Module_Info.memory.Module_Config.data.item.DCIn_Correction_Volt[1][METER_DATA] = temp;
										Module_Info.memory.Module_Config.data.item.DCIn_Correction_Volt[1][MCU_DATA] = (uint16_t) ((double)adc_value.ADC3_IN8.value * vsense1 / 10.0);
										break;
									// reset coefficient to orginal.
									case 9:		
										Module_Info.DCINcoeff.gain_volt = 1;
										Module_Info.DCINcoeff.offset_volt = 0;
										break;
									case 10:
										Module_Info.memory.Module_Config.op_bits.read = ON;
										break;
									default:
										break;
								}
								break;						
							}
							Module_Info.memory.Module_Config.op_bits.update = ON;
							break;
						/*-----------------------------------------
							Firmware update message
						------------------------------------------*/
						case PROTOCOL_MESSAGE_UPGRADE_START:
							tx_len = 8;
							tx[0] = 0xaa;
							tx[1] = PROTOCOL_ADDR;
							tx[2] = uart_rx_buffer[1];
							tx[3] = PROTOCOL_MESSAGE_UPGRADE_START;
							tx[4] = 0x01;
							tx[5] = 0x00;

							// binCRCTarget = (uart_rx_buffer[6] << 24) | (uart_rx_buffer[6] << 16) | (uart_rx_buffer[6] << 8) | (uart_rx_buffer[6] << 0);
							flashdestination = NEW_CODE_ADDRESS;
							if (FLASH_If_Erase(ADDR_FLASH_SECTOR_9, 3) == FLASHIF_OK)
							{
#if defined(DEBUG) || defined(RTOS_STAT)
								// DEBUG_INFO("Firmware transfer start, earase flash success....\n\r");
#endif
								tx[6] = 0x01;
								tx[7] = 0x01;
							}
							else
							{
#if defined(DEBUG) || defined(RTOS_STAT)
// DEBUG_INFO("Firmware transfer start, earase flash fail....\n\r");
#endif
								tx[6] = 0x00;
								tx[7] = 0x00;
							}

							break;
						case PROTOCOL_MESSAGE_UPGRADE_TRANS:
							tx_len = 8;
							tx[0] = 0xaa;
							tx[1] = PROTOCOL_ADDR;
							tx[2] = uart_rx_buffer[1];
							tx[3] = PROTOCOL_MESSAGE_UPGRADE_TRANS;
							tx[4] = 0x01;
							tx[5] = 0x00;

							flashdestination = NEW_CODE_ADDRESS + ((uart_rx_buffer[6] << 0) | (uart_rx_buffer[7] << 8) | (uart_rx_buffer[8] << 16) | (uart_rx_buffer[9] << 24));
							if (FLASH_If_Write(flashdestination, (uint32_t *)&uart_rx_buffer[10], ((((uart_rx_buffer[4]) | (uart_rx_buffer[5]) << 8) - 4) >> 2)) == FLASHIF_OK)
							{
#if defined(DEBUG) || defined(RTOS_STAT)
								// DEBUG_INFO("Firmware transfer start address, length:0x%x, %d...Pass\n\r", flashdestination, (((uart_rx_buffer[4]) | (uart_rx_buffer[5])<<8)-4));
#endif
								tx[6] = 0x01;
								tx[7] = 0x01;
							}
							else
							{
#if defined(DEBUG) || defined(RTOS_STAT)
								// DEBUG_INFO("Firmware transfer start address, length:0x%x, %d...Fail\n\r", flashdestination, (((uart_rx_buffer[4]) | (uart_rx_buffer[5])<<8)-4));
#endif
								tx[6] = 0x00;
								tx[7] = 0x00;
							}

							break;
						case PROTOCOL_MESSAGE_UPGRADE_STOP:
							tx_len = 8;
							tx[0] = 0xaa;
							tx[1] = PROTOCOL_ADDR;
							tx[2] = uart_rx_buffer[1];
							tx[3] = PROTOCOL_MESSAGE_UPGRADE_STOP;
							tx[4] = 0x01;
							tx[5] = 0x00;

							flash = NEW_CODE_ADDRESS;
							crc32 = HAL_CRC_Calculate(&hcrc, (uint32_t *)flash, ((FLASH_AP_LENGTH - 4) >> 2));
							flash = ((uint32_t)(NEW_CODE_ADDRESS + FLASH_AP_LENGTH - 4));
#if defined(DEBUG) || defined(RTOS_STAT)
							// DEBUG_INFO("Firmware transfer end, AP CRC crc32, flash: 0x%x, 0x%x\r\n", crc32, *((uint32_t *)flash) );
#endif
							if (crc32 == *((uint32_t *)flash))
							{
								if (FLASH_If_Write(UPGRADE_REQ_ADDRESS, (uint32_t *)&endFlag[0], 1) == FLASHIF_OK)
								{
#if defined(DEBUG) || defined(RTOS_STAT)
									// DEBUG_INFO("Firmware Confirm Tag write ok..\n\r");
#endif
									tx[6] = 0x01;
									tx[7] = 0x01;

									HAL_GPIO_WritePin(RS485_DE_GPIO_Port, RS485_DE_Pin, GPIO_PIN_SET);
									osDelay(2);
									HAL_UART_Transmit(&IAP_USART, (uint8_t *)tx, tx_len, 0xffff);
									osDelay(2);
									HAL_GPIO_WritePin(RS485_DE_GPIO_Port, RS485_DE_Pin, GPIO_PIN_RESET);

									osDelay(100);
									NVIC_SystemReset();
								}
								else
								{
#if defined(DEBUG) || defined(RTOS_STAT)
									// DEBUG_INFO("Firmware Confirm Tag write fail...\n\r");
#endif
									tx[6] = 0x00;
									tx[7] = 0x00;
								}
							}
							else
							{
#if defined(DEBUG) || defined(RTOS_STAT)
								// DEBUG_INFO("Firmware crc32 compare fail...\n\r");
#endif
								tx[6] = 0x00;
								tx[7] = 0x00;
							}
							break;

						case PROTOCOL_MESSAGE_UPGRADE_ABOARD:
#if defined(DEBUG) || defined(RTOS_STAT)
							// DEBUG_INFO("Firmware update transfer aboard...\n\r");
#endif

							tx_len = 8;
							tx[0] = 0xaa;
							tx[1] = PROTOCOL_ADDR;
							tx[2] = uart_rx_buffer[1];
							tx[3] = PROTOCOL_MESSAGE_UPGRADE_ABOARD;
							tx[4] = 0x01;
							tx[5] = 0x00;
							tx[6] = 0x01;
							tx[7] = 0x01;
							break;

						default:
/* Todo: bin file receive aboard */
#if defined(DEBUG) || defined(RTOS_STAT)
							// DEBUG_INFO("Protocol message unknow...\n\r");
#endif
							tx_len = 8;
							tx[0] = 0xaa;
							tx[1] = PROTOCOL_ADDR;
							tx[2] = uart_rx_buffer[1];
							tx[3] = uart_rx_buffer[3];
							tx[4] = 0x01;
							tx[5] = 0x00;
							tx[6] = 0x00;
							tx[7] = 0x00;

							break;
						}
					}
					else
					{
#if defined(DEBUG) || defined(RTOS_STAT)
						// DEBUG_INFO("Protocol check sum is wrong...\n\r");
#endif
						tx_len = 8;
						tx[0] = 0xaa;
						tx[1] = PROTOCOL_ADDR;
						tx[2] = uart_rx_buffer[1];
						tx[3] = uart_rx_buffer[3];
						tx[4] = 0x01;
						tx[5] = 0x00;
						tx[6] = 0x00;
						tx[7] = 0x00;
					}
					HAL_GPIO_WritePin(RS485_DE_GPIO_Port, RS485_DE_Pin, GPIO_PIN_SET);
					osDelay(2);
					HAL_UART_Transmit(&IAP_USART, (uint8_t *)tx, tx_len, 0xffff);
					osDelay(2);
					HAL_GPIO_WritePin(RS485_DE_GPIO_Port, RS485_DE_Pin, GPIO_PIN_RESET);

					for (int i = 0; i < uart_rx_len; i++)
						uart_rx_buffer[i] = 0;

					uart_rx_len = 0;
				}
				uart_recv_end_flag = 0;						
				HAL_UART_Receive_DMA(&IAP_USART, uart_rx_buffer, UART_BUFFER_SIZE);		
			}
		osDelay(1);
	}
  /* USER CODE END Uart1Task */
}

/* USER CODE BEGIN Header_Adc1Task */
/**
 * @brief Function implementing the adc1Task thread.
 * @param argument: Not used
 * @retval None
 */
/* USER CODE END Header_Adc1Task */
void Adc1Task(void const * argument)
{
  /* USER CODE BEGIN Adc1Task */
	uint16_t i;

	/* Infinite loop */
	for (;;)	
  	{
		if(bADC1_Done)
		{
			bADC1_Done = OFF;	
		
			for	(i = 0;i < ADC1_CHANEL_COUNT;i++)
			{
				ADC1_Value[i] = 0;
			}

			for (i = 0; i < (ADC1_CHANEL_COUNT * ADC1_SAMPLE_COUNT);)
			{
				ADC1_Value[0] += ADC1_Buf[i++];
				ADC1_Value[1] += ADC1_Buf[i++];
				ADC1_Value[2] += ADC1_Buf[i++];
				ADC1_Value[3] += ADC1_Buf[i++];
				ADC1_Value[4] += ADC1_Buf[i++];
				ADC1_Value[5] += ADC1_Buf[i++];
				ADC1_Value[6] += ADC1_Buf[i++];
				ADC1_Value[7] += ADC1_Buf[i++];
				ADC1_Value[8] += ADC1_Buf[i++];
			}

			for	(i = 0;i < ADC1_CHANEL_COUNT;i++)
			{
				ADC1_Value[i] /= ADC1_SAMPLE_COUNT;
			}

			HAL_ADC_Start_DMA(&hadc1, ADC1_Buf, (ADC1_SAMPLE_COUNT * ADC1_CHANEL_COUNT));				

			// Smooth Filter
			adc_filter_move_avg(&adc_value.ADC1_IN0, ADC1_Value[0]);
			adc_filter_move_avg(&adc_value.ADC1_IN1, ADC1_Value[1]);
			adc_filter_move_avg(&adc_value.ADC1_IN2, ADC1_Value[2]);		
			adc_filter_move_avg(&adc_value.ADC1_IN3, ADC1_Value[3]);
			adc_filter_move_avg(&adc_value.ADC1_IN4, ADC1_Value[4]);
			adc_filter_move_avg(&adc_value.ADC1_IN5, ADC1_Value[5]);
			adc_filter_move_avg(&adc_value.ADC1_IN6, ADC1_Value[6]);
			adc_filter_move_avg(&adc_value.ADC1_IN7, ADC1_Value[7]);
			adc_filter_move_avg(&adc_value.ADC1_IN8, ADC1_Value[8]);

			// output result

			Module_Info.SMR1_Relay_V = (uint32_t)(((double)adc_value.ADC1_IN0.value * vsense1 * Module_Info.DCVcoeff[0].gain_volt) + Module_Info.DCVcoeff[0].offset_volt) / 10;
			Module_Info.SMR2_Relay_V = (uint32_t)(((double)adc_value.ADC1_IN2.value * vsense1 * Module_Info.DCVcoeff[1].gain_volt) + Module_Info.DCVcoeff[1].offset_volt) / 10;
			Module_Info.SMR3_Relay_V = (uint32_t)(((double)adc_value.ADC1_IN5.value * vsense1 * Module_Info.DCVcoeff[2].gain_volt) + Module_Info.DCVcoeff[2].offset_volt) / 10;
			Module_Info.SMR4_Relay_V = (uint32_t)(((double)adc_value.ADC1_IN6.value * vsense1 * Module_Info.DCVcoeff[3].gain_volt) + Module_Info.DCVcoeff[3].offset_volt) / 10;
			Module_Info.SMR5_Relay_V = (uint32_t)(((double)adc_value.ADC1_IN7.value * vsense1 * Module_Info.DCVcoeff[4].gain_volt) + Module_Info.DCVcoeff[4].offset_volt) / 10;
			Module_Info.SMR6_Relay_V = (uint32_t)(((double)adc_value.ADC1_IN8.value * vsense1 * Module_Info.DCVcoeff[5].gain_volt) + Module_Info.DCVcoeff[5].offset_volt) / 10;

			
			c_vadc[0] = (float)(adc_value.ADC1_IN1.value * v_div);
			c_vadc[1] = (float)(adc_value.ADC1_IN3.value * v_div);

			Module_Info.SMR1_Relay_C = (uint32_t)(c_vadc[0] * vsense3) / 10;
			Module_Info.SMR2_Relay_C = (uint32_t)(c_vadc[1] * vsense3) / 10;
			//    }

			Module_Info.Vref_165 = (float)(adc_value.ADC1_IN4.value * v_div);
		}	
			osDelay(1);
	}
  /* USER CODE END Adc1Task */
}

/* USER CODE BEGIN Header_Adc2Task */
/**
 * @brief Function implementing the adc2Task thread.
 * @param argument: Not used
 * @retval None
 */
/* USER CODE END Header_Adc2Task */
void Adc2Task(void const * argument)
{
  /* USER CODE BEGIN Adc2Task */
	uint16_t i, j;

	/* Infinite loop */
	for (;;)
	{
		// AC_Contactor off, will stop AC Converstion Calcuate.
		// because of AC_Contactor on/off, the AC_Value will be wrong (746v).
		// Sense 3-Phases voltage before AC-Contracor.

		if (bADC2_Done)
		{
			for (i = 0, j = 0; i < (ADC2_CHANEL_COUNT * ADC2_SAMPLE_COUNT); i += ADC2_CHANEL_COUNT)
			{
				L1_ADC_Each_Value[j] = ADC2_Buf[(i + 0)];
				L2_ADC_Each_Value[j] = ADC2_Buf[(i + 1)];
				L3_ADC_Each_Value[j] = ADC2_Buf[(i + 2)];
				j++;
			}

			HAL_ADC_Start_DMA(&hadc2, ADC2_Buf, (ADC2_SAMPLE_COUNT * ADC2_CHANEL_COUNT));

			ADCSineCalculate2(L1_ADC_Each_Value, ADC2_SAMPLE_COUNT, 212, &AC_Sine[0], vsense2, 0);
			ADCSineCalculate2(L2_ADC_Each_Value, ADC2_SAMPLE_COUNT, 212, &AC_Sine[1], vsense2, 1);
			ADCSineCalculate2(L3_ADC_Each_Value, ADC2_SAMPLE_COUNT, 212, &AC_Sine[2], vsense2, 2);

			// smooth filter
			adc_filter_move_avg(&adc_value.ADC2_IN0, AC_Sine[0].Vrms);
			adc_filter_move_avg(&adc_value.ADC2_IN1, AC_Sine[1].Vrms);
			adc_filter_move_avg(&adc_value.ADC2_IN2, AC_Sine[2].Vrms);

			// Patch the AC_GAIN

			for (i = 0; i < 3; i++)
			{
				switch (i)
				{
				case 0:
					AC_Sine[i].Vrms_AVG = acVolCalWithGain((adc_value.ADC2_IN0.value / 10), i);
					break;
				case 1:
					AC_Sine[i].Vrms_AVG = acVolCalWithGain((adc_value.ADC2_IN1.value / 10), i);
					break;
				case 2:
					AC_Sine[i].Vrms_AVG = acVolCalWithGain((adc_value.ADC2_IN2.value / 10), i);
					break;
				default:

					break;
				}
			}

			// worng filiter
			for (i = 0; i < 3; i++)
			{
				if (AC_Sine[i].Vrms_AVG >= 6000)
					AC_Sine[i].Vrms_AVG = 0;
			}

			// Buffer clean
			//        memset(&ADC2_Buf[0], 0x00, ADC2_CHANEL_COUNT * ADC2_SAMPLE_COUNT);
			//        memset(&L1_ADC_Each_Value[0], 0x00, ADC2_SAMPLE_COUNT);
			//        memset(&L2_ADC_Each_Value[0], 0x00, ADC2_SAMPLE_COUNT);
			//        memset(&L3_ADC_Each_Value[0], 0x00, ADC2_SAMPLE_COUNT);

			// DMA restart
			bADC2_Done = OFF;
		}
		osDelay(1);
	}
  /* USER CODE END Adc2Task */
}

/* USER CODE BEGIN Header_Adc3Task */
/**
 * @brief Function implementing the adc3Task thread.
 * @param argument: Not used
 * @retval None
 */
/* USER CODE END Header_Adc3Task */
void Adc3Task(void const * argument)
{
  /* USER CODE BEGIN Adc3Task */
	/* Infinite loop */

	//   Fail   : <= 100ohm * 950v = 95K ohm
	//  Warning : <= 475K ohm & > 95K ohm
	//   Pass   : > 500ohm * 950v = 475K ohm

for (;;)
{
	float temp[2];
  	uint16_t i;
	uint8_t		gunindex;  	
	uint32_t 	Relay_V;
	// uint32_t 	R_GFD_Total[2];
   
  	if(bADC3_Done)
  	{  	
		bADC3_Done = OFF;		
		for(i = 0, ADC3_Value[0]=0, ADC3_Value[1]=0, ADC3_Value[2]=0; i < (ADC3_CHANEL_COUNT*ADC3_SAMPLE_COUNT); )
		{
			ADC3_Value[0] += ADC3_Buf[i++];
			ADC3_Value[1] += ADC3_Buf[i++];
			ADC3_Value[2] += ADC3_Buf[i++];
		}
		ADC3_Value[0] /= ADC3_SAMPLE_COUNT;     //  GFD 1
		ADC3_Value[1] /= ADC3_SAMPLE_COUNT;     //  GFD 2
		ADC3_Value[2] /= ADC3_SAMPLE_COUNT;     //  Bat_Voltage	

		HAL_ADC_Start_DMA(&hadc3, ADC3_Buf, (ADC3_SAMPLE_COUNT * ADC3_CHANEL_COUNT));	
		
		// Smooth Filter
		adc_filter_move_avg(&adc_value.ADC3_IN8, ADC3_Value[2]);
		
		Module_Info.BAT_Voltage = (uint32_t) (((double)adc_value.ADC3_IN8.value * vsense1
    		* Module_Info.DCINcoeff.gain_volt) + Module_Info.DCINcoeff.offset_volt) / 10; 
	
		for(gunindex = 0 ; gunindex < 2 ; gunindex++){

			if(gunindex == 0)
				Relay_V = Module_Info.SMR1_Relay_V;
			else
				Relay_V = Module_Info.SMR2_Relay_V;	

			if(Gfd.operation[gunindex] == GFD_BALANCE && Gfd.SCBwaitfg[gunindex] == 0){
				
				if(Module_Info.gfd_chk[gunindex].Csu_State != IDLE || bGfd_Correct[gunindex] == 1){
					
					Module_Info.SMR_Gfd_Sense[gunindex] =(float) ADC3_Value[gunindex] * v_div;	  

					if(Gfd.GfdAvgCount[gunindex] < 2){ 	
						Gfd.TotalGFDvalue[gunindex] += Module_Info.SMR_Gfd_Sense[gunindex];
						Gfd.Gfdcount[gunindex]++;
					}else{
						if(Gfd.Gfdcount[gunindex] > Gfd.maxcount[gunindex])
							Gfd.maxcount[gunindex] = Gfd.Gfdcount[gunindex];

						if(Gfd.Gfdcount[gunindex] < Gfd.mincount[gunindex])
							Gfd.mincount[gunindex] = Gfd.Gfdcount[gunindex];	

						if(Gfd.TotalGFDvalue[gunindex] > Gfd.maxgfdcount[gunindex])
							Gfd.maxgfdcount[gunindex] = Gfd.TotalGFDvalue[gunindex];		

						if(Gfd.TotalGFDvalue[gunindex] < Gfd.mingfdcount[gunindex])
							Gfd.mingfdcount[gunindex] = Gfd.TotalGFDvalue[gunindex];		
							
						
						Module_Info.SMR_Gfd_Sense[gunindex] = Gfd.TotalGFDvalue[gunindex] / Gfd.Gfdcount[gunindex];	
						Gfd.TotalGFDvalue[gunindex] = 0;
						Gfd.Gfdcount[gunindex] = 0;	
						Gfd.GfdAvgCount[gunindex] = 0;					
					}					
					
					if(Relay_V > GFD_WORKING_VOLTAGE)		//  > 50v
					{		
						if(Gfd.UpBridgeMaxV[gunindex] == 0){
						Gfd.UpBridgeMaxV[gunindex] = Module_Info.SMR_Gfd_Sense[gunindex];
						}
						if(Gfd.UpBridgeMinV[gunindex] == 0){
						Gfd.UpBridgeMinV[gunindex] = Module_Info.SMR_Gfd_Sense[gunindex];
						}
						if(Module_Info.SMR_Gfd_Sense[gunindex] > Gfd.UpBridgeMaxV[gunindex]){
							Gfd.UpBridgeMaxV[gunindex] = Module_Info.SMR_Gfd_Sense[gunindex];
						}
						if(Module_Info.SMR_Gfd_Sense[gunindex] < Gfd.UpBridgeMinV[gunindex]){
							Gfd.UpBridgeMinV[gunindex] = Module_Info.SMR_Gfd_Sense[gunindex];
						}	

						temp[gunindex] = fabs(Module_Info.SMR_Gfd_Sense[gunindex] - Module_Info.Vref_165);	
						Module_Info.gfd_chk[gunindex].R_GFD = (uint32_t) ((double) Relay_V / 10.0 * GFD_RESISTOR_COEFFICIENT / temp[gunindex]) - 50018;
										
						// if(Module_Info.gfd_chk[gunindex].R_GFD > 1000000)
						// 	Module_Info.gfd_chk[gunindex].R_GFD = 1000000;	

						CalcuteGFDMaxMinValue(gunindex);	
					}
				}	
			}	
		}		
				

			if(Gfd.operation[0] == GFD_UNBALANCE){
				if(Module_Info.gfd_chk[0].Csu_State != IDLE || bGfd_Correct[0] == 1){
						
					Module_Info.SMR_Gfd_Sense[0] =(float) ADC3_Value[0] * v_div;	

					if(Gfd.Gfdtimer < GFD_SWITCH_TIME-2 || (Gfd.Gfdtimer > GFD_SWITCH_TIME && Gfd.Gfdtimer < (GFD_SWITCH_TIME*2)-2)){
						Gfd.TotalGFDvalue[0] = 0;
						Gfd.Gfdcount[0] = 0;
					}	

					if(Gfd.Gfdtimer >=  GFD_SWITCH_TIME-2    && Gfd.Gfdtimer < GFD_SWITCH_TIME || 
				       Gfd.Gfdtimer >= (GFD_SWITCH_TIME*2)-2 && Gfd.Gfdtimer < GFD_SWITCH_TIME*2){		
						Gfd.TotalGFDvalue[0] += Module_Info.SMR_Gfd_Sense[0];
						Gfd.Gfdcount[0]++;
					}else if(Gfd.Gfdtimer >= GFD_SWITCH_TIME && Gfd.Gfdtimer < GFD_SWITCH_TIME+1 ||	
					         Gfd.Gfdtimer >= GFD_SWITCH_TIME*2){
						Module_Info.SMR_Gfd_Sense[0] = Gfd.TotalGFDvalue[0] / Gfd.Gfdcount[0];					
					}					
					
					if(Gfd.Gfdtimer >= GFD_SWITCH_TIME)		//  > 50v
					{	
						//Re+=(Vo*Rsence-(R1+Rsence)*(U1+U2))/U2;		
						//Re-=(Vo*Rsence-(R1+Rsence)*(U1+U2))/U1
						//U1 = |1.65-vadc+| / 8.2
						//U2 = |1.65-vadc-| / 8.2				
						if(Gfd.Gfdtimer == GFD_SWITCH_TIME*2){		

							if(Module_Info.gfd_chk[1].Csu_State == IDLE){
								Gfd.Gfdtimer = 0;
								Gfd.GfdSwitch = 0;
							}
							// printf("2\n\r");
							if(Module_Info.SMR1_Relay_V > GFD_WORKING_VOLTAGE){
								if(Gfd.UpBridgeMaxV[0] == 0){
								Gfd.UpBridgeMaxV[0] = Module_Info.SMR_Gfd_Sense[0];
								}
								if(Gfd.UpBridgeMinV[0] == 0){
								Gfd.UpBridgeMinV[0] = Module_Info.SMR_Gfd_Sense[0];
								}
								if(Module_Info.SMR_Gfd_Sense[0] > Gfd.UpBridgeMaxV[0]){
									Gfd.UpBridgeMaxV[0] = Module_Info.SMR_Gfd_Sense[0];
								}
								if(Module_Info.SMR_Gfd_Sense[0] < Gfd.UpBridgeMinV[0]){
									Gfd.UpBridgeMinV[0] = Module_Info.SMR_Gfd_Sense[0];
								}		

								Module_Info.gfd_chk[0].UP_BRIDGE_OP_V = Module_Info.SMR_Gfd_Sense[0];						
								Module_Info.gfd_chk[0].U2_V = fabs(Module_Info.Vref_165 - Module_Info.gfd_chk[0].UP_BRIDGE_OP_V)/8.2;				

								if(Module_Info.gfd_chk[0].U1_V != 0){
									Module_Info.gfd_chk[0].R_GFD = (uint32_t)(((Module_Info.SMR1_Relay_V /10 * Rsense) - (R1+Rsense)*(Module_Info.gfd_chk[0].U1_V + Module_Info.gfd_chk[0].U2_V))/Module_Info.gfd_chk[0].U2_V);
									Module_Info.gfd_chk[0].P2PE_GFD = Module_Info.gfd_chk[0].R_GFD;	
									// Module_Info.gfd_chk[0].R_GFD = (uint32_t)(((Relay_V /10 * Rsense) -(R1+Rsense)*(Module_Info.gfd_chk[0].U1_V + Module_Info.gfd_chk[0].U2_V))/Module_Info.gfd_chk[0].U1_V);				
									// Module_Info.gfd_chk[0].N2PE_GFD = Module_Info.gfd_chk[0].R_GFD;						
									Module_Info.gfd_chk[0].U1_V = 0;	
									CalcuteGFDMaxMinValue(0);									
								}		
							}else{
								// printf("1V:%d T:%d\n\r",Module_Info.SMR1_Relay_V,Gfd.Gfdtimer);
							}																
						}else if(Gfd.Gfdtimer == GFD_SWITCH_TIME){	
							if(Module_Info.SMR1_Relay_V > GFD_WORKING_VOLTAGE){
								// printf("1\n\r");
								Module_Info.gfd_chk[0].DN_BRIDGE_OP_V = Module_Info.SMR_Gfd_Sense[0];
								Module_Info.gfd_chk[0].U1_V = fabs(Module_Info.Vref_165 - Module_Info.gfd_chk[0].DN_BRIDGE_OP_V)/8.2;
								if(Module_Info.gfd_chk[0].U2_V != 0){
									Module_Info.gfd_chk[0].R_GFD = (uint32_t)(((Module_Info.SMR1_Relay_V /10 * Rsense) -(R1+Rsense)*(Module_Info.gfd_chk[0].U1_V + Module_Info.gfd_chk[0].U2_V))/Module_Info.gfd_chk[0].U1_V);				
									Module_Info.gfd_chk[0].N2PE_GFD = Module_Info.gfd_chk[0].R_GFD;
									Module_Info.gfd_chk[0].U2_V = 0;							
									CalcuteGFDMaxMinValue(0);																
								}	
							}else{
								// printf("1V:%d T:%d\n\r",Module_Info.SMR1_Relay_V,Gfd.Gfdtimer);
							}													
						}	
					}	
				}	
			}	


			if(Gfd.operation[1] == GFD_UNBALANCE){
				if(Module_Info.gfd_chk[1].Csu_State != IDLE || bGfd_Correct[1] == 1){
						
					Module_Info.SMR_Gfd_Sense[1] =(float) ADC3_Value[1] * v_div;	

					if((Gfd.Gfdtimer > GFD_SWITCH_TIME*2 && Gfd.Gfdtimer < (GFD_SWITCH_TIME*3)-2) || 
					   (Gfd.Gfdtimer > GFD_SWITCH_TIME*3 && Gfd.Gfdtimer < (GFD_SWITCH_TIME*4)-2)){
						Gfd.TotalGFDvalue[1] = 0;
						Gfd.Gfdcount[1] = 0;
					}	

					if(Gfd.Gfdtimer >= (GFD_SWITCH_TIME*3)-2 && Gfd.Gfdtimer < GFD_SWITCH_TIME*3 || 
					   Gfd.Gfdtimer >= (GFD_SWITCH_TIME*4)-2 && Gfd.Gfdtimer < GFD_SWITCH_TIME*4){	
						Gfd.TotalGFDvalue[1] += Module_Info.SMR_Gfd_Sense[1];
						Gfd.Gfdcount[1]++;
					}else if(Gfd.Gfdtimer >= (GFD_SWITCH_TIME*3) && Gfd.Gfdtimer < (GFD_SWITCH_TIME*3)+1 || 
					         Gfd.Gfdtimer >= (GFD_SWITCH_TIME*4)){
						Module_Info.SMR_Gfd_Sense[1] =Gfd.TotalGFDvalue[1] / Gfd.Gfdcount[1];					
					}
				
					
					if(Gfd.Gfdtimer >= (GFD_SWITCH_TIME*3))		
					{	
						//Re+=(Vo*Rsence-(R1+Rsence)*(U1+U2))/U2;		
						//Re-=(Vo*Rsence-(R1+Rsence)*(U1+U2))/U1
						//U1 = |1.65-vadc+| / 8.2
						//U2 = |1.65-vadc-| / 8.2				
						if(Gfd.Gfdtimer == (GFD_SWITCH_TIME*4)){		
							// printf("4\n\r");

							if(Module_Info.gfd_chk[0].Csu_State == IDLE){
								Gfd.Gfdtimer = (GFD_SWITCH_TIME*2);
								Gfd.GfdSwitch = 2;
							}else{
								Gfd.Gfdtimer = 0;
								Gfd.GfdSwitch = 0;	
							}
							if(Module_Info.SMR2_Relay_V > GFD_WORKING_VOLTAGE){		

								if(Gfd.UpBridgeMaxV[1] == 0){
								Gfd.UpBridgeMaxV[1] = Module_Info.SMR_Gfd_Sense[1];
								}
								if(Gfd.UpBridgeMinV[1] == 0){
								Gfd.UpBridgeMinV[1] = Module_Info.SMR_Gfd_Sense[1];
								}
								if(Module_Info.SMR_Gfd_Sense[1] > Gfd.UpBridgeMaxV[1]){
									Gfd.UpBridgeMaxV[1] = Module_Info.SMR_Gfd_Sense[1];
								}
								if(Module_Info.SMR_Gfd_Sense[1] < Gfd.UpBridgeMinV[1]){
									Gfd.UpBridgeMinV[1] = Module_Info.SMR_Gfd_Sense[1];
								}		

								Module_Info.gfd_chk[1].UP_BRIDGE_OP_V = Module_Info.SMR_Gfd_Sense[1];						
								Module_Info.gfd_chk[1].U2_V = fabs(Module_Info.Vref_165 - Module_Info.gfd_chk[1].UP_BRIDGE_OP_V)/8.2;				

								if(Module_Info.gfd_chk[1].U1_V != 0){
									Module_Info.gfd_chk[1].R_GFD = (uint32_t)(((Module_Info.SMR2_Relay_V /10 * Rsense) - (R1+Rsense)*(Module_Info.gfd_chk[1].U1_V + Module_Info.gfd_chk[1].U2_V))/Module_Info.gfd_chk[1].U2_V);
									Module_Info.gfd_chk[1].P2PE_GFD = Module_Info.gfd_chk[1].R_GFD;	
									// Module_Info.gfd_chk[1].R_GFD = (uint32_t)(((Relay_V /10 * Rsense) -(R1+Rsense)*(Module_Info.gfd_chk[1].U1_V + Module_Info.gfd_chk[1].U2_V))/Module_Info.gfd_chk[1].U1_V);				
									// Module_Info.gfd_chk[1].N2PE_GFD = Module_Info.gfd_chk[1].R_GFD;						
									Module_Info.gfd_chk[1].U1_V = 0;	
									CalcuteGFDMaxMinValue(1);									
								}	
							}else{
								// printf("2V:%d T:%d\n\r",Module_Info.SMR2_Relay_V,Gfd.Gfdtimer);
							}													
						}else if(Gfd.Gfdtimer == (GFD_SWITCH_TIME*3)){		
							// printf("3\n\r");	
							if(Module_Info.SMR2_Relay_V > GFD_WORKING_VOLTAGE){		
								Module_Info.gfd_chk[1].DN_BRIDGE_OP_V = Module_Info.SMR_Gfd_Sense[1];
								Module_Info.gfd_chk[1].U1_V = fabs(Module_Info.Vref_165 - Module_Info.gfd_chk[1].DN_BRIDGE_OP_V)/8.2;
								if(Module_Info.gfd_chk[1].U2_V != 0){
									Module_Info.gfd_chk[1].R_GFD = (uint32_t)(((Module_Info.SMR2_Relay_V /10 * Rsense) -(R1+Rsense)*(Module_Info.gfd_chk[1].U1_V + Module_Info.gfd_chk[1].U2_V))/Module_Info.gfd_chk[1].U1_V);				
									Module_Info.gfd_chk[1].N2PE_GFD = Module_Info.gfd_chk[1].R_GFD;
									Module_Info.gfd_chk[1].U2_V = 0;							
									CalcuteGFDMaxMinValue(1);	
								}	
							}else{
								// printf("2V:%d T:%d\n\r",Module_Info.SMR2_Relay_V,Gfd.Gfdtimer);	
							}	
						}	
					}	
				}	
			}	

			for(gunindex = 0 ; gunindex < 2 ; gunindex++){
				if(Gfd.GfdMode[gunindex] == GFD_UNBALANCE){

					if(Gfd.operation[gunindex] == GFD_OFF || Module_Info.gfd_chk[gunindex].Csu_State == IDLE){
						Gfd.UpBridgeMaxV[gunindex] = 0;
						Gfd.UpBridgeMinV[gunindex] = 0;
						Gfd.DnBridgeMaxV[gunindex] = 0;
						Gfd.DnBridgeMinV[gunindex] = 0;
						Gfd.MaxP2PE[gunindex] = 0;
						Gfd.MinP2PE[gunindex] = 0;
						Gfd.MaxN2PE[gunindex] = 0;
						Gfd.MinN2PE[gunindex] = 0;	
						Module_Info.gfd_chk[gunindex].R_GFD = 0;
						Module_Info.gfd_chk[gunindex].P2PE_GFD = 0;
						Module_Info.gfd_chk[gunindex].N2PE_GFD = 0;
						Gfd.TotalGFDvalue[gunindex] = 0;
						Gfd.Gfdcount[gunindex] = 0;	
						Gfd.GfdAvgCount[gunindex] = 0;										
					}	
				}		
			}				
		// bADC3_Done = OFF;
		// HAL_ADC_Start_DMA(&hadc3, ADC3_Buf, (ADC3_SAMPLE_COUNT * ADC3_CHANEL_COUNT));		
	}
		osDelay(1);
	}
  /* USER CODE END Adc3Task */
}

/* USER CODE BEGIN Header_GpioTask */
/**
 * @brief Function implementing the gpioTask thread.
 * @param argument: Not used
 * @retval None
 */
/* USER CODE END Header_GpioTask */
void GpioTask(void const * argument)
{
  /* USER CODE BEGIN GpioTask */
	/* Infinite loop */
	for (;;)
	{
		HAL_IWDG_Refresh(&hiwdg);	

	#if 0
	// Output test
		IOdebug();	
	#endif				
	
		if (OpFlag.bRelay_Config_Change == ON)
		{
			OpFlag.bRelay_Config_Change = OFF;
			
			// =================( SMR1_Relay_n  )=======================			
			if (Module_Info.Relay_IO.flags.SMR1_relay_n == ON){
				if (!Exti.EXTI_SMR1_Flag || (Exti.EXTI_SMR1_Flag && EXTI_SMR1_Count >= WeldingCMDDelay)){	//ignore DCM relay command 1s when Relay welding 
					Exti.EXTI_SMR1_Flag = false;
					EXTI_SMR1_Count= 0;	

					HAL_GPIO_WritePin(SMR1_RLY_n_Enable_GPIO_Port, SMR1_RLY_n_Enable_Pin, GPIO_PIN_SET);
					printf(" 1N ON\r\n");	
					
					if(!RelayStatus.SMR1_relay_n)
					{				
						osDelay(Multi_Relay_Delay_Time);		
						RelayStatus.SMR1_relay_n = true;
					}
				}else if(Exti.EXTI_SMR1_Flag && EXTI_SMR1_Count < WeldingCMDDelay){	//Reset count				
						EXTI_SMR1_Count = 0;						
				}	
				
					
			}
			else{
				HAL_GPIO_WritePin(SMR1_RLY_n_Enable_GPIO_Port, SMR1_RLY_n_Enable_Pin, GPIO_PIN_RESET);
				RelayStatus.SMR1_relay_n = false;
				printf(" 1N OFF\r\n");	
			}

			// =================( SMR1_Relay_p  )=======================			
			if (Module_Info.Relay_IO.flags.SMR1_relay_p == ON){
				if (!Exti.EXTI_SMR1_Flag || (Exti.EXTI_SMR1_Flag && EXTI_SMR1_Count >= WeldingCMDDelay)){	//ignore DCM relay command 1s when Relay welding 
					Exti.EXTI_SMR1_Flag = false;
					EXTI_SMR1_Count= 0;	
					HAL_GPIO_WritePin(SMR1_RLY_p_Enable_GPIO_Port, SMR1_RLY_p_Enable_Pin, GPIO_PIN_SET);
					printf(" 1P ON\r\n");	

					if(!RelayStatus.SMR1_relay_p)
					{				
						osDelay(Multi_Relay_Delay_Time);		
						RelayStatus.SMR1_relay_p = true;
					} 
				}else if(Exti.EXTI_SMR1_Flag && EXTI_SMR1_Count < WeldingCMDDelay){	//Reset count
						EXTI_SMR1_Count = 0;
				}		
			}
			else
			{
				HAL_GPIO_WritePin(SMR1_RLY_p_Enable_GPIO_Port, SMR1_RLY_p_Enable_Pin, GPIO_PIN_RESET);
				RelayStatus.SMR1_relay_p = false;
				printf(" 1P OFF\r\n");	
			}
			// =================( SMR2_Relay_n  )=======================			
			if (Module_Info.Relay_IO.flags.SMR2_relay_n == ON){
				if (!Exti.EXTI_SMR2_Flag || (Exti.EXTI_SMR2_Flag && EXTI_SMR2_Count >= WeldingCMDDelay)){	//ignore DCM relay command 1s when Relay welding 
					Exti.EXTI_SMR2_Flag = false;
					EXTI_SMR2_Count= 0;	
					HAL_GPIO_WritePin(SMR2_RLY_n_Enable_GPIO_Port, SMR2_RLY_n_Enable_Pin, GPIO_PIN_SET);
					printf(" 2N ON\r\n");

					if(!RelayStatus.SMR2_relay_n)
					{				
						osDelay(Multi_Relay_Delay_Time);		
						RelayStatus.SMR2_relay_n = true;
					}
				}else if(Exti.EXTI_SMR2_Flag && EXTI_SMR2_Count < WeldingCMDDelay){	//Reset count
						EXTI_SMR2_Count = 0;
				}		
			}
			else
			{
				HAL_GPIO_WritePin(SMR2_RLY_n_Enable_GPIO_Port, SMR2_RLY_n_Enable_Pin, GPIO_PIN_RESET);
				RelayStatus.SMR2_relay_n = false;
				printf(" 2N OFF\r\n");	
			}

			// =================( SMR2_Relay_p  )=======================			
			if (Module_Info.Relay_IO.flags.SMR2_relay_p == ON){
				if (!Exti.EXTI_SMR2_Flag || (Exti.EXTI_SMR2_Flag && EXTI_SMR2_Count >= WeldingCMDDelay)){	//ignore DCM relay command 1s when Relay welding 
					Exti.EXTI_SMR2_Flag = false;
					EXTI_SMR2_Count= 0;	
					HAL_GPIO_WritePin(SMR2_RLY_p_Enable_GPIO_Port, SMR2_RLY_p_Enable_Pin, GPIO_PIN_SET);
					printf(" 2P ON\r\n");
					
					if(!RelayStatus.SMR2_relay_p)
					{				
						osDelay(Multi_Relay_Delay_Time);		
						RelayStatus.SMR2_relay_p = true;
					}
				}else if(Exti.EXTI_SMR2_Flag && EXTI_SMR2_Count < WeldingCMDDelay){	//Reset count
						EXTI_SMR2_Count = 0;
				}			
			}
			else
			{
				HAL_GPIO_WritePin(SMR2_RLY_p_Enable_GPIO_Port, SMR2_RLY_p_Enable_Pin, GPIO_PIN_RESET);
				RelayStatus.SMR2_relay_p = false;
				printf(" 2P OFF\r\n");	
			}
			// =================( SMR3_Relay_n  )=======================			
			if (Module_Info.Relay_IO.flags.SMR3_relay_n == ON){
				if (!Exti.EXTI_SMR3_Flag || (Exti.EXTI_SMR3_Flag && EXTI_SMR3_Count >= WeldingCMDDelay)){	//ignore DCM relay command 1s when Relay welding 
					Exti.EXTI_SMR3_Flag = false;
					EXTI_SMR3_Count= 0;	
					HAL_GPIO_WritePin(SMR3_RLY_n_Enable_GPIO_Port, SMR3_RLY_n_Enable_Pin, GPIO_PIN_SET);
					printf(" 3N ON\r\n");

					if(!RelayStatus.SMR3_relay_n)
					{				
						osDelay(Multi_Relay_Delay_Time);		
						RelayStatus.SMR3_relay_n = true;
					}
				}else if(Exti.EXTI_SMR3_Flag && EXTI_SMR3_Count < WeldingCMDDelay){	//Reset count
						EXTI_SMR3_Count = 0;
				}			
			}
			else
			{
				HAL_GPIO_WritePin(SMR3_RLY_n_Enable_GPIO_Port, SMR3_RLY_n_Enable_Pin, GPIO_PIN_RESET);
				RelayStatus.SMR3_relay_n = false;
				printf(" 3N OFF\r\n");	
			}

			// =================( SMR3_Relay_p  )=======================			
			if (Module_Info.Relay_IO.flags.SMR3_relay_p == ON){
				if (!Exti.EXTI_SMR3_Flag || (Exti.EXTI_SMR3_Flag && EXTI_SMR3_Count >= WeldingCMDDelay)){	//ignore DCM relay command 1s when Relay welding 
					Exti.EXTI_SMR3_Flag = false;
					EXTI_SMR3_Count= 0;	
					HAL_GPIO_WritePin(SMR3_RLY_p_Enable_GPIO_Port, SMR3_RLY_p_Enable_Pin, GPIO_PIN_SET);
					printf(" 3P ON\r\n");

					if(!RelayStatus.SMR3_relay_p)
					{				
						osDelay(Multi_Relay_Delay_Time);		
						RelayStatus.SMR3_relay_p = true;
					}
				}else if(Exti.EXTI_SMR3_Flag && EXTI_SMR3_Count < WeldingCMDDelay){	//Reset count
						EXTI_SMR3_Count = 0;
				}		
			}
			else
			{
				HAL_GPIO_WritePin(SMR3_RLY_p_Enable_GPIO_Port, SMR3_RLY_p_Enable_Pin, GPIO_PIN_RESET);
				RelayStatus.SMR3_relay_p = false;
				printf(" 3P OFF\r\n");	
			}
			// =================( SMR4_Relay_n  )=======================			
			if (Module_Info.Relay_IO.flags.SMR4_relay_n == ON){
				if (!Exti.EXTI_SMR4_Flag || (Exti.EXTI_SMR4_Flag && EXTI_SMR4_Count >= WeldingCMDDelay)){	//ignore DCM relay command 1s when Relay welding 
					Exti.EXTI_SMR4_Flag = false;
					EXTI_SMR4_Count= 0;	
					HAL_GPIO_WritePin(SMR4_RLY_n_Enable_GPIO_Port, SMR4_RLY_n_Enable_Pin, GPIO_PIN_SET);
					printf(" 4N ON\r\n");

					if(!RelayStatus.SMR4_relay_n)
					{				
						osDelay(Multi_Relay_Delay_Time);		
						RelayStatus.SMR4_relay_n = true;
					}
				}else if(Exti.EXTI_SMR4_Flag && EXTI_SMR4_Count < WeldingCMDDelay){	//Reset count
						EXTI_SMR4_Count = 0;
				}		
			}
			else
			{
				HAL_GPIO_WritePin(SMR4_RLY_n_Enable_GPIO_Port, SMR4_RLY_n_Enable_Pin, GPIO_PIN_RESET);
				RelayStatus.SMR4_relay_n = false;
				printf(" 4N OFF\r\n");	
			}

			// =================( SMR4_Relay_p  )=======================			
			if (Module_Info.Relay_IO.flags.SMR4_relay_p == ON){
				if (!Exti.EXTI_SMR4_Flag || (Exti.EXTI_SMR4_Flag && EXTI_SMR4_Count >= WeldingCMDDelay)){	//ignore DCM relay command 1s when Relay welding 
					Exti.EXTI_SMR4_Flag = false;
					EXTI_SMR4_Count= 0;	
					HAL_GPIO_WritePin(SMR4_RLY_p_Enable_GPIO_Port, SMR4_RLY_p_Enable_Pin, GPIO_PIN_SET);
					printf(" 4P ON\r\n");

					if(!RelayStatus.SMR4_relay_p)
					{				
						osDelay(Multi_Relay_Delay_Time);		
						RelayStatus.SMR4_relay_p = true;
					}
				}else if(Exti.EXTI_SMR4_Flag && EXTI_SMR4_Count < WeldingCMDDelay){	//Reset count
						EXTI_SMR4_Count = 0;
				}		
			}
			else
			{
				HAL_GPIO_WritePin(SMR4_RLY_p_Enable_GPIO_Port, SMR4_RLY_p_Enable_Pin, GPIO_PIN_RESET);
				RelayStatus.SMR4_relay_p = false;
				printf(" 4P OFF\r\n");	
			}
			// =================( SMR5_Relay_n  )=======================			
			if (Module_Info.Relay_IO.flags.SMR5_relay_n == ON){
				if (!Exti.EXTI_SMR5_Flag || (Exti.EXTI_SMR5_Flag && EXTI_SMR5_Count >= WeldingCMDDelay)){	//ignore DCM relay command 1s when Relay welding 
					Exti.EXTI_SMR5_Flag = false;
					EXTI_SMR5_Count= 0;	
					HAL_GPIO_WritePin(SMR5_RLY_n_Enable_GPIO_Port, SMR5_RLY_n_Enable_Pin, GPIO_PIN_SET);
					printf(" 5N ON\r\n");

					if(!RelayStatus.SMR5_relay_n)
					{				
						osDelay(Multi_Relay_Delay_Time);		
						RelayStatus.SMR5_relay_n = true;
					}
				}else if(Exti.EXTI_SMR5_Flag && EXTI_SMR5_Count < WeldingCMDDelay){	//Reset count
						EXTI_SMR5_Count = 0;
				}		
			}
			else
			{
				HAL_GPIO_WritePin(SMR5_RLY_n_Enable_GPIO_Port, SMR5_RLY_n_Enable_Pin, GPIO_PIN_RESET);
				RelayStatus.SMR5_relay_n = false;
				printf(" 5N OFF\r\n");	
			}

			// =================( SMR5_Relay_p  )=======================			
			if (Module_Info.Relay_IO.flags.SMR5_relay_p == ON){
				if (!Exti.EXTI_SMR5_Flag || (Exti.EXTI_SMR5_Flag && EXTI_SMR5_Count >= WeldingCMDDelay)){	//ignore DCM relay command 1s when Relay welding 
					Exti.EXTI_SMR5_Flag = false;
					EXTI_SMR5_Count= 0;	
					HAL_GPIO_WritePin(SMR5_RLY_p_Enable_GPIO_Port, SMR5_RLY_p_Enable_Pin, GPIO_PIN_SET);
					printf(" 5P ON\r\n");

					if(!RelayStatus.SMR5_relay_p)
					{				
						osDelay(Multi_Relay_Delay_Time);		
						RelayStatus.SMR5_relay_p = true;
					}
				}else if(Exti.EXTI_SMR5_Flag && EXTI_SMR5_Count < WeldingCMDDelay){	//Reset count
						EXTI_SMR5_Count = 0;
				}		
			}
			else
			{
				HAL_GPIO_WritePin(SMR5_RLY_p_Enable_GPIO_Port, SMR5_RLY_p_Enable_Pin, GPIO_PIN_RESET);
				RelayStatus.SMR5_relay_p = false;
				printf(" 5P OFF\r\n");	
			}
			// =================( SMR6_Relay_n  )=======================			
			if (Module_Info.Relay_IO.flags.SMR6_relay_n == ON){
				if (!Exti.EXTI_SMR6_Flag || (Exti.EXTI_SMR6_Flag && EXTI_SMR6_Count >= WeldingCMDDelay)){	//ignore DCM relay command 1s when Relay welding 
					Exti.EXTI_SMR6_Flag = false;
					EXTI_SMR6_Count= 0;	
					HAL_GPIO_WritePin(SMR6_RLY_n_Enable_GPIO_Port, SMR6_RLY_n_Enable_Pin, GPIO_PIN_SET);
					printf(" 6N ON\r\n");

					if(!RelayStatus.SMR6_relay_n)
					{				
						osDelay(Multi_Relay_Delay_Time);		
						RelayStatus.SMR6_relay_n = true;
					}
				}else if(Exti.EXTI_SMR6_Flag && EXTI_SMR6_Count < WeldingCMDDelay){	//Reset count
						EXTI_SMR6_Count = 0;
				}	
			}
			else
			{
				HAL_GPIO_WritePin(SMR6_RLY_n_Enable_GPIO_Port, SMR6_RLY_n_Enable_Pin, GPIO_PIN_RESET);
				RelayStatus.SMR6_relay_n = false;
				printf(" 6N OFF\r\n");	
			}

			// =================( SMR6_Relay_p  )=======================			
			if (Module_Info.Relay_IO.flags.SMR6_relay_p == ON){
				if (!Exti.EXTI_SMR6_Flag || (Exti.EXTI_SMR6_Flag && EXTI_SMR6_Count >=10)){	//ignore DCM relay command 1s when Relay welding 
					Exti.EXTI_SMR6_Flag = false;
					EXTI_SMR6_Count= 0;	
					HAL_GPIO_WritePin(SMR6_RLY_p_Enable_GPIO_Port, SMR6_RLY_p_Enable_Pin, GPIO_PIN_SET);
					printf(" 6P ON\r\n");

					if(!RelayStatus.SMR6_relay_p)
					{				
						osDelay(Multi_Relay_Delay_Time);		
						RelayStatus.SMR6_relay_p = true;
					}
				}else if(Exti.EXTI_SMR6_Flag && EXTI_SMR6_Count < WeldingCMDDelay){	//Reset count
						EXTI_SMR6_Count = 0;
				}	
			}
			else
			{
				HAL_GPIO_WritePin(SMR6_RLY_p_Enable_GPIO_Port, SMR6_RLY_p_Enable_Pin, GPIO_PIN_RESET);
				RelayStatus.SMR6_relay_p = false;
				printf(" 6P OFF\r\n");	
			}
		// =================( Precharge1 )==============================
			if (Module_Info.Relay_IO.flags.Precharge1 == ON)
			{
				HAL_GPIO_WritePin(Precharge1_Enable_GPIO_Port, Precharge1_Enable_Pin, GPIO_PIN_SET);
				printf("Pre-charge 1 ON\r\n");	
			}
			else
			{
				HAL_GPIO_WritePin(Precharge1_Enable_GPIO_Port, Precharge1_Enable_Pin, GPIO_PIN_RESET);
				printf("Pre-charge 1 OFF\r\n");	
			}	
		// =================( Precharge2 )==============================
			if (Module_Info.Relay_IO.flags.Precharge2 == ON)
			{
				HAL_GPIO_WritePin(Precharge2_Enable_GPIO_Port, Precharge2_Enable_Pin, GPIO_PIN_SET);
				printf("Pre-charge 2 ON\r\n");	
			}
			else
			{
				HAL_GPIO_WritePin(Precharge2_Enable_GPIO_Port, Precharge2_Enable_Pin, GPIO_PIN_RESET);
				printf("Pre-charge 2 OFF\r\n");	
			}		
		// =================( AC_Contactor  )=======================
			if (Module_Info.Relay_IO.flags.AC_Contactor == ON)
			{
				HAL_GPIO_WritePin(Contactor_Enable_GPIO_Port, Contactor_Enable_Pin, GPIO_PIN_SET);
				printf("AC Contactor ON\r\n");	
			}
			else
			{
				HAL_GPIO_WritePin(Contactor_Enable_GPIO_Port, Contactor_Enable_Pin, GPIO_PIN_RESET);
				printf("AC Contactor OFF\r\n");	
			}
		}
		osDelay(1);
	}
  /* USER CODE END GpioTask */
}

/* USER CODE BEGIN Header_MemoryTask */
/**
 * @brief Function implementing the memoryTask thread.
 * @param argument: Not used
 * @retval None
 */
/* USER CODE END Header_MemoryTask */
void MemoryTask(void const * argument)
{
  /* USER CODE BEGIN MemoryTask */
	Module_Info.memory.Module_Config.op_bits.read = ON;
	__IO uint32_t flash;
	int i;

	/* Infinite loop */
	for (;;)
	{
		/*
			Charger config operation
		*/
		if (Module_Info.memory.Module_Config.op_bits.read) // Memory read
		{
			// Read data from block
			// for(uint16_t idx=0; idx<(MEMORY_LENGTH_CONFIG>>2); idx++)
			GainCaliFlag = true;

			for (uint16_t idx = 0; idx < MEM_REAL_LENGTH; idx++)
			{
				flash = ADDR_FLASH_SECTOR_4 + (idx * 4);
				Module_Info.memory.Module_Config.data.value[idx] = *(uint32_t *)flash;

				if ((Module_Info.memory.Module_Config.data.value[idx] == 0xffffffff) ||
					(Module_Info.memory.Module_Config.data.value[idx] == 0))
				{
					if(BridgeBoard)
						break;
					else
						GainCaliFlag = false;
					Module_Info.memory.Module_Config.data.value[idx] = mem_def_data[idx];
				}				
			}

			// coefficient DATA
			
			for (i = 0; i < DC_CORRECT_GAIN_MAX_NUM; i++)
			{
				if (Module_Info.memory.Module_Config.data.item.DC_Correction_Volt[i*2][MCU_DATA] >
					Module_Info.memory.Module_Config.data.item.DC_Correction_Volt[(i*2 + 1)][MCU_DATA]) // Make sure memory have calibration valid value
				{
					CLC_Corr_Gain_Par(Module_Info.memory.Module_Config.data.item.DC_Correction_Volt[i*2][METER_DATA],
									  Module_Info.memory.Module_Config.data.item.DC_Correction_Volt[(i*2 + 1)][METER_DATA],
									  Module_Info.memory.Module_Config.data.item.DC_Correction_Volt[i*2][MCU_DATA],
									  Module_Info.memory.Module_Config.data.item.DC_Correction_Volt[(i*2 + 1)][MCU_DATA],
									  &Module_Info.DCVcoeff[i].gain_volt, &Module_Info.DCVcoeff[i].offset_volt);
				}
				else
				{
					Module_Info.DCVcoeff[i].gain_volt = 1;
					Module_Info.DCVcoeff[i].offset_volt = 0;
				}
			}	

			for (i = 0; i < GFD_CORRECT_GAIN_MAX_NUM; i++)
			{
				if (Module_Info.memory.Module_Config.data.item.GFD_Correction_Resistor[i*2][MCU_DATA] >
					Module_Info.memory.Module_Config.data.item.GFD_Correction_Resistor[(i*2 + 1)][MCU_DATA])
				{
					CLC_Corr_Gain_Par(Module_Info.memory.Module_Config.data.item.GFD_Correction_Resistor[i*2][METER_DATA],
									  Module_Info.memory.Module_Config.data.item.GFD_Correction_Resistor[(i*2 + 1)][METER_DATA],
									  Module_Info.memory.Module_Config.data.item.GFD_Correction_Resistor[i*2][MCU_DATA],
									  Module_Info.memory.Module_Config.data.item.GFD_Correction_Resistor[(i*2 + 1)][MCU_DATA],
									  &Module_Info.GFDcoeff[i].gain_volt, &Module_Info.GFDcoeff[i].offset_volt);
				}
				else
				{
					Module_Info.GFDcoeff[i].gain_volt = 1;
					Module_Info.GFDcoeff[i].offset_volt = 0;
				}
			}	
        
		
			if( Module_Info.memory.Module_Config.data.item.DCIn_Correction_Volt[0][MCU_DATA] >  
				Module_Info.memory.Module_Config.data.item.DCIn_Correction_Volt[(1)][MCU_DATA] )  
			{ 
				CLC_Corr_Gain_Par( Module_Info.memory.Module_Config.data.item.DCIn_Correction_Volt[0][METER_DATA], 
								Module_Info.memory.Module_Config.data.item.DCIn_Correction_Volt[(1)][METER_DATA], 
								Module_Info.memory.Module_Config.data.item.DCIn_Correction_Volt[0][MCU_DATA], 
								Module_Info.memory.Module_Config.data.item.DCIn_Correction_Volt[(1)][MCU_DATA], 
								&Module_Info.DCINcoeff.gain_volt, &Module_Info.DCINcoeff.offset_volt);
			}
			else
			{            
				Module_Info.DCINcoeff.gain_volt = 1;
				Module_Info.DCINcoeff.offset_volt = 0;                        
			}	

			for(uint16_t idx=MEM_MODELNAME_ADDRESS; idx<MEM_MODELNAME_ADDRESS+MEM_MODELNAME_LENGTH; idx++)
			{
				flash = ADDR_FLASH_SECTOR_4 + idx*4;			
				Module_Info.memory.Module_Config.data.value[idx] = *(uint32_t *)flash;
			}	
			memcpy (ModelName, Module_Info.memory.Module_Config.data.item.Modelname, 14); 
			SetGfdMode();  		

			
			Module_Info.memory.Module_Config.op_bits.read = OFF;
			// DEBUG_INFO("Read MEM_ADDR_EVSE_CONFIG block(4k byte) pass.\r\n");
			
  			//  Module_Info.memory.Module_Config.op_bits.update = 1;

			//  for (uint16_t idx = 0; idx < MEM_REAL_LENGTH; idx++)
			//  {
			//  	Module_Info.memory.Module_Config.data.value[idx] = 0;
			//  }	
					          
		}

		if (Module_Info.memory.Module_Config.op_bits.update) // Memory update
		{
			// Erase block data
			if (Module_Info.memory.Module_Config.op_bits.modelname){
				for (uint16_t idx = 0; idx < MEM_REAL_LENGTH; idx++){
					flash = ADDR_FLASH_SECTOR_4 + (idx * 4);
					Module_Info.memory.Module_Config.data.value[idx] = *(uint32_t *)flash;			
				}			
			}
			if (FLASH_If_Erase(ADDR_FLASH_SECTOR_4, 1) == FLASHIF_OK)
			{
#ifdef DEBUG
// DEBUG_INFO("Erase MEM_ADDR_EVSE_CONFIG block(4k bytes) pass.\r\n");
#endif			
				// Write data to block

				if (FLASH_If_Write(ADDR_FLASH_SECTOR_4, (uint32_t *)Module_Info.memory.Module_Config.data.value, MEMORY_LENGTH_CONFIG >> 2) == FLASHIF_OK)
				{
					// DEBUG_INFO("Write MEM_ADDR_EVSE_CONFIG block(4k bytes) pass.\r\n");
				}
				else
				{
					// DEBUG_INFO("Write MEM_ADDR_EVSE_CONFIG block(4k bytes) fail.\r\n");
				}

				if (Module_Info.memory.Module_Config.op_bits.modelname){
					for (uint16_t idx = 0; idx < MEM_REAL_LENGTH; idx++){	
						if ((Module_Info.memory.Module_Config.data.value[idx] == 0xffffffff) ||
							(Module_Info.memory.Module_Config.data.value[idx] == 0)){					
								Module_Info.memory.Module_Config.data.value[idx] = mem_def_data[idx];
						}		
					}				
				}
				
				SetGfdMode();  
				Module_Info.memory.Module_Config.op_bits.update = OFF;
				Module_Info.memory.Module_Config.op_bits.modelname = OFF;
			}
			else
			{
				// DEBUG_INFO("Erase MEM_ADDR_EVSE_CONFIG block(4k bytes) fail.\r\n");
			}
		}

		if (Module_Info.memory.Module_Config.op_bits.clear) // Memory clear
		{
			// Erase block data
			if (FLASH_If_Erase(ADDR_FLASH_SECTOR_4, 1) == FLASHIF_OK)
			{
				// DEBUG_INFO("Erase MEM_ADDR_EVSE_CONFIG block(4k byte) pass.\r\n");

				Module_Info.memory.Module_Config.op_bits.clear = OFF;
			}
			else
			{
				// DEBUG_INFO("Erase MEM_ADDR_EVSE_CONFIG block(4k byte) fail.\r\n");
			}
		}

		osDelay(1);
	}
  /* USER CODE END MemoryTask */
}

/* USER CODE BEGIN Header_Inkey_Task */
/**
 * @brief Function implementing the InkeyTask thread.
 * @param argument: Not used
 * @retval None
 */
/* USER CODE END Header_Inkey_Task */
void Inkey_Task(void const * argument)
{
  /* USER CODE BEGIN Inkey_Task */
	/* Infinite loop */
	for (;;)
	{
		//  	if( (AC_Sine[0].Vrms_AVG < 1600) ||
		//  		(AC_Sine[1].Vrms_AVG < 1600) ||
		//  		(AC_Sine[2].Vrms_AVG < 1600) )
		//  	{
		//  		if(Counter.nAC_Drop > 10)
		//  			HAL_GPIO_WritePin(CSU_IO_HIGH_GPIO_Port, CSU_IO_HIGH_Pin, GPIO_PIN_RESET);
		//        else
		//            Counter.nAC_Drop++;
		//  	}
		//  	else
		//  	{
		//  		Counter.nAC_Drop = 0;
		//  		HAL_GPIO_WritePin(CSU_IO_HIGH_GPIO_Port, CSU_IO_HIGH_Pin, GPIO_PIN_SET);
		//  	}

		// InterLock bit Detect ....
		//  	if(HAL_GPIO_ReadPin(Relay_Interlock_GPIO_Port, Relay_Interlock_Pin) == 1)
		//  	{
		//  		Counter.nInterLock++;
		//  		if(Counter.nInterLock >5)
		//  			OpFlag.bInterLock = ON;
		//  	}
		//  	else
		//  	{
		//  		Counter.nInterLock = OpFlag.bInterLock = OFF;
		//  	}
		//
		//  	if( OpFlag.bInterLock == ON )
		//  	{
		//  		OpFlag.bInterLock= OFF;
		//
		//  		HAL_GPIO_WritePin(Parallel_RLY_n_Enable_GPIO_Port, Parallel_RLY_n_Enable_Pin, GPIO_PIN_RESET);
		//  		HAL_GPIO_WritePin(Parallel_RLY_p_Enable_GPIO_Port, Parallel_RLY_p_Enable_Pin, GPIO_PIN_RESET);
		//		HAL_GPIO_WritePin(SMR1_RLY_n_Enable_GPIO_Port, SMR1_RLY_n_Enable_Pin, GPIO_PIN_RESET);
		//		HAL_GPIO_WritePin(SMR1_RLY_p_Enable_GPIO_Port, SMR1_RLY_p_Enable_Pin, GPIO_PIN_RESET);
		//		HAL_GPIO_WritePin(SMR2_RLY_n_Enable_GPIO_Port, SMR2_RLY_n_Enable_Pin, GPIO_PIN_RESET);
		//		HAL_GPIO_WritePin(SMR2_RLY_p_Enable_GPIO_Port, SMR2_RLY_p_Enable_Pin, GPIO_PIN_RESET);
		//		HAL_GPIO_WritePin(Contactor_Enable_GPIO_Port, Contactor_Enable_Pin, GPIO_PIN_RESET);
		//		HAL_GPIO_WritePin(Precharge_Enable_GPIO_Port, Precharge_Enable_Pin, GPIO_PIN_RESET);
		//
		//		osDelay(10);
		//  	}
		//
		osDelay(1);
	}
  /* USER CODE END Inkey_Task */
}

/* USER CODE BEGIN Header_Gfd_Left_Task */
/**
 * @brief Function implementing the gfd_left_Task thread.
 * @param argument: Not used
 * @retval None
 */
/* USER CODE END Header_Gfd_Left_Task */
void Gfd_Left_Task(void const * argument)
{
  /* USER CODE BEGIN Gfd_Left_Task */
  /* Infinite loop */
  
  	//   Fail   : <= 100ohm * 950v = 95K ohm
  	//  Warning : <= 475K ohm & > 95K ohm
	//   Pass   : > 500ohm * 950v = 475K ohm
  
  for(;;)
  {
  	uint16_t _delay;
  	  
//  	if( ( Module_Info.Dip_status.Mode == m_GUN_1)
//  		|| (Module_Info.Dip_status.Mode == m_ALL)
    // 21-08-26  Henry
//    if( Module_Info.Dip_status.Mode > 0
//  		)
  	{
  		switch(Module_Info.gfd_chk[0].Csu_State)
  		{
  		case IDLE:			// idle
  			_delay = 1000;
  			
  			if(bGfd_Correct[0] == 0)
  			{
  				Module_Info.gfd_chk[0].bResult_Gfd = GFD_UNKNOW;
  				Module_Info.gfd_chk[0].Rfd_State = 0;
  				// Module_Info.gfd_chk[0].bFirstGfd = 1;
  				
  				HAL_GPIO_WritePin(Drv_Up_GPIO_Port, Drv_Up_Pin, GPIO_PIN_RESET);
  				HAL_GPIO_WritePin(Drv_Down_GPIO_Port, Drv_Down_Pin, GPIO_PIN_RESET);
  				HAL_GPIO_WritePin(Sys1_Self_Test_DC_p_GPIO_Port, Sys1_Self_Test_DC_p_Pin, GPIO_PIN_RESET);
  				HAL_GPIO_WritePin(Sys1_Self_Test_DC_n_GPIO_Port, Sys1_Self_Test_DC_n_Pin, GPIO_PIN_RESET);
  			}
  			else 
  			{
  				HAL_GPIO_WritePin(Drv_Up_GPIO_Port, Drv_Up_Pin, GPIO_PIN_SET);
  				HAL_GPIO_WritePin(Drv_Down_GPIO_Port, Drv_Down_Pin, GPIO_PIN_SET);
  				
  				HAL_GPIO_WritePin(Sys1_Self_Test_DC_p_GPIO_Port, Sys1_Self_Test_DC_p_Pin, GPIO_PIN_RESET);
  				HAL_GPIO_WritePin(Sys1_Self_Test_DC_n_GPIO_Port, Sys1_Self_Test_DC_n_Pin, GPIO_PIN_RESET);
  			}
			Gfd.operation[0] = GFD_OFF;
			Gfd.ToggleBridge[0] = 0;
  			break;
  			
  		case CABLE_CHECK:			// Cable check  -- 500v  			
  			switch(Module_Info.gfd_chk[0].Rfd_State)
  			{
  			case 0:
  				// *********  On Up-Down Bridge
  				_delay = WAIT_FOR_RESISTER_CALC;
  				
  				if(Module_Info.gfd_chk[0].bResult_Gfd == GFD_UNKNOW)
  				{
					if(Gfd.operation[0] != Gfd.GfdMode[0]){
						Gfd.operation[0] = Gfd.GfdMode[0];		
						printf("Charge mode ,SMR1 GFD Mode is %s\n\r", Gfd.GfdMode[0] == GFD_BALANCE ? "Balance" : "Unbalance");
					}				

					if(Gfd.operation[0] == GFD_BALANCE){
						HAL_GPIO_WritePin(Drv_Up_GPIO_Port, Drv_Up_Pin, GPIO_PIN_SET);
						HAL_GPIO_WritePin(Drv_Down_GPIO_Port, Drv_Down_Pin, GPIO_PIN_SET);

						HAL_GPIO_WritePin(Sys1_Self_Test_DC_p_GPIO_Port, Sys1_Self_Test_DC_p_Pin, GPIO_PIN_SET);  	
				 		HAL_GPIO_WritePin(Sys1_Self_Test_DC_n_GPIO_Port, Sys1_Self_Test_DC_n_Pin, GPIO_PIN_RESET);	
						Gfd.SCBwaitfg[0] = 1;
					}	

					if(Gfd.operation[0] == GFD_UNBALANCE){
						// HAL_GPIO_WritePin(Drv_Up_GPIO_Port, Drv_Up_Pin, GPIO_PIN_SET);
						// HAL_GPIO_WritePin(Drv_Down_GPIO_Port, Drv_Down_Pin, GPIO_PIN_RESET);

						HAL_GPIO_WritePin(Sys1_Self_Test_DC_p_GPIO_Port, Sys1_Self_Test_DC_p_Pin, GPIO_PIN_SET);  	
						HAL_GPIO_WritePin(Sys1_Self_Test_DC_n_GPIO_Port, Sys1_Self_Test_DC_n_Pin, GPIO_PIN_SET);	
					}					
					Module_Info.gfd_chk[0].P2PE_GFD = 0;
					Module_Info.gfd_chk[0].N2PE_GFD = 0;
					Module_Info.gfd_chk[0].U1_V = 0;
					Module_Info.gfd_chk[0].U2_V = 0;
					Module_Info.gfd_chk[0].Rfd_State++;		
  				}
  				break;
  				
  			case 1:
  				_delay = WAIT_FOR_RESISTER_CALC_LONG;
  				
  				if( ! ((Module_Info.SMR_Gfd_Sense[0] > GFD_SENSE_VOLTAGE_DOWN_LIMIT)
  					&& (Module_Info.SMR_Gfd_Sense[0] < GFD_SENSE_VOLTAGE_UP_LIMIT)
  					&& (Module_Info.SMR1_Relay_V < GFD_WORKING_VOLTAGE))
  				){  					
					Module_Info.gfd_chk[0].Rfd_State++;
					Module_Info.gfd_chk[0].Gfd_Running_Count = 0;	
					// Self_Test_1_DC+
					// HAL_GPIO_WritePin(Sys1_Self_Test_DC_p_GPIO_Port, Sys1_Self_Test_DC_p_Pin, GPIO_PIN_SET);  	
					// HAL_GPIO_WritePin(Sys1_Self_Test_DC_n_GPIO_Port, Sys1_Self_Test_DC_n_Pin, GPIO_PIN_SET);				
  				
				}else{
  					Module_Info.gfd_chk[0].R_GFD = 1000000;		// 1000K Ohm
  					Module_Info.Alarm_CSU.flags.Gfd_Alarm_0 = OFF;  					
  					Module_Info.gfd_chk[0].Rfd_State = 0;
  				}
  				break;
  				
  			case 2:
  				_delay = 10;
  				
  				// begin isolation test ....Self_test
  				if(abs(Module_Info.SMR1_Relay_V - Gfd.IsolationVoltage) < LINE_VOLTAGE_TOLERANCE){    // ABS(20V)  				
  					Module_Info.gfd_chk[0].Gfd_Running_Count++;
  					if(Module_Info.gfd_chk[0].Gfd_Running_Count > 4){
  						if(Module_Info.gfd_chk[0].bFirstGfd ==1){
  							Module_Info.gfd_chk[0].Rfd_State = 5;
  						}else{
  							Module_Info.gfd_chk[0].Rfd_State++;
  						}  						
  						Module_Info.gfd_chk[0].Gfd_Running_Count = 0;
  					}
  				}else{
  					Module_Info.gfd_chk[0].Rfd_State = 0;
  				}
  				break;
  			case 3:
  				_delay = WAIT_FOR_RESISTER_CALC;
//----------------------------------------Banlance self check P2PE ----------------------------------------------
				if(Gfd.operation[0] == GFD_BALANCE){
					if(Gfd.SCBwaitfg[0] == 0 && Module_Info.gfd_chk[0].R_GFD != 0){
						if( Module_Info.gfd_chk[0].R_GFD < GFD_SELF_TEST_RESISTOR){ 		
								
							HAL_GPIO_WritePin(Sys1_Self_Test_DC_p_GPIO_Port, Sys1_Self_Test_DC_p_Pin, GPIO_PIN_RESET);  	
							HAL_GPIO_WritePin(Sys1_Self_Test_DC_n_GPIO_Port, Sys1_Self_Test_DC_n_Pin, GPIO_PIN_SET);	
							Module_Info.gfd_chk[0].Rfd_State++;  
							// Gfd.SCBwaitfg[0] = 1;								
						}else{   							
							Module_Info.gfd_chk[0].Gfd_Running_Count++;
							Module_Info.gfd_chk[0].R_GFD = 0;
						
							if(Module_Info.gfd_chk[0].Gfd_Running_Count > GFD_BALANCE_TEST_COUNT){
								Module_Info.gfd_chk[0].bResult_Gfd = GFD_FAIL;
								Module_Info.Alarm_CSU.flags.Gfd_Alarm_0 = ON; 
								Exti.EXTI_SMR1_Flag = true; 						
								
								Module_Info.gfd_chk[0].R_GFD_Fail 		= Module_Info.gfd_chk[0].R_GFD;
								Module_Info.gfd_chk[0].Rfd_State_Fail 	= Module_Info.gfd_chk[0].Rfd_State;
								Module_Info.gfd_chk[0].SMR_Voltage_Fail = Module_Info.SMR1_Relay_V;  						
								Module_Info.gfd_chk[0].Rfd_State = 0;
								printf("SMR1 GFD P2PE Self-check Fault ,P2PE = %dK\n\r", Module_Info.gfd_chk[0].R_GFD/1000);
							}
						}	
						Module_Info.gfd_chk[0].R_GFD = 0;
					}
				}	
//----------------------------------------Unbanlance self check P2PE ----------------------------------------------
				if(Gfd.operation[0] == GFD_UNBALANCE){
					if(Module_Info.gfd_chk[0].P2PE_GFD !=0 && Module_Info.gfd_chk[0].N2PE_GFD != 0){
						if( Module_Info.gfd_chk[0].P2PE_GFD < GFD_SELF_TEST_RESISTOR){ 		
							Module_Info.gfd_chk[0].Rfd_State++;  		
						}else{   							
							Module_Info.gfd_chk[0].Gfd_Running_Count++;							
							Module_Info.gfd_chk[0].U1_V = 0;
							Module_Info.gfd_chk[0].U2_V = 0;
							if(Module_Info.gfd_chk[0].Gfd_Running_Count > GFD_UNBALANCE_TEST_COUNT){
								Module_Info.gfd_chk[0].bResult_Gfd = GFD_FAIL;
								Module_Info.Alarm_CSU.flags.Gfd_Alarm_0 = ON;  	
								Exti.EXTI_SMR1_Flag = true;					
								
								Module_Info.gfd_chk[0].R_GFD_Fail 		= Module_Info.gfd_chk[0].P2PE_GFD;
								Module_Info.gfd_chk[0].Rfd_State_Fail 	= Module_Info.gfd_chk[0].Rfd_State;
								Module_Info.gfd_chk[0].SMR_Voltage_Fail = Module_Info.SMR1_Relay_V;  						
								Module_Info.gfd_chk[0].Rfd_State = 0;
								printf("SMR1 GFD P2PE Self-check Fault ,P2PE = %d, N2PE = %d \n\r", Module_Info.gfd_chk[0].P2PE_GFD,Module_Info.gfd_chk[0].N2PE_GFD);
							}else{
								Module_Info.gfd_chk[0].P2PE_GFD = 0;
							}
						}	
						Module_Info.gfd_chk[0].P2PE_GFD = 0;
					}
				}	
  				break;
  			case 4:
  				_delay = WAIT_FOR_RESISTER_CALC_FAST;
//----------------------------------------Banlance self check N2PE ----------------------------------------------
				if(Gfd.operation[0] == GFD_BALANCE){
					if(Gfd.SCBwaitfg[0] == 0 && Module_Info.gfd_chk[0].R_GFD != 0){
						if( Module_Info.gfd_chk[0].R_GFD < GFD_SELF_TEST_RESISTOR){ 		
								
							HAL_GPIO_WritePin(Sys1_Self_Test_DC_p_GPIO_Port, Sys1_Self_Test_DC_p_Pin, GPIO_PIN_RESET);  	
							HAL_GPIO_WritePin(Sys1_Self_Test_DC_n_GPIO_Port, Sys1_Self_Test_DC_n_Pin, GPIO_PIN_RESET);	
							Module_Info.gfd_chk[0].Rfd_State++;  
							// Gfd.SCBwaitfg[0] = 1;								

						}else{   							
							Module_Info.gfd_chk[0].Gfd_Running_Count++;							
						
							if(Module_Info.gfd_chk[0].Gfd_Running_Count > GFD_BALANCE_TEST_COUNT){
								Module_Info.gfd_chk[0].bResult_Gfd = GFD_FAIL;
								Module_Info.Alarm_CSU.flags.Gfd_Alarm_0 = ON;  
								Exti.EXTI_SMR1_Flag = true;						
								
								Module_Info.gfd_chk[0].R_GFD_Fail 		= Module_Info.gfd_chk[0].R_GFD;
								Module_Info.gfd_chk[0].Rfd_State_Fail 	= Module_Info.gfd_chk[0].Rfd_State;
								Module_Info.gfd_chk[0].SMR_Voltage_Fail = Module_Info.SMR1_Relay_V;  						
								Module_Info.gfd_chk[0].Rfd_State = 0;
								printf("SMR1 GFD N2PE Self-check Fault ,N2PE = %dK\n\r", Module_Info.gfd_chk[0].R_GFD/1000);
							}
						}								
						Module_Info.gfd_chk[0].R_GFD = 0;
					}
				}	
//----------------------------------------Unbanlance self check N2PE ----------------------------------------------
				if(Gfd.operation[0] == GFD_UNBALANCE){
					if(Module_Info.gfd_chk[0].N2PE_GFD < GFD_SELF_TEST_RESISTOR){	
						Module_Info.gfd_chk[0].Rfd_State++;
						Module_Info.gfd_chk[0].Gfd_Running_Count = 0;
						Module_Info.gfd_chk[0].Gfd_Warning_Count = 0;
						HAL_GPIO_WritePin(Sys1_Self_Test_DC_p_GPIO_Port, Sys1_Self_Test_DC_p_Pin, GPIO_PIN_RESET);  	
						HAL_GPIO_WritePin(Sys1_Self_Test_DC_n_GPIO_Port, Sys1_Self_Test_DC_n_Pin, GPIO_PIN_RESET);							
						Module_Info.gfd_chk[0].U1_V = 0;
						Module_Info.gfd_chk[0].U2_V = 0;
					}else{   					
						Module_Info.gfd_chk[0].Gfd_Running_Count++;
						Module_Info.gfd_chk[0].N2PE_GFD = 0;
						Module_Info.gfd_chk[0].U1_V = 0;
						Module_Info.gfd_chk[0].U2_V = 0;
						if(Module_Info.gfd_chk[0].Gfd_Running_Count > GFD_UNBALANCE_CABLECHK_TEST_COUNT){
							Module_Info.gfd_chk[0].bResult_Gfd = GFD_FAIL;
							Module_Info.Alarm_CSU.flags.Gfd_Alarm_0 = ON;  	
							Exti.EXTI_SMR1_Flag = true;					  					
							
							Module_Info.gfd_chk[0].R_GFD_Fail = Module_Info.gfd_chk[0].N2PE_GFD;
							Module_Info.gfd_chk[0].Rfd_State_Fail 	= Module_Info.gfd_chk[0].Rfd_State;
							Module_Info.gfd_chk[0].SMR_Voltage_Fail = Module_Info.SMR1_Relay_V;  						
							Module_Info.gfd_chk[0].Rfd_State = 0;
							printf("SMR1 GFD N2PE Self-check Fault ,P2PE = %d, N2PE = %d \n\r", Module_Info.gfd_chk[0].P2PE_GFD,Module_Info.gfd_chk[0].N2PE_GFD);
						}else{
								Module_Info.gfd_chk[0].N2PE_GFD = 0;
						}
					}						
					Module_Info.gfd_chk[0].N2PE_GFD = 0;
  				}
  				break;
   			case 5:
   				_delay = WAIT_FOR_RESISTER_CALC;
//----------------------------------------Banlance self check open circle ----------------------------------------------				
				if(Gfd.operation[0] == GFD_BALANCE){
					if(Gfd.SCBwaitfg[0] == 0 && Module_Info.gfd_chk[0].R_GFD != 0){							
						if( Module_Info.gfd_chk[0].R_GFD <= GFD_RESISTOR_FAULT * EVSE_MAX_OUTPUT_VOLTAGE + GFD_TOLERANCE_RESISTOR){
							if(Module_Info.SMR1_Relay_V >= GFD_WORKING_VOLTAGE){
								Module_Info.gfd_chk[0].Gfd_Running_Count++;
								Module_Info.gfd_chk[0].Gfd_Warning_Count = 0;								
							}
							
							if(Module_Info.gfd_chk[0].Gfd_Running_Count >GFD_BALANCE_TEST_COUNT){
								Module_Info.gfd_chk[0].bResult_Gfd = GFD_FAIL;
								Module_Info.Alarm_CSU.flags.Gfd_Alarm_0 = ON;  
								
								Module_Info.gfd_chk[0].R_GFD_Fail = Module_Info.gfd_chk[0].R_GFD;
								Module_Info.gfd_chk[0].Rfd_State_Fail 	= Module_Info.gfd_chk[0].Rfd_State;
								Module_Info.gfd_chk[0].SMR_Voltage_Fail = Module_Info.SMR1_Relay_V;  						
								Module_Info.gfd_chk[0].Rfd_State = 0;
								Exti.EXTI_SMR1_Flag = true;
								printf("SMR1 GFD Open circle Self-check Fault ,R = %dK,\n\r", Module_Info.gfd_chk[0].R_GFD/1000);
							}							
						}else{
							if( Module_Info.gfd_chk[0].R_GFD <= GFD_RESISTOR_WARNING * EVSE_MAX_OUTPUT_VOLTAGE && 
								Module_Info.gfd_chk[0].R_GFD > GFD_RESISTOR_FAULT * EVSE_MAX_OUTPUT_VOLTAGE + GFD_TOLERANCE_RESISTOR){
								
								if(Module_Info.SMR1_Relay_V >= GFD_WORKING_VOLTAGE){
									Module_Info.gfd_chk[0].Gfd_Running_Count = 0;
									Module_Info.gfd_chk[0].Gfd_Warning_Count++;									
								}
								
								if(Module_Info.gfd_chk[0].Gfd_Warning_Count > GFD_BALANCE_TEST_COUNT){	
									Module_Info.Alarm_CSU.flags.Gfd_Alarm_0 = ON;    									
									Module_Info.gfd_chk[0].bResult_Gfd = GFD_WARNING;
									Module_Info.gfd_chk[0].Rfd_State++;		
								printf("SMR1 GFD Open circle Self-check Warning ,R = %dK,\n\r", Module_Info.gfd_chk[0].R_GFD/1000);
									// }
								}					
							}else{
								// Gfd = Pass.							
									Module_Info.gfd_chk[0].bResult_Gfd = GFD_PASS;
									Module_Info.Alarm_CSU.flags.Gfd_Alarm_0 = OFF;    						
									Module_Info.gfd_chk[0].Rfd_State++;									
									printf("SMR1 GFD Self-check Pass ,R = %dK,\n\r", Module_Info.gfd_chk[0].R_GFD/1000);
							}					
						}	
						Module_Info.gfd_chk[0].R_GFD = 0;
					}	
				}	
//----------------------------------------Unbanlance self check open circle ----------------------------------------------				
				if(Gfd.operation[0] == GFD_UNBALANCE){

					if(Module_Info.gfd_chk[0].P2PE_GFD !=0 && Module_Info.gfd_chk[0].N2PE_GFD != 0){
							
						if( Module_Info.gfd_chk[0].P2PE_GFD <= GFD_RESISTOR_FAULT * EVSE_MAX_OUTPUT_VOLTAGE + GFD_TOLERANCE_RESISTOR ||
							Module_Info.gfd_chk[0].N2PE_GFD <= GFD_RESISTOR_FAULT * EVSE_MAX_OUTPUT_VOLTAGE + GFD_TOLERANCE_RESISTOR){
							if(Module_Info.SMR1_Relay_V >= GFD_WORKING_VOLTAGE){
								Module_Info.gfd_chk[0].Gfd_Running_Count++;
								Module_Info.gfd_chk[0].Gfd_Warning_Count = 0;
							}
							
							if(Module_Info.gfd_chk[0].Gfd_Running_Count >GFD_UNBALANCE_CABLECHK_TEST_COUNT){
								Module_Info.gfd_chk[0].bResult_Gfd = GFD_FAIL;
								Module_Info.Alarm_CSU.flags.Gfd_Alarm_0 = ON;  
								Exti.EXTI_SMR1_Flag = true;

								if(Module_Info.gfd_chk[0].P2PE_GFD <= GFD_RESISTOR_FAULT * EVSE_MAX_OUTPUT_VOLTAGE + GFD_TOLERANCE_RESISTOR){
									Module_Info.gfd_chk[0].R_GFD_Fail = Module_Info.gfd_chk[0].P2PE_GFD;
								}else{
									Module_Info.gfd_chk[0].R_GFD_Fail = Module_Info.gfd_chk[0].N2PE_GFD;
								}								
								
								Module_Info.gfd_chk[0].Rfd_State_Fail 	= Module_Info.gfd_chk[0].Rfd_State;
								Module_Info.gfd_chk[0].SMR_Voltage_Fail = Module_Info.SMR1_Relay_V;  						
								Module_Info.gfd_chk[0].Rfd_State = 0;
								printf("SMR1 GFD Self-check Fault ,P2PE = %dK, N2PE = %dK \n\r", Module_Info.gfd_chk[0].P2PE_GFD/1000,Module_Info.gfd_chk[0].N2PE_GFD/1000);
							}else{
								Module_Info.gfd_chk[0].P2PE_GFD = 0;
								Module_Info.gfd_chk[0].N2PE_GFD = 0;
							}
						}else{
							if((Module_Info.gfd_chk[0].P2PE_GFD <= GFD_RESISTOR_WARNING * EVSE_MAX_OUTPUT_VOLTAGE && 
								Module_Info.gfd_chk[0].P2PE_GFD > GFD_RESISTOR_FAULT * EVSE_MAX_OUTPUT_VOLTAGE + GFD_TOLERANCE_RESISTOR) ||
							   (Module_Info.gfd_chk[0].N2PE_GFD <= GFD_RESISTOR_WARNING * EVSE_MAX_OUTPUT_VOLTAGE && 
								Module_Info.gfd_chk[0].N2PE_GFD > GFD_RESISTOR_FAULT * EVSE_MAX_OUTPUT_VOLTAGE + GFD_TOLERANCE_RESISTOR)){
								
								if(Module_Info.SMR1_Relay_V >= GFD_WORKING_VOLTAGE){
									Module_Info.gfd_chk[0].Gfd_Running_Count = 0;
									Module_Info.gfd_chk[0].Gfd_Warning_Count++;
								}
								
								if(Module_Info.gfd_chk[0].Gfd_Warning_Count > GFD_UNBALANCE_CABLECHK_TEST_COUNT){
								
									// if(Module_Info.gfd_chk[0].bFirstGfd ==1){    							
									// 	Module_Info.gfd_chk[0].bFirstGfd = 0;    							
									// 	Module_Info.gfd_chk[0].bResult_Gfd = GFD_WARNING;
										Module_Info.Alarm_CSU.flags.Gfd_Alarm_0 = ON;    							
										
									// 	Module_Info.gfd_chk[0].Rfd_State++; 
									// }else{
										Module_Info.gfd_chk[0].bResult_Gfd = GFD_WARNING;
										Module_Info.gfd_chk[0].Rfd_State++;		
										printf("SMR1 GFD Self-check Warning ,P2PE = %dK, N2PE = %dK \n\r", Module_Info.gfd_chk[0].P2PE_GFD/1000,Module_Info.gfd_chk[0].N2PE_GFD/1000);
									// }
								}else{
									Module_Info.gfd_chk[0].P2PE_GFD = 0;
									Module_Info.gfd_chk[0].N2PE_GFD = 0;	
								}				
							}else{
								// Gfd = Pass.							
									Module_Info.gfd_chk[0].bResult_Gfd = GFD_PASS;
									Module_Info.Alarm_CSU.flags.Gfd_Alarm_0 = OFF;    						
									Module_Info.gfd_chk[0].Rfd_State++;									
									printf("SMR1 GFD Self-check pass,P2PE = %dK, N2PE = %dK \n\r", Module_Info.gfd_chk[0].P2PE_GFD/1000,Module_Info.gfd_chk[0].N2PE_GFD/1000);
							}
						}	
						// Module_Info.gfd_chk[0].P2PE_GFD = 0;
						// Module_Info.gfd_chk[0].N2PE_GFD = 0;
					}	
				}	
  				break;
  			default:
  				if((Module_Info.gfd_chk[0].bResult_Gfd == GFD_UNKNOW) || 
					(Module_Info.gfd_chk[0].bResult_Gfd == GFD_FAIL)){
  					Module_Info.gfd_chk[0].Rfd_State = 0;
  				}else{
  					Module_Info.gfd_chk[0].Rfd_State = 10;
  				}
  				break;
  			}
  			break;
  		case PRECHARGE: 
		case CHARGE:
			//預防系統在cable check未完成時,進入充電狀態
			if(Module_Info.gfd_chk[0].Rfd_State < 10 && Module_Info.gfd_chk[0].bResult_Gfd != GFD_FAIL){
				Module_Info.gfd_chk[0].Rfd_State =10;				
			}	
			
			//預防系統在cable check未完成時,進入充電狀態
			HAL_GPIO_WritePin(Sys1_Self_Test_DC_p_GPIO_Port, Sys1_Self_Test_DC_p_Pin, GPIO_PIN_RESET);  	
			HAL_GPIO_WritePin(Sys1_Self_Test_DC_n_GPIO_Port, Sys1_Self_Test_DC_n_Pin, GPIO_PIN_RESET);		

			if(Gfd.operation[0] != Gfd.GfdMode[0]){
				Gfd.operation[0] = Gfd.GfdMode[0];								
			}						
  			switch(Module_Info.gfd_chk[0].Rfd_State){
  			case 10:
  				// *********  On Up-Down Bridge
  				_delay = 1; 	
  				
  				Module_Info.gfd_chk[0].Rfd_State++;
				break;  				
  			case 11:
  				_delay = WAIT_FOR_RESISTER_CALC_FAST;
  				
  				if( ! ((Module_Info.SMR_Gfd_Sense[0] > GFD_SENSE_VOLTAGE_DOWN_LIMIT)
  					&& (Module_Info.SMR_Gfd_Sense[0] < GFD_SENSE_VOLTAGE_UP_LIMIT)
  					&& (Module_Info.SMR1_Relay_V < GFD_WORKING_VOLTAGE))){
  					Module_Info.gfd_chk[0].Rfd_State++;
  					Module_Info.gfd_chk[0].Gfd_Running_Count = 0;
  					Module_Info.gfd_chk[0].Gfd_Warning_Count = 0;
  				}else{ 								// Not Match to Ground Test condiction.  				
  					// Module_Info.gfd_chk[0].R_GFD = 1000000;		// 1000K Ohm
  					Module_Info.Alarm_CSU.flags.Gfd_Alarm_0 = OFF;
  					
  					Module_Info.gfd_chk[0].Rfd_State = 10;
  				}
  				break;
  			case 12:
   				_delay = WAIT_FOR_RESISTER_CALC_FAST;

				if(Gfd.operation[0] == GFD_BALANCE){   				  		
					if(Module_Info.gfd_chk[0].R_GFD <= ((GFD_RESISTOR_FAULT * EVSE_MAX_OUTPUT_VOLTAGE)+GFD_TOLERANCE_RESISTOR)){
						if(Module_Info.SMR1_Relay_V >= GFD_WORKING_VOLTAGE){
							Module_Info.gfd_chk[0].Gfd_Warning_Count = 0;
							Module_Info.gfd_chk[0].Gfd_Running_Count++;
						}
						
						if(Module_Info.gfd_chk[0].Gfd_Running_Count >GFD_BALANCE_TEST_COUNT){
							Module_Info.gfd_chk[0].bResult_Gfd = GFD_FAIL;
							Module_Info.Alarm_CSU.flags.Gfd_Alarm_0 = ON;    
							Exti.EXTI_SMR1_Flag = true;		
							
							Module_Info.gfd_chk[0].R_GFD_Fail = Module_Info.gfd_chk[0].R_GFD;
							Module_Info.gfd_chk[0].Rfd_State_Fail 	= Module_Info.gfd_chk[0].Rfd_State;
							Module_Info.gfd_chk[0].SMR_Voltage_Fail = Module_Info.SMR1_Relay_V;  						
							Module_Info.gfd_chk[0].Rfd_State = 0;
						}
					}else{
						if( ( Module_Info.gfd_chk[0].R_GFD <= (GFD_RESISTOR_WARNING * EVSE_MAX_OUTPUT_VOLTAGE) ) &&
							(Module_Info.gfd_chk[0].R_GFD > ((GFD_RESISTOR_FAULT * EVSE_MAX_OUTPUT_VOLTAGE)+GFD_TOLERANCE_RESISTOR))){
						
							if(Module_Info.SMR1_Relay_V >= GFD_WORKING_VOLTAGE){
								Module_Info.gfd_chk[0].Gfd_Running_Count = 0;
								Module_Info.gfd_chk[0].Gfd_Warning_Count++;
							}
							
							if(Module_Info.gfd_chk[0].Gfd_Warning_Count >GFD_BALANCE_TEST_COUNT){
								Module_Info.gfd_chk[0].bResult_Gfd = GFD_WARNING;
								Module_Info.gfd_chk[0].Rfd_State++;
							}
						}else{
							Module_Info.gfd_chk[0].bResult_Gfd = GFD_PASS;
							Module_Info.Alarm_CSU.flags.Gfd_Alarm_0 = OFF;
							Module_Info.gfd_chk[0].Rfd_State++;
						}
					}
				}else if(Gfd.operation[0] == GFD_UNBALANCE){
					if(Module_Info.gfd_chk[0].P2PE_GFD !=0 && Module_Info.gfd_chk[0].N2PE_GFD != 0){
						if( Module_Info.gfd_chk[0].P2PE_GFD <= ((GFD_RESISTOR_FAULT * EVSE_MAX_OUTPUT_VOLTAGE)+GFD_TOLERANCE_RESISTOR) ||
							Module_Info.gfd_chk[0].N2PE_GFD <= ((GFD_RESISTOR_FAULT * EVSE_MAX_OUTPUT_VOLTAGE)+GFD_TOLERANCE_RESISTOR)){
							if(Module_Info.SMR1_Relay_V >= GFD_WORKING_VOLTAGE){
								Module_Info.gfd_chk[0].Gfd_Warning_Count = 0;
								Module_Info.gfd_chk[0].Gfd_Running_Count++;
							}
							
							if(Module_Info.gfd_chk[0].Gfd_Running_Count >GFD_UNBALANCE_TEST_COUNT){
								Module_Info.gfd_chk[0].bResult_Gfd = GFD_FAIL;
								Module_Info.Alarm_CSU.flags.Gfd_Alarm_0 = ON;    
								Exti.EXTI_SMR1_Flag = true;		
								
								Module_Info.gfd_chk[0].R_GFD_Fail = Module_Info.gfd_chk[0].R_GFD;
								Module_Info.gfd_chk[0].Rfd_State_Fail 	= Module_Info.gfd_chk[0].Rfd_State;
								Module_Info.gfd_chk[0].SMR_Voltage_Fail = Module_Info.SMR1_Relay_V;  						
								Module_Info.gfd_chk[0].Rfd_State = 0;
							}else{
								Module_Info.gfd_chk[0].P2PE_GFD = 0;
								Module_Info.gfd_chk[0].N2PE_GFD = 0;
							}
						}else{
							if( (Module_Info.gfd_chk[0].P2PE_GFD <= GFD_RESISTOR_WARNING * EVSE_MAX_OUTPUT_VOLTAGE &&
								Module_Info.gfd_chk[0].P2PE_GFD > (GFD_RESISTOR_FAULT * EVSE_MAX_OUTPUT_VOLTAGE)+GFD_TOLERANCE_RESISTOR) ||
								(Module_Info.gfd_chk[0].N2PE_GFD <= GFD_RESISTOR_WARNING * EVSE_MAX_OUTPUT_VOLTAGE &&
								Module_Info.gfd_chk[0].N2PE_GFD > (GFD_RESISTOR_FAULT * EVSE_MAX_OUTPUT_VOLTAGE)+GFD_TOLERANCE_RESISTOR)){
							
								if(Module_Info.SMR1_Relay_V >= GFD_WORKING_VOLTAGE){
									Module_Info.gfd_chk[0].Gfd_Running_Count = 0;
									Module_Info.gfd_chk[0].Gfd_Warning_Count++;
								}
								
								if(Module_Info.gfd_chk[0].Gfd_Warning_Count >GFD_UNBALANCE_TEST_COUNT){
									Module_Info.gfd_chk[0].bResult_Gfd = GFD_WARNING;
									Module_Info.gfd_chk[0].Rfd_State++;
								}else{
									Module_Info.gfd_chk[0].P2PE_GFD = 0;
									Module_Info.gfd_chk[0].N2PE_GFD = 0;
								}
							}else{
								Module_Info.gfd_chk[0].bResult_Gfd = GFD_PASS;
								Module_Info.Alarm_CSU.flags.Gfd_Alarm_0 = OFF;
								Module_Info.gfd_chk[0].Rfd_State++;
							}
						}
					}	
				}	
  				break;
  			default:
  				if(Module_Info.gfd_chk[0].bResult_Gfd != GFD_FAIL)
  					Module_Info.gfd_chk[0].Rfd_State = 10;
  				break;
  			}
  			break;
  		default:  			
  			break;
  		}
  		
  		if(Module_Info.gfd_chk[0].bResult_Gfd == GFD_FAIL)
  		{
  			_delay = 100;  	  			
    		HAL_GPIO_WritePin(SMR1_RLY_n_Enable_GPIO_Port, SMR1_RLY_n_Enable_Pin, GPIO_PIN_RESET);
    		HAL_GPIO_WritePin(SMR1_RLY_p_Enable_GPIO_Port, SMR1_RLY_p_Enable_Pin, GPIO_PIN_RESET);  
    		bRelayFeedback = 1;
  		}    
    	vTaskDelay( _delay / portTICK_RATE_MS);
    }
//    else
//    	osDelay(1);
  }
  /* USER CODE END Gfd_Left_Task */
}

/* USER CODE BEGIN Header_Gfd_Right_Task */
/**
* @brief Function implementing the gfd_right_Task thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_Gfd_Right_Task */
void Gfd_Right_Task(void const * argument)
{
  /* USER CODE BEGIN Gfd_Right_Task */
  /* Infinite loop */
  
  	//   Fail   : <= 100ohm * 950v = 95K ohm
  	//  Warning : <= 475K ohm & > 95K ohm
	//   Pass   : > 500ohm * 950v = 475K
	
   for(;;)
  {
  	uint16_t _delay;
  	  
//  	if( ( Module_Info.Dip_status.Mode == m_GUN_1)
//  		|| (Module_Info.Dip_status.Mode == m_ALL)
    // 21-08-26  Henry
//    if( Module_Info.Dip_status.Mode > 0
//  		)
  	{
  		switch(Module_Info.gfd_chk[1].Csu_State)
  		{
  		case IDLE:			// idle
  			_delay = 1000;
  			
  			if(bGfd_Correct[1] == 0)
  			{
  				Module_Info.gfd_chk[1].bResult_Gfd = GFD_UNKNOW;
  				Module_Info.gfd_chk[1].Rfd_State = 0;
  				// Module_Info.gfd_chk[0].bFirstGfd = 1;
  				
  				HAL_GPIO_WritePin(Drv_Up_2_GPIO_Port, Drv_Up_2_Pin, GPIO_PIN_RESET);
  				HAL_GPIO_WritePin(Drv_Down_2_GPIO_Port, Drv_Down_2_Pin, GPIO_PIN_RESET);
  				HAL_GPIO_WritePin(Sys2_Self_Test_DC_p_GPIO_Port, Sys2_Self_Test_DC_p_Pin, GPIO_PIN_RESET);
  				HAL_GPIO_WritePin(Sys2_Self_Test_DC_n_GPIO_Port, Sys2_Self_Test_DC_n_Pin, GPIO_PIN_RESET);
  			}
  			else 
  			{
  				HAL_GPIO_WritePin(Drv_Up_2_GPIO_Port, Drv_Up_2_Pin, GPIO_PIN_SET);
  				HAL_GPIO_WritePin(Drv_Down_2_GPIO_Port, Drv_Down_2_Pin, GPIO_PIN_RESET);
  				
  				HAL_GPIO_WritePin(Sys2_Self_Test_DC_p_GPIO_Port, Sys2_Self_Test_DC_p_Pin, GPIO_PIN_RESET);
  				HAL_GPIO_WritePin(Sys2_Self_Test_DC_n_GPIO_Port, Sys2_Self_Test_DC_n_Pin, GPIO_PIN_RESET);
  			}
			Gfd.operation[1] = GFD_OFF;
			Gfd.ToggleBridge[1] = 0;			
  			break;
  			
  		case CABLE_CHECK:			// Cable check  -- 500v  			
  			switch(Module_Info.gfd_chk[1].Rfd_State)
  			{
  			case 0:
  				// *********  On Up-Down Bridge
  				_delay = WAIT_FOR_RESISTER_CALC;
  				
  				if(Module_Info.gfd_chk[1].bResult_Gfd == GFD_UNKNOW)
  				{
					if(Gfd.operation[1] != Gfd.GfdMode[1]){
						Gfd.operation[1] = Gfd.GfdMode[1];		
						printf("Charge mode ,SMR2 GFD Mode is %s\n\r", Gfd.GfdMode[1] == GFD_BALANCE ? "Balance" : "Unbalance");
					}						
					if(Gfd.operation[1] == GFD_BALANCE){
						HAL_GPIO_WritePin(Drv_Up_2_GPIO_Port, Drv_Up_2_Pin, GPIO_PIN_SET);
  						HAL_GPIO_WritePin(Drv_Down_2_GPIO_Port, Drv_Down_2_Pin, GPIO_PIN_SET);

						HAL_GPIO_WritePin(Sys2_Self_Test_DC_p_GPIO_Port, Sys2_Self_Test_DC_p_Pin, GPIO_PIN_SET);  	
				 		HAL_GPIO_WritePin(Sys2_Self_Test_DC_n_GPIO_Port, Sys2_Self_Test_DC_n_Pin, GPIO_PIN_RESET);	
						Gfd.SCBwaitfg[1] = 1;
					}	

					if(Gfd.operation[1] == GFD_UNBALANCE){
						// HAL_GPIO_WritePin(Drv_Up_2_GPIO_Port, Drv_Up_2_Pin, GPIO_PIN_RESET);
  						// HAL_GPIO_WritePin(Drv_Down_2_GPIO_Port, Drv_Down_2_Pin, GPIO_PIN_SET);

						HAL_GPIO_WritePin(Sys2_Self_Test_DC_p_GPIO_Port, Sys2_Self_Test_DC_p_Pin, GPIO_PIN_SET);  	
						HAL_GPIO_WritePin(Sys2_Self_Test_DC_n_GPIO_Port, Sys2_Self_Test_DC_n_Pin, GPIO_PIN_SET);	
					}					
					Module_Info.gfd_chk[1].P2PE_GFD = 0;
					Module_Info.gfd_chk[1].N2PE_GFD = 0;
					Module_Info.gfd_chk[1].U1_V = 0;
					Module_Info.gfd_chk[1].U2_V = 0;
					Module_Info.gfd_chk[1].Rfd_State++;		
  				}
  				break;
  				
  			case 1:
  				_delay = WAIT_FOR_RESISTER_CALC_LONG;
  				
  				if( ! ((Module_Info.SMR_Gfd_Sense[1] > GFD_SENSE_VOLTAGE_DOWN_LIMIT)
  					&& (Module_Info.SMR_Gfd_Sense[1] < GFD_SENSE_VOLTAGE_UP_LIMIT)
  					&& (Module_Info.SMR2_Relay_V < GFD_WORKING_VOLTAGE))
  				){  					
					Module_Info.gfd_chk[1].Rfd_State++;
					Module_Info.gfd_chk[1].Gfd_Running_Count = 0;	
					// Self_Test_1_DC+
					// HAL_GPIO_WritePin(Sys1_Self_Test_DC_p_GPIO_Port, Sys1_Self_Test_DC_p_Pin, GPIO_PIN_SET);  	
					// HAL_GPIO_WritePin(Sys1_Self_Test_DC_n_GPIO_Port, Sys1_Self_Test_DC_n_Pin, GPIO_PIN_SET);				
  				
				}else{
  					Module_Info.gfd_chk[1].R_GFD = 1000000;		// 1000K Ohm
  					Module_Info.Alarm_CSU.flags.Gfd_Alarm_1 = OFF;  					
  					Module_Info.gfd_chk[1].Rfd_State = 0;
  				}
  				break;
  				
  			case 2:
  				_delay = 10;					
  				if(abs(Module_Info.SMR2_Relay_V - Gfd.IsolationVoltage) < LINE_VOLTAGE_TOLERANCE){    // ABS(20V)  				
  					Module_Info.gfd_chk[1].Gfd_Running_Count++;
  					if(Module_Info.gfd_chk[1].Gfd_Running_Count > 4){  						
						Module_Info.gfd_chk[1].Rfd_State++;  						 						
  						Module_Info.gfd_chk[1].Gfd_Running_Count = 0;
  					}
  				}else{
  					Module_Info.gfd_chk[1].Rfd_State = 0;
  				}
  				break;
  			case 3:
  				_delay = WAIT_FOR_RESISTER_CALC;
//----------------------------------------Banlance self check P2PE ----------------------------------------------
				if(Gfd.operation[1] == GFD_BALANCE){
					if(Gfd.SCBwaitfg[1] == 0 && Module_Info.gfd_chk[1].R_GFD != 0){
						if( Module_Info.gfd_chk[1].R_GFD < GFD_SELF_TEST_RESISTOR){ 		
								
							HAL_GPIO_WritePin(Sys2_Self_Test_DC_p_GPIO_Port, Sys2_Self_Test_DC_p_Pin, GPIO_PIN_RESET);  	
							HAL_GPIO_WritePin(Sys2_Self_Test_DC_n_GPIO_Port, Sys2_Self_Test_DC_n_Pin, GPIO_PIN_SET);	
							Module_Info.gfd_chk[1].Rfd_State++;  
							// Gfd.SCBwaitfg[1] = 1;	
						}else{   							
							Module_Info.gfd_chk[1].Gfd_Running_Count++;							
						
							if(Module_Info.gfd_chk[1].Gfd_Running_Count > GFD_BALANCE_TEST_COUNT){
								Module_Info.gfd_chk[1].bResult_Gfd = GFD_FAIL;
								Module_Info.Alarm_CSU.flags.Gfd_Alarm_1 = ON;  		
								Exti.EXTI_SMR2_Flag = true;				
								
								Module_Info.gfd_chk[1].R_GFD_Fail 		= Module_Info.gfd_chk[1].R_GFD;
								Module_Info.gfd_chk[1].Rfd_State_Fail 	= Module_Info.gfd_chk[1].Rfd_State;
								Module_Info.gfd_chk[1].SMR_Voltage_Fail = Module_Info.SMR2_Relay_V;  						
								Module_Info.gfd_chk[1].Rfd_State = 0;
								printf("SMR2 GFD P2PE Self-check Fault ,P2PE = %dK\n\r", Module_Info.gfd_chk[1].R_GFD/1000);								
							}							
						}	
						Module_Info.gfd_chk[1].R_GFD = 0;
					}
				}	
//----------------------------------------Unbanlance self check P2PE ----------------------------------------------
				if(Gfd.operation[1] == GFD_UNBALANCE){
					if(Module_Info.gfd_chk[1].P2PE_GFD !=0 && Module_Info.gfd_chk[1].N2PE_GFD != 0){
						if( Module_Info.gfd_chk[1].P2PE_GFD < GFD_SELF_TEST_RESISTOR){ 		
							Module_Info.gfd_chk[1].Rfd_State++;  		
						}else{   							
							Module_Info.gfd_chk[1].Gfd_Running_Count++;							
							Module_Info.gfd_chk[1].U1_V = 0;
							Module_Info.gfd_chk[1].U2_V = 0;
							if(Module_Info.gfd_chk[1].Gfd_Running_Count > GFD_UNBALANCE_TEST_COUNT){
								Module_Info.gfd_chk[1].bResult_Gfd = GFD_FAIL;
								Module_Info.Alarm_CSU.flags.Gfd_Alarm_1 = ON;  	
								Exti.EXTI_SMR2_Flag = true;					
								
								Module_Info.gfd_chk[1].R_GFD_Fail 		= Module_Info.gfd_chk[1].P2PE_GFD;
								Module_Info.gfd_chk[1].Rfd_State_Fail 	= Module_Info.gfd_chk[1].Rfd_State;
								Module_Info.gfd_chk[1].SMR_Voltage_Fail = Module_Info.SMR2_Relay_V;  						
								Module_Info.gfd_chk[1].Rfd_State = 0;
								printf("SMR2 GFD P2PE Self-check Fault ,P2PE = %d, N2PE = %d \n\r", Module_Info.gfd_chk[1].P2PE_GFD,Module_Info.gfd_chk[1].N2PE_GFD);
							}else{
								Module_Info.gfd_chk[1].P2PE_GFD = 0;
								Module_Info.gfd_chk[1].N2PE_GFD = 0;
							}
							
						}	
						Module_Info.gfd_chk[1].P2PE_GFD = 0;
					}
				}	
  				break;
  			case 4:
  				_delay = WAIT_FOR_RESISTER_CALC_FAST;
//----------------------------------------Banlance self check N2PE ----------------------------------------------
				if(Gfd.operation[1] == GFD_BALANCE){
					if(Gfd.SCBwaitfg[1] == 0 && Module_Info.gfd_chk[1].R_GFD != 0){
						if( Module_Info.gfd_chk[1].R_GFD < GFD_SELF_TEST_RESISTOR){ 		
								
							HAL_GPIO_WritePin(Sys2_Self_Test_DC_p_GPIO_Port, Sys2_Self_Test_DC_p_Pin, GPIO_PIN_RESET);  	
							HAL_GPIO_WritePin(Sys2_Self_Test_DC_n_GPIO_Port, Sys2_Self_Test_DC_n_Pin, GPIO_PIN_RESET);	
							Module_Info.gfd_chk[1].Rfd_State++;  
							// Gfd.SCBwaitfg[1] = 1;	
							

						}else{   							
							Module_Info.gfd_chk[1].Gfd_Running_Count++;							
						
							if(Module_Info.gfd_chk[1].Gfd_Running_Count > GFD_BALANCE_TEST_COUNT){
								Module_Info.gfd_chk[1].bResult_Gfd = GFD_FAIL;
								Module_Info.Alarm_CSU.flags.Gfd_Alarm_1 = ON;  	
								Exti.EXTI_SMR2_Flag = true;					
								
								Module_Info.gfd_chk[1].R_GFD_Fail 		= Module_Info.gfd_chk[1].R_GFD;
								Module_Info.gfd_chk[1].Rfd_State_Fail 	= Module_Info.gfd_chk[1].Rfd_State;
								Module_Info.gfd_chk[1].SMR_Voltage_Fail = Module_Info.SMR2_Relay_V;  						
								Module_Info.gfd_chk[1].Rfd_State = 0;
								printf("SMR2 GFD N2PE Self-check Fault ,N2PE = %dK\n\r", Module_Info.gfd_chk[1].R_GFD/1000);
							}
							
						}	
						Module_Info.gfd_chk[1].R_GFD = 0;							
					}
				}	
//----------------------------------------Unbanlance self check N2PE ----------------------------------------------
				if(Gfd.operation[1] == GFD_UNBALANCE){
					if(Module_Info.gfd_chk[1].N2PE_GFD < GFD_SELF_TEST_RESISTOR){	
						Module_Info.gfd_chk[1].Rfd_State++;
						Module_Info.gfd_chk[1].Gfd_Running_Count = 0;
						Module_Info.gfd_chk[1].Gfd_Warning_Count = 0;
						HAL_GPIO_WritePin(Sys2_Self_Test_DC_p_GPIO_Port, Sys2_Self_Test_DC_p_Pin, GPIO_PIN_RESET);  	
						HAL_GPIO_WritePin(Sys2_Self_Test_DC_n_GPIO_Port, Sys2_Self_Test_DC_n_Pin, GPIO_PIN_RESET);	
						Module_Info.gfd_chk[1].P2PE_GFD = 0;
						Module_Info.gfd_chk[1].N2PE_GFD = 0;
						Module_Info.gfd_chk[1].U1_V = 0;
						Module_Info.gfd_chk[1].U2_V = 0;
					}else{   					
						Module_Info.gfd_chk[1].Gfd_Running_Count++;
						
						Module_Info.gfd_chk[1].U1_V = 0;
						Module_Info.gfd_chk[1].U2_V = 0;
						if(Module_Info.gfd_chk[1].Gfd_Running_Count > GFD_UNBALANCE_CABLECHK_TEST_COUNT){
							Module_Info.gfd_chk[1].bResult_Gfd = GFD_FAIL;
							Module_Info.Alarm_CSU.flags.Gfd_Alarm_1 = ON;  			
							Exti.EXTI_SMR2_Flag = true;			  					
							
							Module_Info.gfd_chk[1].R_GFD_Fail = Module_Info.gfd_chk[1].N2PE_GFD;
							Module_Info.gfd_chk[1].Rfd_State_Fail 	= Module_Info.gfd_chk[1].Rfd_State;
							Module_Info.gfd_chk[1].SMR_Voltage_Fail = Module_Info.SMR2_Relay_V;  						
							Module_Info.gfd_chk[1].Rfd_State = 0;
							printf("SMR2 GFD N2PE Self-check Fault ,P2PE = %d, N2PE = %d \n\r", Module_Info.gfd_chk[1].P2PE_GFD,Module_Info.gfd_chk[1].N2PE_GFD);
						}else{
							Module_Info.gfd_chk[1].P2PE_GFD = 0;
							Module_Info.gfd_chk[1].N2PE_GFD = 0;
						}
						Module_Info.gfd_chk[1].N2PE_GFD = 0;
					}	
  				}
  				break;
   			case 5:
   				_delay = WAIT_FOR_RESISTER_CALC;
//----------------------------------------Banlance self check open circle ----------------------------------------------				
				if(Gfd.operation[1] == GFD_BALANCE){
					if(Gfd.SCBwaitfg[1] == 0 && Module_Info.gfd_chk[1].R_GFD != 0){							
						if( Module_Info.gfd_chk[1].R_GFD <= GFD_RESISTOR_FAULT * EVSE_MAX_OUTPUT_VOLTAGE + GFD_TOLERANCE_RESISTOR){
							if(Module_Info.SMR2_Relay_V >= GFD_WORKING_VOLTAGE){
								Module_Info.gfd_chk[1].Gfd_Running_Count++;
								Module_Info.gfd_chk[1].Gfd_Warning_Count = 0;								
							}
							
							if(Module_Info.gfd_chk[1].Gfd_Running_Count >GFD_BALANCE_TEST_COUNT){
								Module_Info.gfd_chk[1].bResult_Gfd = GFD_FAIL;
								Module_Info.Alarm_CSU.flags.Gfd_Alarm_1 = ON;  
								Exti.EXTI_SMR2_Flag = true;
								
								Module_Info.gfd_chk[1].R_GFD_Fail = Module_Info.gfd_chk[1].R_GFD;
								Module_Info.gfd_chk[1].Rfd_State_Fail 	= Module_Info.gfd_chk[1].Rfd_State;
								Module_Info.gfd_chk[1].SMR_Voltage_Fail = Module_Info.SMR2_Relay_V;  						
								Module_Info.gfd_chk[1].Rfd_State = 0;
								printf("SMR2 GFD Open circle Self-check Fault ,R = %dK,\n\r", Module_Info.gfd_chk[1].R_GFD/1000);
							}							
						}else{
							if( Module_Info.gfd_chk[1].R_GFD <= GFD_RESISTOR_WARNING * EVSE_MAX_OUTPUT_VOLTAGE && 
								Module_Info.gfd_chk[1].R_GFD > GFD_RESISTOR_FAULT * EVSE_MAX_OUTPUT_VOLTAGE + GFD_TOLERANCE_RESISTOR){
								
								if(Module_Info.SMR2_Relay_V >= GFD_WORKING_VOLTAGE){
									Module_Info.gfd_chk[1].Gfd_Running_Count = 0;
									Module_Info.gfd_chk[1].Gfd_Warning_Count++;
									
								}
								
								if(Module_Info.gfd_chk[1].Gfd_Warning_Count > GFD_BALANCE_TEST_COUNT){	
									Module_Info.Alarm_CSU.flags.Gfd_Alarm_1 = ON;    									
									Module_Info.gfd_chk[1].bResult_Gfd = GFD_WARNING;
									Module_Info.gfd_chk[1].Rfd_State++;		
									printf("SMR2 GFD Open circle Self-check Warning ,R = %dK,\n\r", Module_Info.gfd_chk[1].R_GFD/1000);									
								}		
										
							}else{
								// Gfd = Pass.							
									Module_Info.gfd_chk[1].bResult_Gfd = GFD_PASS;
									Module_Info.Alarm_CSU.flags.Gfd_Alarm_1 = OFF;    						
									Module_Info.gfd_chk[1].Rfd_State++;									
									printf("SMR2 GFD Self-check Pass ,R = %dK,\n\r", Module_Info.gfd_chk[1].R_GFD/1000);
							}	
										
						}	
						Module_Info.gfd_chk[1].R_GFD = 0;		
					}	
				}	
//----------------------------------------Unbanlance self check open circle ----------------------------------------------				
				if(Gfd.operation[1] == GFD_UNBALANCE){

					if(Module_Info.gfd_chk[1].P2PE_GFD !=0 && Module_Info.gfd_chk[1].N2PE_GFD != 0){
							
						if( Module_Info.gfd_chk[1].P2PE_GFD <= GFD_RESISTOR_FAULT * EVSE_MAX_OUTPUT_VOLTAGE + GFD_TOLERANCE_RESISTOR ||
							Module_Info.gfd_chk[1].N2PE_GFD <= GFD_RESISTOR_FAULT * EVSE_MAX_OUTPUT_VOLTAGE + GFD_TOLERANCE_RESISTOR){
							if(Module_Info.SMR2_Relay_V >= GFD_WORKING_VOLTAGE){
								Module_Info.gfd_chk[1].Gfd_Running_Count++;
								Module_Info.gfd_chk[1].Gfd_Warning_Count = 0;
							}
							
							if(Module_Info.gfd_chk[1].Gfd_Running_Count >GFD_UNBALANCE_CABLECHK_TEST_COUNT){
								Module_Info.gfd_chk[1].bResult_Gfd = GFD_FAIL;
								Module_Info.Alarm_CSU.flags.Gfd_Alarm_1 = ON;  
								Exti.EXTI_SMR2_Flag = true;

								if(Module_Info.gfd_chk[1].P2PE_GFD <= GFD_RESISTOR_FAULT * EVSE_MAX_OUTPUT_VOLTAGE + GFD_TOLERANCE_RESISTOR){
									Module_Info.gfd_chk[1].R_GFD_Fail = Module_Info.gfd_chk[1].P2PE_GFD;
								}else{
									Module_Info.gfd_chk[1].R_GFD_Fail = Module_Info.gfd_chk[1].N2PE_GFD;
								}										
								Module_Info.gfd_chk[1].Rfd_State_Fail 	= Module_Info.gfd_chk[1].Rfd_State;
								Module_Info.gfd_chk[1].SMR_Voltage_Fail = Module_Info.SMR2_Relay_V;  						
								Module_Info.gfd_chk[1].Rfd_State = 0;
								printf("SMR2 GFD Self-check Fault ,P2PE = %dK, N2PE = %dK \n\r", Module_Info.gfd_chk[1].P2PE_GFD/1000,Module_Info.gfd_chk[1].N2PE_GFD/1000);
							}else{
								Module_Info.gfd_chk[1].P2PE_GFD = 0;
								Module_Info.gfd_chk[1].N2PE_GFD = 0;
							}
						}else{
							if((Module_Info.gfd_chk[1].P2PE_GFD <= GFD_RESISTOR_WARNING * EVSE_MAX_OUTPUT_VOLTAGE && 
								Module_Info.gfd_chk[1].P2PE_GFD > GFD_RESISTOR_FAULT * EVSE_MAX_OUTPUT_VOLTAGE + GFD_TOLERANCE_RESISTOR) ||
							   (Module_Info.gfd_chk[1].N2PE_GFD <= GFD_RESISTOR_WARNING * EVSE_MAX_OUTPUT_VOLTAGE && 
								Module_Info.gfd_chk[1].N2PE_GFD > GFD_RESISTOR_FAULT * EVSE_MAX_OUTPUT_VOLTAGE + GFD_TOLERANCE_RESISTOR)){
								
								if(Module_Info.SMR2_Relay_V >= GFD_WORKING_VOLTAGE){
									Module_Info.gfd_chk[1].Gfd_Running_Count = 0;
									Module_Info.gfd_chk[1].Gfd_Warning_Count++;
								}
								
								if(Module_Info.gfd_chk[1].Gfd_Warning_Count > GFD_UNBALANCE_CABLECHK_TEST_COUNT){							
									
										Module_Info.Alarm_CSU.flags.Gfd_Alarm_1 = ON;   								
										Module_Info.gfd_chk[1].bResult_Gfd = GFD_WARNING;
										Module_Info.gfd_chk[1].Rfd_State++;		
										printf("SMR2 GFD Self-check Warning ,P2PE = %dK, N2PE = %dK \n\r", Module_Info.gfd_chk[1].P2PE_GFD/1000,Module_Info.gfd_chk[1].N2PE_GFD/1000);
								}else{
									Module_Info.gfd_chk[1].P2PE_GFD = 0;
									Module_Info.gfd_chk[1].N2PE_GFD = 0;
								}					
							}else{
								// Gfd = Pass.							
									Module_Info.gfd_chk[1].bResult_Gfd = GFD_PASS;
									Module_Info.Alarm_CSU.flags.Gfd_Alarm_1 = OFF;    						
									Module_Info.gfd_chk[1].Rfd_State++;									
									printf("SMR2 GFD Self-check pass,P2PE = %dK, N2PE = %dK \n\r", Module_Info.gfd_chk[1].P2PE_GFD/1000,Module_Info.gfd_chk[1].N2PE_GFD/1000);
							}							
						}	
						// Module_Info.gfd_chk[1].P2PE_GFD = 0;			
						// Module_Info.gfd_chk[1].N2PE_GFD = 0;						
					}	
				}	
  				break;
  			default:
  				if((Module_Info.gfd_chk[1].bResult_Gfd == GFD_UNKNOW) || 
					(Module_Info.gfd_chk[1].bResult_Gfd == GFD_FAIL)){
  					Module_Info.gfd_chk[1].Rfd_State = 0;
  				}else{
  					Module_Info.gfd_chk[1].Rfd_State = 10;
  				}
  				break;
  			}
  			break;
  		case PRECHARGE: 
		case CHARGE:

			//預防系統在cable check未完成時,進入充電狀態
			if(Module_Info.gfd_chk[1].Rfd_State < 10 && Module_Info.gfd_chk[1].bResult_Gfd != GFD_FAIL){
				Module_Info.gfd_chk[1].Rfd_State =10;				
			}	

			//預防系統在cable check未完成時,進入充電狀態
			HAL_GPIO_WritePin(Sys2_Self_Test_DC_p_GPIO_Port, Sys2_Self_Test_DC_p_Pin, GPIO_PIN_RESET);  	
			HAL_GPIO_WritePin(Sys2_Self_Test_DC_n_GPIO_Port, Sys2_Self_Test_DC_n_Pin, GPIO_PIN_RESET);	

			if(Gfd.operation[1] != Gfd.GfdMode[1]){
				Gfd.operation[1] = Gfd.GfdMode[1];								
			}						
  			switch(Module_Info.gfd_chk[1].Rfd_State){
  			case 10:
  				// *********  On Up-Down Bridge
  				_delay = 1; 	
  				
  				Module_Info.gfd_chk[1].Rfd_State++;
				break;  				
  			case 11:
  				_delay = WAIT_FOR_RESISTER_CALC_FAST;
  				
  				if( ! ((Module_Info.SMR_Gfd_Sense[1] > GFD_SENSE_VOLTAGE_DOWN_LIMIT)
  					&& (Module_Info.SMR_Gfd_Sense[1] < GFD_SENSE_VOLTAGE_UP_LIMIT)
  					&& (Module_Info.SMR2_Relay_V < GFD_WORKING_VOLTAGE))){
  					Module_Info.gfd_chk[1].Rfd_State++;
  					Module_Info.gfd_chk[1].Gfd_Running_Count = 0;
  					Module_Info.gfd_chk[1].Gfd_Warning_Count = 0;
  				}else{ 								// Not Match to Ground Test condiction.  				
  					// Module_Info.gfd_chk[1].R_GFD = 1000000;		// 1000K Ohm
  					Module_Info.Alarm_CSU.flags.Gfd_Alarm_1 = OFF;
  					
  					Module_Info.gfd_chk[1].Rfd_State = 10;
  				}
  				break;
  			case 12:
   				_delay = WAIT_FOR_RESISTER_CALC_FAST;

				if(Gfd.operation[1] == GFD_BALANCE){
   				  		
					if(Module_Info.gfd_chk[1].R_GFD <= ((GFD_RESISTOR_FAULT * EVSE_MAX_OUTPUT_VOLTAGE)+GFD_TOLERANCE_RESISTOR)){
						if(Module_Info.SMR2_Relay_V >= GFD_WORKING_VOLTAGE){
							Module_Info.gfd_chk[1].Gfd_Warning_Count = 0;
							Module_Info.gfd_chk[1].Gfd_Running_Count++;
						}
						
						if(Module_Info.gfd_chk[1].Gfd_Running_Count >GFD_UNBALANCE_TEST_COUNT){
							Module_Info.gfd_chk[1].bResult_Gfd = GFD_FAIL;
							Module_Info.Alarm_CSU.flags.Gfd_Alarm_1 = ON;  
							Exti.EXTI_SMR2_Flag = true;	
							Module_Info.gfd_chk[1].R_GFD_Fail = Module_Info.gfd_chk[1].R_GFD;
							Module_Info.gfd_chk[1].Rfd_State_Fail 	= Module_Info.gfd_chk[1].Rfd_State;
							Module_Info.gfd_chk[1].SMR_Voltage_Fail = Module_Info.SMR2_Relay_V;  						
							Module_Info.gfd_chk[1].Rfd_State = 0;
						}
					}else{
						if( ( Module_Info.gfd_chk[1].R_GFD <= (GFD_RESISTOR_WARNING * EVSE_MAX_OUTPUT_VOLTAGE) ) &&
							( Module_Info.gfd_chk[1].R_GFD > ((GFD_RESISTOR_FAULT * EVSE_MAX_OUTPUT_VOLTAGE)+GFD_TOLERANCE_RESISTOR))){
						
							if( Module_Info.SMR2_Relay_V >= GFD_WORKING_VOLTAGE){
								Module_Info.gfd_chk[1].Gfd_Running_Count = 0;
								Module_Info.gfd_chk[1].Gfd_Warning_Count++;
							}
							
							if( Module_Info.gfd_chk[1].Gfd_Warning_Count > GFD_UNBALANCE_TEST_COUNT){
								Module_Info.gfd_chk[1].bResult_Gfd = GFD_WARNING;
								Module_Info.gfd_chk[1].Rfd_State++;
							}
						}else{
							Module_Info.gfd_chk[1].bResult_Gfd = GFD_PASS;
							Module_Info.Alarm_CSU.flags.Gfd_Alarm_1 = OFF;
							Module_Info.gfd_chk[1].Rfd_State++;
						}
					}
				}else if(Gfd.operation[1] == GFD_UNBALANCE){
					if(Module_Info.gfd_chk[1].P2PE_GFD !=0 && Module_Info.gfd_chk[1].N2PE_GFD != 0){
						if( Module_Info.gfd_chk[1].P2PE_GFD <= ((GFD_RESISTOR_FAULT * EVSE_MAX_OUTPUT_VOLTAGE)+GFD_TOLERANCE_RESISTOR) ||
							Module_Info.gfd_chk[1].N2PE_GFD <= ((GFD_RESISTOR_FAULT * EVSE_MAX_OUTPUT_VOLTAGE)+GFD_TOLERANCE_RESISTOR)){
							if(Module_Info.SMR2_Relay_V >= GFD_WORKING_VOLTAGE){
								Module_Info.gfd_chk[1].Gfd_Warning_Count = 0;
								Module_Info.gfd_chk[1].Gfd_Running_Count++;
							}
							
							if(Module_Info.gfd_chk[1].Gfd_Running_Count >GFD_UNBALANCE_TEST_COUNT){
								Module_Info.gfd_chk[1].bResult_Gfd = GFD_FAIL;
								Module_Info.Alarm_CSU.flags.Gfd_Alarm_1 = ON;    
								Exti.EXTI_SMR2_Flag = true;		
								
								Module_Info.gfd_chk[1].R_GFD_Fail = Module_Info.gfd_chk[1].R_GFD;
								Module_Info.gfd_chk[1].Rfd_State_Fail 	= Module_Info.gfd_chk[1].Rfd_State;
								Module_Info.gfd_chk[1].SMR_Voltage_Fail = Module_Info.SMR2_Relay_V;  						
								Module_Info.gfd_chk[1].Rfd_State = 0;
							}else{
								Module_Info.gfd_chk[1].P2PE_GFD = 0;
								Module_Info.gfd_chk[1].N2PE_GFD = 0;
							}
						}else{
							if( (Module_Info.gfd_chk[1].P2PE_GFD <= GFD_RESISTOR_WARNING * EVSE_MAX_OUTPUT_VOLTAGE &&
								Module_Info.gfd_chk[1].P2PE_GFD > (GFD_RESISTOR_FAULT * EVSE_MAX_OUTPUT_VOLTAGE)+GFD_TOLERANCE_RESISTOR) ||
								(Module_Info.gfd_chk[1].N2PE_GFD <= GFD_RESISTOR_WARNING * EVSE_MAX_OUTPUT_VOLTAGE &&
								Module_Info.gfd_chk[1].N2PE_GFD > (GFD_RESISTOR_FAULT * EVSE_MAX_OUTPUT_VOLTAGE)+GFD_TOLERANCE_RESISTOR)){
							
								if(Module_Info.SMR2_Relay_V >= GFD_WORKING_VOLTAGE){
									Module_Info.gfd_chk[1].Gfd_Running_Count = 0;
									Module_Info.gfd_chk[1].Gfd_Warning_Count++;
								}
								
								if(Module_Info.gfd_chk[1].Gfd_Warning_Count >GFD_UNBALANCE_TEST_COUNT){
									Module_Info.gfd_chk[1].bResult_Gfd = GFD_WARNING;
									Module_Info.gfd_chk[1].Rfd_State++;
								}else{
									Module_Info.gfd_chk[1].P2PE_GFD = 0;
									Module_Info.gfd_chk[1].N2PE_GFD = 0;
								}
							}else{
								Module_Info.gfd_chk[1].bResult_Gfd = GFD_PASS;
								Module_Info.Alarm_CSU.flags.Gfd_Alarm_1 = OFF;
								Module_Info.gfd_chk[1].Rfd_State++;
							}
						}
					}	
				}	
  				break;
  			default:
  				if(Module_Info.gfd_chk[1].bResult_Gfd != GFD_FAIL)
  					Module_Info.gfd_chk[1].Rfd_State = 10;
  				break;
  			}
  			break;
  		default:  			
  			break;
  		}
  	
  		
  		if(Module_Info.gfd_chk[1].bResult_Gfd == GFD_FAIL)
  		{
  			_delay = 100; 	
    		HAL_GPIO_WritePin(SMR2_RLY_n_Enable_GPIO_Port, SMR2_RLY_n_Enable_Pin, GPIO_PIN_RESET);
    		HAL_GPIO_WritePin(SMR2_RLY_p_Enable_GPIO_Port, SMR2_RLY_p_Enable_Pin, GPIO_PIN_RESET);    		
    		bRelayFeedback = 1;
  		}
  	   
    	vTaskDelay( _delay / portTICK_RATE_MS);
    }
//    else
//    	osDelay(1);
  }
  /* USER CODE END Gfd_Right_Task */
}

/* USER CODE BEGIN Header_SF_Test_Task */
/**
 * @brief Function implementing the sf_test_Task thread.
 * @param argument: Not used
 * @retval None
 */
/* USER CODE END Header_SF_Test_Task */
void SF_Test_Task(void const * argument)
{
  /* USER CODE BEGIN SF_Test_Task */
	/* Infinite loop */
	uint16_t temp;	
	for (;;)
	{		
		if (sf_t.SF_Config.SF_Act)
		{
//Check AC voltage	bit 0 ~ 2
//CheckACVoltage:
			if(BridgeBoard){
				sf_t.SF_Config.data.value &= ~((uint64_t)1 << sf_t.SF_Config.SF_State);
				sf_t.SF_Config.SF_State++;
				sf_t.SF_Config.data.value &= ~((uint64_t)1 << sf_t.SF_Config.SF_State);
				sf_t.SF_Config.SF_State++;
				sf_t.SF_Config.data.value &= ~((uint64_t)1 << sf_t.SF_Config.SF_State);
				sf_t.SF_Config.SF_State++;
			}else{
				for (int n = 0; n < 3; n++)
				{
					printf("AC %d:%d\r\n",n,AC_Sine[n].Vrms_AVG);
					if (AC_Sine[n].Vrms_AVG > 2200)
						{temp = AC_Sine[n].Vrms_AVG - 2200;
					}else{
						temp = 2200 - AC_Sine[n].Vrms_AVG;
					}	

					if (temp >= 200){
						sf_t.SF_Config.data.value |= ((uint64_t)1 << sf_t.SF_Config.SF_State); // Fail
					}else{
						sf_t.SF_Config.data.value &= ~((uint64_t)1 << sf_t.SF_Config.SF_State);
					}	
					sf_t.SF_Config.SF_State++;
				}
			}	
	
// Check SMR1_Voltage	bit 3
//CheckSMR1Voltage:			
			if(BridgeBoard){
				sf_t.SF_Config.data.value &= ~((uint64_t)1 << sf_t.SF_Config.SF_State);
				sf_t.SF_Config.SF_State++;
			}else{
				printf("SMR1 V:%d\r\n",Module_Info.SMR1_Relay_V);
				if (Module_Info.SMR1_Relay_V > 1500){
					temp = Module_Info.SMR1_Relay_V - 1500;
				}else{
					temp = 1500 - Module_Info.SMR1_Relay_V;
				}

				if (temp >= 30){
					sf_t.SF_Config.data.value |= ((uint64_t)1 << sf_t.SF_Config.SF_State); // Fail
				}else{
					sf_t.SF_Config.data.value &= ~((uint64_t)1 << sf_t.SF_Config.SF_State);
				}
				sf_t.SF_Config.SF_State++;
			}	

// Check SMR2_Voltage	bit 4
//CheckSMR2Voltage:			
			if(BridgeBoard){
				sf_t.SF_Config.data.value &= ~((uint64_t)1 << sf_t.SF_Config.SF_State);
				sf_t.SF_Config.SF_State++;
			}else{
				printf("SMR2 V:%d\r\n",Module_Info.SMR2_Relay_V);
				if (Module_Info.SMR2_Relay_V > 1500)
					temp = Module_Info.SMR2_Relay_V - 1500;
				else
					temp = 1500 - Module_Info.SMR2_Relay_V;

				if (temp >= 30)
					sf_t.SF_Config.data.value |= ((uint64_t)1 << sf_t.SF_Config.SF_State); // Fail
				else
					sf_t.SF_Config.data.value &= ~((uint64_t)1 << sf_t.SF_Config.SF_State);

				sf_t.SF_Config.SF_State++;
			}	
// Check SMR3_Voltage	bit 5
//CheckSMR3Voltage:		
			if(BridgeBoard){
				sf_t.SF_Config.data.value &= ~((uint64_t)1 << sf_t.SF_Config.SF_State);
				sf_t.SF_Config.SF_State++;
			}else{	
				printf("SMR3 V:%d\r\n",Module_Info.SMR3_Relay_V);
				if (Module_Info.SMR3_Relay_V > 1500)
					temp = Module_Info.SMR3_Relay_V - 1500;
				else
					temp = 1500 - Module_Info.SMR3_Relay_V;
				if (temp >= 30)
					sf_t.SF_Config.data.value |= ((uint64_t)1 << sf_t.SF_Config.SF_State); // Fail
				else
					sf_t.SF_Config.data.value &= ~((uint64_t)1 << sf_t.SF_Config.SF_State);

				sf_t.SF_Config.SF_State++;
			}	
// Check SMR4_Voltage	bit 6
//CheckSMR4Voltage:		
			if(BridgeBoard){
				sf_t.SF_Config.data.value &= ~((uint64_t)1 << sf_t.SF_Config.SF_State);
				sf_t.SF_Config.SF_State++;
			}else{	
				printf("SMR4V :%d\r\n",Module_Info.SMR4_Relay_V);
				if (Module_Info.SMR4_Relay_V > 1500)
					temp = Module_Info.SMR4_Relay_V - 1500;
				else
					temp = 1500 - Module_Info.SMR4_Relay_V;
				if (temp >= 30)
					sf_t.SF_Config.data.value |= ((uint64_t)1 << sf_t.SF_Config.SF_State); // Fail
				else
					sf_t.SF_Config.data.value &= ~((uint64_t)1 << sf_t.SF_Config.SF_State);
				sf_t.SF_Config.SF_State++;
			}	
// Check SMR5_Voltage	bit 7
//CheckSMR5Voltage:			
			if(BridgeBoard){
				sf_t.SF_Config.data.value &= ~((uint64_t)1 << sf_t.SF_Config.SF_State);
				sf_t.SF_Config.SF_State++;
			}else{
				printf("SMR5 V:%d\r\n",Module_Info.SMR5_Relay_V);
				if (Module_Info.SMR5_Relay_V > 1500)
					temp = Module_Info.SMR5_Relay_V - 1500;
				else
					temp = 1500 - Module_Info.SMR5_Relay_V;
				if (temp >= 30)
					sf_t.SF_Config.data.value |= ((uint64_t)1 << sf_t.SF_Config.SF_State); // Fail
				else
					sf_t.SF_Config.data.value &= ~((uint64_t)1 << sf_t.SF_Config.SF_State);
				sf_t.SF_Config.SF_State++;
			}	
// Check SMR6_Voltage	bit 8
//CheckSMR6Voltage:			
			if(BridgeBoard){
				sf_t.SF_Config.data.value &= ~((uint64_t)1 << sf_t.SF_Config.SF_State);
				sf_t.SF_Config.SF_State++;
			}else{
				printf("SMR6 V:%d\r\n",Module_Info.SMR6_Relay_V);				
				if (Module_Info.SMR6_Relay_V > 1500)
					temp = Module_Info.SMR6_Relay_V - 1500;
				else
					temp = 1500 - Module_Info.SMR6_Relay_V;
				if (temp >= 30)
					sf_t.SF_Config.data.value |= ((uint64_t)1 << sf_t.SF_Config.SF_State); // Fail
				else
					sf_t.SF_Config.data.value &= ~((uint64_t)1 << sf_t.SF_Config.SF_State);
				sf_t.SF_Config.SF_State++;		
			}		
			// Check SMR6_Voltage	bit 9
//CheckDCInVoltage:			
			if(BridgeBoard){
				sf_t.SF_Config.data.value &= ~((uint64_t)1 << sf_t.SF_Config.SF_State);
				sf_t.SF_Config.SF_State++;
			}else{
				printf("DC In1:%d\r\n",Module_Info.BAT_Voltage);				
				if (Module_Info.BAT_Voltage > 1500)
					temp = Module_Info.BAT_Voltage - 1500;
				else
					temp = 1500 - Module_Info.BAT_Voltage;
				if (temp >= 50)
					sf_t.SF_Config.data.value |= ((uint64_t)1 << sf_t.SF_Config.SF_State); // Fail
				else
					sf_t.SF_Config.data.value &= ~((uint64_t)1 << sf_t.SF_Config.SF_State);
				sf_t.SF_Config.SF_State++;		
			}																				

//Check IO		bit 10~32
//CheckIO:
			if(BridgeBoard){
				sf_t.SF_Config.data.value &= ~((uint64_t)1 << sf_t.SF_Config.SF_State);
				sf_t.SF_Config.SF_State++;
			}else{
				nTestIO(Contactor_Enable_GPIO_Port, Contactor_Enable_Pin, AC_Contactor_Ret_GPIO_Port, AC_Contactor_Ret_Pin, sf_t.SF_Config.SF_State++);
				}
			
			nTestIO(PSU_Enable1_GPIO_Port, PSU_Enable1_Pin, SMR5_Relay_p_Ret_GPIO_Port, SMR5_Relay_p_Ret_Pin, sf_t.SF_Config.SF_State++);		

			if(BridgeBoard){
				sf_t.SF_Config.data.value &= ~((uint64_t)1 << sf_t.SF_Config.SF_State);
				sf_t.SF_Config.SF_State++;
			}else{
				nTestIO(PSU_Enable2_GPIO_Port, PSU_Enable2_Pin, AC_Contactor_Ret_GPIO_Port, AC_Contactor_Ret_Pin, sf_t.SF_Config.SF_State++);
			}
			
			nTestIO(SMR1_RLY_n_Enable_GPIO_Port, SMR1_RLY_n_Enable_Pin, SMR1_Relay_n_Ret_GPIO_Port, SMR1_Relay_n_Ret_Pin, sf_t.SF_Config.SF_State++);
			nTestIO(SMR1_RLY_p_Enable_GPIO_Port, SMR1_RLY_p_Enable_Pin, SMR1_Relay_p_Ret_GPIO_Port, SMR1_Relay_p_Ret_Pin, sf_t.SF_Config.SF_State++);
			nTestIO(SMR2_RLY_n_Enable_GPIO_Port, SMR2_RLY_n_Enable_Pin, SMR2_Relay_n_Ret_GPIO_Port, SMR2_Relay_n_Ret_Pin, sf_t.SF_Config.SF_State++);
			nTestIO(SMR2_RLY_p_Enable_GPIO_Port, SMR2_RLY_p_Enable_Pin, SMR2_Relay_p_Ret_GPIO_Port, SMR2_Relay_p_Ret_Pin, sf_t.SF_Config.SF_State++);
			nTestIO(SMR3_RLY_n_Enable_GPIO_Port, SMR3_RLY_n_Enable_Pin, SMR3_Relay_n_Ret_GPIO_Port, SMR3_Relay_n_Ret_Pin, sf_t.SF_Config.SF_State++);
			nTestIO(SMR3_RLY_p_Enable_GPIO_Port, SMR3_RLY_p_Enable_Pin, SMR3_Relay_p_Ret_GPIO_Port, SMR3_Relay_p_Ret_Pin, sf_t.SF_Config.SF_State++);
			nTestIO(SMR4_RLY_n_Enable_GPIO_Port, SMR4_RLY_n_Enable_Pin, SMR4_Relay_n_Ret_GPIO_Port, SMR4_Relay_n_Ret_Pin, sf_t.SF_Config.SF_State++);
			nTestIO(SMR4_RLY_p_Enable_GPIO_Port, SMR4_RLY_p_Enable_Pin, SMR4_Relay_p_Ret_GPIO_Port, SMR4_Relay_p_Ret_Pin, sf_t.SF_Config.SF_State++);
			nTestIO(SMR5_RLY_n_Enable_GPIO_Port, SMR5_RLY_n_Enable_Pin, SMR5_Relay_n_Ret_GPIO_Port, SMR5_Relay_n_Ret_Pin, sf_t.SF_Config.SF_State++);
			nTestIO(SMR5_RLY_p_Enable_GPIO_Port, SMR5_RLY_p_Enable_Pin, SMR5_Relay_p_Ret_GPIO_Port, SMR5_Relay_p_Ret_Pin, sf_t.SF_Config.SF_State++);
			
			if(BridgeBoard){
				if(CSRHB_VER == 1){
					sf_t.SF_Config.data.value &= ~((uint64_t)1 << sf_t.SF_Config.SF_State);
					sf_t.SF_Config.SF_State++;
					sf_t.SF_Config.data.value &= ~((uint64_t)1 << sf_t.SF_Config.SF_State);
					sf_t.SF_Config.SF_State++;					
				}else{
					nTestIO(SMR6_RLY_n_Enable_GPIO_Port, SMR6_RLY_n_Enable_Pin, SMR6_Relay_n_Ret_GPIO_Port, SMR6_Relay_n_Ret_Pin, sf_t.SF_Config.SF_State++);
					nTestIO(SMR6_RLY_p_Enable_GPIO_Port, SMR6_RLY_p_Enable_Pin, SMR6_Relay_p_Ret_GPIO_Port, SMR6_Relay_p_Ret_Pin, sf_t.SF_Config.SF_State++);
				}
					sf_t.SF_Config.data.value &= ~((uint64_t)1 << sf_t.SF_Config.SF_State);
					sf_t.SF_Config.SF_State++;
					sf_t.SF_Config.data.value &= ~((uint64_t)1 << sf_t.SF_Config.SF_State);
					sf_t.SF_Config.SF_State++;
			}else{
				nTestIO(SMR6_RLY_n_Enable_GPIO_Port, SMR6_RLY_n_Enable_Pin, SMR6_Relay_n_Ret_GPIO_Port, SMR6_Relay_n_Ret_Pin, sf_t.SF_Config.SF_State++);
				nTestIO(SMR6_RLY_p_Enable_GPIO_Port, SMR6_RLY_p_Enable_Pin, SMR6_Relay_p_Ret_GPIO_Port, SMR6_Relay_p_Ret_Pin, sf_t.SF_Config.SF_State++);
				nTestIO(Precharge1_Enable_GPIO_Port, Precharge1_Enable_Pin, Precharge1_Ret_GPIO_Port, Precharge1_Ret_Pin, sf_t.SF_Config.SF_State++);
				nTestIO(Precharge2_Enable_GPIO_Port, Precharge2_Enable_Pin, Precharge2_Ret_GPIO_Port, Precharge2_Ret_Pin, sf_t.SF_Config.SF_State++);	
			}		
			
			nTestEXT_INT(SMR1_RLY_n_Enable_GPIO_Port, SMR1_RLY_n_Enable_Pin, &EXTI_TestFlag1, sf_t.SF_Config.SF_State++);
			nTestEXT_INT(SMR1_RLY_p_Enable_GPIO_Port, SMR1_RLY_p_Enable_Pin, &EXTI_TestFlag2, sf_t.SF_Config.SF_State++);			

			if(BridgeBoard){
				sf_t.SF_Config.data.value &= ~((uint64_t)1 << sf_t.SF_Config.SF_State);
				sf_t.SF_Config.SF_State++;
				sf_t.SF_Config.data.value &= ~((uint64_t)1 << sf_t.SF_Config.SF_State);
				sf_t.SF_Config.SF_State++;
				sf_t.SF_Config.data.value &= ~((uint64_t)1 << sf_t.SF_Config.SF_State);
				sf_t.SF_Config.SF_State++;
				sf_t.SF_Config.data.value &= ~((uint64_t)1 << sf_t.SF_Config.SF_State);
				sf_t.SF_Config.SF_State++;
			}else{	
				nTestEXT_INT(SMR2_RLY_n_Enable_GPIO_Port, SMR2_RLY_n_Enable_Pin, &EXTI_TestFlag3, sf_t.SF_Config.SF_State++);
				nTestEXT_INT(SMR2_RLY_p_Enable_GPIO_Port, SMR2_RLY_p_Enable_Pin, &EXTI_TestFlag4, sf_t.SF_Config.SF_State++);
				nTestEXT_INT(SMR3_RLY_n_Enable_GPIO_Port, SMR3_RLY_n_Enable_Pin, &EXTI_TestFlag5, sf_t.SF_Config.SF_State++);
				nTestEXT_INT(SMR3_RLY_p_Enable_GPIO_Port, SMR3_RLY_p_Enable_Pin, &EXTI_TestFlag6, sf_t.SF_Config.SF_State++);				
			}	

// Check SMR1_Current	bit 33
//CheckSMR1Current:
			if(BridgeBoard){
				sf_t.SF_Config.data.value &= ~((uint64_t)1 << sf_t.SF_Config.SF_State);
				sf_t.SF_Config.SF_State++;
			}else{
				printf("SMR1 C:%d\r\n",Module_Info.SMR1_Relay_C);
				if (Module_Info.SMR1_Relay_C > 1180)
					temp = Module_Info.SMR1_Relay_C - 1180;
				else
					temp = 1180 - Module_Info.SMR1_Relay_C;

				// In Range( 118A +- 5A )
				if (temp >= 50)
					sf_t.SF_Config.data.value |= ((uint64_t)1 << sf_t.SF_Config.SF_State); // Fail
				else
					sf_t.SF_Config.data.value &= ~((uint64_t)1 << sf_t.SF_Config.SF_State);
				sf_t.SF_Config.SF_State++;
			}
// Check SMR2_Current	bit 34
//CheckSMR2Current:
			if(BridgeBoard){
				sf_t.SF_Config.data.value &= ~((uint64_t)1 << sf_t.SF_Config.SF_State);
				sf_t.SF_Config.SF_State++;
			}else{
				printf("SMR2 C:%d\r\n",Module_Info.SMR2_Relay_C);
				if (Module_Info.SMR2_Relay_C > 1180)
					temp = Module_Info.SMR2_Relay_C - 1180;
				else
					temp = 1180 - Module_Info.SMR2_Relay_C;

				// In Range( 118A +- 5A )
				if (temp >= 50)
					sf_t.SF_Config.data.value |= ((uint64_t)1 << sf_t.SF_Config.SF_State); // Fail
				else
					sf_t.SF_Config.data.value &= ~((uint64_t)1 << sf_t.SF_Config.SF_State);
				sf_t.SF_Config.SF_State++;
			}	
//CheckFinish:
			sf_t.SF_Config.SF_Act = 0; // Turn Off
			if (sf_t.SF_Config.data.value > 0)
			{
				sf_t.SF_Config.SF_test_status = 0; // Fail
			}
			else
			{
				sf_t.SF_Config.SF_test_status = 1; // Pass
			}
		
		}
		osDelay(1);
	}
  /* USER CODE END SF_Test_Task */
}

/* USER CODE BEGIN Header_LedTask */
/**
 * @brief Function implementing the _ledTask_ thread.
 * @param argument: Not used
 * @retval None
 */
/* USER CODE END Header_LedTask */
void LedTask(void const * argument)
{
  /* USER CODE BEGIN LedTask */
	/* Infinite loop */
	for (;;)
	{		
		if (dir == 0)
		{
			if (pwmVal < 500)
			{
				if (GainCaliFlag)
					pwmVal++;
				else
					pwmVal += 20;
				__HAL_TIM_SetCompare(&htim4, TIM_CHANNEL_2, pwmVal);
			}
			else
			{
				dir = 1;
				if (GainCaliFlag)
					osDelay(400);
				else
					osDelay(100);
			}
		}
		else
		{
			if (pwmVal > 0)
			{
				if (GainCaliFlag)
					pwmVal--;
				else
					pwmVal -= 20;
				__HAL_TIM_SetCompare(&htim4, TIM_CHANNEL_2, pwmVal);
			}
			else
			{
				dir = 0;
				if (GainCaliFlag)
					osDelay(400);
				else
					osDelay(100);
			}
		}
		osDelay(1);
	}
  /* USER CODE END LedTask */
}

/* USER CODE BEGIN Header_canTask */
/**
* @brief Function implementing the CANTask thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_canTask */
void canTask(void const * argument)
{
  /* USER CODE BEGIN canTask */
  CAN1_sFilterConfig.FilterBank = 0;
  CAN1_sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
  CAN1_sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
//   CAN1_sFilterConfig.FilterIdHigh =(0x0450 << 3) >> 16;
//   CAN1_sFilterConfig.FilterIdLow = (0x0450 << 3) | CAN_ID_EXT;
//   CAN1_sFilterConfig.FilterMaskIdHigh =(0x0450 << 3) >> 16;
//   CAN1_sFilterConfig.FilterMaskIdLow =(0x0450 << 3) ;
  CAN1_sFilterConfig.FilterFIFOAssignment = CAN_RX_FIFO0;
  CAN1_sFilterConfig.FilterActivation = ENABLE;
  CAN1_sFilterConfig.SlaveStartFilterBank = 0;
  
  if(HAL_CAN_ConfigFilter(&hcan1, &CAN1_sFilterConfig) != HAL_OK)
  {
    #ifdef DEBUG
    DEBUG_ERROR("CAN1 filter initialization fail...\r\n");
    #endif
    /* Filter configuration Error */
    Error_Handler();
  }
	
  if (HAL_CAN_Start(&hcan1) != HAL_OK)
  {
    #ifdef DEBUG
    DEBUG_ERROR("CAN1 start fail...\r\n");
    #endif
    /* Start Error */
    Error_Handler();
  }

  if (HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING) != HAL_OK)
  {
    #ifdef DEBUG
    DEBUG_ERROR("CAN1 activateNotification fail...\r\n");
    #endif
    /* Notification Error */
    Error_Handler();
  }

  //CAN1_RX_EndFlag  = 1;	for 2 board can test
  /* Infinite loop */
  for(;;)
  {

	if(CAN1_RX_EndFlag){
		if(HAL_CAN_GetTxMailboxesFreeLevel( &hcan1 ) != 0){        
			CAN1_TxHeader.ExtId = 0x456;
			CAN1_TxHeader.IDE = CAN_ID_EXT;      // IDE = CAN_ID_EXT means Extended ID message.
			//CAN1_TxHeader.SRR = 0;    //stm32 hal lib not .SRR
			CAN1_TxHeader.RTR = 0;      // Not an RTR message.
			CAN1_TxHeader.DLC = 1;      // Send one byte of data.
			CAN1_TxData[0] = 0xAA;
			// CAN1_TxData[1] = 0x22;
			// CAN1_TxData[2] = 0x33;
			// CAN1_TxData[3] = 0x44;
			// CAN1_TxData[4] = 0x55;
			// CAN1_TxData[5] = 0x66;
			// CAN1_TxData[6] = 0x77;
			// CAN1_TxData[7] +=1;
				if (HAL_CAN_AddTxMessage(&hcan1, &CAN1_TxHeader, CAN1_TxData, &CAN1_TxMailbox) != HAL_OK)
					{			
						Error_Handler();
					}
			CAN1_RX_EndFlag = 0;		
		//	osDelay(1000);	
		}			
    }
	
	// osDelay(1000);	
    // if(HAL_CAN_GetTxMailboxesFreeLevel( &hcan1 ) != 0){
        
    //     CAN1_TxHeader.ExtId = 0x123;
    //     CAN1_TxHeader.IDE = CAN_ID_EXT;      // IDE = CAN_ID_EXT means Extended ID message.
    //     //CAN1_TxHeader.SRR = 0;    //stm32 hal lib not .SRR
    //     CAN1_TxHeader.RTR = 0;      // Not an RTR message.
    //     CAN1_TxHeader.DLC = 8;      // Send one byte of data.
	// 	CAN1_TxData[0] = 0xAA;
	// 	CAN1_TxData[1] = 0xBB;
	// 	CAN1_TxData[2] = 0xCC;
	// 	CAN1_TxData[3] = 0xDD;
	// 	CAN1_TxData[4] = 0xEE;
	// 	CAN1_TxData[5] = 0xFF;
	// 	CAN1_TxData[6] = 0x11;
	// 	CAN1_TxData[7] = 0x22;           
    
        
	// 	if (HAL_CAN_AddTxMessage(&hcan1, &CAN1_TxHeader, CAN1_TxData, &CAN1_TxMailbox) != HAL_OK)
	// 	{			
	// 		Error_Handler();
	// 	}
    // }

    osDelay(1);
  }
  /* USER CODE END canTask */
}

/* Private application code --------------------------------------------------*/
/* USER CODE BEGIN Application */
/**
 * @brief  Sets the selected data port bits.
 * @param  GPIOx: where x can be (A..G) to select the GPIO peripheral.
 * @param  GPIO_Pin: specifies the port bits to be written.
 *   This parameter can be any combination of GPIO_Pin_x where x can be (0..15).
 * @retval None
 */
// void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
//{
//   /* Check the parameters */
//   assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
//   assert_param(IS_GPIO_PIN(GPIO_Pin));
//
//   GPIOx->BSRR = GPIO_Pin;
// }

/**
 * @brief  Clears the selected data port bits.
 * @param  GPIOx: where x can be (A..G) to select the GPIO peripheral.
 * @param  GPIO_Pin: specifies the port bits to be written.
 *   This parameter can be any combination of GPIO_Pin_x where x can be (0..15).
 * @retval None
 */
// void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
//{
//   /* Check the parameters */
//   assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
//   assert_param(IS_GPIO_PIN(GPIO_Pin));
//
//   GPIOx->BRR = GPIO_Pin;
// }


void nTestIO(GPIO_TypeDef *GPIO_out_port, uint16_t GPIO_out_Pin, GPIO_TypeDef *GPIO_in_port, uint16_t GPIO_in_Pin, uint8_t nItem)
{

	HAL_GPIO_WritePin(GPIO_out_port, GPIO_out_Pin, GPIO_PIN_SET);
	HAL_Delay(Multi_Relay_Delay_Time);
	if (HAL_GPIO_ReadPin(GPIO_in_port, GPIO_in_Pin) == GPIO_PIN_RESET)
		sf_t.SF_Config.data.value &= ~((uint64_t)1 << nItem);
	else{
		sf_t.SF_Config.data.value |= ((uint64_t)1 << nItem); // Fail
		return;
	}	

	HAL_GPIO_WritePin(GPIO_out_port, GPIO_out_Pin, GPIO_PIN_RESET);
	HAL_Delay(Multi_Relay_Delay_Time);
	if (HAL_GPIO_ReadPin(GPIO_in_port, GPIO_in_Pin) == GPIO_PIN_SET)
		sf_t.SF_Config.data.value &= ~((uint64_t)1 << nItem);
	else
		sf_t.SF_Config.data.value |= ((uint64_t)1 << nItem); // Fail
}

void nTestIO1(GPIO_TypeDef *GPIO_out_port, uint16_t GPIO_out_Pin, GPIO_TypeDef *GPIO_in_port, uint16_t GPIO_in_Pin, uint8_t nItem)
{

	HAL_GPIO_WritePin(GPIO_out_port, GPIO_out_Pin, GPIO_PIN_SET);
	HAL_Delay(Multi_Relay_Delay_Time);
	if (HAL_GPIO_ReadPin(GPIO_in_port, GPIO_in_Pin) == GPIO_PIN_SET)
		sf_t.SF_Config.data.value &= ~((uint64_t)1 << nItem);
	else{
		sf_t.SF_Config.data.value |= ((uint64_t)1 << nItem); // Fail
		return;
	}	

	HAL_GPIO_WritePin(GPIO_out_port, GPIO_out_Pin, GPIO_PIN_RESET);
	HAL_Delay(Multi_Relay_Delay_Time);
	if (HAL_GPIO_ReadPin(GPIO_in_port, GPIO_in_Pin) == GPIO_PIN_RESET)
		sf_t.SF_Config.data.value &= ~((uint64_t)1 << nItem);
	else
		sf_t.SF_Config.data.value |= ((uint64_t)1 << nItem); // Fail
}

void nTestEXT_INT(GPIO_TypeDef *GPIO_out_port, uint16_t GPIO_out_Pin,uint8_t *flag,uint8_t nItem)
{
	*flag = 0;
	HAL_GPIO_WritePin(GPIO_out_port, GPIO_out_Pin, GPIO_PIN_SET);
	HAL_Delay(Multi_Relay_Delay_Time);

	if(*flag){
		sf_t.SF_Config.data.value &= ~((uint64_t)1 << nItem);	
	}else{		
		sf_t.SF_Config.data.value |= ((uint64_t)1 << nItem); // Fail			
	}		
	HAL_GPIO_WritePin(GPIO_out_port, GPIO_out_Pin, GPIO_PIN_RESET);
	HAL_Delay(Multi_Relay_Delay_Time);
}

uint8_t isValidCheckSum(void)
{
	uint8_t result = OFF;
	uint8_t chksum = 0x00;

	if (uart_rx_buffer[0] == PROTOCOL_HEAD)
	{
		for (int idx = 0; idx < (uart_rx_buffer[4] | (uart_rx_buffer[5] << 8)); idx++)
		{
			chksum ^= uart_rx_buffer[(6 + idx)];
		}

		if (chksum == uart_rx_buffer[(6 + (uart_rx_buffer[4] | (uart_rx_buffer[5] << 8)))])
			result = ON;
	}

	return result;
}

// two points
void CLC_Corr_Gain_Par(uint16_t SpecData_H, uint16_t SpecData_L, uint16_t MCUData_H, uint16_t MCUData_L, float *GainA, float *GainB)
{
	*GainA = (float)((float)(SpecData_H - SpecData_L) / (float)(MCUData_H - MCUData_L));
	*GainB = (float)(SpecData_H - (float)(*GainA * MCUData_H));
}

// three points
uint16_t acVolCalWithGain(uint16_t orgValue, uint8_t phase)
{
	uint16_t result = 0;

	if ((Module_Info.memory.Module_Config.data.item.Correction_Volt[(phase * 3) + 0][MCU_DATA] != Module_Info.memory.Module_Config.data.item.Correction_Volt[(phase * 3) + 1][MCU_DATA]) &&
		(Module_Info.memory.Module_Config.data.item.Correction_Volt[(phase * 3) + 0][MCU_DATA] != Module_Info.memory.Module_Config.data.item.Correction_Volt[(phase * 3) + 2][MCU_DATA]) &&
		(Module_Info.memory.Module_Config.data.item.Correction_Volt[(phase * 3) + 1][MCU_DATA] != Module_Info.memory.Module_Config.data.item.Correction_Volt[(phase * 3) + 2][MCU_DATA]))
	{
		// If denominator not equal 0, calculate orgValue with Lagrange polynomial
		result = (uint16_t)((((orgValue - Module_Info.memory.Module_Config.data.item.Correction_Volt[(phase * 3) + 1][MCU_DATA]) * (orgValue - Module_Info.memory.Module_Config.data.item.Correction_Volt[(phase * 3) + 2][MCU_DATA])) / (float)((Module_Info.memory.Module_Config.data.item.Correction_Volt[(phase * 3) + 0][MCU_DATA] - Module_Info.memory.Module_Config.data.item.Correction_Volt[(phase * 3) + 1][MCU_DATA]) * (Module_Info.memory.Module_Config.data.item.Correction_Volt[(phase * 3) + 0][MCU_DATA] - Module_Info.memory.Module_Config.data.item.Correction_Volt[(phase * 3) + 2][MCU_DATA]))) * Module_Info.memory.Module_Config.data.item.Correction_Volt[(phase * 3) + 0][METER_DATA] +
							(((orgValue - Module_Info.memory.Module_Config.data.item.Correction_Volt[(phase * 3) + 0][MCU_DATA]) * (orgValue - Module_Info.memory.Module_Config.data.item.Correction_Volt[(phase * 3) + 2][MCU_DATA])) / (float)((Module_Info.memory.Module_Config.data.item.Correction_Volt[(phase * 3) + 1][MCU_DATA] - Module_Info.memory.Module_Config.data.item.Correction_Volt[(phase * 3) + 0][MCU_DATA]) * (Module_Info.memory.Module_Config.data.item.Correction_Volt[(phase * 3) + 1][MCU_DATA] - Module_Info.memory.Module_Config.data.item.Correction_Volt[(phase * 3) + 2][MCU_DATA]))) * Module_Info.memory.Module_Config.data.item.Correction_Volt[(phase * 3) + 1][METER_DATA] +
							(((orgValue - Module_Info.memory.Module_Config.data.item.Correction_Volt[(phase * 3) + 0][MCU_DATA]) * (orgValue - Module_Info.memory.Module_Config.data.item.Correction_Volt[(phase * 3) + 1][MCU_DATA])) / (float)((Module_Info.memory.Module_Config.data.item.Correction_Volt[(phase * 3) + 2][MCU_DATA] - Module_Info.memory.Module_Config.data.item.Correction_Volt[(phase * 3) + 0][MCU_DATA]) * (Module_Info.memory.Module_Config.data.item.Correction_Volt[(phase * 3) + 2][MCU_DATA] - Module_Info.memory.Module_Config.data.item.Correction_Volt[(phase * 3) + 1][MCU_DATA]))) * Module_Info.memory.Module_Config.data.item.Correction_Volt[(phase * 3) + 2][METER_DATA]);
	}
	else
	{
		// If denominator equal 0, pass orgValue as result
		result = orgValue;
	}

	return result;
}

void CalcuteGFDMaxMinValue(uint8_t gunindex){

	if(Gfd.DnBridgeMaxV[gunindex] == 0){
	Gfd.DnBridgeMaxV[gunindex] = Module_Info.SMR_Gfd_Sense[gunindex];
	}
	if(Gfd.DnBridgeMinV[gunindex] == 0){
	Gfd.DnBridgeMinV[gunindex] = Module_Info.SMR_Gfd_Sense[gunindex];
	}
	if(Module_Info.SMR_Gfd_Sense[gunindex] > Gfd.DnBridgeMaxV[gunindex]){
		Gfd.DnBridgeMaxV[gunindex] = Module_Info.SMR_Gfd_Sense[gunindex];
	}
	if(Module_Info.SMR_Gfd_Sense[gunindex] < Gfd.DnBridgeMinV[gunindex]){
		Gfd.DnBridgeMinV[gunindex] = Module_Info.SMR_Gfd_Sense[gunindex];
	}


	if(Gfd.operation[gunindex] == GFD_BALANCE){
		if(Gfd.MaxP2PE[gunindex] == 0){
			Gfd.MaxP2PE[gunindex] = Module_Info.gfd_chk[gunindex].R_GFD;
		}
		if(Gfd.MinP2PE[gunindex] == 0){
			Gfd.MinP2PE[gunindex] = Module_Info.gfd_chk[gunindex].R_GFD;
		}

		if(Module_Info.gfd_chk[gunindex].R_GFD > Gfd.MaxP2PE[gunindex]){
			Gfd.MaxP2PE[gunindex] = Module_Info.gfd_chk[gunindex].R_GFD;
		}
		if(Module_Info.gfd_chk[gunindex].R_GFD < Gfd.MinP2PE[gunindex]){
			Gfd.MinP2PE[gunindex] = Module_Info.gfd_chk[gunindex].R_GFD;
		}
	}

	if(Gfd.operation[gunindex] == GFD_UNBALANCE){
		if(Gfd.MaxP2PE[gunindex] == 0){
			Gfd.MaxP2PE[gunindex] = Module_Info.gfd_chk[gunindex].P2PE_GFD;
		}
		if(Gfd.MinP2PE[gunindex] == 0){
			Gfd.MinP2PE[gunindex] = Module_Info.gfd_chk[gunindex].P2PE_GFD;
		}
		if(Gfd.MaxN2PE[gunindex] == 0){
			Gfd.MaxN2PE[gunindex] = Module_Info.gfd_chk[gunindex].N2PE_GFD;
		}
		if(Gfd.MinN2PE[gunindex] == 0){
			Gfd.MinN2PE[gunindex] = Module_Info.gfd_chk[gunindex].N2PE_GFD;
		}

		if(Module_Info.gfd_chk[gunindex].P2PE_GFD > Gfd.MaxP2PE[gunindex]){
			Gfd.MaxP2PE[gunindex] = Module_Info.gfd_chk[gunindex].P2PE_GFD;
		}
		if(Module_Info.gfd_chk[gunindex].P2PE_GFD < Gfd.MaxP2PE[gunindex]){
			Gfd.MinP2PE[gunindex] = Module_Info.gfd_chk[gunindex].P2PE_GFD;
		}

		if(Module_Info.gfd_chk[gunindex].N2PE_GFD > Gfd.MaxN2PE[gunindex]){
			Gfd.MaxN2PE[gunindex] = Module_Info.gfd_chk[gunindex].N2PE_GFD;
		}
		if(Module_Info.gfd_chk[gunindex].N2PE_GFD < Gfd.MaxN2PE[gunindex]){
			Gfd.MinN2PE[gunindex] = Module_Info.gfd_chk[gunindex].N2PE_GFD;
		}
	}	
}

void SetGfdMode(void)
{	
	int i;
	for(i=0; i<2; i++){			
		if(ModelName[7+i*2] != 0){
			switch (ModelName[7+i*2])
			{
				case 'J':
				case 'K':
				case 'L':
				case 'S':
				case 'W':
					Gfd.GfdMode[i] = GFD_BALANCE;
					break;
				default:
					Gfd.GfdMode[i] = GFD_UNBALANCE;
					break;					
			}
		
		}
	}	
     
	osDelay(1000);
	printf("Set SMR1 GFD Mode : %s\n\r", Gfd.GfdMode[0] == GFD_BALANCE ? "Balance" : "Unbalance");	
	printf("Set SMR2 GFD Mode : %s\n\r", Gfd.GfdMode[1] == GFD_BALANCE ? "Balance" : "Unbalance");	

	if(ModelName[2] == 'J' || ModelName[3] == 'J' || ModelName[3] == 'R'){
		Gfd.IsolationVoltage = 4500;								
	}else{
		Gfd.IsolationVoltage = 5000;									
	}	
	printf("Set IsolationVoltage:%dV\n\r\n\r",Gfd.IsolationVoltage/10); 
}			

void CSRHB_Ver_Check(void)
{
	CSRHB_VER = 0;
	CSRHB_VER = HAL_GPIO_ReadPin(CSRHB_VER_GPIO_Port, CSRHB_VER_Pin);		
	printf("CSRHB%s\n\r", CSRHB_VER ? "00 Rev02 (5 Relay)":"01 Rev01 (6 Relay)");	
}



void IOdebug(void)
{	
	HAL_GPIO_WritePin(SMR1_RLY_p_Enable_GPIO_Port, SMR1_RLY_p_Enable_Pin, GPIO_PIN_SET);
	HAL_GPIO_WritePin(SMR1_RLY_n_Enable_GPIO_Port, SMR1_RLY_n_Enable_Pin, GPIO_PIN_SET);
	HAL_GPIO_WritePin(SMR2_RLY_p_Enable_GPIO_Port, SMR2_RLY_p_Enable_Pin, GPIO_PIN_SET);
	HAL_GPIO_WritePin(SMR2_RLY_n_Enable_GPIO_Port, SMR2_RLY_n_Enable_Pin, GPIO_PIN_SET);
	HAL_GPIO_WritePin(SMR3_RLY_p_Enable_GPIO_Port, SMR3_RLY_p_Enable_Pin, GPIO_PIN_SET);
	HAL_GPIO_WritePin(SMR3_RLY_n_Enable_GPIO_Port, SMR3_RLY_n_Enable_Pin, GPIO_PIN_SET);
	HAL_GPIO_WritePin(SMR4_RLY_p_Enable_GPIO_Port, SMR4_RLY_p_Enable_Pin, GPIO_PIN_SET);
	HAL_GPIO_WritePin(SMR4_RLY_n_Enable_GPIO_Port, SMR4_RLY_n_Enable_Pin, GPIO_PIN_SET);
	HAL_GPIO_WritePin(SMR5_RLY_p_Enable_GPIO_Port, SMR5_RLY_p_Enable_Pin, GPIO_PIN_SET);
	HAL_GPIO_WritePin(SMR5_RLY_n_Enable_GPIO_Port, SMR5_RLY_n_Enable_Pin, GPIO_PIN_SET);
	HAL_GPIO_WritePin(SMR6_RLY_p_Enable_GPIO_Port, SMR6_RLY_p_Enable_Pin, GPIO_PIN_SET);
	HAL_GPIO_WritePin(SMR6_RLY_n_Enable_GPIO_Port, SMR6_RLY_n_Enable_Pin, GPIO_PIN_SET);
	HAL_GPIO_WritePin(Precharge1_Enable_GPIO_Port, Precharge1_Enable_Pin, GPIO_PIN_SET);
	HAL_GPIO_WritePin(Precharge2_Enable_GPIO_Port, Precharge2_Enable_Pin, GPIO_PIN_SET);		

	HAL_GPIO_WritePin(Contactor_Enable_GPIO_Port, Contactor_Enable_Pin, GPIO_PIN_SET);
	HAL_GPIO_WritePin(PSU_Enable1_GPIO_Port, PSU_Enable1_Pin, GPIO_PIN_SET);	
	HAL_GPIO_WritePin(PSU_Enable2_GPIO_Port, PSU_Enable2_Pin, GPIO_PIN_SET);	
	HAL_GPIO_WritePin(LED2_GPIO_Port, LED2_Pin, GPIO_PIN_SET);	
	HAL_GPIO_WritePin(LED3_GPIO_Port, LED3_Pin, GPIO_PIN_SET);	
	osDelay(200);		

	Module_Info.Relay_Status.flags.SMR1_relay_n = ~HAL_GPIO_ReadPin(SMR1_Relay_n_Ret_GPIO_Port, SMR1_Relay_n_Ret_Pin);
	Module_Info.Relay_Status.flags.SMR1_relay_p = ~HAL_GPIO_ReadPin(SMR1_Relay_p_Ret_GPIO_Port, SMR1_Relay_p_Ret_Pin);
	Module_Info.Relay_Status.flags.SMR2_relay_n = ~HAL_GPIO_ReadPin(SMR2_Relay_n_Ret_GPIO_Port, SMR2_Relay_n_Ret_Pin);
	Module_Info.Relay_Status.flags.SMR2_relay_p = ~HAL_GPIO_ReadPin(SMR2_Relay_p_Ret_GPIO_Port, SMR2_Relay_p_Ret_Pin);
	Module_Info.Relay_Status.flags.SMR3_relay_n = ~HAL_GPIO_ReadPin(SMR3_Relay_n_Ret_GPIO_Port, SMR3_Relay_n_Ret_Pin);
	Module_Info.Relay_Status.flags.SMR3_relay_p = ~HAL_GPIO_ReadPin(SMR3_Relay_p_Ret_GPIO_Port, SMR3_Relay_p_Ret_Pin);
	Module_Info.Relay_Status.flags.SMR4_relay_n = ~HAL_GPIO_ReadPin(SMR4_Relay_n_Ret_GPIO_Port, SMR4_Relay_n_Ret_Pin);
	Module_Info.Relay_Status.flags.SMR4_relay_p = ~HAL_GPIO_ReadPin(SMR4_Relay_p_Ret_GPIO_Port, SMR4_Relay_p_Ret_Pin);
	Module_Info.Relay_Status.flags.SMR5_relay_n = ~HAL_GPIO_ReadPin(SMR5_Relay_n_Ret_GPIO_Port, SMR5_Relay_n_Ret_Pin);
	Module_Info.Relay_Status.flags.SMR5_relay_p = ~HAL_GPIO_ReadPin(SMR5_Relay_p_Ret_GPIO_Port, SMR5_Relay_p_Ret_Pin);
	Module_Info.Relay_Status.flags.SMR6_relay_n = ~HAL_GPIO_ReadPin(SMR6_Relay_n_Ret_GPIO_Port, SMR6_Relay_n_Ret_Pin);
	Module_Info.Relay_Status.flags.SMR6_relay_p = ~HAL_GPIO_ReadPin(SMR6_Relay_p_Ret_GPIO_Port, SMR6_Relay_p_Ret_Pin);
	Module_Info.Relay_Status.flags.Precharge1   = ~HAL_GPIO_ReadPin(Precharge1_Ret_GPIO_Port, Precharge1_Ret_Pin);
	Module_Info.Relay_Status.flags.Precharge2   = ~HAL_GPIO_ReadPin(Precharge2_Ret_GPIO_Port, Precharge2_Ret_Pin);
	// printf("RELAY ON:%llx\r\n", Module_Info.Relay_Status.All);
	printf("RELAY ON:S1:%x     S2:%x     S3:%x     S4:%x\r\n",Module_Info.Relay_Status.Status[0],Module_Info.Relay_Status.Status[1],Module_Info.Relay_Status.Status[2],Module_Info.Relay_Status.Status[3]);
	printf("RELAY ON:S5:%x     S6:%x     S7:%x\r\n\r\n",Module_Info.Relay_Status.Status[4],Module_Info.Relay_Status.Status[5],Module_Info.Relay_Status.Status[6]);
	osDelay(1800);		 
	
	HAL_GPIO_WritePin(SMR1_RLY_p_Enable_GPIO_Port, SMR1_RLY_p_Enable_Pin, GPIO_PIN_RESET);
	HAL_GPIO_WritePin(SMR1_RLY_n_Enable_GPIO_Port, SMR1_RLY_n_Enable_Pin, GPIO_PIN_RESET);
	HAL_GPIO_WritePin(SMR2_RLY_p_Enable_GPIO_Port, SMR2_RLY_p_Enable_Pin, GPIO_PIN_RESET);
	HAL_GPIO_WritePin(SMR2_RLY_n_Enable_GPIO_Port, SMR2_RLY_n_Enable_Pin, GPIO_PIN_RESET);
	HAL_GPIO_WritePin(SMR3_RLY_p_Enable_GPIO_Port, SMR3_RLY_p_Enable_Pin, GPIO_PIN_RESET);
	HAL_GPIO_WritePin(SMR3_RLY_n_Enable_GPIO_Port, SMR3_RLY_n_Enable_Pin, GPIO_PIN_RESET);
	HAL_GPIO_WritePin(SMR4_RLY_p_Enable_GPIO_Port, SMR4_RLY_p_Enable_Pin, GPIO_PIN_RESET);
	HAL_GPIO_WritePin(SMR4_RLY_n_Enable_GPIO_Port, SMR4_RLY_n_Enable_Pin, GPIO_PIN_RESET);
	HAL_GPIO_WritePin(SMR5_RLY_p_Enable_GPIO_Port, SMR5_RLY_p_Enable_Pin, GPIO_PIN_RESET);
	HAL_GPIO_WritePin(SMR5_RLY_n_Enable_GPIO_Port, SMR5_RLY_n_Enable_Pin, GPIO_PIN_RESET);
	HAL_GPIO_WritePin(SMR6_RLY_p_Enable_GPIO_Port, SMR6_RLY_p_Enable_Pin, GPIO_PIN_RESET);
	HAL_GPIO_WritePin(SMR6_RLY_n_Enable_GPIO_Port, SMR6_RLY_n_Enable_Pin, GPIO_PIN_RESET);
	HAL_GPIO_WritePin(Precharge1_Enable_GPIO_Port, Precharge1_Enable_Pin, GPIO_PIN_RESET);
	HAL_GPIO_WritePin(Precharge2_Enable_GPIO_Port, Precharge2_Enable_Pin, GPIO_PIN_RESET);

	HAL_GPIO_WritePin(Contactor_Enable_GPIO_Port, Contactor_Enable_Pin, GPIO_PIN_RESET);
	HAL_GPIO_WritePin(PSU_Enable1_GPIO_Port, PSU_Enable1_Pin, GPIO_PIN_RESET);	
	HAL_GPIO_WritePin(PSU_Enable2_GPIO_Port, PSU_Enable2_Pin, GPIO_PIN_RESET);	
	HAL_GPIO_WritePin(LED2_GPIO_Port, LED2_Pin, GPIO_PIN_RESET);	
	HAL_GPIO_WritePin(LED3_GPIO_Port, LED3_Pin, GPIO_PIN_RESET);
	osDelay(200);
	Module_Info.Relay_Status.flags.SMR1_relay_n = ~HAL_GPIO_ReadPin(SMR1_Relay_n_Ret_GPIO_Port, SMR1_Relay_n_Ret_Pin);
	Module_Info.Relay_Status.flags.SMR1_relay_p = ~HAL_GPIO_ReadPin(SMR1_Relay_p_Ret_GPIO_Port, SMR1_Relay_p_Ret_Pin);
	Module_Info.Relay_Status.flags.SMR2_relay_n = ~HAL_GPIO_ReadPin(SMR2_Relay_n_Ret_GPIO_Port, SMR2_Relay_n_Ret_Pin);
	Module_Info.Relay_Status.flags.SMR2_relay_p = ~HAL_GPIO_ReadPin(SMR2_Relay_p_Ret_GPIO_Port, SMR2_Relay_p_Ret_Pin);
	Module_Info.Relay_Status.flags.SMR3_relay_n = ~HAL_GPIO_ReadPin(SMR3_Relay_n_Ret_GPIO_Port, SMR3_Relay_n_Ret_Pin);
	Module_Info.Relay_Status.flags.SMR3_relay_p = ~HAL_GPIO_ReadPin(SMR3_Relay_p_Ret_GPIO_Port, SMR3_Relay_p_Ret_Pin);
	Module_Info.Relay_Status.flags.SMR4_relay_n = ~HAL_GPIO_ReadPin(SMR4_Relay_n_Ret_GPIO_Port, SMR4_Relay_n_Ret_Pin);
	Module_Info.Relay_Status.flags.SMR4_relay_p = ~HAL_GPIO_ReadPin(SMR4_Relay_p_Ret_GPIO_Port, SMR4_Relay_p_Ret_Pin);
	Module_Info.Relay_Status.flags.SMR5_relay_n = ~HAL_GPIO_ReadPin(SMR5_Relay_n_Ret_GPIO_Port, SMR5_Relay_n_Ret_Pin);
	Module_Info.Relay_Status.flags.SMR5_relay_p = ~HAL_GPIO_ReadPin(SMR5_Relay_p_Ret_GPIO_Port, SMR5_Relay_p_Ret_Pin);
	Module_Info.Relay_Status.flags.SMR6_relay_n = ~HAL_GPIO_ReadPin(SMR6_Relay_n_Ret_GPIO_Port, SMR6_Relay_n_Ret_Pin);
	Module_Info.Relay_Status.flags.SMR6_relay_p = ~HAL_GPIO_ReadPin(SMR6_Relay_p_Ret_GPIO_Port, SMR6_Relay_p_Ret_Pin);
	Module_Info.Relay_Status.flags.Precharge1   = ~HAL_GPIO_ReadPin(Precharge1_Ret_GPIO_Port, Precharge1_Ret_Pin);
	Module_Info.Relay_Status.flags.Precharge2   = ~HAL_GPIO_ReadPin(Precharge2_Ret_GPIO_Port, Precharge2_Ret_Pin);
	// printf("RELAY OFF:%llx\r\n", Module_Info.Relay_Status.All);
	printf("RELAY OFF:S1:%x     S2:%x     S3:%x     S4:%x\r\n",Module_Info.Relay_Status.Status[0],Module_Info.Relay_Status.Status[1],Module_Info.Relay_Status.Status[2],Module_Info.Relay_Status.Status[3]);
	printf("RELAY OFF:S5:%x     S6:%x     S7:%x\r\n\r\n",Module_Info.Relay_Status.Status[4],Module_Info.Relay_Status.Status[5],Module_Info.Relay_Status.Status[6]);

	osDelay(1800);	
}	

void UartCMDtest(void)
{


	if(Cmdcount > 0){
		// osDelay(1000);
		uart_recv_end_flag  = 1;
		uart_rx_buffer[0] = 0xAA;
		uart_rx_buffer[1] = 0x0;
		uart_rx_buffer[2] = 0xFF;	
		uart_rx_buffer[3] = PROTOCOL_MESSAGE_CONFIG_MODEL_NAME;	
		uart_rx_buffer[4] = 14;	
		uart_rx_buffer[5] = 00;	
		uart_rx_buffer[6] = 'D';
		uart_rx_buffer[7] = 'D';
		uart_rx_buffer[8] = 'Y';
		// uart_rx_buffer[9] = 'C';
		uart_rx_buffer[10] = '3';
		uart_rx_buffer[11] = '6';
		uart_rx_buffer[12] = '2';
		// uart_rx_buffer[13] = '0';
		uart_rx_buffer[14] = '0';
		// uart_rx_buffer[15] = '0';
		uart_rx_buffer[16] = 'E';
		uart_rx_buffer[17] = '2';
		uart_rx_buffer[18] = 'O';
		uart_rx_buffer[19] = 'A';
		
		uart_rx_buffer[20] = 0;
		for(int idx=0; idx<(uart_rx_buffer[4] | (uart_rx_buffer[5]<<8));idx++)
		{
			uart_rx_buffer[20] ^= uart_rx_buffer[(6+ idx)];   
		}
		Cmdcount --;
	}	
}

/* USER CODE END Application */