/**************************************************************************/
/**	File:  		RPS.C										                	    **/
/**	Author:  	Terry W. Jackson													 **/
/**	Company:		U. S. Nuclear Regulatory Comm.								 **/
/**	Date:			March 11, 1997													    **/
/**----------------------------------------------------------------------**/
/**	Description:  This file decodes the appropriate simulation code or **/
/**					  setpoint change and performs simulations.				 **/
/**************************************************************************/
#include <stdlib.h>
#include <time.h>
#include <math.h>
#include "gwrps.h"

/********************** External Global Variables *************************/
extern int SIMULATE;		/* Determines which simulation to run             */
extern int RESET;			/* Determines when to reset variables to normal   */
extern int TRIP;			/* Determines when to stop simulation				  */

/*********************** Plant Process Variables **************************/
extern SRNF_Type A_Source_Range_Neutron_Flux;
extern SRNF_Type B_Source_Range_Neutron_Flux;

extern int A_Intermed_Range_Flux;
extern int B_Intermed_Range_Flux;

extern int A_Power_Range_Flux;
extern int B_Power_Range_Flux;
extern int C_Power_Range_Flux;
extern int D_Power_Range_Flux;

extern int A_Delta_Neutron_Flux;
extern int B_Delta_Neutron_Flux;
extern int C_Delta_Neutron_Flux;
extern int D_Delta_Neutron_Flux;

extern int A_Delta_Temperature;
extern int B_Delta_Temperature;
extern int C_Delta_Temperature;
extern int D_Delta_Temperature;

extern int A_Press;
extern int B_Press;
extern int C_Press;
extern int D_Press;

extern int A_Press_Level;
extern int B_Press_Level;
extern int C_Press_Level;

extern int A1_Cool_Flow;
extern int B1_Cool_Flow;
extern int C1_Cool_Flow;
extern int A2_Cool_Flow;
extern int B2_Cool_Flow;
extern int C2_Cool_Flow;
extern int A3_Cool_Flow;
extern int B3_Cool_Flow;
extern int C3_Cool_Flow;
extern int A4_Cool_Flow;
extern int B4_Cool_Flow;
extern int C4_Cool_Flow;

extern int A1_SG_Level;
extern int B1_SG_Level;
extern int C1_SG_Level;
extern int A2_SG_Level;
extern int B2_SG_Level;
extern int C2_SG_Level;
extern int A3_SG_Level;
extern int B3_SG_Level;
extern int C3_SG_Level;
extern int A4_SG_Level;
extern int B4_SG_Level;
extern int C4_SG_Level;

extern int A1_Feed_Flow;
extern int B1_Feed_Flow;
extern int A2_Feed_Flow;
extern int B2_Feed_Flow;
extern int A3_Feed_Flow;
extern int B3_Feed_Flow;
extern int A4_Feed_Flow;
extern int B4_Feed_Flow;

extern int A1_Steam_Flow;
extern int B1_Steam_Flow;
extern int A2_Steam_Flow;
extern int B2_Steam_Flow;
extern int A3_Steam_Flow;
extern int B3_Steam_Flow;
extern int A4_Steam_Flow;
extern int B4_Steam_Flow;

extern int RCP_1A_Volt;
extern int RCP_1B_Volt;
extern int RCP_2A_Volt;
extern int RCP_2B_Volt;

extern int RCP_1A_Freq;
extern int RCP_1B_Freq;
extern int RCP_2A_Freq;
extern int RCP_2B_Freq;

extern int A_Oil_Press;
extern int B_Oil_Press;
extern int C_Oil_Press;

extern int A_Stop_Valve;
extern int B_Stop_Valve;
extern int C_Stop_Valve;
extern int D_Stop_Valve;

/********************* Process Simulation Setpoints ***********************/
extern SRNF_Type Source_Range_Setpoint;
extern int Intermed_Range_Setpoint;
extern int Low_Power_Range_Setpoint;
extern int High_Power_Range_Setpoint;
extern int Neg_Delta_Flux_Setpoint;
extern int Pos_Delta_Flux_Setpoint;
extern int OT_Delta_Setpoint;
extern int OP_Delta_Setpoint;
extern int Low_Press_Setpoint;
extern int High_Press_Setpoint;
extern int High_Press_Level_Setpoint;
extern int Cool_Flow_Setpoint;
extern int Low_Low_SG_Level_Setpoint;
extern int Low_SG_Level_Setpoint;
extern int Bus_UVolt_Setpoint;
extern int Bus_UFreq_Setpoint;
extern int Oil_Press_Setpoint;

