/* 
 *  Copyright 2004 by Soos, Antal 
 *  All rights reserved. Property of Soos, Antal. 
 *  Restricted rights to use, duplicate or disclose this code are 
 *  granted through contract.   
 */ 
/***************************************************************************/ 
/*                                                                         */ 
/*     AVR_Exciter . c	                                                   */ 
/*                                                                         */ 
/*     AVR Exciter from IEEE Standard Algorithm inplementation.            */ 
/*                                                                         */ 
/*                                                                         */ 
/***************************************************************************/ 

#include "AVR_Exciter.h"
#include "dsk_lib.h"


// Macro definitions:
//------------------------------------------------------------------------------------- 
#define  HV_gate(a, b)             	( (a) > (b) ? (a) : (b) )

#define  LV_gate(a, b)             	( (a) < (b) ? (a) : (b) )

//------------------------------------------------------------------------------------- 

 //------------------------------------------------------------------------------------- 
  // Paramether definitions:
	// To calculate the teminal line voltage loss (compensation for it):
   	#define Rc  0.0     /*0.0 resistive component of load compensatino  */
   	#define Xc  0.0	     /*0.0 reactance component of load componsatino */
						

	#define Tr  0.0001	 // 0.001    /*0.04 regulator input filter time constant */

	/* AVR voltage reference   VT_REF      */
   #define VT_REF  2.95			// 2.7V  <->  243   V
	       						// 2.5V  <->  224   V
								// 2.35V <->  211.3 V 
								// 2.3   <->  206.9 V
								// 2.325v <-> 209.1 V
								// 2.32   <-> 208.6 V
								// 2.315  <-> 208.2 V
								// 2.314  <-> 208.0 V 
								// 2.319  <-> 208.5 V
								// 2.3185 <-> 208.3 V
						// 2.8 V 

	
	#define	REF_POT_CHANGE  0.00001	/* Reference increment */
	#define	REF_POT_STEP  (0.03 * VT_REF)	/* 2% Reference increment */
	
	
 // LED signalization:	
	#define	VT_REF_L  (VT_REF* 0.9 )
	#define	VT_REF_iL (VT_REF* 0.99)						
	#define	VT_REF_iU (VT_REF* 1.01) 
	#define	VT_REF_U  (VT_REF* 1.1 )
																														
																									
	#define Vimin  -5.0 /*-9.0 AVR internal signal upper limit */
	#define Vimax  5.0 /*9.0 AVR internal signal lower limit */

	#define Vuel  0.0 /*0.0 under-excitation limiter output  */


   	#define Tb   0.0          /*10.0 AVR time constant */
   	#define Tc   0.0          /*1.0 AVR time constant */
   	#define Tb1  0.0          /*0.0 AVR time constant */
   	#define Tc1   0.0         /*0.0 AVR time constant */

	#define Ta   0.01      //0.01 /*0.01 AVR time constant  */  
	#define Ka  11.0     //12.0  /*190.0 AVR gain	  */
  
	#define Vamin  -5.5   /*-5.0 AVR internal signal upper limiter	   */
	#define Vamax  5.5   /*5.0 AVR internal signal lower limiter	   */

	#define Ilr  0.0      /*0.0 exciter output current limit reference */

	#define Klr  0.0     /* 0.0 exciter output current limiter gain   */

	#define Voel  5.0    /* 9.0 over-excitation limiter output */

   	#define Tf  1.0     /* 1.0 AVR stabilizer time constant   */
  	#define Kf  0.00     /* 0.05 AVR stabilizer gain    */
   	   	   
   
   	#define Kc  0.0      /* rectifier loading factor proportional to   */
   								/* commutating reactance			   */
   	#define Vrmin  -3.0  /*-4.0 AVR internal signal upper limit */
	#define Vrmax  3.0   /*4.0 AVR internal signal lower limit */    
   	
   	
    // 0.1 pu (10%) sygnal of the AVR's level, limit for the Upss:
   	#define MAX_Upss     0.25   /* 0.35 */
    #define MIN_Upss    (-MAX_Upss) 	
   	
   	
   	
 //------------------------------------------------------------------------------------- 
 // Paramethers initialised at the DSP code start:

 	static 	float Rt;  /* Terminal line resistance Rt = sqrt(Rc^2 + Xc^2) */

 	static 	float Rb0, Rb1,Ra1;

 	static 	float Cb0,Cb1,Cb2;
 	static 	float Ba1,Ba2;

 	static 	float Ab0, Ab1, Aa1;
		
 	static 	float Fb0, Fb1, Fa1;

//--------------------------------------------------------------------------
//--------------------------------------------------------------------------
	//State variables:
	
	static float Vref ;       /* Variable reference voltage */

	static float Vk, Vk1;     /* output of terminal voltage transducer */
	static float Vr, Vr1;     /* load compensation element	 */
    static float Vi;          /* AVR input voltage error */
	static float Vc,Vc1,Vc2;  /* AVR internal signal	 */
	static float Vb, Vb1, Vb2;/* available AVR voltage	 */
	static float Va, Va1;     /* AVR internal voltage	 */
	static float Vl;          /* AVR inner voltage		 */
	static float Ve;          /* AVR inner voltage	     */
	static float Ef;		  /* AVR output voltage */ 
	static float Ef1;         /* AVR output voltage n-1 */ 
	static float Vf,Vf1;      /* AVR stabilizer output	 */



