#ifndef __CONTROL_H
#define __CONTROL_H 

#ifdef __cplusplus
extern "C" {
#endif

/////constant///////////
#include "hc32_ll.h"
#include "math.h"

//#define OFF_GRID_CLOSELOOP_DEBUG
//#define OFF_GRID_OPENLOOP_DEBUG
//#define DRIVER_DEBUG
//#define PHASE_A_DRIVE_TEST
//#define PHASE_B_DRIVE_TEST
//#define MPPT_DISABLE
//#define UPDATE_CAL_PAR
#define TWO_PHASE_BOTH_WORKING

#define FBPWM_DISABLE      CM_HRPWM_COMMON->SSTAIDLR |= (HRPWM_COMMON_SSTAIDLR_SSTAIDL1A|HRPWM_COMMON_SSTAIDLR_SSTAIDL4A)
#define FBPWM1_DISABLE     CM_HRPWM_COMMON->SSTAIDLR |= (HRPWM_COMMON_SSTAIDLR_SSTAIDL1A)
#define FBPWM2_DISABLE     CM_HRPWM_COMMON->SSTAIDLR |= (HRPWM_COMMON_SSTAIDLR_SSTAIDL4A)
#define FBPWM1_ENABLE      CM_HRPWM_COMMON->SSTARUNR1 |= (HRPWM_COMMON_SSTARUNR1_SSTARUN1A)
#define FBPWM2_ENABLE      CM_HRPWM_COMMON->SSTARUNR1 |= (HRPWM_COMMON_SSTARUNR1_SSTARUN4A)
#define INVPWM_DISABLE     CM_GPIO->PORRA |=(GPIO_PORR_POR08|GPIO_PORR_POR09);CM_GPIO->PORRC |=(GPIO_PORR_POR08|GPIO_PORR_POR09)
#define INVPWM_POS         CM_GPIO->PORRA |=(GPIO_PORR_POR08);CM_GPIO->PORRC |=(GPIO_PORR_POR09);CM_GPIO->POSRA |=(GPIO_POSR_POS09);CM_GPIO->POSRC |=(GPIO_POSR_POS08)
#define INVPWM_POS_SCROFF  CM_GPIO->PORRA |=(GPIO_PORR_POR08);CM_GPIO->PORRC |=(GPIO_POSR_POS08|GPIO_PORR_POR09);CM_GPIO->POSRA |=(GPIO_POSR_POS09)
#define INVPWM_NEG         CM_GPIO->PORRA |=(GPIO_PORR_POR09);CM_GPIO->PORRC |=(GPIO_PORR_POR08);CM_GPIO->POSRA |=(GPIO_POSR_POS08);CM_GPIO->POSRC |=(GPIO_POSR_POS09)
#define INVPWM_NEG_SCROFF  CM_GPIO->PORRA |=(GPIO_PORR_POR09);CM_GPIO->PORRC |=(GPIO_POSR_POS08|GPIO_PORR_POR09);CM_GPIO->POSRA |=(GPIO_POSR_POS08)

#define LED_GREEN_ON       CM_GPIO->POSRC |=(GPIO_POSR_POS11)
#define LED_GREEN_OFF      CM_GPIO->PORRC |=(GPIO_PORR_POR11);
#define LED_RED_ON         CM_GPIO->POSRA |=(GPIO_POSR_POS12)
#define LED_RED_OFF        CM_GPIO->PORRA |=(GPIO_PORR_POR12);
#define UART_TXFIFO_EMPITY ((CM_USART2->SR & USART_FLAG_TX_EMPTY)==USART_FLAG_TX_EMPTY)
#define UART_RX_NEMPITY    ((CM_USART2->SR&USART_FLAG_RX_FULL)==USART_FLAG_RX_FULL)
/////system parameter

//main control interrupt period
#define Ts                              0.00005f

//20ms counter number in control interrupt
#define CONTROL_INT_CNT_1MS             20
#define TIME_COUNT_20MS                 (20*CONTROL_INT_CNT_1MS-1)
#define TIME_COUNT_500MS                (500*CONTROL_INT_CNT_1MS-1)

//PI, sqrt(2) and related constant value
#define PI                              3.14159265359f
#define PIDIV2                          1.570796326795f
#define PIDIV2X3                        4.71238898f
#define PIX2                            6.28318530718f

#define SQRT2                           1.414f
#define SQRT2_DIV                       0.707f

//control related time parameter normalization value
#define CTRL_TIME_PU_VALUE              12.0f //us

//on and off
#define TURN_ON                         1
#define TURN_OFF                        0

//inverter start conditions
#define GRIDVOLRMS_START_MIN_THRESHOLD  220.0f*0.85f  //Grid voltage rms must in [0.85,1.15]pu
#define GRIDVOLRMS_START_MAX_THRESHOLD  220.0f*1.15f
#define PVVOL_START_MIN_THRESHOLD       35.0f //PV voltage must in [35,60]
#define PVVOL_START_MAX_THRESHOLD       60.0f
#define SYSTEM_READY_THRESHOLD          20000 //system is ready if Grid voltage and PV voltage meets the start condition for SYSTEM_READY_THRESHOLD times
#define SSTART_THETA_THRESHOLD          0.03f //grid angle(@negative to positive zero-crossing) to start unfolding PWMs
#define SSTART_DELAY_THRESHOLD          1000 //delay time from  unfolding inverter PWMs enable to flyback PWMs enable
#define RUN_THETA_THRESHOLD             0.03f //grid angle(@negative to positive zero-crossing) to start flyback PWMs

//microinverter system parameters
#define TRANSFORM_N_RATIO               6.0f // flyback teansformer ratio
#define TRANSFORM_N_INVRATIO            0.166667f // 1/TRANSFORM_N_RATIO
#define TRANSFORM_LM                    10.0f //uH flyback teansformer magnetinezing inductance
#define SYSTEM_RATED_POWER              500.0f //system rated  power
#define SYSTEM_RATED_AC_CURRENT_AMP     3.2f //system max current value

//feedforward value related paramerters
#define CTRL_TIME_PU_VALUE_DIV_LM       1.2f  //=CTRL_TIME_PU_VALUE/TRANSFORM_LM

///power limit parameter
#define POWER_LIMIT_VOLTAGE_THRESHOLD   42.0f // above POWER_LIMIT_VOLTAGE_THRESHOLD, full power; below POWER_LIMIT_VOLTAGE_THRESHOLD, power limit
#define POWER_LIMIT_RATIO               20.0f // below POWER_LIMIT_VOLTAGE_THRESHOLD, the power decreases to POWER_LIMIT_RATIO*(real time PV voltage - POWER_LIMIT_VOLTAGE_THRESHOLD);

//reactive current compensation
#define REACTIVE_COMPENSATION_VALUE     0.05f //the amplitude value of reactive current when the grid voltage is rated
#define GRIDVOL_RATEDRMS_DIV            0.0045f// =1/220, to compensate the influence of grid voltage variation

//PLL related parameter
#define PLL_OK_DELAY_THRESHOLD          9999   //PLL is ok if the q-axis absolute value is < PLL_OK_ERROR_THRESHOLD for PLL_OK_DELAY_THRESHOLD*Ts;
#define PLL_OK_ERROR_THRESHOLD          10.0f  //PLL q-axis value to  judge if PLL is ok
#define FRE_BASE                        50.0f  //grid base frequency
#define FLL_K                           -0.5f  //FLL k ratio

//zero-crossing unfolding and flyback start and stop condition
#define UNFOLDING_THETA_ON_THRESHOLD    0.0314f //unfolding start offset angle after zero-crosing
#define UNFOLDING_THETA_OFF_THRESHOLD   0.02f //unfolding mosfet stop offset angle after zero-crosing
#define SCR_THETA_OFF_THRESHOLD         0.10f //unfolding SCR stop offset angle after zero-crosing
#define FB_THETA_OFF_THRESHOLD          0.0314f //unfolding flyback stop offset angle after zero-crosing, the start offset angle is same as UNFOLDING_THETA_ON_THRESHOLD
#define UNFOLDING_VG_ON_THRESHOLD       4.0f //unfolding start condition: the grid voltage abs value is above UNFOLDING_VG_ON_THRESHOLD

//reference volatge ramp step for PV voltage loop
#define PV_VOL_STEP                     0.1f

//power allocation
#define BOTHWORK_UPLIMIT_THRESHOLD      0.35f //one flyback to two flybacks working condition: ontime pu >= BOTHWORK_UPLIMIT_THRESHOLD && 0.5*period pu without delay time >= BOTHWORK_PERIOD_UPLIMIT_THRESHOLD
#define BOTHWORK_LOWLIMIT_THRESHOLD     0.25f //two flybacks to one flyback working condition: ontime pu < BOTHWORK_UPLIMIT_THRESHOLD || 0.5*period pu without delay time < BOTHWORK_PERIOD_UPLIMIT_THRESHOLD
#define BOTHWORK_PERIOD_UPLIMIT_THRESHOLD 0.45f
#define BOTHWORK_PERIOD_LOWLIMIT_THRESHOLD 0.4f
#define BOTHWORK_DISTRIBUTION_RATIO     0.55f // if two flybacks is both working , the ontime for every flyback = ontime*BOTHWORK_DISTRIBUTION_RATIO, 
//this ratio must be changed if the system charactor is changed including transformer, flyback mosfet and diode and other related charactor. or the output current may have distortion @the working flyback number is changed

//AC current loop parameter
#define ACCUR_RESONANT_GAIN_RATIO       150.0f //resonant loop gain
#define ACCURLOOP_ONTIME_RATIO          92160.0f //12us =CTRL_TIME_PU_VALUE*120*64
#define FLYBACK_MIN_ONTIME              1600 //min on time
#define FLYBACK_MIN_ONTIMEX2            3200 //min on time for two flyback
#define FLYBACK_MAX_ONTIME              92160 //max on time=ACCURLOOP_ONTIME_RATIO
#define FLYBACK_MAX_ONTIMEX2            184320 //max on time for two flyback = ACCURLOOP_ONTIME_RATIO*2

//MPPT parameters
#define MPPT_STEP_STEADY                0.05f //if the MPP is find @step=0.2, decrease step slowly to MPPT_STEP_STEADY
#define MPPT_STEP_MIN                   0.2f //MPPT disturbance min step
#define MPPT_STEP_MAX                   0.5f //MPPT disturbance max step
#define MPPT_DELAY_TIME_THRESHOLD       6000 //MPPT start after flyback is working for MPPT_DELAY_TIME_THRESHOLD
#define MPPT_STEP_INCREASE_RATIO        20.0f //incease step if power> MPPT_STEP_INCREASE_RATIO*step
#define MPPT_STEP_DECREASE_RATIO        7.0f //decrease step if power< MPPT_STEP_DECREASE_RATIO*step
#define MPPT_INITIAL_VOL_RATIO          0.95f //the initial PV voltage loop reference

//the average power ratio
#define INSTANT_POWER_AVERAGE_RATIO     0.25f

//LED twincle interval
#define TWINKLE_INTERVAL_THRESHOLD      60000

//blanking time
#define MIN_PERIOD_RATIO                0.7f //blanking time for the cmp output for MIN_PERIOD_RATIO*period
#define MIN_PERIOD_MIN                  30720 //the minimum blaking time

//vally switching 
#define VALLY_SW_PERIOD                 16128  //vally switching rsonant period
#define VALLY_SW_DELAY_ONE              1230 //turn on flyback PWM @ the fist vally, it considers the delay time of cmp and hrpwm timer loop
#define VALLY_SW_DELAY_TWO              17358 //=VALLY_SW_PERIOD+VALLY_SW_DELAY_ONE turn on flyback PWM @ the second vally
#define VALLY_SW_DELAY_THREE            33486 //=VALLY_SW_PERIOD*2+VALLY_SW_DELAY_ONE turn on flyback PWM @ the third vally
#define VALLY_SW_DELAY_FOUR             49614 //=VALLY_SW_PERIOD*3+VALLY_SW_DELAY_ONE turn on flyback PWM @ the fourth vally
#define VALLY_SW_DELAY_INIT             81870 //=VALLY_SW_PERIOD*5+VALLY_SW_DELAY_ONE turn on flyback PWM @ the sixth vally

#define VALLY_SW_DELAY_ONE_PU           0.0875f //=VALLY_SW_DELAY_ONE/ACCURLOOP_ONTIME_RATIO
#define VALLY_SW_DELAY_TWO_PU           0.2625f //=VALLY_SW_DELAY_TWO/ACCURLOOP_ONTIME_RATIO
#define VALLY_SW_DELAY_THREE_PU         0.4375f //=VALLY_SW_DELAY_THREE/ACCURLOOP_ONTIME_RATIO
#define VALLY_SW_DELAY_FOUR_PU          0.6125f //=VALLY_SW_DELAY_FOUR/ACCURLOOP_ONTIME_RATIO
#define VALLY_SW_DELAY_INIT_PU          0.9625f //=VALLY_SW_DELAY_INIT/ACCURLOOP_ONTIME_RATIO

//vally swtiching condition
#define VALLY_INIT2FOUR_CUR_THRESHOLD    0.09f
#define VALLY_FOUR2INIT_CUR_THRESHOLD    0.07f

#define VALLY_FOUR2THREE_CUR_THRESHOLD   0.16f
#define VALLY_THREE2FOUR_CUR_THRESHOLD   0.14f

#define VALLY_THREE2TWO_CUR_THRESHOLD    0.23f
#define VALLY_TWO2THREE_CUR_THRESHOLD    0.21f

#define VALLY_TWO2ONE_CUR_THRESHOLD      0.31f
#define VALLY_ONE2TWO_CUR_THRESHOLD      0.29f

//feedforward ratio
#define VALLY_SW_IDEAL_RATIO             0.7f

//interleave phase adjustment when two flybacks is both working
//flyback1 on time < TIME_6US, the phase compensation = phase error*PHASE_ADJUST_RATIO
//flyback1 on time > TIME_9US, the phase compensation = phase error*PHASE_ADJUST_RATIO_MAX
//else the phase compensation = phase error*Flyback1_OnTime*PHASE_ADJUST_RATIO_WITH_K
#define TIME_6US                        46080
#define TIME_8US                        61440
#define TIME_9US                        69120
#define PHASE_ADJUST_RATIO              0.125f
#define PHASE_ADJUST_RATIO_WITH_K       0.00000271267f
#define PHASE_ADJUST_RATIO_MAX          0.1875f
//the phase compensation uplimit=Flyback1_OnTime>>INTERLEAVE_MAX_TIME_RATIO;
#define INTERLEAVE_MAX_TIME_RATIO       2

/////enum
typedef enum{
	STANDBY,	
	SSTART,
	RUN,
	FAULT,
} SYSTEM_STATE_TYPE;

typedef enum{
	DELAY_VALLY_INIT,
	DELAY_VALLY_4,	
	DELAY_VALLY_3,
	DELAY_VALLY_2,
	DELAY_VALLY_1,
} DELAY_VALLY_STATE_TYPE;

///////struct definition////////
typedef struct {
                  float   SOGI_Uin;     /* Input: Reference input  */
                  float   SOGI_amp;
                  float   SOGI_dv1;     /* Input: Feedback input  */
                  float   SOGI_err;     /* Variable: Error    */
                  float   SOGI_K;       /* Parameter: Proportional gain  */
                  float   SOGI_dv2;     /* Variable: Proportional output  */
                  float   SOGI_qv1;     /* Variable: Integral output    */
                  float   SOGI_qv2;     /* Variable: Derivative output    */
                  float   SOGI_w;       /* Parameter: Integral gain   */
                }SOGI;

#define SOGI_DEFAULT {0.0f,\
                     0.0f,\
                     0.0f,\
                     0.0f,\
                     1.05f,\
                     0.0f,\
                     0.0f,\
                     0.0f,\
                     314.15926536f,\
                     }
