PROGRAM Control
(* First Scan Variable Setting*)
IF (__SYSVA_FIRST_SCAN) THEN
	Shutdown_Time := __SYSVA_CYCLEDATE;
	Device_Status:= 'Startup';
	Restart_Command := FALSE;
	Restart_Allowed := FALSE;
	Run_Permissive := FALSE;
	Start_Permissive := FALSE;
	cfg_READ := TRUE;
END_IF;

(*Convert kWh and kWh regen to REAL from LREAL for HMI use *)
E300_kWh := ANY_TO_REAL(E300.RealEnergyConsumedOdometer);
E300_kWh_Regen := ANY_TO_REAL(E300.RealEnergyGeneratedOdometer);

IF Downhole_Tool_Enabled THEN
	(*Modbus Mapping*)
	DH_IntakeTemperature 				:= ANY_TO_REAL(Modbus_Read0[2]) / 10.0;
	DH_IntakePressure 					:= ANY_TO_REAL(Modbus_Read0[3]);
	DH_NumChannels						:= Modbus_Read0[10];
	DH_ToolVoltage						:= Modbus_Read0[11];
	DH_MaxIntakeTemperature_Startup		:= ANY_TO_REAL(Modbus_Read0[40]) / 10.0;
	DH_MaxIntakePressure_Startup		:= Modbus_Read0[41];
	DH_DownholeStatus_INT				:= Modbus_Read0[99];
	DH_Fluid_Level 						:= (DH_IntakePressure - 14.0) * (1.0 / 0.433);

	CASE Modbus_Read0[99] OF
		0: DH_DownholeStatus := 'OK';
		1: DH_DownholeStatus := 'Connecting';
		2: DH_DownholeStatus := 'Open Circuit';
		3: DH_DownholeStatus := 'Shorted';
		4: DH_DownholeStatus := 'Cannot Decode';
	ELSE
		DH_DownholeStatus := 'Error';
	END_CASE;

	DH_ToolType							:= Modbus_Read1000[5];
	DH_PSIRating						:= Modbus_Read1000[7] * 1000;
	DH_MaxIntakeTemperature_Forever		:= ANY_TO_REAL(Modbus_Read1000[8]) / 10.0;
	DH_MaxIntakePressure_Forever		:= Modbus_Read1000[9];
ELSE
	DH_DownholeStatus := 'Disabled';
	Pressure_Shutdown_Enabled := FALSE;
	Pressure_Startup_Enabled := FALSE;
	Temp_Shutdown_Enabled := FALSE;
	Temp_Startup_Enabled := FALSE;
END_IF;

(*IO Mapping*)
IF NOT Test_Mode THEN
	Contactor_Status := DigitalInput_Status_0;
	Start_Button := DigitalInput_Status_1;
	Auto_Mode := DigitalInput_Status_2;
	Hand_Mode := DigitalInput_Status_3;
	LinearScale_Pressure(13107.0, 65535.0, Pressure_EU_Min, Pressure_EU_Max, ANY_TO_REAL(_IO_P1_AI_00));
	Pressure_In := LinearScale_Pressure.EU_Out;
ELSE
	Contactor_Status := E300_OUTPUT_CMD_VALUE;
	VoltageOK := TRUE;
END_IF;

IF Pressure_Transducer_Enabled AND 
	Contactor_Status AND 
	ANY_TO_DINT(Run_Time) > (Pressure_Alarm_Startup_Delay * 1000) THEN

	IF Pressure_In >= Pressure_Hi_SP THEN
		Pressure_Hi := TRUE;
		Pressure_Lo := FALSE;
	ELSIF Pressure_in <= Pressure_Lo_SP THEN
		Pressure_Hi := FALSE;
		Pressure_Lo := TRUE;
	ELSE
		Pressure_Hi := FALSE;
		Pressure_Lo := FALSE;
	END_IF;
	
	IF NOT Pressure_Hi AND NOT Pressure_Lo THEN
		Pressure_OK := TRUE;
		Pressure_OOT_Scans := 0;
		Pressure_OOT_Seconds := 0;
	ELSE
		Pressure_OOT_Scans := Pressure_OOT_Scans + 1;
		Pressure_OOT_Seconds := Pressure_OOT_Scans * ANY_TO_UDINT(__SYSVA_TCYCURRENT) / 1000;
	END_IF;
	
	IF Pressure_OOT_Seconds > Pressure_Alarm_Delay THEN
		Pressure_OK := FALSE;
	END_IF;
