//This file was generated by the LASAL2 CodeGenerator  -- 
//Please, do not edit this file (it might be overwritten by the next generator run)

//{{LSL_DEFINES

#define BUS_IF_SDIAS_MAX_NR_DO 100
//}}LSL_DEFINES

//{{LSL_DECLARATION
#include "..\..\Source\BusInterface.h"
#include "..\..\Class\SdiasManager\SdiasManager.h"

(*!
<Class
	Name               = "BusInterfaceSdias"
	Revision           = "1.26"
	GUID               = "{74134B4E-6C37-4D4E-A553-14246973EFB6}"
	RealtimeTask       = "false"
	CyclicTask         = "false"
	BackgroundTask     = "false"
	Sigmatek           = "true"
	OSInterface        = "false"
	HighPriority       = "false"
	Automatic          = "false"
	UpdateMode         = "Prescan"
	IconPath           = ".\Class\s-dias.ico"
	SharedCommandTable = "true"
	Objectsize         = "(502,120)">
	<Channels>
		<Server Name="CallCommand" GUID="{ED97C549-C92F-403A-AE0A-92E0072A5024}" Visualized="true" Initialize="false" WriteProtected="true" Retentive="false"/>
		<Server Name="ClassState">
		</Server>
	</Channels>
	<Dependencies>
		<Files>
			<File Path=".\Source\BusInterface.h" Include="true"/>
			<File Path=".\Class\SdiasManager\SdiasManager.h" Include="true"/>
		</Files>
	</Dependencies>
	<RevDoku>
		<Owner Company="Sigmatek" Author="RamAnd"/>
		<Dokumentation Revision="1.26" Date="04.02.2021" Author="EisMic" Company="Sigmatek" Description="Added support for BC032."/>
		<Dokumentation Revision="1.25" Date="02.12.2020" Author="RamAnd" Company="Sigmatek" Description="Added a possibility for the operator class to use default behavior by returning QUIT at the hardware diagnosis functions."/>
		<Dokumentation Revision="1.24" Date="16.01.2020" Author="LanSte" Company="Sigmatek" Description="Changed Place.Read() = DEACTIVATED_LSL() to IsDeactivated(). (_BUS_IF_GET_DEACTIVATED_STATE is called in 1st init by other classes.)"/>
		<Dokumentation Revision="1.23" Date="09.01.2019" Author="FurDom" Company="Sigmatek" Description="Added function for Spi Write in SdiasBase class."/>
		<Dokumentation Revision="1.22" Date="28.05.2018" Author="LanSte" Company="Sigmatek" Description="Added support for dynamic accesses."/>
		<Dokumentation Revision="1.21" Date="13.04.2018" Author="PieSte" Company="Sigmatek" Description="Add numbers for the assignment of the log messages."/>
		<Dokumentation Revision="1.20" Date="23.01.2018" Author="RamAnd&#13;&#10;ZoePat" Company="Sigmatek" Description="Log messages have been standardized for easier maintenance, easier use in any class and to allow spam filtering. Code for the logging functions is now only located in HwControl.&#13;&#10;If module is deacitvated by using DEACITVATED_LSL the client place is also set to the value DEACTIVATED_LSL."/>
		<Dokumentation Revision="1.19" Date="16.05.2017" Author="RamAnd" Company="Sigmatek" Description="When adding an SDO (i.e. via ReadSPIData) from background priority it was possible that the adding process got interrupted by receiving the answer to this SDO which is handled in cyclic priority. In the error case the answer was unexpected and therefore ignored. Then the class signals a timeout while waiting for the answer, which already arrived before waiting for it. Added mutex and changed instruction order to prevent this error."/>
		<Dokumentation Revision="1.18" Date="01.03.2016" Author="EisMic" Company="Sigmatek" Description="Corrected BoundExceed Error in base class at Write method of LEDControl Server when Place = LSL_DEACTIVATED."/>
		<Dokumentation Revision="1.17" Date="17.03.2015" Author="RamAnd" Company="Sigmatek" Description="Added HW Version for sdias clients."/>
		<Dokumentation Revision="1.16" Date="10.03.2015" Author="RamAnd" Company="Sigmatek" Description="Added hardware diagnosis support for modules without subbusses."/>
		<Dokumentation Revision="1.15" Date="17.02.2015" Author="RamAnd" Company="Sigmatek" Description="Added command to use control accesses from the connected object which is needed to configure the PLL."/>
		<Dokumentation Revision="1.14" Date="03.11.2014" Author="LanSte" Company="Sigmatek" Description="Implemented new Interface to set and get the ClassState. "/>
		<Dokumentation Revision="1.13" Date="25.08.2014" Author="LanSte" Company="Sigmatek" Description="Moved defaut call of &apos;GetPointer2ObjectPath&apos; to last init phase, so that it can be overwritten by other classes. (SdiasSafetyManager)"/>
		<Dokumentation Revision="1.12" Date="21.07.2014" Author="LanSte" Company="Sigmatek" Description="Added support for reading hardware diagnosis."/>
		<Dokumentation Revision="1.11" Date="04.06.2014" Author="RamAnd" Company="Sigmatek" Description="Added possibility to detect a periphery reset which may be caused by a lost power supply."/>
		<Dokumentation Revision="1.10" Date="22.01.2014" Author="RamAnd&#13;&#10;PieSte" Company="Sigmatek" Description="Removed single run handling, which isn&apos;t needed for SDIAS.&#13;&#10;Read Client Required and Place in Init SdiasBase."/>
		<Dokumentation Revision="1.0" Date="23.09.2013" Author="RamAnd" Company="Sigmatek" Description="First library version"/>
	</RevDoku>
	<Network Name="BusInterfaceSdias">
		<!-- List of Components in this network -->
		<Components>
			<Object
				Name       = "_base"
				GUID       = "{66306A96-0DB5-4E8A-B3DA-04985F421BC7}"
				Class      = "SdiasBase"
				Position   = "(218,120)"
				Visualized = "true">
				<Channels>
					<Server Name="ClassState"/>
					<Server Name="DeviceID"/>
					<Server Name="FPGAVersion"/>
					<Server Name="HwVersion"/>
					<Server Name="LEDControl" Value="0"/>
					<Server Name="RetryCounter"/>
					<Server Name="SDOState"/>
					<Server Name="SerialNo"/>
					<Client Name="Place" Value="0"/>
					<Client Name="Required" Value="1"/>
					<Client Name="SdiasIn"/>
					<Client Name="ToStdLib"/>
				</Channels>
			</Object>
		</Components>
		<Comments>
		</Comments>
		<!-- List of Connections in this network -->
		<Connections>
			<Connection Source="this.ClassState" Destination="_base.ClassState" Vertices="(804,210),(632,210),"/>
			<Connection Source="this.DeviceID" Destination="_base.DeviceID" Vertices="(804,270),(632,270),"/>
			<Connection Source="this.SerialNo" Destination="_base.SerialNo" Vertices="(804,450),(632,450),"/>
			<Connection Source="this.RetryCounter" Destination="_base.RetryCounter" Vertices="(804,510),(632,510),"/>
			<Connection Source="this.LEDControl" Destination="_base.LEDControl" Vertices="(804,570),(632,570),"/>
			<Connection Source="_base.SdiasIn" Destination="this.SdiasIn" Vertices="(218,210),(38,210),"/>
			<Connection Source="_base.Place" Destination="this.Place" Vertices="(218,270),(38,270),"/>
			<Connection Source="_base.Required" Destination="this.Required" Vertices="(218,330),(38,330),"/>
			<Connection Source="this.FPGAVersion" Destination="_base.FPGAVersion" Vertices="(804,330),(632,330),"/>
			<Connection Source="this.HwVersion" Destination="_base.HwVersion" Vertices="(804,390),(632,390),"/>
		</Connections>
		<!-- Headerfiles -->
		<Options>
		</Options>
	</Network>
</Class>
*)
#pragma using SdiasBase

BusInterfaceSdias : CLASS
: SdiasBase
	TYPE
#pragma pack(push, 1)
	  t_CALLBACK_POINTERS : STRUCT
	    p_Callback : pVirtualBase;
	    p_UpdateCy : pVirtualBase;
	    p_UpdateRt : pVirtualBase;
	    p_UpDateRtPostScan : pVirtualBase;
	  END_STRUCT;