/****************************** Permissives *******************************/
extern int P_6;
extern int P_7;
extern int P_8;
extern int P_9;
extern int P_10;

/*************************** Trip Block Signals ***************************/
extern int Block_Source;
extern int Block_Intermed;
extern int Block_Power;

/***************************** Trip Signals *******************************/
extern int Source_Range_Trip;
extern int Intermed_Range_Trip;
extern int Low_Power_Range_Trip;
extern int High_Power_Range_Trip;
extern int Neg_Delta_Flux_Trip;
extern int Pos_Delta_Flux_Trip;
extern int OT_Delta_T_Trip;
extern int OP_Delta_T_Trip;
extern int Low_Press_Trip;
extern int High_Press_Trip;
extern int High_Press_Level_Trip;
extern int Low_Cool_Flow_Trip;
extern int Low_Low_SG_Level_Trip;
extern int Low_SG_Level_Trip;
extern int Bus_UVolt_Trip;
extern int Bus_UFreq_Trip;
extern int Turbine_Trip;
extern int ESF_Trip;
extern int Manual_Trip;

/************************ Function Prototypes *****************************/
void rps(void);	/* Performs the reactor protection functions and sim.   */
int vote2_4(int value, int first, int second, int third, int fourth);
						/* Performs 2 out of 4 Voting logic				  			  */
int vote2_4n(int value, int first, int second, int third, int fourth);
						/* Performs 2 out of 4 voting for negative values		  */
SRNF_Type source_readings(SRNF_Type *Sensor, SRNF_Type Base_Val, int noise);
						/* Returns sensor values for source range neutron flux  */