ELSE 
	Pressure_OK := TRUE;
END_IF;


(* Pressure should be above the startup pressure setpoint and temperature should be below the startup temp setpoint to begin*)
IF ((((DH_IntakePressure > Pressure_Startup) AND Pressure_Startup_Enabled) OR NOT Pressure_Startup_Enabled) AND 
	(((DH_IntakeTemperature < Temp_Startup) AND Temp_Startup_Enabled) OR NOT Temp_Startup_Enabled) AND 
	(Hand_Mode OR Auto_Mode OR Test_Mode) AND
	(NOT TripStatus) AND
	VoltageOK
	) THEN
	Start_Permissive := TRUE;
ELSE
	Start_Permissive := FALSE;
	Device_Status := 'Not ready to start';
END_IF;

(* Pressure should be be above the shutdown pressure and temperature should be below shutdown temp setpoint to continue to run *)
IF ((((DH_IntakePressure > Pressure_Shutdown) AND Pressure_Shutdown_Enabled) OR NOT Pressure_Shutdown_Enabled) AND 
	(((DH_IntakeTemperature < Temp_Shutdown) AND Temp_Shutdown_Enabled) OR NOT Temp_Shutdown_Enabled) AND 
	(Hand_Mode OR Auto_Mode OR Test_Mode)
	AND (NOT TripStatus)
	AND Pressure_OK
	) THEN
	Run_Permissive := TRUE;
ELSE
	Run_Permissive := FALSE;
END_IF;

IF (NOT Run_Permissive AND E300_OUTPUT_CMD_VALUE) THEN
	Device_Status := 'Lost Run Permissive';
	Shutdown_Time := __SYSVA_CYCLEDATE;
END_IF;

(*  Run only if commanded to start and start permissive is met or already running and not being told to stop *)
IF ((((Start_Button OR Start_Command OR (Restart_Allowed AND Restart_Command)) AND Start_Permissive) OR E300_OUTPUT_CMD_VALUE) AND 
	(NOT Stop_Command) AND Run_Permissive) THEN
	E300_OUTPUT_CMD_VALUE := TRUE;
	Restart_Command:= FALSE;
	Start_Command := FALSE;
	IF NOT Start_Time_Set THEN
		Start_Time := __SYSVA_CYCLEDATE;
		Start_Time_Set := TRUE;
	END_IF;
		
	
	IF Contactor_Status THEN
		Device_Status := 'Running';
		Run_Time := __SYSVA_CYCLEDATE - Start_Time;
	END_IF;
ELSE
	E300_OUTPUT_CMD_VALUE := FALSE;
END_IF;

IF E300_OUTPUT_CMD_VALUE AND NOT Contactor_Status THEN
	Start_Command := TRUE;
	Device_Status := 'Contactor Failure, Recovering';
	
	IF NOT E300_Output_Enable THEN
		IF E300_Output_Toggled THEN
			E300_Output_Enable := TRUE;
		END_IF;
		E300_Output_Toggled := TRUE;
	ELSE
		IF NOT E300_Output_Toggled THEN
			E300_Output_Enable := FALSE;
		END_IF;
	END_IF;
END_IF;