#pragma pack(pop)
	  t_InitSSW :
	  (
	    _InitVariables,
	    _ConfigModule,
	    _ReadState,
	    _Finish,
	    _InitError
	  )$UDINT;
	  t_ResponseState :
	  (
	    _idle,
	    _wait,
	    _valid
	  )$UDINT;
	END_TYPE
  //Servers:
	CallCommand 	: SvrChCmd_DINT;
  //Clients:
  //Variables:
		eInitSSW 	: t_InitSSW;
		eResponseState 	: t_ResponseState;
		udNrDO 	: UDINT;
		DOList : ARRAY [0..BUS_IF_SDIAS_MAX_NR_DO-1] OF t_SDIASDOCfg;

		NrDOMove 	: UDINT;
		DOListMove : ARRAY [0..BUS_IF_SDIAS_MAX_NR_DO-1] OF UDINT;

		mt_api 	: ^LSL_MT_TYPE;
		pMutex 	: pVoid;
		sdOnline 	: DINT;
		BusCycleTime 	: UDINT;
		pUserCalls 	: t_CALLBACK_POINTERS;
		ppResetDetectionState 	: ^t_SDIAS_pStateByte;
		pResetDetectionState 	: t_SDIAS_pStateByte;
		OldStateByte 	: t_SDIAS_StateByte;
  //Functions:
	
	FUNCTION VIRTUAL GLOBAL Init;
	
	FUNCTION BusInterfaceSdias
		VAR_OUTPUT
			ret_code 	: ConfStates;
		END_VAR;
	
	FUNCTION VIRTUAL GLOBAL UpdateRt;
	
	FUNCTION VIRTUAL GLOBAL UpdateRtPostScan;
	
	FUNCTION VIRTUAL GLOBAL UpdateCy;
	
	FUNCTION VIRTUAL GLOBAL AddAccesses
		VAR_OUTPUT
			eModuleInitState 	: iprStates;
		END_VAR;
	
	FUNCTION VIRTUAL GLOBAL ConnectEvent;
	
	FUNCTION VIRTUAL GLOBAL DisconnectEvent;
				//! <Function Comment="Methode should be used to run a Statemachine to Initialize the Module." Name="InitModule"/>
	FUNCTION VIRTUAL GLOBAL InitModule
		VAR_OUTPUT
			eModuleInitState 	: iprStates;			//! <Variable Comment="Return BUSY until the Initialisation is finished." Name="InitModule.eModuleInitState"/>
		END_VAR;
				//! <Function Comment="This Methode should be used, to check the DeviceID of the Module." Name="CheckDeviceID"/>
	FUNCTION VIRTUAL GLOBAL CheckDeviceID
		VAR_INPUT
			udID2Check 	: UDINT;			//! <Variable Comment="Device ID of connected Module." Name="CheckDeviceID.udID2Check"/>
		END_VAR
		VAR_OUTPUT
			bIsOK 	: BOOL;			//! <Variable Comment="FALSE = Wrong DeviceID for Module&#13;&#10;TRUE  = DeviceID of Module is correct" Name="CheckDeviceID.bIsOK"/>
		END_VAR;
				//! <Function Comment="Methode to receive the Response in case of SDO-Communication." Name="ReceiveSDOResponse"/>
	FUNCTION VIRTUAL ReceiveSDOResponse
		VAR_INPUT
			eCommand 	: t_SDIAS_SDO_Cmd;			//! <Variable Comment="Type of SDO-Command" Name="ReceiveSDOResponse.eCommand"/>
			hOffset 	: HINT;			//! <Variable Comment="Address-Offset in Module." Name="ReceiveSDOResponse.hOffset"/>
			usLength 	: USINT;			//! <Variable Comment="Length of Data." Name="ReceiveSDOResponse.usLength"/>
			eResult 	: iprStates;			//! <Variable Comment="State of SDO-Communication." Name="ReceiveSDOResponse.eResult"/>
			pResponseBuffer 	: ^USINT;			//! <Variable Comment="Pointer of ResponseBuffer, where the SDO-Data is located." Name="ReceiveSDOResponse.pResponseBuffer"/>
			ResponseLength 	: USINT;			//! <Variable Comment="Size of the ResponseBuffer." Name="ReceiveSDOResponse.ResponseLength"/>
		END_VAR
		VAR_OUTPUT
			ret_code 	: iprStates;			//! <Variable Comment="Indicates if the Methode was successful." Name="ReceiveSDOResponse.ret_code"/>
		END_VAR;
	
	FUNCTION VIRTUAL GetTaskCfg
		VAR_OUTPUT
			TaskCfg 	: BDINT;			//! <Variable Comment="Select which tasks will be available for this module:&#13;&#10;Bit0..Realtime PreScan&#13;&#10;Bit1..Realtime PostScan&#13;&#10;Bit2..Cyclic&#13;&#10;&#13;&#10;e.g. if only realtime postscan is needed:&#13;&#10;2#010" Name="GetTaskCfg.TaskCfg"/>
		END_VAR;
	
	FUNCTION GLOBAL AddDO
		VAR_INPUT
			pCmd 	: ^CmdStruct;
			presult 	: ^results;
		END_VAR;
	
	FUNCTION GLOBAL AddTask
		VAR_INPUT
			pCmd 	: ^CmdStruct;
			presult 	: ^results;
		END_VAR;
	
	FUNCTION GLOBAL SetRunState
		VAR_INPUT
			pCmd 	: ^CmdStruct;
			presult 	: ^results;
		END_VAR;
	
	FUNCTION CheckHandle
		VAR_INPUT
			Handle 	: UDINT;
		END_VAR
		VAR_OUTPUT
			IsOk 	: BOOL;
		END_VAR;
	
	FUNCTION GLOBAL SetOperatorClass
		VAR_INPUT
			pOperator 	: pVirtualBase;
		END_VAR
		VAR_OUTPUT
			sd_retval 	: t_BusIFRetvalErrorcode;
		END_VAR;
	
	FUNCTION CheckMovHandle
		VAR_INPUT
			Handle 	: UDINT;
		END_VAR
		VAR_OUTPUT
			IsOk 	: BOOL;
		END_VAR;
	
	FUNCTION VIRTUAL LogErrorExt
		VAR_INPUT
			e_msg 	: ^CHAR;
			p_extThis1 	: pVirtualBase;
			p_extThis2 	: pVirtualBase;
		END_VAR;
	
	FUNCTION GLOBAL UpdateDO
		VAR_INPUT
			pCmd 	: ^CmdStruct;
			presult 	: ^results;
		END_VAR;
	
	FUNCTION GLOBAL IsDeactivated
		VAR_OUTPUT
			isDeactivated 	: BOOL;
		END_VAR;
	
	FUNCTION VIRTUAL GLOBAL ClassState::NewInst
		VAR_INPUT
			pPara 	: ^CmdStruct;
			pResult 	: ^results;
		END_VAR
		VAR_OUTPUT
			ret_code 	: iprStates;
		END_VAR;
	
	FUNCTION VIRTUAL GLOBAL CallCommand::NewInst
		VAR_INPUT
			pPara 	: ^CmdStruct;
			pResult 	: ^results;
		END_VAR
		VAR_OUTPUT
			ret_code 	: iprStates;
		END_VAR;
  //Tables:
	FUNCTION @STD
		VAR_OUTPUT
			ret_code	: CONFSTATES;
		END_VAR;
	FUNCTION GLOBAL TAB @CT_;
END_CLASS;

//}}LSL_DECLARATION


FUNCTION GLOBAL TAB BusInterfaceSdias::@CT_
0$UINT,
2#0100000000000000$UINT, //TY_BUSINTERFACESDIAS
1$UINT, 26$UINT, (SIZEOF(::BusInterfaceSdias))$UINT, 
1$UINT, 0$UINT, 0$UINT, 
TO_UDINT(2368828999), "BusInterfaceSdias", //Class
TO_UDINT(3175101883), "SdiasBase", 1$UINT, 60$UINT, //Baseclass
//Servers:
(::BusInterfaceSdias.CallCommand.pMeth)$UINT, _CH_CMD$UINT, 2#0000000000000000$UINT, TO_UDINT(1059212957), "CallCommand", 
//Clients:
END_FUNCTION


#define USER_CNT_BusInterfaceSdias 26

TYPE
	_LSL_STD_VMETH	: STRUCT
			CmdTable	: CMDMETH;
			UserFcts	: ARRAY[0..USER_CNT_BusInterfaceSdias] OF ^Void;
	END_STRUCT;
END_TYPE