//--------------------------------------------------------------------------
//--------------------------------------------------------------------------

float AVR_Exciter(float Upss)
{

	// External variables:
	//extern float Vt;    /* Terminal voltage   */
	//extern float It;    /* Terminal current   */
	//extern float If;    /* Field current      */
	//extern float Upss;  /* PSS control signal */


 
   	float Efmin; /* AVR control signal lower limit */
	float Efmax; /* AVR control signal upper limit */
 


	/* Vk calculations from Vt and It, paramethers Rc and Xc */
  // Vk : 
  	Vk = Vt + Rt*It;
      
	/* Vr calculations from Vk, paramether Tr */
  // Vr :  
	Vr = Rb0 * Vk + Rb1 * Vk1 - Ra1 * Vr1;
	Vk1 = Vk; 
	Vr1 = Vr;
     
   //Vi :
       // For ptotection we shold limit the Upss signal:
	Upss = Upss * MAX_Upss;   // convert the +/- 1pu Upss signal to voltage levels
    Upss = LIMIT( MIN_Upss, Upss, MAX_Upss );  // for the start it shold be limited
    
    Vref = adjust_Vref(Vref);  // Reference voltage manipulations
    
    // Vi : The AVR's summing junction:
	Vi = Vref + Upss - Vr - Vf;
	Vi  = LIMIT( Vimin, Vi, Vimax );

	//Vc :
	Vc  = HV_gate( Vuel, Vi );


   /* Vb calculations from Vc, paramethers: Tc,Tc1,Tb,Tb1 */

	Vb = Cb0 * Vc + Cb1 * Vc1 + Cb2 * Vc2 - Ba1 * Vb1 - Ba2 * Vb2;
   
	Vc2 = Vc1;
	Vc1 = Vc;
	Vb2 = Vb1;
	Vb1 = Vb;


   /* Va calculation from Vb, paramethers Ta, Ka */

	Va = Ab0 * Vb + Ab1 * Vb1 - Aa1 * Va1;
	
	//Vb1 = Vb; using the Vb1 from above!
	Va  = LIMIT( Vamin, Va, Vamax);
	Va1 = Va;   // To prevent saturation

   /* Vl calculation */
   
	Vl = Klr * (If - Ilr); 


	Ve = Va - Vl;

	Ef = LV_gate(Voel, Ve);

   

   /* Vf calculation parameters Kf, Tf, input Ef */

	Vf  = Fb0 * Ef + Fb1 * Ef1 - Fa1 * Vf1;

	Ef1 = Ef;
	Vf1 = Vf;


	Efmin  = (Vt * Vrmin) - (Kc * If) ;
	Efmax  = (Vt * Vrmax) - (Kc * If) ;
 
	Ef = LIMIT( Efmin, Ef, Efmax );
    Ef = LIMIT( 0.0, Ef, 4.9 );  // To protect the TRANSISTOR 
	return Ef;  /* Valif in limit -1 .. +1 */

}

//--------------------------------------------------------------------------
//--------------------------------------------------------------------------

void init_AVR_Exciter(void)
{
  // Ts;    /* Samle time period  */
	float Ts_inv;
	float Tc_p,Tc_n;
	float Tc1_p,Tc1_n;
	float Tb_p,Tb_n;
	float Tb1_p,Tb1_n;
    float Tb_p1p;

	float ftemp1;

	Ts_inv = 1.0 / Ts; /* Sample time inverse */

	/* Vc1 calculations from Vt and It, paramethers Rc and Xc */
	Rt = sqrt((Rc*Rc) + (Xc*Xc));


		/* Vr calculations from Vk, paramether Tr */
	ftemp1 = 1/(Ts + 2*Tr);
	Rb0 = Ts * ftemp1;
	Rb1 = Rb0 ;
	Ra1 = (Ts - 2*Tr) * ftemp1;
   

	/* Vb calculations from Vc, paramethers: Tc,Tc1,Tb,Tb1 */
	ftemp1 = 2 * Tc * Ts_inv;
	Tc_p = 1 + ftemp1;
	Tc_n = 1 - ftemp1;

	ftemp1 = 2 * Tc1 * Ts_inv;
	Tc1_p = 1 + ftemp1;
	Tc1_n = 1 - ftemp1;

	ftemp1 = 2 * Tb * Ts_inv;
	Tb_p = 1 + ftemp1;
	Tb_n = 1 - ftemp1;

	ftemp1 = 2 * Tb1 * Ts_inv;
	Tb1_p = 1 + ftemp1;
	Tb1_n = 1 - ftemp1;

	Tb_p1p = 1/(Tb_p * Tb1_p);


	Cb0 = Tc_p * Tc1_p * Tb_p1p;
	Cb1 = ((Tc_p * Tc1_n) + (Tc_n * Tc1_p)) * Tb_p1p;
	Cb2 = Tc_n * Tc1_n * Tb_p1p;  
	Ba1 = ((Tb_p * Tb1_n) + (Tb_n * Tb1_p)) * Tb_p1p;
	Ba2 = Tb_n * Tb1_n * Tb_p1p;


   /* Vl calculation */
	ftemp1 = 1.0 / (1.0 + (2.0 * Ta * Ts_inv));
	Ab0 = Ka * ftemp1;
	Ab1 = Ab0;
	Aa1 = (1.0 - (2 * Ta * Ts_inv)) * ftemp1;


 /* Vf calculation parameters Kf, Tf, input Ef */
	ftemp1 = 1.0 / (1.0 + (2.0 * Tf * Ts_inv));

	Fb0 = 2.0 * Kf * Ts_inv * ftemp1 ;
	Fb1 = -Fb0;
	Fa1 = (1.0 - (2.0 * Tf * Ts_inv)) * ftemp1;
	
	init_AVR_states();  

}


