/**************************************************************************/
/**	File:  		GWRPS.C										                   **/
/**	Author:  	Terry W. Jackson													 **/
/**	Company:		U. S. Nuclear Regulatory Comm.								 **/
/**	Date:			February 28, 1997													 **/
/**----------------------------------------------------------------------**/
/**	Description:  This file contains the main function for the GWRPS   **/
/**   simulation program.  The main function controls the overall opera- **/
/**   tion of the simulation by calling the monitor, keyboard, process   **/
/**   simulation, and GWRPS system at the appropriate times.				 **/
/**----------------------------------------------------------------------**/
/**	Functions Called:											                   **/
/**                                                                      **/
/**	Monitor - Controls the monitor functions.                          **/
/**   Keyboard - Controls the keyboard functions.                        **/
/**   RPS - Contains the reactor protection system functions.            **/
/**************************************************************************/
#include <stdio.h>
#include <time.h>
#include <conio.h>
#include <dos.h>
#include <stdlib.h>
#include <setjmp.h>
#include "gwrps.h"

#define DISPSEG 0xb800

/********************** External Function Prototypes **********************/
extern void Monitor(void);					/* Updates monitor                 */
extern void Keyboard(char input);		/* Supports user input             */

/********************** Internal Function Prototypes **********************/
void wint();								/* Writes setpoints to a file         */
void rint();								/* Reads setpoints from file		  	  */
void InitInterrupt(void);				/* Initializes interrupt			     */
void DeinitInterrupt(void);			/* Deinitializes interrupt				  */
/* void interrupt (far *oldVector)(void);	/* Save old interrupt vector		  */
/* void interrupt ShowTime(void);			/* Shows time at bottom of screen	  */

/*************************** Global Variables *****************************/
int key = TRUE;								/* 1 - continue(def.), 0 - exit    */
int Update_Screen_1 = TRUE;				/* 1st screen update, default true */
int Update_Screen_2 = TRUE;				/* 2nd screen update, default true */
int Update_Screen_3 = TRUE;				/* 3rd screen flag, default off    */
int Update_Screen_4 = TRUE;				/* 4th screen flag, default off    */
int Screen_Select = 0;						/* Current screen, default 1st     */
int SIMULATE = 0;								/* Controls simulated variables    */
int RESET = TRUE;								/* TRUE - reset simulation			  */
int TRIP = FALSE;								/* TRUE - enable simulation		  */
jmp_buf jumpinfo;								/* Location to jump back to		  */

/********************** Process Simulation Variables **********************/
SRNF_Type A_Source_Range_Neutron_Flux = {10.1, 3};
SRNF_Type B_Source_Range_Neutron_Flux = {9.8, 4};

int A_Intermed_Range_Flux = 11;
int B_Intermed_Range_Flux = 9;

int A_Power_Range_Flux = 100;
int B_Power_Range_Flux = 99;
int C_Power_Range_Flux = 98;
int D_Power_Range_Flux = 100;

int A_Delta_Neutron_Flux = 0;
int B_Delta_Neutron_Flux = 1;
int C_Delta_Neutron_Flux = 2;
int D_Delta_Neutron_Flux = 0;

int A_Delta_Temperature = 62;
int B_Delta_Temperature = 62;
int C_Delta_Temperature = 62;
int D_Delta_Temperature = 62;

int A_Press = 2385;
int B_Press = 5;
int C_Press = 125;
int D_Press = 1000;

int A_Press_Level = 70;
int B_Press_Level = 70;
int C_Press_Level = 70;

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

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

int A1_Feed_Flow = 50;
int B1_Feed_Flow = 50;
int A2_Feed_Flow = 50;
int B2_Feed_Flow = 50;
int A3_Feed_Flow = 50;
int B3_Feed_Flow = 50;
int A4_Feed_Flow = 50;
int B4_Feed_Flow = 50;

int A1_Steam_Flow = 50;
int B1_Steam_Flow = 50;
int A2_Steam_Flow = 50;
int B2_Steam_Flow = 50;
int A3_Steam_Flow = 50;
int B3_Steam_Flow = 50;
int A4_Steam_Flow = 50;
int B4_Steam_Flow = 50;

int RCP_1A_Volt = 4160;
int RCP_1B_Volt = 4160;
int RCP_2A_Volt = 4160;
int RCP_2B_Volt = 4160;

int RCP_1A_Freq = 60;
int RCP_1B_Freq = 60;
int RCP_2A_Freq = 60;
int RCP_2B_Freq = 60;