typedef struct {
              float alpha;
              float beta;
              float fdb;
              float ref;
              float error;
              float kp;
              float ki;
              float up;
              float ui;
              float pi;
              float mode;
              float pi_i;
              float freq;
              float theta;
            }PLL;
//PLL parameter
#define PLL_DEFAULT { 0.0f,\
                  0.0f,\
                  0.0f,\
                  0.0f,\
                  0.0f,\
                  0.04f,\
                  0.000021f,\
                  0.0f,\
                  0.0f,\
                  0.0f,\
                  0.0f,\
                  0.0f,\
                  0.0f,\
                  0.0f,\
            }

typedef struct {
						 float input;     /* Input: input  */
						 float k;         /* parameter: filter parameter */
						 float output;    /* output: filter parameter  */
						 float output_pre;/* Variable: previous output */
              }LPF_1st;
#define LPF_1st_1kHz {0.0f,\
                      0.239057223611f,\
                      0.0f,\
                      0.0f,\
                     }
#define LPF_1st_500Hz {0.0f,\
                      0.135755248164f,\
                      0.0f,\
                      0.0f,\
                     }
#define LPF_1st_10Hz {0.0f,\
                      0.003131753958f,\
                      0.0f,\
                      0.0f,\
                     }
#define LPF_1st_5Hz {0.0f,\
                      0.001565876979f,\
                      0.0f,\
                      0.0f,\
                     }