/**************************************************************************/
/********************************** RPS ***********************************/
/**************************************************************************/
/*	RPS is called by the main function to perform the plant process simu-  */
/* lations and the reactor protection system functions.						  */
/**************************************************************************/
void rps(void)
{
	static SRNF_Type Source_Flux;	/* Source flux									  */
	static int Power_Flux;			/* Power flux									  */
	static int Th;						/* Hot leg temperature						  */
	static int Tc;						/* Cold leg temperature						  */
	static int Tavg;					/* Average reactor coolant temperature	  */
	static int Tavg_Prev;			/* Previous avg. reactor coolant temp.	  */
	static int Pressure;				/* Pressurizer pressure						  */
	static int Press_Level;			/* Pressurizer water level					  */
	static int Cool_Flow;			/* Reactor coolant flow						  */
	static int Bus_Volt;				/* Reactor coolant pump bus voltage		  */
	static int Bus_Freq;				/* Reactor coolant pump bus frequency	  */
	static int SG_Level;				/* Steam generator water level			  */
	static int Oil_Press;			/* Turbine oil pressure						  */
	static int SG_Feed_Flow;		/* Steam generator feedwater flow		  */
	static int SG_Steam_Flow;		/* Steam generator steam flow				  */
	static double K3;					/* Constant for calculating OT, delta T  */
	static double K6;					/* Constant for calculating OP, delta T  */

	static int counter;				/* Simulation step counter					  */
	static int A_last;				/* Previous A channel power flux			  */
	static int B_last;				/* Previous B channel power flux			  */
	static int C_last;				/* Previous C channel power flux			  */
	static int D_last;				/* Previous D channel power flux			  */
	double a, b, c;					/* Intermediate double variables			  */

	/*********************** Reset process variables ***********************/
	if (RESET)
	{
		Source_Flux.mantissa = 1.0;
		Source_Flux.exponent = 5;
		Power_Flux = 20;
		Th = 609;
		Tc = 547;
		Tavg = 578;
		Tavg_Prev = 578;
		Pressure = 2250;
		Press_Level = 70;
		Cool_Flow = 98;
		Bus_Volt = 4160;
		Bus_Freq = 60;
		SG_Level = 50;
		Oil_Press = 50;
		SG_Feed_Flow = 50;
		SG_Steam_Flow = 50;
		RESET = FALSE;
		counter = 0;
		A_last = 20;
		B_last = 20;
		C_last = 20;
		D_last = 20;
		Block_Source = TRUE;				/* Block low power trips			*/
		Block_Intermed = TRUE;
		Block_Power = TRUE;
		K3 = 0.003;
		K6 = 0.03;
		A_Stop_Valve = FALSE;
		B_Stop_Valve = FALSE;
		C_Stop_Valve = FALSE;
		D_Stop_Valve = FALSE;
		ESF_Trip = FALSE;
      Manual_Trip = FALSE;
	}
	else
	{
		/****************** Perform appropriate simulation *******************/
		switch(SIMULATE)
		{
			case 0:									/* Normal Operation					*/
				Block_Source = TRUE;
				Block_Intermed = TRUE;
				Block_Power = TRUE;
				break;

			case 1:									/* Source Range Neutron Flux		*/
				if (counter == 0)
				{
					Block_Source = FALSE;
					A_last = 0;
					B_last = 0;
					C_last = 0;
					D_last = 0;
					Power_Flux = 0;
					Source_Flux.mantissa = 1.0;
					Source_Flux.exponent = 0;
				}
				else if (counter < 20)
				{
					Source_Flux.mantissa += 50;
					if (Source_Flux.mantissa > 100)
					{
						Source_Flux.mantissa = Source_Flux.mantissa / 10;
						Source_Flux.exponent++;
					}
				}
				break;

			case 2:									/* Intermed. Range Neutron Flux	*/
				Block_Power = FALSE;
				if (counter == 0)
				{
					Block_Intermed = FALSE;
					A_last = 0;
					B_last = 0;
					C_last = 0;
					D_last = 0;
					Power_Flux = 0;
				}
				else if (counter < 20)
					Power_Flux++;
				break;

			case 3:									/* Low SP, Power Range Flux		*/
				Block_Intermed = TRUE;
				if (counter == 0)
				{
					Block_Power = FALSE;
					A_last = 20;
					B_last = 20;
					C_last = 20;
					D_last = 20;
					Power_Flux = 20;
				}
				else if (counter < 20)
					Power_Flux++;
				break;

			case 4:									/* High SP, Power Range Flux		*/
				Block_Power = TRUE;
				if (counter == 0)
				{
					A_last = 95;
					B_last = 95;
					C_last = 95;
					D_last = 95;
					Power_Flux = 95;
				}
				else if (counter < 20)
					Power_Flux++;
				break;

			case 5:									/* Pos. Neutron Flux Rate			*/
				if (counter == 0)
				{
					Power_Flux = 20;
					A_last = 20;
					B_last = 20;
					C_last = 20;
					D_last = 20;
				}
				else if (counter == 15)
					Power_Flux += 30;
				else if (counter < 20)
					Power_Flux++;
				break;

			case 6:									/* Neg. Neutron Flux Rate		   */
				if (counter == 0)
				{
					A_last = 100;
					B_last = 100;
					C_last = 100;
					D_last = 100;
					Power_Flux = 100;
				}
				else if (counter == 15)
					Power_Flux -= 30;
				else if (counter < 20)
					Power_Flux--;
				break;

			case 7:									/* Over Temp., Delta T				*/
				if (counter == 0)
					Block_Power = TRUE;
				else if (Power_Flux < 100)
				{
					Th += 2;
					Power_Flux++;
					Pressure -= 1;
				}
				if (OT_Delta_T_Trip && OP_Delta_T_Trip)
					TRIP = TRUE;
				break;

			case 8:									/* Over Power, Delta T			  */
				if (counter == 0)
					Block_Power = TRUE;
				else if (Power_Flux < 100)
				{
					Th += 5;
					Power_Flux++;
               Pressure--;
				}
				if (OT_Delta_T_Trip && OP_Delta_T_Trip)
					TRIP = TRUE;
				break;

			case 9:									/* Low Pressurizer Pressure		*/
				if (counter < 20)
				{
					Power_Flux = 10;
					A_last = 10;
					B_last = 10;
					C_last = 10;
					D_last = 10;
					Pressure -= 20;
					K3 = 0.0003;
					K6 = 0.0003;
				}
				break;

			case 10:									/* High Pressurizer Pressure		*/
				if (counter < 20)
				{
            	K3 = 0.0003;
					K6 = 0.0003;
					Pressure += 20;
				}
				break;

			case 11:									/* High Pressurizer Water Level	*/
				if (Press_Level < 100)
					Press_Level++;
				break;

			case 12:									/* Low Reactor Coolant Flow		*/
				if (counter < 20)
				{
					Power_Flux = 40;
					A_last = 40;
					B_last = 40;
					C_last = 40;
					D_last = 40;
					Cool_Flow--;
				}
				break;

			case 13:      							/* RCP Bus UnderVoltage				*/
				if (counter < 20)
					Bus_Volt -= 65;
				break;

			case 14:									/* RCP Bus UnderFrequency			*/
				if (counter < 20)
					Bus_Freq--;
				break;

			case 15:									/* Low-Low Steam Generator Level	*/
				SG_Level = (counter < 20) ? (SG_Level - 1) : (SG_Level);
				break;

			case 16:									/* Low Steam Generator Level		*/
				if (counter < 20)
					if (SG_Level > 37)
						SG_Level--;
					SG_Steam_Flow += 2;
				break;

			case 17:     							/* Turbine Trip - Oil Pressure	*/
				if (counter < 20)
					Power_Flux = 60;
					A_last = 60;
					B_last = 60;
					C_last = 60;
					D_last = 60;
					Oil_Press--;
				break;

			case 18:									/* Turbine Trip - Stop valves		*/
				if (counter < 5)
				{
					A_Stop_Valve = FALSE;
					B_Stop_Valve = FALSE;
					C_Stop_Valve = FALSE;
					D_Stop_Valve = FALSE;
				}
				else if (counter == 5)
					A_Stop_Valve = TRUE;
				else if (counter == 10)
					B_Stop_Valve = TRUE;
				else if (counter == 15)
					C_Stop_Valve = TRUE;
				else if (counter == 20)
					D_Stop_Valve = TRUE;
				break;

			case 19:									/* ESF Actuation						*/
				if (counter <= 10)
					ESF_Trip = FALSE;
				else
				{
					ESF_Trip = TRUE;
					TRIP = TRUE;
				}

			default:
				break;
		}
		++counter;
	}


	/*********************** Drive Plant Parameters *************************/
	/* Get random seed																		*/
	randomize();

	/* Get source range neutron flux readings 										*/
	source_readings(&A_Source_Range_Neutron_Flux, Source_Flux, random(3));
	source_readings(&B_Source_Range_Neutron_Flux, Source_Flux, random(3));

	/* Make sure intermediate range neutron flux does not exceed 20%			*/
	A_Intermed_Range_Flux = Power_Flux + random(3);
	if (A_Intermed_Range_Flux > 20)
		A_Intermed_Range_Flux = 20;
	B_Intermed_Range_Flux = Power_Flux + random(3);
	if (B_Intermed_Range_Flux > 20)
		B_Intermed_Range_Flux = 20;

	/* Record previous power range flux and get new readings						*/
	if (counter > 1)
	{
		A_last = A_Power_Range_Flux;
		B_last = B_Power_Range_Flux;
		C_last = C_Power_Range_Flux;
		D_last = D_Power_Range_Flux;
	}
	A_Power_Range_Flux = Power_Flux + random(2);
	B_Power_Range_Flux = Power_Flux + random(2);
	C_Power_Range_Flux = Power_Flux + random(2);
	D_Power_Range_Flux = Power_Flux + random(2);

	/* Get delta temperature readings													*/
	A_Delta_Temperature = Th - Tc + random(3);
	B_Delta_Temperature = Th - Tc + random(3);
	C_Delta_Temperature = Th - Tc + random(3);
	D_Delta_Temperature = Th - Tc + random(3);

	/* Get pressurizer pressure readings												*/
	A_Press = Pressure + random(3);
	B_Press = Pressure + random(3);
	C_Press = Pressure + random(3);
	D_Press = Pressure + random(3);

	/* Get pressurizer level readings													*/
	A_Press_Level = Press_Level + random(3);
	B_Press_Level = Press_Level + random(3);
	C_Press_Level = Press_Level + random(3);

	/* Get reactor coolant flow readings												*/
	A1_Cool_Flow = Cool_Flow + random(3);
	A2_Cool_Flow = Cool_Flow + random(3);
	A3_Cool_Flow = Cool_Flow + random(3);
	A4_Cool_Flow = Cool_Flow + random(3);
	B1_Cool_Flow = Cool_Flow + random(3);
	B2_Cool_Flow = Cool_Flow + random(3);
	B3_Cool_Flow = Cool_Flow + random(3);
	B4_Cool_Flow = Cool_Flow + random(3);
	C1_Cool_Flow = Cool_Flow + random(3);
	C2_Cool_Flow = Cool_Flow + random(3);
	C3_Cool_Flow = Cool_Flow + random(3);
	C4_Cool_Flow = Cool_Flow + random(3);

	/* Get steam generator level readings												*/
	A1_SG_Level = SG_Level + random(3);
	A2_SG_Level = SG_Level + random(3);
	A3_SG_Level = SG_Level + random(3);
	A4_SG_Level = SG_Level + random(3);
	B1_SG_Level = SG_Level + random(3);
	B2_SG_Level = SG_Level + random(3);
	B3_SG_Level = SG_Level + random(3);
	B4_SG_Level = SG_Level + random(3);
	C1_SG_Level = SG_Level + random(3);
	C2_SG_Level = SG_Level + random(3);
	C3_SG_Level = SG_Level + random(3);
	C4_SG_Level = SG_Level + random(3);

	/* Get Reactor Coolant Pump Bus Voltages											*/
	RCP_1A_Volt = Bus_Volt + random(3);
	RCP_1B_Volt = Bus_Volt + random(3);
	RCP_2A_Volt = Bus_Volt + random(3);
	RCP_2B_Volt = Bus_Volt + random(3);

	/* Get Reactor Coolant Pump Bus Frequencies										*/
	RCP_1A_Freq = Bus_Freq + random(3);
	RCP_1B_Freq = Bus_Freq + random(3);
	RCP_2A_Freq = Bus_Freq + random(3);
	RCP_2B_Freq = Bus_Freq + random(3);

	/* Get one steam generator steam flow												*/
	B2_Steam_Flow = SG_Steam_Flow;

	/* Get turbine oil pressure															*/
	A_Oil_Press = Oil_Press + random(2);
	B_Oil_Press = Oil_Press + random(2);
	C_Oil_Press = Oil_Press + random(2);


	/************ Over Temperature, Delta T Setpoint Calculation ************/
	Tavg_Prev = Tavg;
	Tavg = (Th + Tc) / 2;
	OT_Delta_Setpoint = (int)62*(1.3 + 0.02*(Tavg - 578) +
									 K3*(Pressure - 2250));

	/************** Over Power, Delta T Setpoint Calculation ****************/
	OP_Delta_Setpoint = (int)62*(1.3 - 0.0008*(Tavg - Tavg_Prev) -
									 K6*(Pressure - 2250));

	/***************************** Permissive 6 *****************************/
	a = pow10(A_Source_Range_Neutron_Flux.exponent)
		* A_Source_Range_Neutron_Flux.mantissa;
	b = pow10(B_Source_Range_Neutron_Flux.exponent)
		* B_Source_Range_Neutron_Flux.mantissa;
	if ((a >= 10.0) || (b >= 10.0))
		P_6 = TRUE;
	else
		P_6 = FALSE;

	/************************* Permissive 7 and 10 **************************/
	if (vote2_4(10, A_Power_Range_Flux, B_Power_Range_Flux,
						 C_Power_Range_Flux, D_Power_Range_Flux))
	{
		P_7 = FALSE;
		P_10 = TRUE;
	}
	else
	{
		P_7 = TRUE;
		P_10 = FALSE;
	}

	/***************************** Permissive 8 *****************************/
	if (vote2_4(35, A_Power_Range_Flux, B_Power_Range_Flux,
						 C_Power_Range_Flux, D_Power_Range_Flux))
		P_8 = TRUE;
	else
		P_8 = FALSE;

	/***************************** Permissive 9 *****************************/
	if (vote2_4(50, A_Power_Range_Flux, B_Power_Range_Flux,
						 C_Power_Range_Flux, D_Power_Range_Flux))
		P_9 = TRUE;
	else
		P_9 = FALSE;

	/************** Source Range Neutron Flux Protection Logic **************/
	c = pow10(Source_Range_Setpoint.exponent) * Source_Range_Setpoint.mantissa;
	if (!P_6)
		Block_Source = FALSE;
	if (((a >= c) || (b >= c)) && (!Block_Source))
	{
		TRIP = TRUE;
		Source_Range_Trip = TRUE;
	}
	else
		Source_Range_Trip = FALSE;

	/*********** Intermediate Range Neutron Flux Protection Logic ***********/
	if (!P_10)
	{
		Block_Intermed = FALSE;
		Block_Power = FALSE;
	}
	if (((A_Intermed_Range_Flux >= Intermed_Range_Setpoint)  ||
		  (B_Intermed_Range_Flux >= Intermed_Range_Setpoint)) &&
		  (!Block_Intermed))
	{
		TRIP = TRUE;
		Intermed_Range_Trip = TRUE;
	}
	else
		Intermed_Range_Trip = FALSE;

	/******* Power Range Neutron Flux Protection Logic, Low Setpoint ********/
	if (!P_10)
		Block_Intermed = FALSE;
	if ((vote2_4(Low_Power_Range_Setpoint, A_Power_Range_Flux,
		 B_Power_Range_Flux, C_Power_Range_Flux, D_Power_Range_Flux))
		 && (!Block_Power))
	{
		Low_Power_Range_Trip = TRUE;
		TRIP = TRUE;
	}
	else
		Low_Power_Range_Trip = FALSE;

	/******* Power Range Neutron Flux Protection Logic, High Setpoint *******/
	if (vote2_4(High_Power_Range_Setpoint, A_Power_Range_Flux,
		 B_Power_Range_Flux, C_Power_Range_Flux, D_Power_Range_Flux))
	{
		High_Power_Range_Trip = TRUE;
		TRIP = TRUE;
	}
	else
		High_Power_Range_Trip = FALSE;

	/************** Positive Neutron Flux Rate Protection Logic *************/
	A_Delta_Neutron_Flux = A_Power_Range_Flux - A_last;
	B_Delta_Neutron_Flux = B_Power_Range_Flux - B_last;
	C_Delta_Neutron_Flux = C_Power_Range_Flux - B_last;
	D_Delta_Neutron_Flux = D_Power_Range_Flux - B_last;
	if (vote2_4(Pos_Delta_Flux_Setpoint,
					A_Delta_Neutron_Flux,
					B_Delta_Neutron_Flux,
					C_Delta_Neutron_Flux,
					D_Delta_Neutron_Flux))
	{
		Pos_Delta_Flux_Trip = TRUE;
		TRIP = TRUE;
	}
	else
		Pos_Delta_Flux_Trip = FALSE;

	/******* Power Range Neutron Flux Protection Logic, High Setpoint *******/
	if (vote2_4n(Neg_Delta_Flux_Setpoint,
					A_Delta_Neutron_Flux,
					B_Delta_Neutron_Flux,
					C_Delta_Neutron_Flux,
					D_Delta_Neutron_Flux))
	{
		Neg_Delta_Flux_Trip = TRUE;
		TRIP = TRUE;
	}
	else
		Neg_Delta_Flux_Trip = FALSE;

	/************** Over Temperature, Delta T Protection Logic **************/
	if (vote2_4(OT_Delta_Setpoint,
					A_Delta_Temperature,
					B_Delta_Temperature,
					C_Delta_Temperature,
					D_Delta_Temperature))
	{
		OT_Delta_T_Trip = TRUE;
		TRIP = TRUE;
	}
	else
		OT_Delta_T_Trip = FALSE;

	/***************** Over Power, Delta T Protection Logic ****************/
	if (vote2_4(OP_Delta_Setpoint,
					A_Delta_Temperature,
					B_Delta_Temperature,
					C_Delta_Temperature,
					D_Delta_Temperature))
	{
		OP_Delta_T_Trip = TRUE;
		TRIP = TRUE;
	}
	else
		OP_Delta_T_Trip = FALSE;

	/*************** Pressurizer Low Pressure Protection Logic **************/
	if ((vote2_4n(Low_Press_Setpoint, A_Press, B_Press, C_Press, D_Press)) &&
		 (!P_7))
	{
		Low_Press_Trip = TRUE;
		TRIP = TRUE;
	}
	else
		Low_Press_Trip = FALSE;

	/************** Pressurizer High Pressure Protection Logic **************/
	if (vote2_4(High_Press_Setpoint, A_Press, B_Press, C_Press, D_Press))
	{
		High_Press_Trip = TRUE;
		TRIP = TRUE;
	}
	else
		High_Press_Trip = FALSE;

	/*************** Pressurizer Water Level Protection Logic ***************/
	if ((vote2_4(High_Press_Level_Setpoint,
		A_Press_Level,
		B_Press_Level,
		C_Press_Level,
		(High_Press_Level_Setpoint - 1))) && (!P_7))	/* Substitute point		*/
	{
		High_Press_Level_Trip = TRUE;
		TRIP = TRUE;
	}
	else
		High_Press_Level_Trip = FALSE;

	/***************** Reactor Coolant Flow Protection Logic ****************/
	a = 0.0;
	if (vote2_4n(Cool_Flow_Setpoint, A1_Cool_Flow, B1_Cool_Flow,
					 C1_Cool_Flow,(Cool_Flow_Setpoint + 1)))
		a += 1;
	if (vote2_4n(Cool_Flow_Setpoint, A2_Cool_Flow, B2_Cool_Flow,
					 C2_Cool_Flow,(Cool_Flow_Setpoint + 1)))
		a += 1;
	if (vote2_4n(Cool_Flow_Setpoint, A3_Cool_Flow, B3_Cool_Flow,
					 C3_Cool_Flow,(Cool_Flow_Setpoint + 1)))
		a += 1;
	if (vote2_4n(Cool_Flow_Setpoint, A4_Cool_Flow, B4_Cool_Flow,
					 C4_Cool_Flow,(Cool_Flow_Setpoint + 1)))
		a += 1;
	if ((a > 3.9) && (!P_8))
	{
		TRIP = TRUE;
		Low_Cool_Flow_Trip = TRUE;
	}
	else if ((a > 2.9) && (P_8))
	{
		TRIP = TRUE;
		Low_Cool_Flow_Trip = TRUE;
	}
	else
		Low_Cool_Flow_Trip = FALSE;

	/************* Low-Low Steam Generator Level Protection Logic ***********/
	if ((vote2_4n(Low_Low_SG_Level_Setpoint, A1_SG_Level, B1_SG_Level,
					 C1_SG_Level,(Low_Low_SG_Level_Setpoint + 1)))            ||
		 (vote2_4n(Low_Low_SG_Level_Setpoint, A1_SG_Level, B1_SG_Level,
					 C1_SG_Level,(Low_Low_SG_Level_Setpoint + 1)))            ||
		 (vote2_4n(Low_Low_SG_Level_Setpoint, A1_SG_Level, B1_SG_Level,
					 C1_SG_Level,(Low_Low_SG_Level_Setpoint + 1))))
	{
		Low_Low_SG_Level_Trip = TRUE;
		TRIP = TRUE;
	}
	else
		Low_Low_SG_Level_Trip = FALSE;

	/*********** Reactor Coolant Pump Bus Voltage Protection Logic **********/
	if (((RCP_1A_Volt < Bus_UVolt_Setpoint)  ||
		  (RCP_1B_Volt < Bus_UVolt_Setpoint)) &&
		 ((RCP_2A_Volt < Bus_UVolt_Setpoint)  ||
		  (RCP_2B_Volt < Bus_UVolt_Setpoint)) &&
		  (!P_7))
	{
		Bus_UVolt_Trip = TRUE;
		TRIP = TRUE;
	}
	else
		Bus_UVolt_Trip = FALSE;

	/********** Reactor Coolant Pump Bus Frequency Protection Logic *********/
	if (((RCP_1A_Freq < Bus_UFreq_Setpoint)  ||
		  (RCP_1B_Freq < Bus_UFreq_Setpoint)) &&
		 ((RCP_2A_Freq < Bus_UFreq_Setpoint)  ||
		  (RCP_2B_Freq < Bus_UFreq_Setpoint)) &&
		  (!P_7))
	{
		Bus_UFreq_Trip = TRUE;
		TRIP = TRUE;
	}
	else
		Bus_UFreq_Trip = FALSE;

	/************** Low Steam Generator Level Protection Logic **************/
	if (((A1_SG_Level < Low_SG_Level_Setpoint)  ||
		  (B1_SG_Level < Low_SG_Level_Setpoint)) &&
		 (((A1_Steam_Flow - A1_Feed_Flow) > Low_SG_Level_Setpoint) ||
		  ((B1_Steam_Flow - B1_Feed_Flow) > Low_SG_Level_Setpoint)))
	{
		Low_SG_Level_Trip = TRUE;
		TRIP = TRUE;
	}
	else if (((A2_SG_Level < Low_SG_Level_Setpoint)  ||
		  (B2_SG_Level < Low_SG_Level_Setpoint))      &&
		 (((A2_Steam_Flow - A2_Feed_Flow) > Low_SG_Level_Setpoint) ||
		  ((B2_Steam_Flow - B2_Feed_Flow) > Low_SG_Level_Setpoint)))
	{
		Low_SG_Level_Trip = TRUE;
		TRIP = TRUE;
	}
	else if (((A3_SG_Level < Low_SG_Level_Setpoint)  ||
		  (B3_SG_Level < Low_SG_Level_Setpoint))      &&
		 (((A3_Steam_Flow - A3_Feed_Flow) > Low_SG_Level_Setpoint) ||
		  ((B3_Steam_Flow - B3_Feed_Flow) > Low_SG_Level_Setpoint)))
	{
		Low_SG_Level_Trip = TRUE;
		TRIP = TRUE;
	}
	else if (((A4_SG_Level < Low_SG_Level_Setpoint)  ||
		  (B4_SG_Level < Low_SG_Level_Setpoint))		 &&
		 (((A4_Steam_Flow - A4_Feed_Flow) > Low_SG_Level_Setpoint) ||
		  ((B4_Steam_Flow - B4_Feed_Flow) > Low_SG_Level_Setpoint)))
	{
		Low_SG_Level_Trip = TRUE;
		TRIP = TRUE;
	}
	else
		Low_SG_Level_Trip = FALSE;

	/*********************** Turbine Protection Logic ***********************/
	if (((vote2_4n(Oil_Press_Setpoint, A_Oil_Press, B_Oil_Press,
					 C_Oil_Press,(Oil_Press_Setpoint + 1))) && P_9) ||
		 (A_Stop_Valve && B_Stop_Valve && C_Stop_Valve && D_Stop_Valve))
	{
		TRIP = TRUE;
		Turbine_Trip = TRUE;
	}
	else
		Turbine_Trip = FALSE;

	/********************** Update the last Power Flux **********************/
	A_last = A_Power_Range_Flux;
	B_last = B_Power_Range_Flux;
	C_last = C_Power_Range_Flux;
	D_last = D_Power_Range_Flux;
}