int A_Oil_Press = 99;
int B_Oil_Press = 10;
int C_Oil_Press = 50;

int A_Stop_Valve = FALSE;
int B_Stop_Valve = FALSE;
int C_Stop_Valve = FALSE;
int D_Stop_Valve = FALSE;

/********************* Process Simulation Setpoints ***********************/
SRNF_Type Source_Range_Setpoint = {10.1, 5};
int Intermed_Range_Setpoint = 15;
int Low_Power_Range_Setpoint = 25;
int High_Power_Range_Setpoint = 109;
int Neg_Delta_Flux_Setpoint = -3;
int Pos_Delta_Flux_Setpoint = +10;
int OT_Delta_Setpoint = 62;
int OP_Delta_Setpoint = 62;
int Low_Press_Setpoint = 1976;
int High_Press_Setpoint = 2390;
int High_Press_Level_Setpoint = 92;
int Cool_Flow_Setpoint = 90;
int Low_Low_SG_Level_Setpoint = 35;
int Low_SG_Level_Setpoint = 40;
int Bus_UVolt_Setpoint = 2970;
int Bus_UFreq_Setpoint = 56;
int Oil_Press_Setpoint = 45;

/****************************** Permissives *******************************/
int P_6 = FALSE;
int P_7 = FALSE;
int P_8 = FALSE;
int P_9 = FALSE;
int P_10 = FALSE;

/*************************** Trip Block Signals ***************************/
int Block_Source = FALSE;
int Block_Intermed = FALSE;
int Block_Power = FALSE;

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

extern void rps(void);						/* Reactor Protection System       */
extern HeyDay(int w, int x, char y, char z);
													/* This does nothing					  */

/**************************************************************************/
/***************************** Main Program *******************************/
/**************************************************************************/
/* The main program receives input from the keyboard and calls the sup-   */
/* porting functions.  Also sets up cleans up for the program.            */
/**************************************************************************/

int main(void)
{
	char user_input;									/* User selection variable   */
	int value;											/* Spare variable				  */
	time_t old_time, new_time;						/* Time update variables     */

	/********************** Begin main loop operation **********************/
	rint();												/* Read setpoints				  */
	InitInterrupt();									/* Set up to display time	  */
	old_time = time(NULL);							/* Initialize second value   */
   value = setjmp(jumpinfo);						/* Set jump back to here	  */

TOP:	if (!key)										/* Loop until user exits     */
			goto BOTTOM;
		else
		{
			if (kbhit())									/* See if user has input     */
			{
				textbackground(BLACK);
				textcolor(LIGHTGRAY);
				user_input = getche();              /* Keyboard hit - get input  */
				Keyboard(user_input);               /* Call keyboard routine     */
			}

			new_time = time(NULL);						/* Get system time           */
			if (new_time != old_time)					/* A new second has occured  */
			{
				old_time = new_time;						/* Update time record        */
				if (!TRIP)
					rps();									/* Call the RPS              */
				_setcursortype(_NOCURSOR);				/* Make cursor invisible	  */
				Monitor();									/* Update monitor            */
				_setcursortype(_NORMALCURSOR);		/* Make cursor visible		  */
			}
		}
		goto TOP;

BOTTOM:
		wint();												/* Store setpoints		  */
		DeinitInterrupt();								/* Reset interrupt vector */
      clrscr();											/* Clears the screen		  */
}


/**************************************************************************/
/******************************** Rint() **********************************/
/**************************************************************************/
/* Performs a disk read to get the setpoint values that were stored 		  */
/* during the previous operation.													  */
/**************************************************************************/

void rint()
{
	FILE *inpf;

	inpf = fopen("SETPOINT.DAT", "rb");
	fread(&Source_Range_Setpoint.mantissa,
			 sizeof(double), 1, inpf);
	fread(&Source_Range_Setpoint.exponent,
			 sizeof(int), 1, inpf);
	fread(&Intermed_Range_Setpoint, sizeof(int), 1, inpf);
	fread(&Low_Power_Range_Setpoint, sizeof(int), 1, inpf);
	fread(&High_Power_Range_Setpoint, sizeof(int), 1, inpf);
	fread(&Neg_Delta_Flux_Setpoint, sizeof(int), 1, inpf);
	fread(&Pos_Delta_Flux_Setpoint, sizeof(int), 1, inpf);
	fread(&OT_Delta_Setpoint, sizeof(int), 1, inpf);
	fread(&OP_Delta_Setpoint, sizeof(int), 1, inpf);
	fread(&Low_Press_Setpoint, sizeof(int), 1, inpf);
	fread(&High_Press_Setpoint, sizeof(int), 1, inpf);
	fread(&High_Press_Level_Setpoint, sizeof(int), 1, inpf);
	fread(&Cool_Flow_Setpoint, sizeof(int), 1, inpf);
	fread(&Low_Low_SG_Level_Setpoint, sizeof(int), 1, inpf);
	fread(&Low_SG_Level_Setpoint, sizeof(int), 1, inpf);
	fread(&Bus_UVolt_Setpoint, sizeof(int), 1, inpf);
	fread(&Bus_UFreq_Setpoint, sizeof(int), 1, inpf);
	fread(&Oil_Press_Setpoint, sizeof(int), 1, inpf);
	fclose(inpf);
}