FUNCTION BusInterfaceSdias::@STD
	VAR_OUTPUT
		ret_code	: CONFSTATES;
	END_VAR
	VAR
		vmt	: _LSL_STD_VMETH;
		nCmdSize	: UINT;
	END_VAR

	ret_code	:= SdiasBase::@STD();
	IF ret_code <> C_OK THEN
		RETURN;
	END_IF;
	nCmdSize		:= SdiasBase::ClassState.pMeth^.nCmds$UINT*SIZEOF(pVoid) + CMDMETH.Init;

	_memcpy((#vmt.CmdTable)$^USINT, SdiasBase::ClassState.pMeth, nCmdSize);
	vmt.CmdTable.nCmds		:= nSTDCMD + USER_CNT_BusInterfaceSdias;
	vmt.CmdTable.NewInstr		:= #ClassState::NewInst();
	vmt.CmdTable.Init		:= #Init();
#pragma warning (disable : 74)
	vmt.UserFcts[0]		:= #UpdateRt();

#pragma warning (default : 74)
#pragma warning (disable : 74)
	vmt.UserFcts[1]		:= #UpdateRtPostScan();

#pragma warning (default : 74)
#pragma warning (disable : 74)
	vmt.UserFcts[3]		:= #UpdateCy();

#pragma warning (default : 74)
#pragma warning (disable : 74)
	vmt.UserFcts[4]		:= #AddAccesses();

#pragma warning (default : 74)
#pragma warning (disable : 74)
	vmt.UserFcts[5]		:= #ConnectEvent();

#pragma warning (default : 74)
#pragma warning (disable : 74)
	vmt.UserFcts[6]		:= #DisconnectEvent();

#pragma warning (default : 74)
#pragma warning (disable : 74)
	vmt.UserFcts[7]		:= #InitModule();

#pragma warning (default : 74)
#pragma warning (disable : 74)
	vmt.UserFcts[8]		:= #CheckDeviceID();

#pragma warning (default : 74)
#pragma warning (disable : 74)
	vmt.UserFcts[9]		:= #ReceiveSDOResponse();

#pragma warning (default : 74)
#pragma warning (disable : 74)
	vmt.UserFcts[13]		:= #GetTaskCfg();

#pragma warning (default : 74)
#pragma warning (disable : 74)
	vmt.UserFcts[25]		:= #LogErrorExt();

#pragma warning (default : 74)
	SdiasBase::ClassState.pMeth		:= StoreCmd (pCmd := #vmt.CmdTable, SHARED);

	IF SdiasBase::ClassState.pMeth THEN
		ret_code	:= C_OK;
	ELSE
		ret_code	:= C_OUTOF_NEAR;
		RETURN;
	END_IF;
	_memcpy((#vmt.CmdTable)$^USINT, CallCommand.pMeth, SIZEOF(CMDMETH));
	vmt.CmdTable.nCmds		:= nSTDCMD;
	vmt.CmdTable.NewInstr		:= #CallCommand::NewInst();
	CallCommand.pMeth		:= StoreCmd (pCmd := #vmt.CmdTable, SHARED);

	IF CallCommand.pMeth THEN
		ret_code	:= C_OK;
	ELSE
		ret_code	:= C_OUTOF_NEAR;
		RETURN;
	END_IF;
	ret_code	:= BusInterfaceSdias();

END_FUNCTION

//{{LSL_IMPLEMENTATION


FUNCTION VIRTUAL GLOBAL BusInterfaceSdias::UpdateRt
  VAR
    ActStateByte  : t_SDIAS_StateByte;
  	tempCmd     : CmdStruct;
    _result     : results;
  END_VAR

  // check if periphery reset occurs or disappears (only if activated via command _BUS_IF_ADD_RESET_DETECTION_4_DO)
  if pResetDetectionState then
    ActStateByte := pResetDetectionState^;
    if (ActStateByte.PeripheryResetLatched = TRUE) & (OldStateByte.PeripheryResetLatched = FALSE) then
      // reset latch detected
      tempCmd.uiCmd := _BUS_IF_RESET_DETECTED;
      pUserCalls.p_Callback^.pSvrChCmd.NewInst(#tempCmd,#_result);
    elsif (ActStateByte.PeripheryResetLatched = FALSE) & (OldStateByte.PeripheryResetLatched = TRUE) then
      // reset latch gone detected
      tempCmd.uiCmd := _BUS_IF_RESET_GONE_DETECTED;
      pUserCalls.p_Callback^.pSvrChCmd.NewInst(#tempCmd,#_result);
    end_if;
    OldStateByte := ActStateByte;
  end_if;

  // call operator, who returns the init state (busy = call me again, error = error occured/cancel init, ready = init successfully finished)
  if pUserCalls.p_UpdateRt then
    // Call the corresponding function in the operator class
    pUserCalls.p_UpdateRt^.RtWork(EAX:=CALL_OPTION_RT_PRESCAN);
  end_if;

END_FUNCTION


FUNCTION VIRTUAL GLOBAL BusInterfaceSdias::UpdateRtPostScan

  // call operator, who returns the init state (busy = call me again, error = error occured/cancel init, ready = init successfully finished)
  if pUserCalls.p_UpDateRtPostScan then
    // Call the corresponding function in the operator class
    pUserCalls.p_UpDateRtPostScan^.RtWork(EAX:=CALL_OPTION_RT_POSTSCAN);
  end_if;

END_FUNCTION


FUNCTION VIRTUAL GLOBAL BusInterfaceSdias::ConnectEvent
  VAR
  	tempCmd     : CmdStruct;
    _result     : results;
  END_VAR

  // call operator, who returns the init state (busy = call me again, error = error occured/cancel init, ready = init successfully finished)
  if pUserCalls.p_Callback then
    // Call the corresponding function in the operator class
    tempCmd.uiCmd := _BUS_IF_HWCONNECT;
    pUserCalls.p_Callback^.pSvrChCmd.NewInst(#tempCmd,#_result);
  end_if;

  if (ppResetDetectionState & ppResetDetectionState^) then
    pResetDetectionState := ppResetDetectionState^;
  end_if;
  
  eInitState    := _NotInitialized;

END_FUNCTION


FUNCTION VIRTUAL GLOBAL BusInterfaceSdias::DisconnectEvent
  VAR
  	tempCmd     : CmdStruct;
    _result     : results;
  END_VAR

  // call operator, who returns the init state (busy = call me again, error = error occured/cancel init, ready = init successfully finished)
  if pUserCalls.p_Callback then
    // Call the corresponding function in the operator class
    tempCmd.uiCmd := _BUS_IF_HWDISCONNECT;
    pUserCalls.p_Callback^.pSvrChCmd.NewInst(#tempCmd,#_result);
  end_if;

  SdiasBase::DisconnectEvent();

END_FUNCTION


FUNCTION VIRTUAL GLOBAL BusInterfaceSdias::CallCommand::NewInst
	VAR_INPUT
		pPara 	: ^CmdStruct;
		pResult 	: ^Results;
	END_VAR
	VAR_OUTPUT
		ret_code 	: IprStates;
	END_VAR
  VAR    
    pBusIFAddCallback : ^t_BusIFAddCallback;
    pTemp : ^void;
    pCurrentDO        : ^t_SDIASDOCfg;
//    sd_retval : DINT;
//  	pRDWRDOCfg        : ^t_RDWRDOCfg;
  END_VAR

	ret_code := READY;

	CASE pPara^.uiCmd OF
  
    //**********************************************************************************************************************************************************
    _BUS_IF_SET_SDIAS_MODE:
      
      pResult^.uiLng := 4;
      pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_OK;
    
      //nothing to do here (is used for businterfacevaran)
  
//**********************************************************************************************************************************************************
    _BUS_IF_ADD_CALLBACK :         // Set Callbackpointer
      pResult^.uiLng    := 4;
      pBusIFAddCallback := (pPara^.aPara[0])$^t_BusIFAddCallback;
      
      pResult^.aData[0]$t_BusIFRetvalErrorcode := SetOperatorClass(pBusIFAddCallback^.pthis);
      
      if pResult^.aData[0]$t_BusIFRetvalErrorcode <> _BUS_IF_RETVAL_OK then
        ret_code := ERROR;
      end_if;
          
//**********************************************************************************************************************************************************
    _BUS_IF_ADD_DO :               // Add Data Object
      OS_MT_WAIT(pMutex);
      AddDO(pPara, pResult);
      OS_MT_SIGNAL(pMutex);

//**********************************************************************************************************************************************************
    _BUS_IF_UPDATE_DO :            // Update Data Object
      
      OS_MT_WAIT(pMutex);
      UpdateDO(pPara, pResult);
      if pResult^.aData[0]$t_BusIFRetvalErrorcode <> _BUS_IF_RETVAL_OK then
        ret_code := ERROR;
      end_if;
      OS_MT_SIGNAL(pMutex);
          
//**********************************************************************************************************************************************************
    _BUS_IF_RESET_DO :             // Reset Data Object 
      // not available in this interface class
      pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_ERROR_NOT_SUPPORTED;
      ret_code := ERROR;
     
//**********************************************************************************************************************************************************
    _BUS_IF_ADD_TASK :             // Add Task
      AddTask(pPara, pResult); 

//**********************************************************************************************************************************************************
    _BUS_IF_RD_DA :                // Direct Access Read
      // not available in this interface class
      pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_ERROR_NOT_SUPPORTED;
      ret_code := ERROR;

//**********************************************************************************************************************************************************
    _BUS_IF_WR_DA :               // Direct Access Write
      // not available in this interface class
      pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_ERROR_NOT_SUPPORTED;
      ret_code := ERROR;

//**********************************************************************************************************************************************************
    _BUS_IF_SET_RUN_STATE :       // Set the run State 
      OS_MT_WAIT(pMutex);
      SetRunState(pCmd:=pPara, presult:=pResult);
      OS_MT_SIGNAL(pMutex);
      if pResult^.aData[0]$t_BusIFRetvalErrorcode <> _BUS_IF_RETVAL_OK then
        ret_code := ERROR;
      end_if;
          
//**********************************************************************************************************************************************************
    _BUS_IF_SET_ONLINE:           // Sets the online Server
      // not available in this interface class
      pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_ERROR_NOT_SUPPORTED;
      ret_code := ERROR;
          
//**********************************************************************************************************************************************************
    _BUS_IF_SET_DO_PRESCALER :    // Set DO Prescaler 
      // not available in this interface class
      pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_ERROR_NOT_SUPPORTED;
      ret_code := ERROR;
          
//**********************************************************************************************************************************************************
    _BUS_IF_SET_TASKS_PRESCALER : // Set Task Prescaler 
      // not available in this interface class
      pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_ERROR_NOT_SUPPORTED;
      ret_code := ERROR;
        
//**********************************************************************************************************************************************************
    _BUS_IF_SET_SYNC :            // Set the sync data 
      // not available in this interface class
      pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_ERROR_NOT_SUPPORTED;
      ret_code := ERROR;

//**********************************************************************************************************************************************************
    _BUS_IF_WAIT_4_POST_INIT:
      // not available in this interface class
      pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_ERROR_NOT_SUPPORTED;
      ret_code := ERROR;
        
//**********************************************************************************************************************************************************
    _BUS_IF_POST_INIT_FINISHED:
      // not available in this interface class
      pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_ERROR_NOT_SUPPORTED;
      ret_code := ERROR;

//**********************************************************************************************************************************************************
    _BUS_IF_GET_HW_PATH:
      pTemp := GetPointer2ObjectPath(pPara^.aPara[0]$pVirtualBase);
      if pTemp then
        pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_OK;
        pResult^.aData[4]$^void := pTemp;
      else
        pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_ERROR_INVALID_POINTER;
        pResult^.aData[4]$^void := NIL;
        ret_code := ERROR;
      end_if;

//**********************************************************************************************************************************************************
    _BUS_IF_ADD_MOVE_DO:
      // forward it to the sdias manager
      ret_code := SdiasIn.NewInst(pPara, pResult);
      
      // save the handle
      if (ret_code = READY) & (pResult^.aData[0]$t_BusIFRetvalErrorcode = _BUS_IF_RETVAL_OK) then
        DOListMove[NrDOMove] := pResult^.aData$t_AddMoveDORet.Handle;
        NrDOMove += 1;
      end_if;

//**********************************************************************************************************************************************************
    _BUS_IF_GET_DEACTIVATED_STATE:
      // if the module has the deactivate-place number => tell the operator
      if IsDeactivated() then
        pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_OK;
        pResult^.aData[4]$BOOL := TRUE;
      else      
        // otherwise forward it to the sdias manager
        ret_code := SdiasIn.NewInst(pPara, pResult);
      end_if;
      
//**********************************************************************************************************************************************************
    _BUS_IF_CREATE_MUTEX,
    _BUS_IF_GET_BUSCYCLE_TIME,
    _BUS_IF_IS_VARAN_AVAILABLE,
    _BUS_IF_UPDATE_MOVE_DO,
    _BUS_IF_GET_ACCESS_INFO:
      // forward it to the sdias manager
      ret_code := SdiasIn.NewInst(pPara, pResult);
     
//**********************************************************************************************************************************************************
    _BUS_IF_SET_REQUIRED:
      Required := 1;
      pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_OK;
      
      // forward it to the sdias manager
      ret_code := SdiasIn.NewInst(pPara, pResult);
                
//**********************************************************************************************************************************************************
    _BUS_IF_SET_REQUIRED_ERROR:
      // show the required error on this modules
      ClassState := _RequiredError;
    
      // forward it to the sdias manager (to crash)
      ret_code := SdiasIn.NewInst(pPara, pResult);

//**********************************************************************************************************************************************************
    _BUS_IF_GET_REQUIRED_SETTING:
      pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_OK;
      pResult^.aData[4] := Required$USINT;

//**********************************************************************************************************************************************************
    _BUS_IF_GET_OBJECT_THIS_PTR:
      pResult^.aData[0]$UDINT := GetObjectThisp(pObjectPath := pPara^.aPara[0]$^USINT);
      if pResult^.aData[0]$UDINT = 0 then
        ret_code := ERROR;
#ifdef HWC_LogError
        HWC_LogError(this, "@02D3 (BusInterfaceSdias::CallCommand::NewInst) Failed to get this pointer via hardware path");
#endif
      end_if;

//**********************************************************************************************************************************************************
    _BUS_IF_WRITE_VIA_SDO:
      ret_code := StartWriteSDO(hOffset:=pPara^.aPara[0]$HINT, usLength:=pPara^.aPara[1]$USINT, pWriteBuffer:=pPara^.aPara[2]$^USINT, eCommand:=SDIAS_SDO_CMD_MEM_WRITE);
    
//**********************************************************************************************************************************************************
    _BUS_IF_WRITE_VIA_SDO_CTRL:
      ret_code := StartWriteSDO(hOffset:=pPara^.aPara[0]$HINT, usLength:=pPara^.aPara[1]$USINT, pWriteBuffer:=pPara^.aPara[2]$^USINT, eCommand:=SDIAS_SDO_CMD_CTRL_WRITE);
    
//**********************************************************************************************************************************************************
    _BUS_IF_READ_VIA_SDO:
      ret_code := StartReadSDO(hOffset:=pPara^.aPara[0]$HINT, usLength:=pPara^.aPara[1]$USINT, eCommand:=SDIAS_SDO_CMD_MEM_READ);

//**********************************************************************************************************************************************************
    _BUS_IF_READ_VIA_SDO_CTRL:
      ret_code := StartReadSDO(hOffset:=pPara^.aPara[0]$HINT, usLength:=pPara^.aPara[1]$USINT, eCommand:=SDIAS_SDO_CMD_CTRL_READ);

//**********************************************************************************************************************************************************
    _BUS_IF_GET_INTERFACE_TYPE:
      pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_OK;
      pResult^.aData[4]$t_BusIFType := _BUS_IF_TYPE_SDIAS;
    
//**********************************************************************************************************************************************************
    _BUS_IF_ADD_RESET_DETECTION_4_DO:
      // check if it's on our handle list
      if CheckHandle(Handle:= pPara^.aPara[0]$HDINT) then
        
        pCurrentDO := pPara^.aPara[0]$^t_SDIASDOCfg;
        ppResetDetectionState := #pCurrentDO^.pStatusByte;
      end_if;
      
//**********************************************************************************************************************************************************      
    _BUS_IF_SET_CLASS_STATE:
      
      ClassState := eInitState := (pPara^.aPara[0])$t_e_VaranErrors;
      
      pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_OK;

//**********************************************************************************************************************************************************      
    _BUS_IF_GET_CLASS_STATE:
    
      pResult^.aData[1]$t_e_VaranErrors        := ClassState;      
      pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_OK; 

//**********************************************************************************************************************************************************      
    _BUS_IF_LOG_ERROR_MSG:
      // check for valid pointer to message
      if pPara^.aPara[0]$t_LogErrorMsg.e_msg then
        pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_OK;
        
        if (pPara^.aPara[0]$t_LogErrorMsg.p_extThis1 = nil) then
#ifdef HWC_LogError
          HWC_LogError(this, pPara^.aPara[0]$t_LogErrorMsg.e_msg);
#endif
        else
          LogErrorExt(e_msg       := pPara^.aPara[0]$t_LogErrorMsg.e_msg
                    , p_extThis1  := pPara^.aPara[0]$t_LogErrorMsg.p_extThis1
                    , p_extThis2  := pPara^.aPara[0]$t_LogErrorMsg.p_extThis2);
        end_if;
      else
        pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_ERROR_INVALID_POINTER;
      end_if;

//**********************************************************************************************************************************************************      
    _BUS_IF_LOG_VALUES:
      // check for valid pointer to message
      if pPara^.aPara[0]$t_LogValue.e_msg then
        pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_OK;
        if pPara^.aPara[0]$t_LogValue.p_extThis then
#ifdef HWC_LogValue3
          HWC_LogValue3( pPara^.aPara[0]$t_LogValue.p_extThis
                       , pPara^.aPara[0]$t_LogValue.e_msg
                       , pPara^.aPara[0]$t_LogValue.val1
                       , pPara^.aPara[0]$t_LogValue.val2
                       , pPara^.aPara[0]$t_LogValue.val3
                       );
#endif
        else
#ifdef HWC_LogValue3
          HWC_LogValue3( this
                       , pPara^.aPara[0]$t_LogValue.e_msg
                       , pPara^.aPara[0]$t_LogValue.val1
                       , pPara^.aPara[0]$t_LogValue.val2
                       , pPara^.aPara[0]$t_LogValue.val3
                       );
#endif
        end_if;   
      else
        pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_ERROR_INVALID_POINTER;
      end_if;

//**********************************************************************************************************************************************************      
    _BUS_IF_SET_PARAM:            
//      case pPara^.aPara[0]$UDINT of
//                 
//      else
        //unknown command
        ret_code := ERROR;
//      end_case;
          
//**********************************************************************************************************************************************************      
    _BUS_IF_GET_PARAM:
      case pPara^.aPara[0]$UDINT of
        _BUS_IF_DEVICEID: 
          pResult^.aData[4]$UDINT                  := DeviceID;      
          pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_OK;   

        _BUS_IF_SERIALNO_LENGTH:           
          pResult^.aData[4]$UDINT                  := SerialNoStr.GetLength();    
          pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_OK;
          
        _BUS_IF_SERIALNO_DATA:          
          SerialNoStr.GetDataAt(pData  :=(pPara^.aPara[1]$^USINT)
                             , udSize  :=(pPara^.aPara[2])$UDINT
                             , udAt    :=(pPara^.aPara[3])$UDINT
                             );
          pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_OK;
          
        _BUS_IF_FPGA_VERSION: 
          pResult^.aData[4]$HDINT                  := FPGAVersion;      
          pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_OK;   
      
        _BUS_IF_RETRYCOUNTER: 
          pResult^.aData[4]$UDINT                  := RetryCounter;      
          pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_OK;   
        
        _BUS_IF_HW_VERSION:
          pResult^.aData[4]$UDINT                  := HwVersion;      
          pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_OK;   
        
      else
        //unknown command
        ret_code := ERROR;
      end_case;
  
//**********************************************************************************************************************************************************
    // forward commands from clients to manager 
    SDIAS_CMD_ADD_RD_ACCESS,
    SDIAS_CMD_ADD_WR_ACCESS,
    SDIAS_CMD_SDO_SEND_REQUEST,
    SDIAS_CMD_CHANGE_LED_STATE,
    SDIAS_CMD_DA_RD_ACCESS,
    SDIAS_CMD_DA_WR_ACCESS,
    SDIAS_CMD_REQUIRED_ERROR,
    SDIAS_CMD_INIT_STATE_LOGIN,
    SDIAS_CMD_GET_HW_PATH,
    SDIAS_CMD_INSTALL_CYCLIC_TASK,
    SDIAS_CMD_GET_CONNECTION_TYPE:
      ret_code := SdiasIn.NewInst(pPara, pResult);
//**********************************************************************************************************************************************************
  else
    // forward commands to the derivation
      ret_code := ClassState.NewInst(pPara, pResult);
	END_CASE;

END_FUNCTION


FUNCTION GLOBAL BusInterfaceSdias::AddDO
	VAR_INPUT
		pCmd 	: ^CmdStruct;
		presult 	: ^results;
	END_VAR
  VAR
  	pADDDOCfg    : ^t_AddDOCfg;
    _ud_dol_type : UDINT;
    pCurrentDO   : ^t_SDIASDOCfg;
    retcode      : iprStates;
  END_VAR

//******************************************************************************
//** We're still in the InitAccesses call where the operator installs the DOs **
//******************************************************************************

  presult^.uiLng    := sizeof(t_AddDORet);
  
  if udNrDO < BUS_IF_SDIAS_MAX_NR_DO then            
    
    pADDDOCfg := ((pCmd^.aPara[0])$^t_AddDOCfg);  
    
    // Convert passed t_Priority to VARAN ud_dol_type
    if (pADDDOCfg^.Priority)$t_BusIFPriority  = _BUS_IF_ISO then
      _ud_dol_type := VARAN_DOL_ISO;
    else    
      _ud_dol_type := VARAN_DOL_ASY;
    end_if;
    
    pCurrentDO := #DOList[udNrDO];
    
    // Add read object
    if pADDDOCfg^.RdWr = _BUS_IF_READ then      
      
      retcode := AddRdAccess(hOffset              := pADDDOCfg^.ud_addressoff_read$HINT
                           , uLength              := pADDDOCfg^.ui_length_read
                           , ppData               := pADDDOCfg^.ppDataRead
                           , ppStateByte          := #pCurrentDO^.pStatusByte
                           , ppControlByte        := #pCurrentDO^.pControlByte
                           , pAccessHandle        := #pCurrentDO^.AccessHandle
                           , WaitForAccessHandle  := pADDDOCfg^.ud_WaitForAccessHandle
                           );
                           
    // Add write object
    elsif pADDDOCfg^.RdWr = _BUS_IF_WRITE then
      
      retcode := AddWrAccess(hOffset              := pADDDOCfg^.ud_addressoff_write$HINT
                           , uLength              := pADDDOCfg^.ui_length_write
                           , ppData               := pADDDOCfg^.ppDataWrite
                           , ppStateByte          := #pCurrentDO^.pStatusByte
                           , ppControlByte        := #pCurrentDO^.pControlByte
                           , pAccessHandle        := #pCurrentDO^.AccessHandle
                           , WaitForAccessHandle  := pADDDOCfg^.ud_WaitForAccessHandle
                           );        
    
    // Add read dynamic object
    elsif pADDDOCfg^.RdWr = _BUS_IF_READ_DYN then             
      
      retcode := AddDynRdAccess( hOffset              := pADDDOCfg^.ud_addressoff_read$HINT
                               , uLength              := pADDDOCfg^.ui_length_read
                               , ppData               := pADDDOCfg^.ppDataRead
                               , ppStateByte          := #pCurrentDO^.pStatusByte
                               , ppControlByte        := #pCurrentDO^.pControlByte
                               , pAccessHandle        := #pCurrentDO^.AccessHandle
                               , WaitForAccessHandle  := pADDDOCfg^.ud_WaitForAccessHandle
                               );
      
    // Add write dynamic object
    elsif pADDDOCfg^.RdWr = _BUS_IF_WRITE_DYN then
      
      retcode := AddDynWrAccess(  hOffset             := pADDDOCfg^.ud_addressoff_write$HINT
                                , uLength             := pADDDOCfg^.ui_length_write
                                , ppData              := pADDDOCfg^.ppDataWrite
                                , ppStateByte         := #pCurrentDO^.pStatusByte
                                , ppControlByte       := #pCurrentDO^.pControlByte
                                , pAccessHandle       := #pCurrentDO^.AccessHandle
                                , WaitForAccessHandle := pADDDOCfg^.ud_WaitForAccessHandle
                                );
    else
      retcode := ERROR;
      pResult^.aData$t_AddDORet.retcode   := _BUS_IF_RETVAL_ERROR_NOT_SUPPORTED;
      pResult^.aData$t_AddDORet.sd_retval := _BUS_IF_RETVAL_ERROR_NOT_SUPPORTED$DINT;
      return;
    end_if;
    
    // Overwritte if retcode = READY
    pResult^.aData$t_AddDORet.retcode   := _BUS_IF_RETVAL_ERROR_CREATE_DO_FAILED;      
    pResult^.aData$t_AddDORet.sd_retval := _BUS_IF_RETVAL_ERROR_CREATE_DO_FAILED$DINT;
    if retcode = READY then              
                            
      // Only Save relevant lengths and offsets      
      if ( (pADDDOCfg^.RdWr)$t_BusIFRDWR = _BUS_IF_READ) | 
         ( (pADDDOCfg^.RdWr)$t_BusIFRDWR = _BUS_IF_READ_DYN)  then         
        pCurrentDO^.lengthRead     := pADDDOCfg^.ui_length_read;
        pCurrentDO^.AddrOffsetRead := pADDDOCfg^.ud_addressoff_read;
      elsif ( (pADDDOCfg^.RdWr)$t_BusIFRDWR = _BUS_IF_WRITE) | 
            ( (pADDDOCfg^.RdWr)$t_BusIFRDWR = _BUS_IF_WRITE_DYN) then
        pCurrentDO^.lengthWrite    := pADDDOCfg^.ui_length_write;
        pCurrentDO^.AddrOffsetWrite:= pADDDOCfg^.ud_addressoff_write;   
      end_if;
      
      pCurrentDO^.RdWr           := (pADDDOCfg^.RdWr)$t_BusIFRDWR;
      pCurrentDO^.Priority       := pADDDOCfg^.Priority;
      pCurrentDO^.Enable         := 1;
      pCurrentDO^.EnableFlag     := 0;
      pCurrentDO^.b_DOIsRunning  := 0;  // Disabled by default on creation      

      // Return Values
      presult^.aData$t_AddDORet.retcode       := _BUS_IF_RETVAL_OK;
      pResult^.aData$t_AddDORet.sd_retval     := _BUS_IF_RETVAL_OK;
      pResult^.aData$t_AddDORet.Handle        := (#pCurrentDO^)$UDINT;
      pResult^.aData$t_AddDORet.pDataRead     := pCurrentDO^.pDataRead;
      pResult^.aData$t_AddDORet.pDataWrite    := pCurrentDO^.pDataWrite;
      presult^.aData$t_AddDORet.AccessHandle  := pCurrentDO^.AccessHandle;
      
      udNrDO += 1;
    end_if;
  else            
    pResult^.aData$t_AddDORet.retcode := _BUS_IF_RETVAL_ERROR_DO_LIST_FULL;              
  end_if;

END_FUNCTION


FUNCTION GLOBAL BusInterfaceSdias::AddTask
	VAR_INPUT
		pCmd 	  : ^CmdStruct;
		presult : ^results;
	END_VAR
  VAR
  	pTASKCfg    : ^t_TaskCfg;
    _ud_dol_type  : UDINT;
  	tempCmd         : CmdStruct;
    _result         : results;
  END_VAR

  presult^.uiLng    := sizeof(t_BusIFRetvalErrorcode);
  
  pTASKCfg := ((pCmd^.aPara[0])$^t_TaskCfg);
  
  // Check for null pointer
  if pTASKCfg^.pthis then   
    
        // Convert passed t_BusIFPriority  to VARAN ud_dol_type
    if pTASKCfg^.Priority = _BUS_IF_ISO then
      _ud_dol_type := VARAN_DOL_ISO;
    else    
      _ud_dol_type := VARAN_DOL_ASY;
    end_if;
    
    // Save the passed callback pointer according to the callOptions
    if pTASKCfg^.callOptions = CALL_OPTION_RT_PRESCAN then 
      pUserCalls.p_UpdateRt := (pTASKCfg^.pthis)$pVirtualBase;
    elsif pTASKCfg^.callOptions = CALL_OPTION_RT_POSTSCAN then
      pUserCalls.p_UpDateRtPostScan := (pTASKCfg^.pthis)$pVirtualBase;    
    elsif pTASKCfg^.callOptions = (CALL_OPTION_RT_PRESCAN or CALL_OPTION_RT_POSTSCAN) then
      pUserCalls.p_UpdateRt := (pTASKCfg^.pthis)$pVirtualBase;
      pUserCalls.p_UpDateRtPostScan := (pTASKCfg^.pthis)$pVirtualBase;    
    else
      pUserCalls.p_UpdateCy := (pTASKCfg^.pthis)$pVirtualBase;

      tempCmd.uiCmd := SDIAS_CMD_INSTALL_CYCLIC_TASK;
      tempCmd.aPara[0] := Place$DINT;
      
      if SdiasIn.NewInst(pPara:=#tempCmd, pResult:=#_result) <> READY then
        pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_ERROR_INVALID_DATA;
        return;
      end_if;
    end_if;
        
    pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_OK;
  else
    pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_ERROR_INVALID_POINTER;
  end_if;

END_FUNCTION


FUNCTION GLOBAL BusInterfaceSdias::SetRunState
	VAR_INPUT
		pCmd 	    : ^CmdStruct;
		presult 	: ^results;
	END_VAR
  VAR
  	pSETRUNSTATECfg   : ^t_SetRunStateCfg;
    pCurrentDO        : ^t_SDIASDOCfg;
  END_VAR

  presult^.uiLng    := 4;
  
  pSETRUNSTATECfg := ((pCmd^.aPara[0])$^t_SetRunStateCfg);
  
  // check if it's on our handle list
  if CheckHandle(Handle:= pSETRUNSTATECfg^.Handle) then
    
    pCurrentDO := (pSETRUNSTATECfg^.Handle)$^t_SDIASDOCfg;
    
    if pSETRUNSTATECfg^.NewRunState = _BUS_IF_RUN_STATE_SINGLE_RUN then
      pCurrentDO^.b_DOIsRunning.ContRun       := false; // Override cont run 
      pCurrentDO^.b_DOIsRunning.StartRequest  := true;
      pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_OK;
    elsif pSETRUNSTATECfg^.NewRunState = _BUS_IF_RUN_STATE_CONT_RUN then
      pCurrentDO^.pControlByte^.EnableDO := TRUE;
      pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_OK;
      pCurrentDO^.b_DOIsRunning         := 0; // Override any singlerun states
      pCurrentDO^.b_DOIsRunning.ContRun := true;
    else
      pCurrentDO^.pControlByte^.EnableDO := FALSE;
      pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_OK;
      pCurrentDO^.b_DOIsRunning         := 0;
    end_if;
    
  // if it's not, check if it's a move handle
  elsif CheckMovHandle(Handle:=pSETRUNSTATECfg^.Handle) then
    // forward it to the sdias manager who forwards it to the bus interface for varan
    SdiasIn.NewInst(pCmd, presult);
  else
    pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_ERROR_INVALID_HANDLE;
  end_if;
  
END_FUNCTION  


FUNCTION BusInterfaceSdias::CheckHandle
	VAR_INPUT
		Handle 	: UDINT;
	END_VAR
	VAR_OUTPUT
		IsOk 	: BOOL;
	END_VAR
  VAR
    ListOffset : UDINT;
  END_VAR
  
  IsOk := false;
  
  // Handle must be not nil and there must be elements in the array.
  if Handle & udNrDO then
    ListOffset := (Handle - (#DOList[0])$UDINT);
    if ((ListOffset MOD sizeof(t_SDIASDOCfg)) = 0) & ((ListOffset/sizeof(t_SDIASDOCfg)) < udNrDO) then
      IsOk := true;
    end_if;
  end_if;

END_FUNCTION


FUNCTION GLOBAL BusInterfaceSdias::SetOperatorClass
	VAR_INPUT
		pOperator 	: pVirtualBase;
	END_VAR
	VAR_OUTPUT
		sd_retval 	: t_BusIFRetvalErrorcode;
	END_VAR
        
  if pOperator then
    sd_retval := _BUS_IF_RETVAL_OK;
    pUserCalls.p_Callback := pOperator;
  else
    sd_retval := _BUS_IF_RETVAL_ERROR_INVALID_POINTER;
  end_if;

END_FUNCTION


FUNCTION VIRTUAL GLOBAL BusInterfaceSdias::Init
  VAR
  	tempCmd    : CmdStruct;
    _result    : results;
    TempStr         : ARRAY [0..9] OF CHAR;
  END_VAR;

  IF IsDeactivated() THEN
    return;
  END_IF;

  SdiasBase::Init();

  if usInitCounter = 1 then

    // install mutex for DO manipulation
    _strcpy(dest:=#TempStr[0], src:="AddSDOs");
    tempCmd.uiCmd := _BUS_IF_CREATE_MUTEX;
    tempCmd.aPara[0] := (#TempStr)$DINT;
    tempCmd.aPara[1] := this$DINT;
    SdiasIn.NewInst(pPara:=#tempCmd, pResult:=#_result);
    
    if _result.aData[0]$t_GetBusCycleTime.retcode <> _BUS_IF_RETVAL_OK then
#ifdef HWC_LogError
      HWC_LogError(this, "@02D4 (BusInterfaceSdias::Init) Failed to create Mutex for manipulating DOs");
#endif
    else
      pMutex := _result.aData[4]$^void;
    end_if;    

  end_if;

END_FUNCTION


FUNCTION BusInterfaceSdias::BusInterfaceSdias
	VAR_OUTPUT
		ret_code 	: ConfStates;
	END_VAR

  if (OS_CILGet("LSL_MULTITASK", #mt_api$void)) THEN
#ifdef HWC_LogError
    HWC_LogError(this, "@02D5 (BusInterfaceSdias::BusInterfaceSdias) Failed to get MULTITASK OS-Interface for Mutex usage");
#endif
  end_if;

	ret_code := C_OK;

END_FUNCTION


FUNCTION VIRTUAL GLOBAL BusInterfaceSdias::UpdateCy

  // call operator, who returns the init state (busy = call me again, error = error occured/cancel init, ready = init successfully finished)
  if pUserCalls.p_UpdateCy then
    // Call the corresponding function in the operator class
    pUserCalls.p_UpdateCy^.CyWork(0);
  end_if;

END_FUNCTION


FUNCTION VIRTUAL GLOBAL BusInterfaceSdias::InitModule
	VAR_OUTPUT
		eModuleInitState 	: iprStates;
	END_VAR
  VAR
  	tempCmd     : CmdStruct;
    _result     : results;
  END_VAR

  // call operator, who returns the init state (busy = call me again, error = error occured/cancel init, ready = init successfully finished)
  if pUserCalls.p_Callback then
    // Call the corresponding function in the operator class
    tempCmd.uiCmd := _BUS_IF_INIT_MODULE;
    eModuleInitState := pUserCalls.p_Callback^.pSvrChCmd.NewInst(#tempCmd,#_result);
    
    if eModuleInitState = READY then
      eInitState := _ClassOk;
    end_if;
  else
    eModuleInitState := READY;
  end_if;

END_FUNCTION


FUNCTION VIRTUAL GLOBAL BusInterfaceSdias::CheckDeviceID
	VAR_INPUT
		udID2Check 	: UDINT;
	END_VAR
	VAR_OUTPUT
		bIsOK 	: BOOL;
	END_VAR
  VAR
  	tempCmd     : CmdStruct;
    _result     : results;
  END_VAR

	//look if it is right hardware => ask operator
  if pUserCalls.p_Callback then
    // Call the corrosponding function in the operator class
    tempCmd.uiCmd := _BUS_IF_CHECK_DEVICE_ID;  
    tempCmd.aPara[0] := udID2Check$DINT;
    
    pUserCalls.p_Callback^.pSvrChCmd.NewInst(#tempCmd,#_result);
    
    if _result.aData[0] then
      bIsOK         := TRUE;
    else
      bIsOK         := FALSE;
    end_if;
  else
    bIsOK := READY;
  end_if;

END_FUNCTION


FUNCTION VIRTUAL BusInterfaceSdias::ReceiveSDOResponse
	VAR_INPUT
		eCommand 	: t_SDIAS_SDO_Cmd;
		hOffset 	: HINT;
		usLength 	: USINT;
		eResult 	: iprStates;
		pResponseBuffer 	: ^USINT;
		ResponseLength 	: USINT;
	END_VAR
	VAR_OUTPUT
		ret_code 	: iprStates;
	END_VAR
  VAR
  	tempCmd : CmdStruct;
    _result : results;
  END_VAR
  
  ret_code := SdiasBase::ReceiveSDOResponse(eCommand, hOffset, usLength, eResult, pResponseBuffer, ResponseLength);

  if eResult = READY then
    
    case eCommand of
//**********************************************************************************************************************************************************
      SDIAS_SDO_CMD_MEM_WRITE:
        if pUserCalls.p_Callback then
          // Call the corresponding function in the operator class
          tempCmd.uiCmd := _BUS_IF_SDO_RESPONSE;
          tempCmd.aPara[0] := _BUS_IF_WRITE_VIA_SDO;
          tempCmd.aPara[1] := hOffset;
          tempCmd.aPara[2] := usLength;
          tempCmd.aPara[3] := eResult$DINT;
          tempCmd.aPara[4] := NIL$DINT;
          tempCmd.aPara[5] := 0;
          ret_code := pUserCalls.p_Callback^.pSvrChCmd.NewInst(#tempCmd,#_result);
        end_if;

//**********************************************************************************************************************************************************
      SDIAS_SDO_CMD_CTRL_WRITE:
        if pUserCalls.p_Callback then
          // Call the corresponding function in the operator class
          tempCmd.uiCmd := _BUS_IF_SDO_RESPONSE;
          tempCmd.aPara[0] := _BUS_IF_WRITE_VIA_SDO_CTRL;
          tempCmd.aPara[1] := hOffset;
          tempCmd.aPara[2] := usLength;
          tempCmd.aPara[3] := eResult$DINT;
          tempCmd.aPara[4] := NIL$DINT;
          tempCmd.aPara[5] := 0;
          ret_code := pUserCalls.p_Callback^.pSvrChCmd.NewInst(#tempCmd,#_result);
        end_if;

//**********************************************************************************************************************************************************
      SDIAS_SDO_CMD_MEM_READ:
        if pUserCalls.p_Callback then
          // Call the corresponding function in the operator class
          tempCmd.uiCmd := _BUS_IF_SDO_RESPONSE;
          tempCmd.aPara[0] := _BUS_IF_READ_VIA_SDO;
          tempCmd.aPara[1] := hOffset;
          tempCmd.aPara[2] := usLength;
          tempCmd.aPara[3] := eResult$DINT;
          tempCmd.aPara[4] := pResponseBuffer$DINT;
          tempCmd.aPara[5] := ResponseLength;
          ret_code := pUserCalls.p_Callback^.pSvrChCmd.NewInst(#tempCmd,#_result);
        end_if;

//**********************************************************************************************************************************************************
      SDIAS_SDO_CMD_CTRL_READ:
        if pUserCalls.p_Callback then
          // Call the corresponding function in the operator class
          tempCmd.uiCmd := _BUS_IF_SDO_RESPONSE;
          tempCmd.aPara[0] := _BUS_IF_READ_VIA_SDO_CTRL;
          tempCmd.aPara[1] := hOffset;
          tempCmd.aPara[2] := usLength;
          tempCmd.aPara[3] := eResult$DINT;
          tempCmd.aPara[4] := pResponseBuffer$DINT;
          tempCmd.aPara[5] := ResponseLength;
          ret_code := pUserCalls.p_Callback^.pSvrChCmd.NewInst(#tempCmd,#_result);
        end_if;

//**********************************************************************************************************************************************************
    end_case;
    
  else
    case eCommand of
      SDIAS_SDO_CMD_MEM_WRITE:
#ifdef HWC_LogError
        HWC_LogError(this, "@02D6 (BusInterfaceSdias::ReceiveSDOResponse) Error while writing");
#endif

      SDIAS_SDO_CMD_MEM_READ:
#ifdef HWC_LogError
        HWC_LogError(this, "@02D7 (BusInterfaceSdias::ReceiveSDOResponse) Error while reading");
#endif

    end_case;
    eInitSSW := _InitError;
  end_if;

END_FUNCTION


FUNCTION VIRTUAL GLOBAL BusInterfaceSdias::ClassState::NewInst
	VAR_INPUT
		pPara 	: ^CmdStruct;
		pResult 	: ^Results;
	END_VAR
	VAR_OUTPUT
		ret_code 	: IprStates;
	END_VAR
  VAR
  	tempCmd     : CmdStruct;
    _result     : results;   
    // local variables for the Requested HWTString
    pStr_HWTRequested     : ^CHAR;
    us_HWTRequestedCurrIndex  : USINT;
  END_VAR

	ret_code := READY;

	CASE pPara^.uiCmd OF
//**********************************************************************************************************************************************************
		SDIAS_CMD_DATA_POINTER_AVAILABLE:
      // tell the operator
      if pUserCalls.p_Callback then
        // Call the corrosponding function in the operator class
        tempCmd.uiCmd := _BUS_IF_DATA_POINTER_AVAILABLE;         
        ret_code := pUserCalls.p_Callback^.pSvrChCmd.NewInst(#tempCmd,#_result);
      end_if;
      
//**********************************************************************************************************************************************************
    CMD_GET_HARDWARE_DIAGNOSIS:
            
      pResult^.aData$t_HWCGetHardwareDiagnosisOut.retcode := _HWC_RETVAL_ERROR_CLASS_NOT_ONLINE;
      ret_code := ERROR;      
      
      pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.retcode := _HWC_RETVAL_ERROR;
      
      pStr_HWTRequested := pPara^.aPara[0]$t_HWCGetHardwareDiagnosisIn.pStr_HardewareTreeEntry;
      
      // Check HWT String
      if pStr_HWTRequested then      
        
        // Points to place of SDIAS Module
        us_HWTRequestedCurrIndex  := pPara^.aPara[0]$t_HWCGetHardwareDiagnosisIn.us_current_index;
        
        // Check if current index + 2 is valid, pStr_HWTRequested^ + 2 for extra byte of length
        if (us_HWTRequestedCurrIndex + 2) <= (pStr_HWTRequested$^UINT^ + 2) then
          
          us_HWTRequestedCurrIndex += 1;
          
          // Check for any Escape sequence
          if (pStr_HWTRequested + us_HWTRequestedCurrIndex)^ and HWT_ESCAPE_SEQU then
         
            // Update Current index to next position = Place of SDIAS Safety Module
            pPara^.aPara[0]$t_HWCGetHardwareDiagnosisIn.us_current_index   += 2;
            pPara^.aPara[0]$t_HWCGetHardwareDiagnosisIn.us_current_length  -= 2;
              
            if pUserCalls.p_Callback then 
              ret_code := pUserCalls.p_Callback^.pSvrChCmd.NewInst(pPara,pResult); //Pass on command to connected extension module
            end_if;

          end_if;
                    
        else
          ret_code := SdiasBase::ClassState.NewInst(pPara, pResult);  // Pass on command to base
        end_if;

      end_if;
        
//**********************************************************************************************************************************************************
    CMD_GET_HARDWARE_TREE_ENTRY:

      pResult^.aData$t_HWCGetHardwareTreeEntryOut.retcode := _HWC_RETVAL_ERROR_CLASS_NOT_ONLINE;
      ret_code := ERROR;
      
      pStr_HWTRequested := pPara^.aPara[0]$t_HWCGetHardwareTreeEntryIn.pStr_LastHardewareTreeEntry;      
      
      // Check HWT String
      if pStr_HWTRequested & pObjectPath then      
        
        // Check if the passed string is smaller than the own string
        if pStr_HWTRequested$^USINT^ < pObjectPath^ then        
        
          // Call base
          ret_code := SdiasBase::ClassState.NewInst(pPara, pResult);  // Pass on command to base 
        
        // Check if last call was to Base itself
        // Compare string content
        elsif _memcmp( ptr1 := pStr_HWTRequested + 2, 
                       ptr2 := pObjectPath +1, 
                       cntr := pObjectPath^) = 0 then
                            
          // Compare string length
          if (pStr_HWTRequested$^USINT^ = pObjectPath^) then
        
            // Last module called was the BusIF Object itself, next module is the 1st behind the extension module               
            if pUserCalls.p_Callback then    
              
              ret_code := pUserCalls.p_Callback^.pSvrChCmd.NewInst(pPara,pResult); //Pass on command to extension module            

              // if we should quit treating this module special => use standard behavior
              if ret_code = QUIT then
                ret_code := SdiasBase::ClassState.NewInst(pPara, pResult);  // Pass on command to base            
              elsif ret_code <> READY then
                // Command not implemented => No extension module
                ret_code := READY;
                pResult^.aData[0]$t_HWCGetHardwareTreeEntryOut.retcode := _HWC_RETVAL_OK_END_OF_LIST;
              end_if;

            else
              pResult^.aData[0]$t_HWCGetHardwareTreeEntryOut.retcode := _HWC_RETVAL_OK_END_OF_LIST;
            end_if;
          
          elsif (pStr_HWTRequested$^USINT^ > pObjectPath^ + 1) then // Must be at least 2 Bytey larger, ESCAPE Sequence + Place
            
            // Check escape sequence
            if ( (pStr_HWTRequested + (pObjectPath^) + 2 )^ AND HWT_ESCAPE_SEQU) then // First place after extension module Itself is escape sequence + 1 for addional length byte
              // Last Module must have been a Module behind an extension module
              // Update index
              pPara^.aPara[0]$t_HWCGetHardwareTreeEntryIn.us_current_index  := pObjectPath^ + 3; // Second place after BUSIF Itself is place + 1 for addional length byte
              pPara^.aPara[0]$t_HWCGetHardwareTreeEntryIn.us_current_length := pStr_HWTRequested^ - pObjectPath^ - 1;
              
              if pUserCalls.p_Callback then    
                ret_code := pUserCalls.p_Callback^.pSvrChCmd.NewInst(pPara,pResult); //Pass on command to extension module            
              else
                ret_code := READY;
                pResult^.aData[0]$t_HWCGetHardwareTreeEntryOut.retcode := _HWC_RETVAL_OK_END_OF_LIST;
              end_if;
            end_if;

//            else 
//              // should be impossible, ERROR
          end_if;
        
        else
          ret_code := SdiasBase::ClassState.NewInst(pPara, pResult);  // Pass on command to base            
        end_if;
      else
        // pStr_HWTRequested is probably nil, pass on command to base
        ret_code := SdiasBase::ClassState.NewInst(pPara, pResult);  // Pass on command to base            
      end_if;
      
//**********************************************************************************************************************************************************      
  ELSE
    // we forward this message to the SDIAS Manager
    ret_code := SdiasBase::ClassState.NewInst(pPara, pResult);
	END_CASE;
  
END_FUNCTION


FUNCTION BusInterfaceSdias::CheckMovHandle
	VAR_INPUT
		Handle 	: UDINT;
	END_VAR
	VAR_OUTPUT
		IsOk 	: BOOL;
	END_VAR
  VAR
    i : UDINT;
  END_VAR
  
  IsOk := false;
  
  // Handle must be not nil and there must be elements in the array.
  if Handle & NrDOMove then
    for i := 0 to NrDOMove-1 do
      if DOListMove[i] = Handle then
        IsOk := true;
        return;
      end_if;
    end_for;
  end_if;

END_FUNCTION


FUNCTION VIRTUAL GLOBAL BusInterfaceSdias::AddAccesses
	VAR_OUTPUT
		eModuleInitState 	: iprStates;
	END_VAR
  VAR
  	tempCmd    : CmdStruct;
    _result    : results;
  END_VAR

  // call operator, who adds all the accesses
  if pUserCalls.p_Callback then
    // Call the corresponding function in the operator class
    tempCmd.uiCmd := _BUS_IF_INIT_ACCESSES;
    eModuleInitState := pUserCalls.p_Callback^.pSvrChCmd.NewInst(#tempCmd,#_result);
  end_if;

END_FUNCTION


FUNCTION VIRTUAL BusInterfaceSdias::GetTaskCfg
	VAR_OUTPUT
		TaskCfg 	: BDINT;
	END_VAR

  TaskCfg := SDIAS_TASK_MASK_RT_PRE OR SDIAS_TASK_MASK_RT_POST OR SDIAS_TASK_MASK_CY;
  
END_FUNCTION


FUNCTION VIRTUAL BusInterfaceSdias::LogErrorExt
	VAR_INPUT
		e_msg 	: ^CHAR;
		p_extThis1 	: pVirtualBase;
		p_extThis2 	: pVirtualBase;
	END_VAR
  VAR
    sz_name     : ARRAY [ 0..255 ] OF CHAR;
    MyMsg       : ARRAY [0..599] OF CHAR;
  END_VAR

  if p_extThis1 = nil then
    p_extThis1 := this;
  end_if;
    
  if p_extThis2 then
    _GetObjName( p_extThis2, #sz_name[ 0 ] );
#ifdef HWC_LimitObjName
    HWC_LimitObjName(#sz_name[ 0 ]);
#endif
    _strncpy(dest:=#MyMsg[0], src:=e_msg, max:=200);
    _strcat( dest:=#MyMsg[0], src:=" ");
    _strcat( dest:=#MyMsg[0], src:=#sz_name[0]);

#ifdef HWC_LogError
  HWC_LogError(p_extThis1, #MyMsg[0]);
#endif

  else  
#ifdef HWC_LogError
    HWC_LogError(p_extThis1, e_msg);
#endif
  end_if;

END_FUNCTION

FUNCTION GLOBAL BusInterfaceSdias::UpdateDO
	VAR_INPUT
		pCmd 	            : ^CmdStruct;
		presult 	        : ^results;
	END_VAR
  VAR
    pUPDATEDOCfg      : ^t_UpdateDOCfg;
    pCurrentDO        : ^t_SDIASDOCfg;
  END_VAR
  
  pUPDATEDOCfg := ((pCmd^.aPara[0])$^t_UpdateDOCfg); 
  
  pResult^.uiLng := 4;
  
  pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_ERROR_INVALID_HANDLE;
  if CheckHandle(Handle:= pUPDATEDOCfg^.Handle) then
    
    pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_ERROR_UPDATEDO_DOLENGTH;
    
    pCurrentDO := (pUPDATEDOCfg^.Handle)$^t_SDIASDOCfg;    
    
    // Read Object
    if pCurrentDO^.RDWR = _BUS_IF_READ_DYN then
    
      if pUPDATEDOCfg^.ud_length_read  then  
      
        if ChangeDynAccess( AccessHandle  := pCurrentDO^.AccessHandle
                          , NewOffset     := pUPDATEDOCfg^.ud_addressoff_read
                          , NewLength     := pUPDATEDOCfg^.ud_length_read) 
                          = READY then
          
          pCurrentDO^.AddrOffsetRead  := pUPDATEDOCfg^.ud_addressoff_read;
          pCurrentDO^.lengthRead      := pUPDATEDOCfg^.ud_length_read;
          pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_OK;  
        end_if;
        
      end_if;
      
    // Write Object
    elsif pCurrentDO^.RDWR = _BUS_IF_WRITE_DYN then
    
      if pUPDATEDOCfg^.ud_length_write  then
        
        if ChangeDynAccess( AccessHandle  := pCurrentDO^.AccessHandle
                          , NewOffset     := pUPDATEDOCfg^.ud_addressoff_write
                          , NewLength     := pUPDATEDOCfg^.ud_length_write) 
                          = READY then
          
          pCurrentDO^.AddrOffsetWrite := pUPDATEDOCfg^.ud_addressoff_write;
          pCurrentDO^.lengthWrite     := pUPDATEDOCfg^.ud_length_write;
          pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_OK;  
        end_if;
      
      end_if;
    end_if;
  end_if;  
  
END_FUNCTION


FUNCTION GLOBAL BusInterfaceSdias::IsDeactivated
	VAR_OUTPUT
		isDeactivated 	: BOOL;
	END_VAR

  isDeactivated := FALSE;
  
#ifdef DEACTIVATED_LSL
  IF Place.Read() = DEACTIVATED_LSL THEN
    Place := DEACTIVATED_LSL;
    ClassState := _NoHardware;
    isDeactivated := TRUE;
  END_IF;
#endif

END_FUNCTION