#define LPF_1st_2Hz {0.0f,\
                      0.0006263507916f,\
                      0.0f,\
                      0.0f,\
                     }
typedef struct{
                 float input;     /* Input: input  */
                 float input_pre1;     /* Input: input  */
                 float input_pre2;     /* Input: input  */
                 float A1;         /* parameter: filter parameter */
                 float A2;         /* parameter: filter parameter */
                 float A3;         /* parameter: filter parameter */
                 float B1;         /* parameter: filter parameter */
                 float B2;         /* parameter: filter parameter */
                 float output;    /* output: filter parameter  */
                 float output_pre1;/* Variable: previous output */
                 float output_pre2;/* Variable: previous output */
}NOTCH_LPF;

#define LPF_notch_100Hz_20k_Q1 {0.0f,\
                      0.0f,\
                      0.0f,\
                      0.9845387169174757f,\
                      -1.9681059727680088f,\
                      0.9845387169174757f,\
                      -1.9681059727680088f,\
                      0.9690774338349514f,\
                      0.0f,\
                      0.0f,\
                      0.0f,\
                     }
typedef struct {  
								float  pid_ref_reg;     /* Input: Reference input  */
                float  pid_fdb_reg;     /* Input: Feedback input  */
                float  e_reg;           /* Variable: Error    */
                float  up_reg;          /* Variable: Proportional output  */
                float  ui_reg;          /* Variable: Integral output    */
                float  pid_out_max;       /* Parameter: Maximum output    */
                float  pid_out_min;       /* Parameter: Minimum output    */
                float  pid_out_reg;     /* Output: PID output    */
                float  Kp_reg;           /* Parameter: Proportional gain  */
                float  Ki_reg;           /* Parameter: Integral gain   */
                float  output;
               } PIREG;