(* If run permissive goes false, do not allow a restart for a specified amount of time *)
IF (Auto_Mode AND (NOT OverloadTrip) AND NOT Contactor_Status AND Restart_Allowed) THEN
	IF (__SYSVA_CYCLEDATE - Shutdown_Time) > Downtime_Time_Parameter THEN 
		IF (NOT Restart_Command) THEN
			TripResetCmd := TRUE;
			Restart_Command := True;
		END_IF;
	ELSE
		(* Attempt to clear trip every 15 seconds *)
		(*IF NOT Downtime_Timer.Q AND TripStatus THEN
			Downtime_Timer(TRUE, Clear_Trip_Cycle);
		ELSE
			TripResetCmd := TRUE;
		END_IF;*)
		
		Restart_Command := FALSE;
		Time_Until_Startup := Downtime_Time_Parameter - (__SYSVA_CYCLEDATE - Shutdown_Time);
		Time_Until_Startup_String := ANY_TO_STRING(Time_Until_Startup);
		IF Auto_Mode THEN
			Device_Status := 'Waiting to attempt restart ' + Time_Until_Startup_String;
		END_IF;
		
	END_IF;
ELSIF (Auto_Mode AND OverloadTrip AND NOT Contactor_Status AND Restart_Allowed) THEN
	IF (__SYSVA_CYCLEDATE - Shutdown_Time) > Downtime_Time_Parameter_OL THEN 
		IF (NOT Restart_Command) THEN
			Restart_Command := True;
		END_IF;
	ELSE
		Restart_Command := FALSE;
		Time_Until_Startup := Downtime_Time_Parameter - (__SYSVA_CYCLEDATE - Downtime_Time_Parameter_OL);
		Time_Until_Startup_String := ANY_TO_STRING(Time_Until_Startup);
		IF Auto_Mode THEN
			Device_Status := 'Waiting to restart (OL Timer)' + Time_Until_Startup_String;
		END_IF;
	END_IF;
END_IF;

IF NOT Auto_Mode THEN
	Restart_Command := FALSE;
	Restart_Allowed := FALSE;
END_IF;

(* If the pump hasn't been started by the user, don't allow it to auto-restart *)
IF (Start_Command OR Start_Button) AND Start_Permissive THEN
	Restart_Allowed := TRUE;
END_IF;

IF Stop_Command THEN
	Restart_Allowed := FALSE;
	Device_Status := 'User Stopped';
END_IF;

IF NOT Contactor_Status THEN
	Start_Time_Set := FALSE;
END_IF;


(* Start Permissive Status *)
IF Pressure_Startup_Enabled THEN
	IF (DH_IntakePressure > Pressure_Startup) THEN
		SP_Pressure := TRUE;
	ELSE
		SP_Pressure := FALSE;
	END_IF;
ELSE
	SP_Pressure := TRUE;
END_IF;

IF Temp_Startup_Enabled THEN
	IF DH_IntakeTemperature < Temp_Startup THEN
		SP_Temperature := TRUE;
	ELSE
		SP_Temperature := FALSE;
	END_IF;
ELSE
	SP_Temperature := TRUE;
END_IF;

IF Hand_Mode OR Auto_Mode OR Test_Mode THEN
	SP_Mode := TRUE;
ELSE
	SP_Mode := FALSE;
END_IF;

SP_Trip := NOT TripStatus;
SP_Voltage := VoltageOK;

(* Run Permissive Status *)
IF Pressure_Shutdown_Enabled THEN
	IF DH_IntakePressure > Pressure_Shutdown THEN
		RP_Pressure := TRUE;
	ELSE
		RP_Pressure := FALSE;
	END_IF;
ELSE
	RP_Pressure := TRUE;
END_IF;

IF Temp_Shutdown_Enabled THEN
	IF DH_IntakeTemperature > Temp_Shutdown THEN
		RP_Temperature := TRUE;
	ELSE
		RP_Temperature := FALSE;
	END_IF;
ELSE
	RP_Temperature := TRUE;
END_IF;

IF Hand_Mode OR Auto_Mode OR Test_Mode THEN
	RP_Mode := TRUE;
ELSE	
	RP_Mode := FALSE;
END_IF;

RP_Trip := NOT TripStatus;
RP_TubingPressure := Pressure_OK;



END_PROGRAM