/**************************************************************************/
/******************************** Wint() **********************************/
/**************************************************************************/
/* Performs a disk write to store up the setpoint values before the pro-  */
/* gram exits.  Keeps changes made to the setpoints.							  */
/**************************************************************************/

void wint()
{
	FILE *outf;

	outf = fopen("SETPOINT.DAT", "w+b");
	fwrite(&Source_Range_Setpoint.mantissa,
			 sizeof(double), 1, outf);
	fwrite(&Source_Range_Setpoint.exponent,
			 sizeof(int), 1, outf);
	fwrite(&Intermed_Range_Setpoint, sizeof(int), 1, outf);
	fwrite(&Low_Power_Range_Setpoint, sizeof(int), 1, outf);
	fwrite(&High_Power_Range_Setpoint, sizeof(int), 1, outf);
	fwrite(&Neg_Delta_Flux_Setpoint, sizeof(int), 1, outf);
	fwrite(&Pos_Delta_Flux_Setpoint, sizeof(int), 1, outf);
	fwrite(&OT_Delta_Setpoint, sizeof(int), 1, outf);
	fwrite(&OP_Delta_Setpoint, sizeof(int), 1, outf);
	fwrite(&Low_Press_Setpoint, sizeof(int), 1, outf);
	fwrite(&High_Press_Setpoint, sizeof(int), 1, outf);
	fwrite(&High_Press_Level_Setpoint, sizeof(int), 1, outf);
	fwrite(&Cool_Flow_Setpoint, sizeof(int), 1, outf);
	fwrite(&Low_Low_SG_Level_Setpoint, sizeof(int), 1, outf);
	fwrite(&Low_SG_Level_Setpoint, sizeof(int), 1, outf);
	fwrite(&Bus_UVolt_Setpoint, sizeof(int), 1, outf);
	fwrite(&Bus_UFreq_Setpoint, sizeof(int), 1, outf);
	fwrite(&Oil_Press_Setpoint, sizeof(int), 1, outf);
	fclose(outf);
}


/**************************************************************************/
/***************************** InitInterrupt ******************************/
/**************************************************************************/
/* Redirects the unused BIOS interrupt which cycles periodically          */
/* on the PC to the ShowTime interrupt vector.									  */
/**************************************************************************/

void InitInterrupt(void)
{
/*	oldVector = getvect(0x1c);							/* Save current vector		*/
/*	setvect(0x1c, ShowTime);							/* Set the new vector		*/
}


/**************************************************************************/
/***************************** InitInterrupt ******************************/
/**************************************************************************/
/* Redirects the unused BIOS interrupt which cycles periodically          */
/* on the PC to the ShowTime interrupt vector.									  */
/**************************************************************************/

void DeinitInterrupt(void)
{
/*	setvect(0x1c, oldVector);  */
}


/**************************************************************************/
/******************************* ShowTime *********************************/
/**************************************************************************/
/* Shows the time on the screen.														  */
/**************************************************************************/

/*void interrupt ShowTime(void)
{
	asm
	{
		xor ax, ax
		mov ds, ax
		mov ax, [0x046d]
		mov bx, DISPSEG
		mov ds, bx
		mov word ptr [0x04ca], 0x0f07c
		mov bh, 0x70
		push ax
		xchg ah, al
		aam
		or ax, 0x3030
		mov bl, ah
		mov [0x04c6], bx
		mov bl, al
		mov [0x04c8], bx
		pop ax
		mov cx, 0x0f06
		mul ch
		shr ax, cl
		aam
		or ax, 0x3030
		mov bl, ah
		mov [0x04cc], bx
		mov bl, al
		mov [0x04ce], bx						
	}
	HeyDay(1, 2, 'a', 'b');								
}   */