/**************************************************************************/
/******************************** Vote2_4 *********************************/
/**************************************************************************/
/* Vote2_4 is true if two out of the four input variables are greater 	  */
/* than or equal to the setpoint value.											  */
/*------------------------------------------------------------------------*/
/* Inputs:	value - setpoint comparison value.									  */
/*				first - first input variable.											  */
/*				second - second input variable.										  */
/*				third - third input variable.											  */
/*				fourth - fourth input variable.										  */
/*------------------------------------------------------------------------*/
/* Outputs:   returns TRUE if 2 or more inputs are greater than or equal  */
/*					to the setpoint.  Else returns FALSE.				  			  */
/**************************************************************************/

int vote2_4(int value, int first, int second, int third, int fourth)
{
	int count = 0;

	if (first >= value)
		++count;
	if (second >= value)
		++count;
	if (third >= value)
		++count;
	if (fourth >= value)
		++count;
	if (count >= 2)
		return TRUE;
	else
		return FALSE;
}


/**************************************************************************/
/******************************** Vote2_4n ********************************/
/**************************************************************************/
/* Vote2_4n is true if two out of the four input variables are less than  */
/* or equal to the setpoint value.													  */
/*------------------------------------------------------------------------*/
/* Inputs:	value - setpoint comparison value.									  */
/*				first - first input variable.											  */
/*				second - second input variable.										  */
/*				third - third input variable.											  */
/*				fourth - fourth input variable.										  */
/*------------------------------------------------------------------------*/
/* Outputs:   returns TRUE if 2 or more inputs are less than or equal to  */
/*					the setpoint.  Else returns FALSE.						  		  */
/**************************************************************************/

int vote2_4n(int value, int first, int second, int third, int fourth)
{
	int count = 0;

	if (first <= value)
		++count;
	if (second <= value)
		++count;
	if (third <= value)
		++count;
	if (fourth <= value)
		++count;
	if (count >= 2)
		return TRUE;
	else
		return FALSE;
}


/**************************************************************************/
/**************************** Source_Readings *****************************/
/**************************************************************************/
/* Provides the sensor readings for Source Range Neutron Flux sensors.	  */
/*------------------------------------------------------------------------*/
/* Inputs:	*Sensor - pointer to sensor structure								  */
/*				Base_Val - the base structure.										  */
/*				noise - white noise to be added.										  */
/*------------------------------------------------------------------------*/
/* Outputs:   returns via pointer the sensor values for that particular	  */
/*					source range neutron flux.											  */
/**************************************************************************/
SRNF_Type source_readings(SRNF_Type *Sensor, SRNF_Type Base_Val, int noise)
{
	Sensor->mantissa = Base_Val.mantissa + noise;
	Sensor->exponent = Base_Val.exponent;
}
