﻿<?xml version="1.0" encoding="utf-8"?>
<TcPlcObject Version="1.1.0.1">
  <POU Name="EmergencyStop" Id="{236ac593-dbab-4fab-a76d-4961f70f6771}" SpecialFunc="None">
    <Declaration><![CDATA[FUNCTION_BLOCK EmergencyStop IMPLEMENTS p7type.IEmergencyStop;
VAR_INPUT
	Enabled									: BOOL;
	Config 									: REFERENCE TO ConfigEmergencyStop; 
END_VAR
VAR
	{attribute 'hide'}	started 							: BOOL;
	{attribute 'hide'}	state								: EStopSM;
	{attribute 'hide'}	startUpTimer						: TON;
	{attribute 'hide'}	grpResetStart						: TON;
	{attribute 'hide'}	grpResetExe							: TON;
	{attribute 'hide'}	grpResetEnd							: TON;
	{attribute 'hide'}	cycleGen							: SymmetricPulse;
	{attribute 'hide'}	ledFlasher							: SymmetricPulse;
	
	{attribute 'hide'} _resetGroup								: BOOL;	
	{attribute 'hide'} _idx 									: INT;
	{attribute 'hide'} n 										: INT;	// iterator for lights
	
	{attribute 'hide'} _switchIdx 								: INT;  //Switch identifier
	{attribute 'hide'} _switchName								: p7type.P6IdName;
//	{attribute 'hide'} _lastSwitchIdx 							: INT;  
//	{attribute 'hide'} _lastSswitchName							: p7type.P6IdName;

	_EstopInputs			AT %I* 			: ARRAY [0..param.noEmergencyStopSw-1] OF SwitchInputs; 
	_EStopLights 			AT %Q* 			: ARRAY [0..param.noEmergencyStopSw-1] OF BOOL; //Emergency stop indicatorLights
	_NoEStopDetected 		AT %I* 			: BOOL;	 //Emergency stop signal
	
	_ExternEStop 							: BOOL;
	_TwinSafe_Run 			AT %Q* 			: BOOL := TRUE;  //Run TwinSAFE logic
	_TwinSafeFB_Reset 		AT %Q*			: BOOL;	//Reset emergency stop
	_TwinSafeGroup_Reset	AT %Q*			: BOOL; //Group Reset	
	_TwinSafeGroupErrCom	AT %I*			: BOOL; // Group Com error
	_TwinSafeGroupErrFB		AT %I*			: BOOL; // Group FB Error
	_TwinSafeGroupErrOther	AT %I*			: BOOL; // Group Other Error	
	_currentSwitchOK						: BOOL;
	
	EstopAlarm								: p6com.AlarmDigital(TC_Events.LocalEvents.EMERGENCY_STOP);
END_VAR
]]></Declaration>
    <Implementation>
      <ST><![CDATA[IF NOT started THEN
	started := TRUE;
	// Estop for Deck HPU is disconnected/removed, we need to set the inputs high all the time
	_EstopInputs[13].A := _EstopInputs[13].B := TRUE;
END_IF

ledFlasher(CLK := T#400MS);									// for flashing emStop light
cycleGen(CLK:=T#200MS);
_TwinSafeFB_Reset := cycleGen.Value;

startUpTimer(IN:=(state=EStopSM.WAITRESET), PT:=T#1500MS);
grpResetStart(IN:=(state=EStopSM.GRP_RST_START), PT:=T#3000MS);
grpResetExe(IN:=(state=EStopSM.GRP_RST_EXE), PT:=T#300MS);
grpResetEnd(IN:=(state=EStopSM.GRP_RST_END), PT:=T#300MS);

// if any issues exsist in twinSAFE, then reset group
// {warning  'Used for testing on Liaoyu, should be implemented from HMI ?'}
IF GroupError THEN 
	_resetGroup := TRUE;
END_IF

//indicator lights
FOR n := 0 TO DINT_TO_INT(Param.noEmergencyStopSw) -1 DO
	// Only check estops with a name... in case array is larger than actual number of estops in use.
	IF  NOT (config.switchname[n]= '') THEN
		_currentSwitchOK := _EstopInputs[n].A AND _EstopInputs[n].B; 										// OK if both inputs are good
		_EStopLights[n] :=  (NOT _NoEStopDetected) AND (_currentSwitchOK OR ledFlasher.Value);				// turn on/off/flash estop indicator
	END_IF
END_FOR

CASE state OF
	EStopSM.STARTUP:
		_TwinSafeGroup_Reset := TRUE;
		_TwinSafe_Run := TRUE;
		_resetGroup := FALSE;
		_switchName := '';
		_switchIdx := -1; //Emergency stop ok
		state := EStopSM.WAITRESET;
		
	EStopSM.WAITRESET:
		_TwinSafe_Run := TRUE;
		_TwinSafeGroup_Reset := FALSE;
		IF (NOT startUpTimer.Q) THEN
			state := EStopSM.GRP_RST_START;
		END_IF
	
	EStopSM.IDLE:
		_TwinSafe_Run := TRUE;
		_TwinSafeGroup_Reset := FALSE;
		IF (NOT _NoEStopDetected) AND Enabled THEN
			state := EStopSM.ESTOP;
		ELSIF _resetGroup THEN
			_resetGroup := FALSE;
			state := EStopSM.GRP_RST_START;
		END_IF
	
	EStopSM.ESTOP:
		_TwinSafe_Run := TRUE;
		_TwinSafeGroup_Reset := FALSE;
		IF _resetGroup THEN
			_resetGroup := FALSE;
			state := EStopSM.GRP_RST_START;
		ELSIF NOT _NoEStopDetected THEN								// Estop on somewhere
			_switchIdx := -1;
			FOR _idx := 0 TO p6com.Parameters.SizeOfEStopArray-1 DO
				_currentSwitchOK := _EstopInputs[_idx].A AND _EstopInputs[_idx].B; // OK if both inputs are good
				IF NOT _currentSwitchOK THEN 										// found active Estop
					IF _switchIdx = -1 THEN											// Only tag the first estop (for HMI etc.)
						_switchIdx := _idx;
						_switchName := Config.switchname[_idx];
					END_IF
				END_IF
			END_FOR
		ELSE
			state := EStopSM.ESTOP_RELEASED;						// Estop cleared.
		END_IF
	
	EStopSM.ESTOP_RELEASED:
		_TwinSafe_Run := TRUE;
		_TwinSafeGroup_Reset := FALSE;
		_switchName := '';
		_switchIdx := -1;
		objManDev.buzzer.SilenceBuzzer();
		state := EStopSM.IDLE;
	
	ESTOPSM.GRP_RST_START:
		_TwinSafe_Run := FALSE;
		_TwinSafeGroup_Reset := FALSE;
		IF grpResetStart.Q THEN
			state := ESTOPSM.GRP_RST_EXE;
		END_IF
		
	ESTOPSM.GRP_RST_EXE:
		_TwinSafe_Run := FALSE;
		_TwinSafeGroup_Reset := TRUE;
		IF grpResetExe.Q THEN
			state := ESTOPSM.GRP_RST_END;
		END_IF

	ESTOPSM.GRP_RST_END:
		_TwinSafe_Run := FALSE;
		_TwinSafeGroup_Reset := FALSE;
		IF grpResetEnd.Q THEN
			state := ESTOPSM.IDLE;
		END_IF
END_CASE


IF _switchIdx > -1 AND _switchName <> '' THEN
	EstopAlarm(Value := (NOT _NoEStopDetected), ID := INT_TO_UDINT(_switchIdx), IDName := _switchName, TimeSpan := T#0.2S);	// send (or clear) estop alarm event
ELSE
	EstopAlarm(Value := NOT _NoEStopDetected, TimeSpan := T#0.2S);	
END_IF



]]></ST>
    </Implementation>
    <Property Name="Activated" Id="{17f31f37-b032-4282-aee6-ad294ff39bf3}">
      <Declaration><![CDATA[{attribute 'monitoring' := 'call'}
{attribute 'TcRpcEnable'}
PROPERTY Activated : BOOL]]></Declaration>
      <Get Name="Get" Id="{c1560ed3-c91d-4934-8d63-cf9cf52611b2}">
        <Declaration><![CDATA[VAR
END_VAR
]]></Declaration>
        <Implementation>
          <ST><![CDATA[Activated := ((NOT _NoEStopDetected) OR _externEStop) AND Enabled;]]></ST>
        </Implementation>
      </Get>
    </Property>
    <Property Name="ActivatedSwitchIdx" Id="{310f7c79-305d-4f36-a1d9-0670bc3cc5dd}">
      <Declaration><![CDATA[{attribute 'monitoring' := 'call'}
{attribute 'TcRpcEnable'}
PROPERTY ActivatedSwitchIdx : INT]]></Declaration>
      <Get Name="Get" Id="{de052ede-ab4e-439d-ac53-4778d3c339b7}">
        <Declaration><![CDATA[VAR
END_VAR
]]></Declaration>
        <Implementation>
          <ST><![CDATA[ActivatedSwitchIdx := _switchIdx;
]]></ST>
        </Implementation>
      </Get>
    </Property>
    <Property Name="ActivatedSwitchName" Id="{3e827487-cd45-4dd7-bb06-35d08f6fe5c9}">
      <Declaration><![CDATA[{attribute 'monitoring' := 'call'}
{attribute 'TcRpcEnable'}
PROPERTY ActivatedSwitchName : p7type.P6IdName
]]></Declaration>
      <Get Name="Get" Id="{a499a06a-fbde-4e00-a97e-c4e782186dc2}">
        <Declaration><![CDATA[VAR
END_VAR
]]></Declaration>
        <Implementation>
          <ST><![CDATA[ActivatedSwitchName := _switchName;
]]></ST>
        </Implementation>
      </Get>
    </Property>
    <Property Name="GroupError" Id="{634d0d06-4003-4bfd-ada3-2c3cc94b9bf1}">
      <Declaration><![CDATA[{attribute 'monitoring' := 'call'}
{attribute 'TcRpcEnable'}
PROPERTY GroupError : BOOL]]></Declaration>
      <Get Name="Get" Id="{e4d50311-940b-4fc4-b0d0-eec43c331738}">
        <Declaration><![CDATA[VAR
END_VAR
]]></Declaration>
        <Implementation>
          <ST><![CDATA[GroupError := _TwinSafeGroupErrCom OR _TwinSafeGroupErrFB OR _TwinSafeGroupErrOther;


]]></ST>
        </Implementation>
      </Get>
    </Property>
    <Method Name="resetGroupError" Id="{828c6e83-926a-41c0-a7ed-251ac2db2b66}">
      <Declaration><![CDATA[{attribute 'TcRpcEnable'}
METHOD resetGroupError : BOOL
]]></Declaration>
      <Implementation>
        <ST><![CDATA[_resetGroup := TRUE;]]></ST>
      </Implementation>
    </Method>
    <Property Name="ExternEStop" Id="{f6861a1f-a58c-088b-3377-00ee15265bb6}">
      <Declaration><![CDATA[PROPERTY ExternEStop : BOOL]]></Declaration>
      <Set Name="Set" Id="{7c3c2c13-dd61-04c8-3363-d7bb562f23ce}">
        <Declaration><![CDATA[VAR
END_VAR
]]></Declaration>
        <Implementation>
          <ST><![CDATA[_ExternEStop := ExternEStop;]]></ST>
        </Implementation>
      </Set>
    </Property>
  </POU>
</TcPlcObject>