/*******************************************************************************************************/
//micro_inverter calibration file
//date: 2023.11.02
//owner: xie wei
/*******************************************************************************************************/
//head file
#include "control.h"
#include "calibration.h"
#include "main.h"
/////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////
CALIBRATION_STATE_TYPE GridVol_Cali_State;
uint8_t Cmd_cal=0;
float_t GridVol_S1_Value_LSB = 0,GridVol_S2_Value_LSB=0;
float_t GridVol_Cali_Gain=0;
float_t GridVol_Cali_Offset=0;
/////////////////////Grid Voltage calibration/////////////////
//////////////////////////////////////////////////////////////
uint8_t GridVol_Cali_Rootine(void)
{
	uint8_t flag = 0;
		switch( GridVol_Cali_State )
		{
			case START:
					DDL_Printf("Grid voltage calibration is started!\r\n");
			    GridVol_Cali_State = STEP_1;
					flag=0;
				break;
			case STEP_1:
					DDL_Printf("Please connect AC to 100V!\r\n");
					DDL_Printf("if AC voltage is ok, please input 'A'!\r\n");
					Cmd_cal=0;
			    while(Cmd_cal!='A')
					{
						Cmd_cal=comm_uart_cal();
					}
					Cmd_cal=0;
					GridVol_S1_Value_LSB = Vgrid_LSB_LPF.output;
					GridVol_Cali_State = STEP_2;
					DDL_Printf("Please connect AC to 200V!\r\n");
					DDL_Printf("if AC voltage is ok, please input 'B'!\r\n");
					flag=0;
				break;
			case STEP_2:
				  Cmd_cal=0;
					while(Cmd_cal!='B')
					{
						Cmd_cal=comm_uart_cal();
					}
					Cmd_cal=0;
					GridVol_S2_Value_LSB = Vgrid_LSB_LPF.output;
					GridVol_Cali_State = CALC;
					flag=0;
				break;
			case CALC:
					GridVol_Cali_Gain = 100.0f/( GridVol_S2_Value_LSB - GridVol_S1_Value_LSB );
					GridVol_Cali_Offset = ( GridVol_S2_Value_LSB - GridVol_S1_Value_LSB ) - GridVol_S1_Value_LSB;
			    DDL_Printf("GridVol_Cali_Gain=%.5f\r\n",GridVol_Cali_Gain);
			    DDL_Printf("GridVol_Cali_Offset=%.5f\r\n",GridVol_Cali_Offset);
			    if( (GridVol_Cali_Gain < (VGRID_GAIN_IDEAL*1.1f)) && (GridVol_Cali_Gain > (VGRID_GAIN_IDEAL*0.9f)) 
						&& (GridVol_Cali_Offset < (VGRID_OFFSET_IDEAL+50.0f)) && (GridVol_Cali_Offset > (VGRID_OFFSET_IDEAL-50.0f)) )
					{
					    DDL_Printf("Grid voltage calibration is succeeded!\r\n");
							DDL_Printf("Save the calibration parameters? --> Input 'Y' or 'N'\r\n");
							Cmd_cal=0;
							while( Cmd_cal!='Y' && Cmd_cal!='N' )
							{
								Cmd_cal=comm_uart_cal();
							}
							if( Cmd_cal=='Y' )
							{
								Update_CalPar_cmd=1;
								VGRID_GAIN = GridVol_Cali_Gain;
								VGRID_OFFSET = GridVol_Cali_Offset;
							}
					}
					else
					{
						DDL_Printf("Grid voltage calibration is failed!\r\n");
					}
					GridVol_Cali_State = DONE;
					flag=0;
				break;
			case DONE:
				flag=1;
			  GridVol_Cali_State = START;
				break;
		  default:
				GridVol_Cali_State = START;
				flag=0;
				break;
		}
	
	return flag;
}
///////////////////////////////////////////////////////////////
/////////////////////PV Voltage calibration/////////////////
CALIBRATION_STATE_TYPE PVVol_Cali_State;
float_t PVVol_S1_Value_LSB = 0,PVVol_S2_Value_LSB=0;
float_t PVVol_Cali_Gain=0;
float_t PVVol_Cali_Offset=0;
//////////////////////////////////////////////////////////////
uint8_t PVVol_Cali_Rootine(void)
{
	uint8_t flag = 0;
		switch( PVVol_Cali_State )
		{
			case START:
					DDL_Printf("PV voltage calibration is started!\r\n");
			    PVVol_Cali_State = STEP_1;
					flag=0;
				break;
			case STEP_1:
					DDL_Printf("Please connect PV Voltage to 30V!\r\n");
					DDL_Printf("if PV voltage is ok, please input 'A'\r\n");
					Cmd_cal=0;
					while(Cmd_cal!='A')
					{
						Cmd_cal=comm_uart_cal();
					}
					PVVol_S1_Value_LSB = Vpv_LSB_LPF.output;
					PVVol_Cali_State = STEP_2;
					DDL_Printf("Please connect PV Voltage to 40V!\r\n");
					DDL_Printf("if PV voltage is ok, please input 'B'\r\n");
					flag=0;
				break;
			case STEP_2:
					Cmd_cal=0;
					while(Cmd_cal!='B')
					{
						Cmd_cal=comm_uart_cal();
					}
					Cmd_cal=0;
					PVVol_S2_Value_LSB = Vpv_LSB_LPF.output;
					PVVol_Cali_State = CALC;
					flag=0;
				break;
			case CALC:
					PVVol_Cali_Gain = 10.0f/( PVVol_S2_Value_LSB - PVVol_S1_Value_LSB );
					PVVol_Cali_Offset = 3.0f*( PVVol_S2_Value_LSB - PVVol_S1_Value_LSB )-PVVol_S1_Value_LSB;
			    DDL_Printf("PVVol_Cali_Gain=%.5f\r\n",PVVol_Cali_Gain);
			    DDL_Printf("PVVol_Cali_Offset=%.5f\r\n",PVVol_Cali_Offset);
					if( (PVVol_Cali_Gain < (VPV_GAIN_IDEAL*1.1f)) && (PVVol_Cali_Gain > (VPV_GAIN_IDEAL*0.9f)) 
						&& (PVVol_Cali_Offset < (VPV_OFFSET_IDEAL+20.0f)) && (PVVol_Cali_Offset > (VPV_OFFSET_IDEAL-20.0f)) )
					{
					    DDL_Printf("PV voltage calibration is succeeded!\r\n");
							DDL_Printf("Save the calibration parameters? --> Input 'Y' or 'N'\r\n");
							Cmd_cal=0;
							while( Cmd_cal!='Y' && Cmd_cal!='N' )
							{
								Cmd_cal=comm_uart_cal();
							}
							if( Cmd_cal=='Y' )
							{
								Update_CalPar_cmd=1;
								VPV_GAIN = PVVol_Cali_Gain;
								VPV_OFFSET = PVVol_Cali_Offset;
							}
					}
					else
					{
						DDL_Printf("PV voltage calibration is failed!\r\n");
					}
			    PVVol_Cali_State = DONE;
					flag=0;
				break;
			case DONE:
				PVVol_Cali_State = START;
				flag=1;
				break;	
      default:
				PVVol_Cali_State = START;
				flag=0;
				break;
		}
	
	return flag;
}
/////////////////////PV Voltage calibration/////////////////
CALIBRATION_STATE_TYPE ACCur_Cali_State;
float_t ACCur_L_Offset=0,ACCur_R_Offset=0;
//////////////////////////////////////////////////////////////
uint8_t ACCur_Cali_Rootine(void)
{
	uint8_t flag = 0;
		switch( ACCur_Cali_State )
		{
			case START:
					DDL_Printf("AC Current offset calibration is started!\r\n");
			    ACCur_Cali_State = CALC;
			    flag = 0;
				break;
			case CALC:
					ACCur_L_Offset = -Ig_L_LSB;
					ACCur_R_Offset = -Ig_R_LSB;
					DDL_Printf("ACCur_L_Offset=%.5f\r\n",ACCur_L_Offset);
			    DDL_Printf("ACCur_R_Offset=%.5f\r\n",ACCur_R_Offset);
					if( (ACCur_L_Offset < (IGL_OFFSET_IDEAL+10.0f)) && (ACCur_L_Offset > (IGL_OFFSET_IDEAL-10.0f)) 
						&& (ACCur_R_Offset < (IGR_OFFSET_IDEAL+10.0f)) && (ACCur_R_Offset > (IGR_OFFSET_IDEAL-10.0f)))
					{
					    DDL_Printf("AC current calibration is succeeded!\r\n");
							DDL_Printf("Save the calibration parameters? --> Input 'Y' or 'N'\r\n");
							Cmd_cal=0;
							while( Cmd_cal!='Y' && Cmd_cal!='N' )
							{
								Cmd_cal=comm_uart_cal();
							}
							if( Cmd_cal=='Y' )
							{
								Update_CalPar_cmd=1;
								IGL_OFFSET = ACCur_L_Offset;
								IGR_OFFSET = ACCur_R_Offset;
							}
					}
					else
					{
						DDL_Printf("AC current calibration is failed!\r\n");
					}
					ACCur_Cali_State = DONE;
					flag = 0;
				break;
			case DONE:
				  ACCur_Cali_State = START;
					flag=1;
				break;	
      default:
				break;
		}
	return flag;
}
//////////////////////////////////////////////////////////////
SYSTEM_CALIBMODE_TYPE SysCali_State;
uint8_t Calib_Sel=0;
uint8_t SysCali_Cmd=0;
uint8_t Print_flag=0;
//////////////////////////////////////////////////////////////
void System_Calib_Statemachine(void)
{
		switch( SysCali_State )
		{
			case IDLE:
				  if( Print_flag == 0)
					{
						Print_flag=1;
						DDL_Printf("Please Select The Calibration Parameter: \r\n");
						DDL_Printf("Grid voltage calibrate         --> Input '1' \r\n");
						DDL_Printf("PV voltage calibrate           --> Input '2' \r\n");
						DDL_Printf("AC Current offset calibrate    --> Input '3' \r\n");
						DDL_Printf("Write initial parameters       --> Input '4' \r\n");
						DDL_Printf("Write calibration parameters   --> Input '5' \r\n");
						DDL_Printf("Display calibration parameters --> Input '6' \r\n");
						DDL_Printf("Exit calibration mode          --> Input 'T' \r\n");
					}
			    Calib_Sel=comm_uart_cal();
			    if( Calib_Sel == '1' )
					{
						SysCali_State = GRIDVOL_CALIB;
						Calib_Sel=0;
					}
					else if( Calib_Sel == '2' )
					{
						SysCali_State = PVVOL_CALIB;
						Calib_Sel=0;
					}
					else if( Calib_Sel == '3' )
					{
						SysCali_State = ACCUR_CALIB;
						Calib_Sel=0;
					}
					else if( Calib_Sel == '4' )
					{
						SysCali_State = PARA_INIT;
						Calib_Sel=0;
					}
					else if( Calib_Sel == '5' )
					{
						Calib_Sel=0;
						SysCali_State = IDLE;
			      Update_CalPar_cmd=1;
			      Print_flag=0;
					}
					else if( Calib_Sel == '6' )
					{
						DDL_Printf("IFB1_GAIN:    %.5f\r\n",IFB1_GAIN);
						DDL_Printf("IFB1_OFFSET:  %.5f\r\n",IFB1_OFFSET);
						DDL_Printf("IFB2_GAIN:    %.5f\r\n",IFB2_GAIN);
						DDL_Printf("IFB2_OFFSET:  %.5f\r\n",IFB2_OFFSET);
						DDL_Printf("IGL_GAIN:     %.5f\r\n",IGL_GAIN);
						DDL_Printf("IGL_OFFSET:   %.5f\r\n",IGL_OFFSET);
						DDL_Printf("IGR_GAIN:     %.5f\r\n",IGR_GAIN);
						DDL_Printf("IGR_OFFSET:   %.5f\r\n",IGR_OFFSET);
						DDL_Printf("IPV_GAIN:     %.5f\r\n",IPV_GAIN);
						DDL_Printf("IPV_OFFSET:   %.5f\r\n",IPV_OFFSET);		
						DDL_Printf("VPV_GAIN:     %.5f\r\n",VPV_GAIN);
						DDL_Printf("VPV_OFFSET:   %.5f\r\n",VPV_OFFSET);		
						DDL_Printf("VGRID_GAIN:   %.5f\r\n",VGRID_GAIN);
						DDL_Printf("VGRID_OFFSET: %.5f\r\n",VGRID_OFFSET);	
						DDL_Printf("ZCD_CAL_GAIN: %.5f\r\n",ZCD_CAL_GAIN);							
						SysCali_State = IDLE;
						Calib_Sel=0;
						Print_flag=0;
					}
					else if( Calib_Sel == 'T' )
					{
						SysCali_State = IDLE;
						SysCali_Cmd = 0;
						Calib_Sel=0;
						DDL_Printf("calibration mode is Exit!");
					}
				break;
			case GRIDVOL_CALIB:
			  if( GridVol_Cali_Rootine() == 1 )
				{
					SysCali_State = IDLE;
					Print_flag=0;
				}
				else
				{;}
				break;
			case PVVOL_CALIB:
				if( PVVol_Cali_Rootine() == 1 )
				{
					SysCali_State = IDLE;
					Print_flag=0;
				}
				else
				{;}
				break;
			case ACCUR_CALIB:
				if( ACCur_Cali_Rootine() == 1 )
				{
					SysCali_State = IDLE;
					Print_flag=0;
				}
				else
				{;}
				break;
			case PARA_INIT:
				CalPara_Init();
			  SysCali_State = IDLE;
			  Update_CalPar_cmd=1;
			  Print_flag=0;
			  DDL_Printf("Writing Initial parameters is done!\r\n");	
			default:
				SysCali_State = IDLE;
			  Print_flag=0;
				break;		
		}
}
///////////////////////////////////////////////////////////////
uint8_t comm_uart_cal(void)
{
	static uint8_t Cmd_in=0;
	
	WDT_FeedDog();
	
	if( bCM_USART2->SR_b.ORE == 1 )
	{
		 CM_USART2->CR1 |= USART_CR1_CORE;
	}
	
	if( UART_RX_NEMPITY == 1 )
	{
		Cmd_in = CM_USART2->RDR;
		return Cmd_in;
	}
	else
	{
		return 0;
	}
}
///////////////////////////////////////////////////////////////
float_t	IFB2_GAIN = 0.0f;
float_t	IFB2_OFFSET = 0.0f;
float_t	IFB1_GAIN = 0.0f;
float_t  IFB1_OFFSET = 0.0f;
float_t  IGL_GAIN = 0.0f;
float_t  IGL_OFFSET = 0.0f;
float_t  IGR_GAIN = 0.0f;
float_t  IGR_OFFSET = 0.0f;
float_t  IPV_GAIN = 0.0f;
float_t  IPV_OFFSET = 0.0f;
float_t  ZCD_CAL_GAIN = 0.0f;