//--------------------------------------------------------------------------
//--------------------------------------------------------------------------

void init_AVR_states(void)
{

	Vref = VT_REF; 
    Vk   = 0.0;
    Vk1  = 0.0;
	Vr   = 0.0;
	Vr1  = 0.0;
    Vi   = 0.0;
	Vc   = 0.0;
	Vc1  = 0.0;
	Vc2  = 0.0;
	Vb   = 0.0;
	Vb1  = 0.0;
	Vb2  = 0.0;
	Va   = 0.0;
	Va1  = 0.0;
	Vl   = 0.0;
	Ve   = 0.0;
	Ef   = 0.0;
	Ef1  = 0.0;
	Vf   = 0.0;
	Vf1  = 0.0;
    
}


//--------------------------------------------------------------------------
//--------------------------------------------------------------------------

float adjust_Vref(float Vref)  // Reference voltage manipulations
{

    float ftemp;

    if(Switch_isOn(SWITCH_1)) // Voltag reference step change
    {
    
       	if( Switch_isOn(SWITCH_A1))
		{
       	
       		if(!(xflag & XF_ExVoReStChP))
			{
					Vref += REF_POT_STEP;
					xflag = xflag | XF_ExVoReStChP;
					xflag = xflag & XF_ExVoReStChNX;
			}
		}
		else if( Switch_isOn(SWITCH_A2))
		{
		
       		if(!(xflag & XF_ExVoReStChN))
			{
					Vref -= REF_POT_STEP;
					xflag = xflag | XF_ExVoReStChN;
					xflag = xflag & XF_ExVoReStChPX;
			}				
			
		}
							
	}
	else
	{
	  		if( Switch_isOn(SWITCH_A1) & Switch_isOff(SWITCH_A2))  // Increment the Vef
			{
				Vref += REF_POT_CHANGE;
				LED_on(LED_A2D2A_Y);
				LED_off(LED_A2D2A_R);	
			}
			else if( Switch_isOn(SWITCH_A2) & Switch_isOff(SWITCH_A1))  // Decrement the Vref
			{
				Vref -= REF_POT_CHANGE;	
				LED_on(LED_A2D2A_R);
				LED_off(LED_A2D2A_Y);
			}
			else if( Switch_isOn(SWITCH_A1) & Switch_isOn(SWITCH_A2))  // Set to initval
			{
			    ftemp = Vref;
				init_AVR_states();
				//Vref = VT_REF;  // othervise the return will overwrite it!
				Vref = ftemp;  // othervise the return will overwrite it!
				
				LED_on(LED_A2D2A_R);
				LED_on(LED_A2D2A_Y);
				rec->x[4] = 0.0;  //  Clear the PSS from the DSP-II	
			}
	  		else
	  		{
	  			LED_off(LED_A2D2A_Y);
	  			LED_off(LED_A2D2A_R);
	  		}
	  		xflag = xflag & XF_ExVoReStChPX;  //Clear the step change flag
	  		xflag = xflag & XF_ExVoReStChNX;
	}


   if( Vref < VT_REF_L )
   	{	
   		LED_off(LED_DSK_R);
		LED_off(LED_DSK_Y);
		LED_on(LED_DSK_G);
	 }
 
 	else if( Vref < VT_REF_iL )
 	{
   		LED_off(LED_DSK_R);
		LED_on(LED_DSK_Y);
		LED_on(LED_DSK_G);
 	}
    else if( Vref < VT_REF_iU )
    {
    	LED_off(LED_DSK_R);
		LED_on(LED_DSK_Y);
		LED_off(LED_DSK_G);
    }
    else if( Vref < VT_REF_U )
    {
    	LED_on(LED_DSK_R);
		LED_on(LED_DSK_Y);
		LED_off(LED_DSK_G);
    }
 
    else 
    {
   		LED_on(LED_DSK_R);
		LED_off(LED_DSK_Y);
		LED_off(LED_DSK_G); 
    }
            
	
	return Vref;
}

//--------------------------------------------------------------------------
//--------------------------------------------------------------------------