//PV voltage loop initial paramters					 
#define PVVOL_PI_DEFAULT { 0.0f,\
                     0.0f,\
                     0.0f,\
                     0.0f,\
                     0.0f,\
                     3.2f,\
                     0.0f,\
                     0.0f,\
                     0.1f,\
                     0.001f,\
                     0.0f,\
                 }
//ac current PI loop initial paramters	
#define ACCUR_PI_DEFAULT { 0,\
                     0.0f,\
                     0.0f,\
                     0.0f,\
                     0.0f,\
                     600.0f,\
                     -600.0f,\
                     0.0f,\
                     0.5f,\
                     7.0f,\
                     0.0f,\
                 }
typedef struct
{
								float input;
								float input_old1;
								float input_old2;
								float a;
								float b0;
								float b1;
								float output;
								float output_old1;
								float output_old2;
}RESONANT_LPF;

//ac current resonant loop initial paramters	
#define ACCUR_R_DEFAULT { 0.0f,\
                     0.0f,\
                     0.0f,\
                     0.00024998332985477f,\
                     -1.9997432770095525f,\
                     0.9999900006668085f,\
                     0.0f,\
										 0.0f,\
										 0.0f,\
                 }
/////////////////////////////////////////////////
extern PLL Ug_info;
extern int16_t PLL_ok_cnt,PLL_ok_flag;
extern float_t Ugridrms,Ugridrms_Div_AMP;
extern uint8_t InvPWM_En_cmd;
extern uint8_t FBPWM_En_cmd,MPPT_En_cmd;
extern uint8_t pos_ON_FB_sample;
extern uint8_t neg_ON_FB_sample;
extern float_t I_fb1,I_fb2;
extern float_t Vpv,Ipv;
extern float_t Vgrid,Ig_L,Ig_R;
extern float_t Iac,Iac_protect;
extern SOGI U_alpha;
extern int32_t Flyback1_OnTime,Flyback2_OnTime;
extern float_t Vpv_LSB,Ipv_LSB;
extern LPF_1st Vpv_LPF;
extern NOTCH_LPF Vpv_Notch;
extern float_t SystemPower_After_Limit,Power_Limit_Current_MAX;
extern SYSTEM_STATE_TYPE MicroInv_State;
extern uint32_t TEST_TIME_THRESHOLD;
extern float_t cur_set_value;
extern uint8_t System_status_upload_cmd;
extern float_t Vally_SW_Delay_pu,Vally_SW_FF_ratio;
extern uint32_t Vally_SW_Delay_Time;
extern DELAY_VALLY_STATE_TYPE Vally_SW_State;
extern float_t Vgrid_LPF_abs,MinDutyDiv,Period_Ton_pu;
extern PIREG ACCur_PILoop,PVVol_PILoop;
extern uint8_t MPPT_Run_Flag;
extern float_t costheta;
extern float_t ACCur_loop_output_duty;
extern float_t Vally_PI_RATIO;
extern float_t Iac_Rms_Sum_Cal;
extern uint16_t Rms_Sum_Flag,RMS_cnt_Cal;
extern float_t System_Power_Ins,System_Power_Avg;
extern uint8_t System_Power_cnt;
extern uint8_t MPPT_State_Flag;
extern uint8_t System_Ready_Flag;
extern uint8_t MicroInv_Start_cmd;
extern LPF_1st Vpv_LSB_LPF;
extern LPF_1st Vgrid_LSB_LPF;
extern uint16_t Time_50us_Cnt;
extern uint16_t Time_1ms_Cnt;
extern uint16_t Time_100ms_Cnt;
extern uint16_t Time_1s_Cnt;
extern float_t Ig_L_LSB,Ig_R_LSB;
extern float_t Interleave_ratio;
/////////////////////////////////////////////////
extern inline void AllPWM_Disable(void);
extern inline void MicroInv_StateMachine(void);
extern inline void PLL_FUN(void);
extern inline void MicroInv_Unfolding_Driver(uint8_t cmd);
extern inline void Grid_HalfCycle_cal(void);
extern inline void MicroInv_PV_VOLTAGE_LOOP(uint8_t cmd);
extern inline void MicroInv_AC_CURRENT_LOOP(uint8_t cmd);
extern inline void MPPT(uint8_t cmd);
extern inline void FlyBack_Interleaved_adjustment(void);
extern inline void Micro_inverter_CTRL(void);
extern inline void ZCD_Threshold_Cal(void);
extern inline void SampleCondition_Cal(void);
extern inline void Vally_SW_Delay_Cal(uint8_t cmd);
extern inline void main_func(void);
extern inline void Timer_Counter(void);
/////////////////////////////////////////////////
#ifdef __cplusplus
}
#endif

#endif /* __MAIN_H */