float_t  VPV_GAIN = 0.0f;
float_t  VPV_OFFSET = 0.0f;
float_t  VGRID_GAIN = 0.0f;
float_t  VGRID_OFFSET = 0.0f;
///////////////////////////////////////////////////////////////
void CalPara_Init(void)
{
	IFB2_GAIN = IFB2_GAIN_IDEAL;
	IFB2_OFFSET = IFB2_OFFSET_IDEAL;
	IFB1_GAIN = IFB1_GAIN_IDEAL;
  IFB1_OFFSET = IFB1_OFFSET_IDEAL;
  IGL_GAIN = IGL_GAIN_IDEAL;
  IGL_OFFSET = IGL_OFFSET_IDEAL;
  IGR_GAIN = IGR_GAIN_IDEAL;
  IGR_OFFSET = IGR_OFFSET_IDEAL;
  IPV_GAIN = IPV_GAIN_IDEAL;
  IPV_OFFSET = IPV_OFFSET_IDEAL;
  ZCD_CAL_GAIN = ZCD_CAL_GAIN_IDEAL;

  VPV_GAIN = VPV_GAIN_IDEAL;
  VPV_OFFSET = VPV_OFFSET_IDEAL;
  VGRID_GAIN = VGRID_GAIN_IDEAL;
  VGRID_OFFSET = VGRID_OFFSET_IDEAL;
}








