//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 BUSIF_VARAN_MAX_NR_DO     100
#define BUSIF_VARAN_MAX_NR_MOVEDO 100

#define BUSIF_VARAN_MAX_SDO 1

#define BUSIF_VARAN_BUS_READY_VER 16#1109
//}}LSL_DEFINES

//{{LSL_DECLARATION
#include "..\..\Source\BusInterface.h"
#include "..\..\Source\interfaces\lsl_st_mt.h"
#include "..\..\Source\interfaces\lsl_st_pci.h"
#include "..\..\Class\HwControl\HwControl.h"

(*!
<Class
	Name               = "BusInterfaceVARAN"
	Revision           = "1.75"
	GUID               = "{013BA757-940A-4EA8-B1BE-51A701626C2E}"
	RealtimeTask       = "false"
	CyclicTask         = "false"
	BackgroundTask     = "false"
	Sigmatek           = "true"
	OSInterface        = "false"
	HighPriority       = "false"
	Automatic          = "false"
	UpdateMode         = "Prescan"
	IconPath           = ".\Class\Varan_16x16.ico"
	SharedCommandTable = "true"
	Objectsize         = "(484,120)"
	Comment            = "This class provides access to VARAN client functionality over an BUS independent interface. &#13;&#10;s. &quot;BusInterface.h&quot; for interface definition. &#13;&#10;The class methods are access via the CallCommand channel.">
	<Channels>
		<Server Name="CallCommand" GUID="{104C7F4B-A60F-4FE9-B7DF-4C03842A30B0}" Visualized="true" Initialize="false" WriteProtected="true" Retentive="false" Comment="Command Channel to access the functionality of this class. All methods are access via the NewInst() method of this Server."/>
		<Server Name="State">
		</Server>
		<Client Name="ToOSKernel" Required="false" Internal="false"/>
	</Channels>
	<Dependencies>
		<Files>
			<File Path=".\Source\BusInterface.h" Include="true"/>
			<File Path=".\Source\interfaces\lsl_st_mt.h" Include="true"/>
			<File Path=".\Source\interfaces\lsl_st_pci.h" Include="true"/>
			<File Path=".\Class\HwControl\HwControl.h" Include="true"/>
		</Files>
	</Dependencies>
	<RevDoku>
		<Owner Company="Sigmatek" Author="LanSte"/>
		<Dokumentation Revision="1.75" Date="16.10.2023" Author="LanSte" Company="Sigmatek" Description="Added GetRequiredWaitTime. If this method is overwritten, the class will wait for for an required module in the init()"/>
		<Dokumentation Revision="1.74" Date="01.08.2023" Author="EisMic" Company="Sigmatek" Description="Added support for _BUS_IF_GET_TRANSPARENT_STATE command."/>
		<Dokumentation Revision="1.73" Date="16.06.2023" Author="EisMic" Company="Sigmatek" Description="The NewInst commando _BUS_IF_NEED_POST_INIT_TASK_DELAY is now forwarded to the manager."/>
		<Dokumentation Revision="1.72" Date="15.06.2022" Author="RamAnd" Company="Sigmatek" Description="Added new Server HardwareVersion to show the hardware version of the VARAN type label."/>
		<Dokumentation Revision="1.71" Date="03.02.2021" Author="EisMic" Company="Sigmatek" Description="Added support for BC032."/>
		<Dokumentation Revision="1.70" Date="09.02.2021" Author="PieSte" Company="Sigmatek" Description="Add support for adding data objects later to DO list."/>
		<Dokumentation Revision="1.69" Date="27.11.2020" Author="FurDom" Company="Sigmatek" Description="The newinst commando CMD_HWC_REQ_PLLNS_REGULATION is now be forwared to the HwControl."/>
		<Dokumentation Revision="1.68" Date="07.04.2020" Author="EisMic" Company="Sigmatek" Description="Changed comment of client &quot;UserAction&quot; in Varan_Base class."/>
		<Dokumentation Revision="1.67" Date="09.12.2019" Author="LanSte" Company="Sigmatek" Description="Added Server ProtocolVersion. InterframeGap is included in the resource calculation.&#13;&#10;Changed Transparent.Read() to IsTransparent(). (_BUS_IF_GET_DEACTIVATED_STATE is called in 1st init by other classes.)"/>
		<Dokumentation Revision="1.66" Date="23.08.2018" Author="ZoePat" Company="Sigmatek" Description="Corrected error in setting the divided sync. It was set from an uninitialized stack variable. Feature was not in used, corrected for further developments."/>
		<Dokumentation Revision="1.65" Date="02.07.2018" Author="RamAnd" Company="Sigmatek" Description="Corrected logging function which could have led to an incorrect log message because of an uninitialized string."/>
		<Dokumentation Revision="1.64" Date="11.04.2018" Author="EisMic" Company="Sigmatek" Description="Added support for multivaran."/>
		<Dokumentation Revision="1.63" Date="06.03.2018" Author="EisMic" Company="Sigmatek" Description="Attached header files no longer point to the installation directory of LASAL but instead now point to the the source/interfaces folder."/>
		<Dokumentation Revision="1.62" Date="23.01.2018" Author="RamAnd" 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."/>
		<Dokumentation Revision="1.61" Date="06.02.2017" Author="HaeTho&#13;&#10;&#13;&#10;ZoePat" Company="Sigmatek" Description="All Operations which where done until now on Online-Server are now done on Variable bOnline.&#13;&#10;Server Online is now set an begin of state &apos;Operational&apos; in function UpdateRT().&#13;&#10;SdiasModules can now request to increase the PostInit timeout."/>
		<Dokumentation Revision="1.60" Date="10.01.2017" Author="PieSte" Company="Sigmatek" Description="Corrected handover value for length at &quot;ChangeDOLengthOffset()&quot; method in &quot;UpdateDO()&quot; method call of payload path."/>
		<Dokumentation Revision="1.59" Date="10.05.2016" Author="RamAnd" Company="Sigmatek" Description="Suppressed warning that would occur with target ARM on compiler version 30 or higher."/>
		<Dokumentation Revision="1.58" Date="17.02.2016" Author="EisMic" Company="Sigmatek" Description="Prescalersettings were not set correctly when Payload is active."/>
		<Dokumentation Revision="1.57" Date="26.01.2016" Author="EisMic" Company="Sigmatek" Description="Return Transparent.Read() in NewInst _BUS_IF_GET_DEACTIVATED_STATE to prevent an access exception."/>
		<Dokumentation Revision="1.56" Date="12.06.2015" Author="PieSte" Company="Sigmatek" Description="Add newinst command to call method DisableDevice() and EnableDevice() to avoid retrys when disconnected."/>
		<Dokumentation Revision="1.55" Date="26.05.2015" Author="EisMic" Company="Sigmatek" Description="Corrected step CMD_GET_HARDWARE_TREE_ENTRY in NewInst due to problems with the Typelabel SCL."/>
		<Dokumentation Revision="1.54" Date="15.04.2015" Author="RamAnd" Company="Sigmatek" Description="Added another step in initialisation to prevent watchdog error."/>
		<Dokumentation Revision="1.53" Date="13.04.2015&#13;&#10;09.04.2015" Author="RamAnd&#13;&#10;PieSte" Company="Sigmatek" Description="Added support for Edge2 cpu.&#13;&#10;Changes for new varan drive hardware SDD1000."/>
		<Dokumentation Revision="1.52" Date="24.03.2015" Author="RamAnd" Company="Sigmatek" Description="Check pointer p_NodeInfo for validity in method GetRetryTimeout due to access exception error if method Varan_HWDisconnect is called and no hardware was available."/>
		<Dokumentation Revision="1.51" Date="24.01.2015" Author="RamAnd" Company="Sigmatek" Description="Long-DOs are not handled differently with payload support now (is not neccessary and resulted in a crash)"/>
		<Dokumentation Revision="1.50" Date="06.11.2014" Author="LanSte" Company="Sigmatek" Description="Implemented new Interface to set and get the ClassState. "/>
		<Dokumentation Revision="1.49" Date="24.06.2014" Author="EisMic" Company="Sigmatek" Description="Added support for reading hardware diagnosis and hardwaretree entry."/>
		<Dokumentation Revision="1.48" Date="24.06.2014" Author="PieSte" Company="Sigmatek" Description="Add request of UserAction Client to avoid crash if it returns zero."/>
		<Dokumentation Revision="1.47" Date="04.06.2014" Author="RamAnd" Company="Sigmatek" Description="The CreateMutex-Command now also returns the pointer to the multitask API. This saves CIL_Get calls (boot time) in other classes."/>
		<Dokumentation Revision="1.46" Date="05.05.2014" Author="LanSte" Company="Sigmatek" Description="Minimized the interface request via CILGET by useing private pointers to reduce time in init."/>
		<Dokumentation Revision="1.45" Date="18.04.2014" Author="LanSte" Company="Sigmatek" Description="Added Check for Varancallback before adding DOs."/>
		<Dokumentation Revision="1.44" Date="31.03.2014" Author="LanSte" Company="Sigmatek" Description="AddDO method: Return the sd_retval if the call to AddDO fails."/>
		<Dokumentation Revision="1.43" Date="25.02.2014" Author="LanSte" Company="Sigmatek" Description="Added Interface to Log error Messages."/>
		<Dokumentation Revision="1.42" Date="14.04.2014" Author="RamAnd" Company="Sigmatek" Description="Added new Interface Varan_HwSubBusReady which is called by OS as soon as it has finished enumerating the connected devices on available subbusses."/>
		<Dokumentation Revision="1.41" Date="10.04.2014" Author="RamAnd" Company="Sigmatek" Description="Error trace messages are now also stored in the event log file."/>
		<Dokumentation Revision="1.40" Date="22.01.2014" Author="RamAnd&#13;&#10;RamAnd&#13;&#10;RamAnd" Company="Sigmatek" Description="Initialisation of VaranManager and SdiasManager has been reworked for cases where multiple Safety cpus are connected via VI021.&#13;&#10;Added command to get required setting.&#13;&#10;Added parameter for Post Init login to define if DOs via VARAN are necessary."/>
		<Dokumentation Revision="1.30" Date="05.12.2013" Author="RamAnd&#13;&#10;RamAnd&#13;&#10;RamAnd&#13;&#10;LanSte" Company="Sigmatek" Description="Check if the module is online, before doing anything in realtime or cyclic.&#13;&#10;DOs can now be copied internally if there is no DMA available.&#13;&#10;Retrytimeout is now properly calculated for LongDOs.&#13;&#10;Added support for Move-Command."/>
		<Dokumentation Revision="1.20" Date="30.08.2013" Author="RamAnd" Company="Sigmatek" Description="Moved callback installation from 2nd to 4th initialisation (needed for deeper hierarchy of modules)"/>
		<Dokumentation Revision="1.10" Date="01.08.2013" Author="LanSte&#13;&#10;RamAnd" Company="Sigmatek" Description="Added Payload Support Direct Accesses and GetLongDOsPossible.&#13;&#10;Now a required error works also in the first init."/>
		<Dokumentation Revision="1.0" Date="18.07.2013" Author="RamAnd" Company="Sigmatek" Description="First library version"/>
	</RevDoku>
	<Network Name="BusInterfaceVARAN">
		<!-- List of Components in this network -->
		<Components>
			<Object
				Name       = "_base"
				GUID       = "{059D45DC-B9D1-4D6D-ADF0-FFF05DD71A89}"
				Class      = "Varan_Base"
				Position   = "(218,120)"
				Visualized = "true">
				<Channels>
					<Server Name="ConnectCounter"/>
					<Server Name="DeviceAddress"/>
					<Server Name="DeviceID"/>
					<Server Name="DiagControl"/>
					<Server Name="FaultCounter"/>
					<Server Name="HardwareVersion"/>
					<Server Name="Online"/>
					<Server Name="ProtocolVersion"/>
					<Server Name="Release"/>
					<Server Name="RetryCounter"/>
					<Server Name="RXLost"/>
					<Server Name="SerialNo"/>
					<Server Name="State"/>
					<Server Name="TXLost"/>
					<Server Name="ValidateSerNo"/>
					<Server Name="VendorID"/>
					<Client Name="Required"/>
					<Client Name="SerNoValidation"/>
					<Client Name="TimeBase" Value="0"/>
					<Client Name="TimeBaseOffset" Value="0"/>
					<Client Name="To_MultiTask"/>
					<Client Name="To_StdLib"/>
					<Client Name="Transparent" Value="0"/>
					<Client Name="UserAction"/>
					<Client Name="VaranIn"/>
				</Channels>
			</Object>
		</Components>
		<Comments>
		</Comments>
		<!-- List of Connections in this network -->
		<Connections>
			<Connection Source="this.State" Destination="_base.State" Vertices="(874,210),(702,210),"/>
			<Connection Source="this.Online" Destination="_base.Online" Vertices="(874,270),(702,270),"/>
			<Connection Source="this.Release" Destination="_base.Release" Vertices="(874,330),(702,330),"/>
			<Connection Source="this.DeviceAddress" Destination="_base.DeviceAddress" Vertices="(874,450),(702,450),"/>
			<Connection Source="this.VendorID" Destination="_base.VendorID" Vertices="(874,510),(702,510),"/>
			<Connection Source="this.DeviceID" Destination="_base.DeviceID" Vertices="(874,570),(702,570),"/>
			<Connection Source="this.SerialNo" Destination="_base.SerialNo" Vertices="(874,630),(702,630),"/>
			<Connection Source="this.RetryCounter" Destination="_base.RetryCounter" Vertices="(874,690),(702,690),"/>
			<Connection Source="this.ValidateSerNo" Destination="_base.ValidateSerNo" Vertices="(874,750),(702,750),"/>
			<Connection Source="this.DiagControl" Destination="_base.DiagControl" Vertices="(874,810),(702,810),"/>
			<Connection Source="this.ConnectCounter" Destination="_base.ConnectCounter" Vertices="(874,870),(702,870),"/>
			<Connection Source="this.FaultCounter" Destination="_base.FaultCounter" Vertices="(874,930),(702,930),"/>
			<Connection Source="this.RXLost" Destination="_base.RXLost" Vertices="(874,990),(702,990),"/>
			<Connection Source="this.TXLost" Destination="_base.TXLost" Vertices="(874,1050),(702,1050),"/>
			<Connection Source="_base.VaranIn" Destination="this.VaranIn" Vertices="(218,210),(38,210),"/>
			<Connection Source="_base.Required" Destination="this.Required" Vertices="(218,270),(38,270),"/>
			<Connection Source="_base.Transparent" Destination="this.Transparent" Vertices="(218,450),(38,450),"/>
			<Connection Source="_base.SerNoValidation" Destination="this.SerNoValidation" Vertices="(218,390),(38,390),"/>
			<Connection Source="_base.UserAction" Destination="this.UserAction" Vertices="(218,330),(38,330),"/>
			<Connection Source="this.ProtocolVersion" Destination="_base.ProtocolVersion" Vertices="(874,1110),(702,1110),"/>
			<Connection Source="this.HardwareVersion" Destination="_base.HardwareVersion" Vertices="(874,390),(702,390),"/>
		</Connections>
		<!-- Headerfiles -->
		<Options>
		</Options>
	</Network>
</Class>
*)
#pragma using Varan_Base

BusInterfaceVARAN : CLASS
: Varan_Base
	TYPE
	  t_AsyDOUsage :
	  (
	    _NotUsed:=0,
	    _UsedBySSW:=1,
	    _UsedBySDO:=2,
	    _UsedByLED:=3,
	    _UsedByWD:=4
	  )$USINT;
#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)
#pragma pack(push, 1)
	  t_LocalMemList : STRUCT
	    pSource : pVoid;
	    pDest : pVoid;
	    Length : UINT;
	  END_STRUCT;
#pragma pack(pop)
#pragma pack(push, 1)
	  t_PayloadAccess : STRUCT
	    Handle : UDINT;
	    AccessHandle : UDINT;
	    pData : pVoid;
	    pDataDPRAM : pVoid;
	    Offset : HINT;
	    Length : UINT;
	  END_STRUCT;
#pragma pack(pop)
	  t_SdiasManagerInitSSW :
	  (
	    _StartInit,
	    _InitAccesses,
	    _CallHwConnect,
	    _ModuleInitialisation,
	    _FinishInitialisation,
	    _InitFinished,
	    _PrepareError,
	    _ErrorOccured
	  )$UDINT;
	  t_SdiasManagerRtSSW :
	  (
	    _RtIdle,
	    _CreateAndModifyDOs,
	    _Wait4DOs,
	    _Wait4PllSync,
	    _Wait2Ticks,
	    _CntDownSyncStart,
	    _PreOperationalWait4DataReady,
	    _PreOperational,
	    _Operational
	  )$UDINT;
#pragma pack(push, 1)
	  t_SDORingBufEntry : STRUCT
	    pCallBackSvr : ^SvrChCmd;
	    Command : HINT;
	    pWriteData : ^void;
	    udLength : UDINT;
	    udOffset : UDINT;
	    udState : UDINT;
	  END_STRUCT;
#pragma pack(pop)
#pragma pack(push, 1)
	  t_SDOHandling : STRUCT
	    pRingBufMemStart : ^t_SDORingBufEntry;
	    pLastEntry : ^t_SDORingBufEntry;
	    pActEntry : ^t_SDORingBufEntry;
	    pWrite : ^t_SDORingBufEntry;
	    RingBufSize : UDINT;
	    EntriesUsed : UDINT;
	    OffsetSDOReq : HINT;
	    OffsetSDOResp : HINT;
	    udRequestTime : UDINT;
	    WaitForResponse : DINT;
	  END_STRUCT;
#pragma pack(pop)
#pragma pack(push, 1)
	  t_TASK_PRESCALER : STRUCT
	    Cnt : USINT;
	    CntCy : USINT;
	    MaxCnt : USINT;
	    RtPreScanTigger : USINT;
	    RtPostScanTrigger : USINT;
	    CyTrigger : USINT;
	  END_STRUCT;
#pragma pack(pop)
	END_TYPE
  //Servers:
	CallCommand 	: SvrChCmd_DINT;
  //Clients:
	ToOSKernel 	: CltChCmd__OSKernel;
  //Variables:
		us_Firstscan 	: USINT;
		p_UserCalls 	: t_CALLBACK_POINTERS;
		NrDO 	: USINT;			//! <Variable Comment="Nr of Data Objects in DO_list" Name="NrDO"/>
		DOList : ARRAY [0..BUSIF_VARAN_MAX_NR_DO-1] OF t_DOCfg;

		NrDOMove 	: USINT;			//! <Variable Comment="Nr of Data Objects in Move DO_list" Name="NrDOMove"/>
		DOListMove : ARRAY [0..BUSIF_VARAN_MAX_NR_MOVEDO-1] OF t_DOMoveCfg;

		SyncOffset 	: DINT;
		udVaranTime 	: UDINT;
		udIsoStartPoint 	: UDINT;
		ExtSetOnline 	: BOOL;			//! <Variable Comment="When this flag is set, the Server &quot;Online&quot; is set via external commands. &#13;&#10;Online is always turned off on HW Disconnect&#13;&#10;Otherwise a default is used for the server. (Set when HW Connect was Successful)&#13;&#10;This flag is set when external set command comes and cannot be reset." Name="ExtSetOnline"/>
		TaskPrescaler 	: t_TASK_PRESCALER;
		FirstRT 	: BOOL;
		SyncData : ARRAY [0..3] OF t_SyncData;

		bSetPll 	: DINT;
		pv_Mutex 	: pVoid;
		pv_MutexSDOs 	: pVoid;
		b_LongDOsPossible 	: BOOL;
		b_CallBackInstalled 	: BOOL;
		LocalRdCopyNo 	: USINT;
		apLocalRdCopyDOs : ARRAY [0..BUSIF_VARAN_MAX_NR_DO-1] OF t_LocalMemList;

		LocalWrCopyNo 	: USINT;
		apLocalWrCopyDOs : ARRAY [0..BUSIF_VARAN_MAX_NR_DO-1] OF t_LocalMemList;

		ui_PostInitIndex 	: UINT;
		us_SkippedWriteBlocks 	: USINT;
		us_PLLDivider 	: USINT;
		DeviceIDDiagnosis 	: UDINT;
		bAddDOsToListSupport 	: BOOL;
		bSimulateSDIASManager 	: BOOL;
		eSdiasManagerInitSSW 	: t_SdiasManagerInitSSW;
		eSdiasManagerRTSSW 	: t_SdiasManagerRtSSW;
		SDOHandling 	: t_SDOHandling;
		AsyCtrlReadDO 	: t_PayloadAccess;
		AsyMemReadDO 	: t_PayloadAccess;
		AsyCtrlWriteDO 	: t_PayloadAccess;
		AsyMemWriteDO 	: t_PayloadAccess;
		b_PostInitFinished 	: BOOL;
		eErrorInitStep 	: t_SdiasManagerInitSSW;
		bSendRtSyncReady 	: BOOL;
		InitStartTime 	: UDINT;
		bCallHwConnectInRT 	: BOOL;
  //Functions:
				//! <Function Comment="Init for Varan Client" Name="Init"/>
	FUNCTION VIRTUAL GLOBAL Init;
	
	FUNCTION BusInterfaceVARAN
		VAR_OUTPUT
			ret_code 	: ConfStates;
		END_VAR;
				//! <Function Comment="Cy - Funktion of Varan class ( called bei VaranMaster )" Name="UpdateCy"/>
	FUNCTION VIRTUAL GLOBAL UpdateCy;
				//! <Function Comment="Rt - Funktion of Varan class ( called bei VaranMaster )" Name="UpdateRt"/>
	FUNCTION VIRTUAL GLOBAL UpdateRt;
				//! <Function Comment="Function is called by VaranRtPostScan if used" Name="UpdateRtPostScan"/>
	FUNCTION VIRTUAL GLOBAL UpdateRtPostScan;
				//! <Function Comment="Function is called if a varan module is connected&#13;&#10;" Name="Varan_HwConnect"/>
	FUNCTION AWL VIRTUAL GLOBAL Varan_HwConnect
		VAR_INPUT
			ud_data 	: UDINT;			//! <Variable Comment="data of callback function" Name="Varan_HwConnect.ud_data"/>
		END_VAR
		VAR_OUTPUT
			sd_retval 	: DINT;			//! <Variable Comment="return value of OS" Name="Varan_HwConnect.sd_retval"/>
		END_VAR;
				//! <Function Comment="Function is called if a varan interrupt occures" Name="Varan_HwInterrupt"/>
	FUNCTION VIRTUAL GLOBAL Varan_HwInterrupt
		VAR_INPUT
			ud_reason 	: UDINT;
			ud_data 	: ^t_CallBackInterrupt;
		END_VAR
		VAR_OUTPUT
			sd_retval 	: DINT;
		END_VAR;
				//! <Function Comment="Function is called if a varan module is disconnected&#13;&#10;" Name="Varan_HwDisconnect"/>
	FUNCTION AWL VIRTUAL GLOBAL Varan_HwDisconnect
		VAR_INPUT
			ud_data 	: UDINT;
		END_VAR
		VAR_OUTPUT
			sd_retval 	: DINT;
		END_VAR;
	
	FUNCTION VIRTUAL GLOBAL Varan_HwSubBusReady
		VAR_INPUT
			ud_data 	: UDINT;
		END_VAR
		VAR_OUTPUT
			sd_retval 	: DINT;
		END_VAR;
				//! <Function Comment="Function to set all Data Objects off" Name="SetDOsOff"/>
	FUNCTION VIRTUAL GLOBAL SetDOsOff;
				//! <Function Comment="Function to update module retry counter" Name="UpdateRetryCounter"/>
	FUNCTION VIRTUAL GLOBAL UpdateRetryCounter;
				//! <Function Comment="Check if DeviceID is supported by class" Name="CheckDeviceID"/>
	FUNCTION VIRTUAL GLOBAL CheckDeviceID
		VAR_INPUT
			ID2Check 	: UDINT;			//! <Variable Comment="VARAN DeviceID, which should be checked" Name="CheckDeviceID.ID2Check"/>
		END_VAR
		VAR_OUTPUT
			IsOK 	: BOOL;			//! <Variable Comment="TRUE...DeviceID is ok with this class&#13;&#10;FALSE..DeviceID is not ok with this class" Name="CheckDeviceID.IsOK"/>
		END_VAR;
				//! <Function Comment="Install callback function&#13;&#10;&#13;&#10;Overload the method if the derived class needs its own Callback Method. See VDM085, VDM086 for example." Name="InstallCallbackObject"/>
	FUNCTION VIRTUAL InstallCallbackObject
		VAR_OUTPUT
			sd_retval 	: DINT;
		END_VAR;
	
	FUNCTION VIRTUAL GLOBAL GetDeviceID
		VAR_OUTPUT
			output 	: UDINT;
		END_VAR;
	
	FUNCTION VIRTUAL GLOBAL AddDO
		VAR_INPUT
			pCmd 	: ^CmdStruct;
			presult 	: ^results;
			bCtrlAcc 	: BOOL := false;
		END_VAR;
	
	FUNCTION VIRTUAL GLOBAL UpdateDO
		VAR_INPUT
			pCmd 	: ^CmdStruct;
			presult 	: ^results;
		END_VAR;
	
	FUNCTION VIRTUAL GLOBAL AddTask
		VAR_INPUT
			pCmd 	: ^CmdStruct;
			presult 	: ^results;
		END_VAR;
	
	FUNCTION VIRTUAL GLOBAL SetRunState
		VAR_INPUT
			pCmd 	: ^CmdStruct;
			presult 	: ^results;
		END_VAR;
				//! <Function Comment="Sets the pointer to the operator class.&#13;&#10;This pointer must be set in the init phase. &#13;&#10;The passed pointer is used to call functions in the operator class via NewInst.&#13;&#10;Examples: HwConnect, CheckDeviceID ..." Name="SetOperatorClass"/>
	FUNCTION VIRTUAL GLOBAL SetOperatorClass
		VAR_INPUT
			pOperator 	: pVirtualBase;
		END_VAR
		VAR_OUTPUT
			sd_retval 	: DINT;			//! <Variable Comment="0 .. ok&#13;&#10;1 .. 0 pointer was passed" Name="SetOperatorClass.sd_retval"/>
		END_VAR;
	
	FUNCTION VIRTUAL CheckHandle
		VAR_INPUT
			Handle 	: UDINT;			//! <Variable Comment="Checks if the passed Handle is valid" Name="CheckHandle.Handle"/>
		END_VAR
		VAR_OUTPUT
			IsOk 	: BOOL;
		END_VAR;
	
	FUNCTION VIRTUAL GLOBAL ResetDO
		VAR_INPUT
			pCmd 	: ^CmdStruct;
			presult 	: ^results;
		END_VAR;
	
	FUNCTION VIRTUAL GLOBAL SetDOPrescaler
		VAR_INPUT
			pCmd 	: ^CmdStruct;
			presult 	: ^results;
		END_VAR;
	
	FUNCTION VIRTUAL GLOBAL SetSyncData
		VAR_INPUT
			pCmd 	: ^CmdStruct;
			presult 	: ^results;
		END_VAR;
	
	FUNCTION VIRTUAL GLOBAL SetTasksPrescaler
		VAR_INPUT
			pCmd 	: ^CmdStruct;
			presult 	: ^results;
		END_VAR;
	
	FUNCTION VIRTUAL LogErrorExt
		VAR_INPUT
			e_msg 	: ^CHAR;
			p_extThis1 	: pVirtualBase := nil;
			p_extThis2 	: pVirtualBase := nil;
		END_VAR;
	
	FUNCTION VIRTUAL GetLongDOsPossible
		VAR_OUTPUT
			LongDOsPossible 	: BOOL;
		END_VAR;
	
	FUNCTION VIRTUAL GLOBAL AddMoveDO
		VAR_INPUT
			pCmd 	: ^CmdStruct;
			presult 	: ^results;
		END_VAR;
	
	FUNCTION VIRTUAL CheckMovHandle
		VAR_INPUT
			Handle 	: UDINT;
		END_VAR
		VAR_OUTPUT
			IsOk 	: BOOL;
		END_VAR;
	
	FUNCTION VIRTUAL AddSDORequest
		VAR_INPUT
			pCmdSvr 	: ^SvrChCmd;
			Command 	: HINT;
			Offset 	: UDINT;
			Length 	: UDINT;
			pWriteBuf 	: ^void;
		END_VAR
		VAR_OUTPUT
			sd_retval 	: DINT;
		END_VAR;
	
	FUNCTION VIRTUAL GLOBAL UpdateMoveDO
		VAR_INPUT
			pCmd 	: ^CmdStruct;
			presult 	: ^results;
		END_VAR;
	
	FUNCTION VIRTUAL GLOBAL GetPayloadSupportState
		VAR_OUTPUT
			dRetCode 	: DINT;
		END_VAR;
	
	FUNCTION VIRTUAL CyclicSDOHandling;
	
	FUNCTION VIRTUAL ChangeAsyRd
		VAR_INPUT
			Offset 	: HINT;
			Length 	: USINT;
			RunState 	: t_BusIFRunState;
			bIsCtrlACC 	: BOOL;
		END_VAR
		VAR_OUTPUT
			Success 	: BOOL;
		END_VAR;
	
	FUNCTION VIRTUAL ChangeAsyWr
		VAR_INPUT
			Offset 	: HINT;
			Length 	: USINT;
			RunState 	: t_BusIFRunState;
			bIsCtrlACC 	: BOOL;
		END_VAR
		VAR_OUTPUT
			Success 	: BOOL;
		END_VAR;
	
	FUNCTION VIRTUAL SendPostInitFinished
		VAR_INPUT
			DisableThisObject 	: BOOL := FALSE;
		END_VAR;
	
	FUNCTION VIRTUAL SimulateSDIASManagerCywork;
	
	FUNCTION VIRTUAL SimulateSDIASManagerRtwork;
	
	FUNCTION VIRTUAL SetRequiredError;
	
	FUNCTION VIRTUAL GLOBAL State::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;

#pragma usingLtd _OSKernel


//}}LSL_DECLARATION


FUNCTION GLOBAL TAB BusInterfaceVARAN::@CT_
0$UINT,
2#0100000000000000$UINT, //TY_BUSINTERFACEVARAN
1$UINT, 75$UINT, (SIZEOF(::BusInterfaceVARAN))$UINT, 
1$UINT, 1$UINT, 0$UINT, 
TO_UDINT(24783181), "BusInterfaceVARAN", //Class
TO_UDINT(862125188), "Varan_Base", 2$UINT, 21$UINT, //Baseclass
//Servers:
(::BusInterfaceVARAN.CallCommand.pMeth)$UINT, _CH_CMD$UINT, 2#0000000000000000$UINT, TO_UDINT(1059212957), "CallCommand", 
//Clients:
(::BusInterfaceVARAN.ToOSKernel.pCh)$UINT, _CH_CLT_OBJ$UINT, 2#0000000000000000$UINT, TO_UDINT(2889244023), "ToOSKernel", TO_UDINT(3045737964), "_OSKernel", 0$UINT, 5$UINT, 
END_FUNCTION


#define USER_CNT_BusInterfaceVARAN 73

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

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

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

	_memcpy((#vmt.CmdTable)$^USINT, Varan_Base::State.pMeth, nCmdSize);
	vmt.CmdTable.nCmds		:= nSTDCMD + USER_CNT_BusInterfaceVARAN;
	vmt.CmdTable.NewInstr		:= #State::NewInst();
	vmt.CmdTable.Init		:= #Init();
#pragma warning (disable : 74)
	vmt.UserFcts[0]		:= #UpdateCy();

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	IF Varan_Base::State.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	:= BusInterfaceVARAN();

END_FUNCTION

//{{LSL_IMPLEMENTATION
#include <lsl_st_kernel.h>

FUNCTION VIRTUAL GLOBAL BusInterfaceVARAN::Init
  VAR
    sd_retval		: DINT;
    dataADDDO       : t_AddDOCfg;        
  	tempCmd           : CmdStruct;
    _result           : results;    
  END_VAR

#ifdef IsTransparent_IS_AVAILABLE
  IF IsTransparent() THEN
    return;
  END_IF;
#endif

  us_Firstscan += 1;

  	//in first init phase
	if ( us_Firstscan = 1 ) then  

		//-----------------------------------------------------------------------------------------------
    
    // Set FirstRT flag, will be reset on first RT Callback
    FirstRT := true;
        
		//init the base class
		Varan_Base::Init();

		//if an error in base class occurs return
		if ( State <> _NotInitialized ) then
			return;
		end_if;
    
    //--- Calculate SyncOffset
    udVaranTime := VaranIn.GetVaranTime(p_ud_IsoStartPoint:=#udIsoStartPoint);   
    SyncOffset  := (udVaranTime - udIsoStartPoint)$DINT / 10;

    // install mutex for manipulating DOs (could be done from different tasks at the same time)
    pv_Mutex := CreateMutex("ManipulateDOs");
    if pv_Mutex = NIL then
      LogError("@018C (BusInterfaceVARAN::Init) Failed to create Mutex for manipulating DOs");
    end_if;
        
    //Reset Flag
    bAddDOsToListSupport := FALSE;    
    
    //bAddDosToListSupport Flag:
    //Install the isochrone dataobjects in cywork and not in the realtime task, due to the high realtime load in the first rt cycles.
    //The dataobjects are only installed an not added to the DOL in the os with the mask VARAN_DOL_NOT_INSERT_DO_INTO_DOL.
    //With the new os-function MULTI_VARAN_IINSERTDOINTODOL the Dataobjects are now added to the DOL List in the Os.
    //pMultiVaran-Interfaceversion must be equal or higher than 16#1003
    
    //Check interface version
    if b_PayloadSupport then
      if pMultiVaran then
        if pMultiVaran^.udVersion >= VM_MULTIVARAN_ADD_DO_INTO_DOL then
        // We have the new interface, set flag to remember it later
          bAddDOsToListSupport := TRUE;
        end_if;
      end_if;
    end_if;

  // In 4th init phase
  elsif us_Firstscan = 4 then
    // install callback here, because in the first init the operator may set this object required
    sd_retval := VaranIn.SetObjectCallback( p_us_position_info  := p_VaranPosition
                                          , ud_action_ptr       := ( #Varan_CallBack() )$UDINT
                                          , ud_thisp            := this$UDINT
                                          , sd_required         := Required
                                          );

    if sd_retval = VARANMANAGER_OK then
      b_CallBackInstalled := TRUE;
    end_if;

  
  elsif us_Firstscan = 7 then
  
    if bSimulateSDIASManager then
    
      // install mutex for manipulating DOs (could be done from different tasks at the same time)
      pv_MutexSDOs := CreateMutex("ADDSDOs_BusIfVaran");
      if pv_MutexSDOs = NIL then
        LogError("@018C (BusInterfaceVARAN::Init) Failed to create Mutex for adding SDOs");
      end_if;  

      // allocate memory for the SDO ringbuffer and initialize the pointers
      SDOHandling.pRingBufMemStart$^void := To_StdLib.Malloc(size:=BUSIF_VARAN_MAX_SDO * sizeof(t_SDORingBufEntry));
      if SDOHandling.pRingBufMemStart then
        SDOHandling.RingBufSize := BUSIF_VARAN_MAX_SDO * sizeof(t_SDORingBufEntry);
        _memset(dest:=SDOHandling.pRingBufMemStart, usByte:=0, cntr:=SDOHandling.RingBufSize);
        SDOHandling.pActEntry := SDOHandling.pWrite := SDOHandling.pRingBufMemStart;
        
        SDOHandling.pLastEntry := SDOHandling.pRingBufMemStart + (BUSIF_VARAN_MAX_SDO-1) * sizeof(t_SDORingBufEntry);
      else
        LogError("@002C (BusInterfaceVARAN::Init) Failed to allocate memory for the SDO Ringbuffer");
        State := _NoMem;
      end_if;
      
      // DO for ASY MEM Read
      dataADDDO.Priority            := _BUS_IF_ASY;
      dataADDDO.RdWr                := _BUS_IF_READ;
      dataADDDO.ud_addressoff_read  := 0;
      dataADDDO.ui_length_read      := 128;
      dataADDDO.b_UseLocalCopy      := FALSE;

      tempCmd.uiCmd     := _BUS_IF_ADD_DO;
      tempCmd.aPara[0]  := (#dataADDDO)$DINT;
      
      CallCommand.NewInst(pPara:=#tempCmd, pResult:=#_result);
      
      if _result.aData[0]$t_BusIFRetvalErrorcode = _BUS_IF_RETVAL_OK then
        AsyMemReadDO.Handle        := _result.aData$t_AddDORet.Handle;
        AsyMemReadDO.pData         := _result.aData$t_AddDORet.pDataRead;
        AsyMemReadDO.AccessHandle  := _result.aData$t_AddDORet.AccessHandle;
      else
        LogError("@0036 (BusInterfaceVARAN::Init) Failed to add DO for the asynchronous memory read data");
        State := _CreateDOFailed;
      end_if;
      
      
      // DO for ASY CTRL Read
      dataADDDO.Priority            := _BUS_IF_ASY;
      dataADDDO.RdWr                := _BUS_IF_READ;
      dataADDDO.ud_addressoff_read  := 0;
      dataADDDO.ui_length_read      := 128;
      dataADDDO.b_UseLocalCopy      := FALSE;

      tempCmd.uiCmd     := _BUS_IF_ADD_CTRL_DO;
      tempCmd.aPara[0]  := (#dataADDDO)$DINT;
      
      CallCommand.NewInst(pPara:=#tempCmd, pResult:=#_result);
      
      if _result.aData[0]$t_BusIFRetvalErrorcode = _BUS_IF_RETVAL_OK then
        AsyCtrlReadDO.Handle        := _result.aData$t_AddDORet.Handle;
        AsyCtrlReadDO.pData         := _result.aData$t_AddDORet.pDataRead;
        AsyCtrlReadDO.AccessHandle  := _result.aData$t_AddDORet.AccessHandle;
      else
        LogError("@0036 (BusInterfaceVARAN::Init) Failed to add DO for the asynchronous control read data");
        State := _CreateDOFailed;
      end_if;      
      
      // DO for ASY MEM write
      dataADDDO.Priority            := _BUS_IF_ASY;
      dataADDDO.RdWr                := _BUS_IF_WRITE;
      dataADDDO.ud_addressoff_write := 0;
      dataADDDO.ui_length_write     := 128;
      dataADDDO.b_UseLocalCopy      := FALSE;

      tempCmd.uiCmd     := _BUS_IF_ADD_DO;
      tempCmd.aPara[0]  := (#dataADDDO)$DINT;
      
      CallCommand.NewInst(pPara:=#tempCmd, pResult:=#_result);
      
      if _result.aData[0]$t_BusIFRetvalErrorcode = _BUS_IF_RETVAL_OK then
        AsyMemWriteDO.Handle        := _result.aData$t_AddDORet.Handle;
        AsyMemWriteDO.pData         := _result.aData$t_AddDORet.pDataWrite;
        AsyMemWriteDO.AccessHandle  := _result.aData$t_AddDORet.AccessHandle;
      else
        LogError("@0036 (BusInterfaceVARAN::Init) Failed to add DO for the asynchronous memory write data");
        State := _CreateDOFailed;
      end_if;
      
      
      // DO for ASY CTRL write
      dataADDDO.Priority            := _BUS_IF_ASY;
      dataADDDO.RdWr                := _BUS_IF_WRITE;
      dataADDDO.ud_addressoff_write := 0;
      dataADDDO.ui_length_write     := 128;
      dataADDDO.b_UseLocalCopy      := FALSE;

      tempCmd.uiCmd     := _BUS_IF_ADD_CTRL_DO;
      tempCmd.aPara[0]  := (#dataADDDO)$DINT;
      
      CallCommand.NewInst(pPara:=#tempCmd, pResult:=#_result);
      
      if _result.aData[0]$t_BusIFRetvalErrorcode = _BUS_IF_RETVAL_OK then
        AsyCtrlWriteDO.Handle        := _result.aData$t_AddDORet.Handle;
        AsyCtrlWriteDO.pData         := _result.aData$t_AddDORet.pDataWrite;
        AsyCtrlWriteDO.AccessHandle  := _result.aData$t_AddDORet.AccessHandle;
      else
        LogError("@0036 (BusInterfaceVARAN::Init) Failed to add DO for the asynchronous control write data");
        State := _CreateDOFailed;
      end_if;   
      
    end_if;

  // In last init phase
  elsif us_Firstscan = 11 then

    //-----------------------------------------------------------------------------------------------
    //call connect hardware function
    sd_retval := Varan_CallBack	( ud_reason	:= VARANMANAGER_CB_CONNECT
                                , ud_data	  := 0
                                );

    //produce Varan Error if module not ok
    if ( sd_retval <> VARANMANAGER_OK ) then
      VaranIn.SetVaranError( p_Node := p_VaranPosition );
    end_if;
  end_if;

END_FUNCTION


FUNCTION VIRTUAL GLOBAL BusInterfaceVARAN::Varan_HwConnect
	VAR_INPUT
		ud_data 	  : UDINT;
	END_VAR
	VAR_OUTPUT
		sd_retval   : DINT;
	END_VAR
  VAR
  	tempCmd     : CmdStruct;
    _result     : results;
    i           : USINT;
    Settings    : BSINT;
  END_VAR    
  
  sd_retval     := GetNodeInfo();
  
  // look for an error
	if ( sd_retval <> VARANMANAGER_OK ) then
	  return;
	end_if;  
  
  // We must wait because peripherie reset needs 15ms
	To_MultiTask.TASKDELAY( timeout0 := 15ms );	
  
  if bSetPll then
    // Start PLL, initvalue for pll divider is 0
    sd_retval := SetNewPllData(us_divider:=us_PLLDivider);
    
    //look for an error
    if ( sd_retval <> VARANMANAGER_OK ) then
      return;
    end_if;
    
    // enable syncs ---------------------------------------------
    for i :=0 to 3 do
      if SyncData[i].us_sync_nr <> 16#FF then
        
        sd_retval := EnableSyncOut( us_sync_nr              := SyncData[i].us_sync_nr,
                                    sd_offset               := SyncData[i].sd_offset,
                                    us_period_multiplier    := SyncData[i].us_period_multiplier, 
                                    us_frame_count_treshold := SyncData[i].us_frame_count_threshold, 
                                    us_enable_frame_count   := SyncData[i].us_enable_frame_count,
                                    b_use_divider_sync      := SyncData[i].b_use_divider_sync);
      
        //look for an error
        if ( sd_retval <> VARANMANAGER_OK ) then
          return;
        end_if;
      
      end_if;
    end_for;                  
  end_if;
  
  // Check for 0 pointer
  if p_UserCalls.p_Callback then
  
    if bSimulateSDIASManager = FALSE then
    // Call the corresponding function in the operator class
    tempCmd.uiCmd := _BUS_IF_HWCONNECT;  
    p_UserCalls.p_Callback^.pSvrChCmd.NewInst(#tempCmd,#_result);
    
    if _result.aData[0] then
      return;
    end_if;
    else
      //we have to call the connect event in the realtime task for SDIAS - because the DOs are enabled in the ConnectEvent method and at VARAN the DOs have to be enabled in the right task
      bCallHwConnectInRT := TRUE;
  end_if;
  
  end_if;
  
  if bSimulateSDIASManager then

    //Reset SSW (so that we begin at the beginning after plug&play
    eSdiasManagerInitSSW := _StartInit;
    eSdiasManagerRTSSW   := _RtIdle;  
  
    // install post init call back only if we're still in init (if we install it in init(), we may get called even the module is not connected)
    if us_Firstscan < 12 then
      tempCmd.uiCmd := _BUS_IF_WAIT_4_POST_INIT;
      
      
      Settings := 0;
      Settings.1 := TRUE; //Wait4DOCreation
      Settings.2 := TRUE; //Wait4MoveDOCreation
      Settings.3 := TRUE; //Wait4SyncSend
        
      tempCmd.aPara[0] := Settings;
      
      CallCommand.NewInst(pPara:=#tempCmd, pResult:=#_result);

      if _result.aData[0]$t_BusIFRetvalErrorcode <> _BUS_IF_RETVAL_OK then
        LogError("@0076 (BusInterfaceVARAN::ConnectEvent) Failed to install post init callback");
        State := _InvalidConfguration;
        return;
      end_if;
    else
      b_PostInitFinished := TRUE;    
    end_if;
  end_if;

  if ExtSetOnline = false then
    if bSimulateSDIASManager then
      //do not set online yet, will be set if all data is valid
    else
    Online := 1;  
  end_if;
  end_if;
  
  sd_retval         := VARANMANAGER_OK;
  State	            := _ClassOk;
  
END_FUNCTION


FUNCTION VIRTUAL GLOBAL BusInterfaceVARAN::Varan_HwDisconnect
	VAR_INPUT
		ud_data 	: UDINT;
	END_VAR
	VAR_OUTPUT
		sd_retval : DINT;
	END_VAR
  VAR
  	tempCmd   : CmdStruct;
    _result   : results;
  END_VAR;
  
  // Turn off DO's
  SetDOsOff();
  
  // Check for 0 pointer
  if p_UserCalls.p_Callback then
    // Call the corrosponding function in the operator class
    tempCmd.uiCmd := _BUS_IF_HWDISCONNECT;  
    p_UserCalls.p_Callback^.pSvrChCmd.NewInst(#tempCmd,#_result);
  end_if;
  
  sd_retval := Varan_Base::Varan_HwDisconnect(ud_data);
  
END_FUNCTION


FUNCTION VIRTUAL GLOBAL BusInterfaceVARAN::SetDOsOff
  VAR
  	i     : USINT;
  END_VAR

  if NrDO then
    for i := 0 to (NrDO - 1) do
      DisableDO(ud_DOHandle := DOList[i].pHandle$UDINT);
      DOList[i].b_DOIsRunning := 0;    
    end_for;
  end_if;
  
END_FUNCTION


FUNCTION VIRTUAL GLOBAL BusInterfaceVARAN::UpdateCy
  VAR
  	i : USINT;
  END_VAR

  // only if the module is connected
  if State = _ClassOk then

    // Call CyWork of calling class
    
    // No Prescaler
    if TaskPrescaler.MaxCnt = 0 then
    
      if bSimulateSDIASManager = TRUE then
        SimulateSDIASManagerCywork();
      else
        //Normal mode, just call cywork of connected module
        p_UserCalls.p_UpdateCy^.CyWork(EAX:=0);
      end_if;
    
    else
      // if DOList[0].pHandle^.ucExePrescalerCnt = DOList[0].pHandle^.ucExePrescaler then
      if TaskPrescaler.CntCy = TaskPrescaler.CyTrigger then
        if bSimulateSDIASManager = TRUE then
          SimulateSDIASManagerCywork();
        else
          p_UserCalls.p_UpdateCy^.CyWork(EAX:=0);
        end_if;
      end_if;
      
      TaskPrescaler.CntCy += 1;
      if TaskPrescaler.CntCy > TaskPrescaler.MaxCnt then
        TaskPrescaler.CntCy := 0;
      end_if;
    
    end_if;
    
    if b_PayloadSupport then
      // No direct singlerun with payload, use singlerun statemaschie
      for i := 0 to (NrDO - 1) do
        if DOList[i].Priority = _BUS_IF_ASY then
          SingleRunSM(p_DOhandle      := (#DOList[i].pHandle)$^UDINT
                    , p_b_DOIsRunning := #DOList[i].b_DOIsRunning );
        end_if;    
      end_for;
    end_if;
  end_if;  

END_FUNCTION


FUNCTION VIRTUAL GLOBAL BusInterfaceVARAN::UpdateRt
  VAR
  	i         : USINT;
    pMemList  : ^t_LocalMemList;
  END_VAR
  
  // only if the module is connected
  if State = _ClassOk then

    
    if bSimulateSDIASManager then
    
      SimulateSDIASManagerRtwork();
    
    end_if;
    
    // Call RtWork of calling class
    
    // No Prescaler
    if TaskPrescaler.MaxCnt = 0 then
      // copy to local memory
      if LocalRdCopyNo then 
        pMemList := #apLocalRdCopyDOs[0];
        for i := 0 to LocalRdCopyNo-1 do
          _memcpy(ptr1:=pMemList^.pDest, ptr2:=pMemList^.pSource, cntr:=pMemList^.Length);
          pMemList += sizeof(apLocalRdCopyDOs[0]);
        end_for;
      end_if;

      p_UserCalls.p_UpdateRt^.RtWork(EAX:=CALL_OPTION_RT_PRESCAN);
    else  
    
      if FirstRT then

        if b_PayloadSupport = false then  // Autodone with Payload support
          // Init Prescaler counter 
          for i := 0 to NrDO -1 do
            if DOList[i].PreScaler then
              DOList[i].pHandle^.ucExePrescalerCnt := DOList[i].PreScaler;
            end_if;

          end_for;
        end_if;
        
        FirstRT := false;
        
      elsif TaskPrescaler.Cnt = TaskPrescaler.RtPreScanTigger then
        p_UserCalls.p_UpdateRt^.RtWork(EAX:=CALL_OPTION_RT_PRESCAN);
      end_if;      
      
      if p_UserCalls.p_UpDateRtPostScan = NIL then  // only increment if there is no RtPostScan, otherwise we increment there
        TaskPrescaler.Cnt += 1;
        if TaskPrescaler.Cnt > TaskPrescaler.MaxCnt then
          TaskPrescaler.Cnt := 0;
        end_if;

      end_if;

    end_if;


    if b_PayloadSupport & 
       p_UserCalls.p_UpDateRtPostScan = nil then
       
      // No direct singlerun with payload, use singlerun statemachine
      // Run in UpdateRt if there is no UpdateRtPostScan
      
      for i := 0 to (NrDO - 1) do
        if DOList[i].Priority = _BUS_IF_ISO then
          SingleRunSM(p_DOhandle      := (#DOList[i].pHandle)$^UDINT
                    , p_b_DOIsRunning := #DOList[i].b_DOIsRunning );
        end_if;    
      end_for;
    end_if;
  end_if;

END_FUNCTION


FUNCTION VIRTUAL GLOBAL BusInterfaceVARAN::UpdateRtPostScan
  VAR
  	i         : USINT;
    pMemList  : ^t_LocalMemList;
  END_VAR
  
  // only if the module is connected
  if State = _ClassOk then

    // Call RtWork of calling class
    
    if TaskPrescaler.MaxCnt = 0 then
      p_UserCalls.p_UpDateRtPostScan^.RtWork(EAX:=CALL_OPTION_RT_POSTSCAN);

      // copy from local memory
      if LocalWrCopyNo then 
        pMemList := #apLocalWrCopyDOs[0];
        for i := 0 to LocalWrCopyNo-1 do
          _memcpy(ptr1:=pMemList^.pDest, ptr2:=pMemList^.pSource, cntr:=pMemList^.Length);
          pMemList += sizeof(apLocalWrCopyDOs[0]);
        end_for;
      end_if;
    else
      
      if FirstRT then

        if b_PayloadSupport = false then  // Autodone with Payload support      
          // Init Prescaler counter 
          for i := 0 to NrDO -1 do
            if DOList[i].PreScaler then
              DOList[i].pHandle^.ucExePrescalerCnt := DOList[i].PreScaler;
            end_if;
          end_for;
        end_if;
        
        FirstRT := false;
        
      elsif TaskPrescaler.Cnt = TaskPrescaler.RtPostScanTrigger then
        p_UserCalls.p_UpDateRtPostScan^.RtWork(EAX:=CALL_OPTION_RT_POSTSCAN);
      
      end_if;  
      
      TaskPrescaler.Cnt += 1;
      if TaskPrescaler.Cnt > TaskPrescaler.MaxCnt then
        TaskPrescaler.Cnt := 0;
      end_if;

    end_if;
    
    if b_PayloadSupport then
       
      // No direct singlerun with payload, use singlerun statemaschie    
      for i := 0 to (NrDO - 1) do
        if DOList[i].Priority = _BUS_IF_ISO then
          SingleRunSM(p_DOhandle      := (#DOList[i].pHandle)$^UDINT
                    , p_b_DOIsRunning := #DOList[i].b_DOIsRunning );
        end_if;    
      end_for;
    end_if;
  end_if;
    
END_FUNCTION


FUNCTION VIRTUAL GLOBAL BusInterfaceVARAN::CallCommand::NewInst
	VAR_INPUT
		pPara 	          : ^CmdStruct;
		pResult           : ^results;
	END_VAR
	VAR_OUTPUT
		ret_code 	        : iprStates;
	END_VAR
  VAR    
  	pRDWRDOCfg        : ^t_RDWRDOCfg;
    pBusIFAddCallback : ^t_BusIFAddCallback;
    pTemp             : ^void;
    sd_retval         : DINT;
    ManagerState      : t_e_VaranErrors;
  	tempCmd           : CmdStruct;
    _result           : results;
  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;
     
      //BusinterfaceVARAN should work like the SDIAS Manager - same process (like we simulate InitModule e.g.)
      bSimulateSDIASManager := TRUE;
          
    //**********************************************************************************************************************************************************
    _BUS_IF_READ_VIA_SDO:
    
      if AddSDORequest(pCmdSvr  :=  pPara^.aPara[3]$^SvrChCmd
                     , Command  :=  _BUS_IF_READ_VIA_SDO
                     , Offset   :=  pPara^.aPara[0]$HINT
                     , Length   :=  pPara^.aPara[1]$USINT
                     , pWriteBuf:=  NIL) = 0 then        
        ret_code := READY;
      else
        ret_code := ERROR;
      end_if;
    
    //**********************************************************************************************************************************************************
    _BUS_IF_READ_VIA_SDO_CTRL:
    
      if AddSDORequest(pCmdSvr  :=  pPara^.aPara[3]$^SvrChCmd
                     , Command  :=  _BUS_IF_READ_VIA_SDO_CTRL
                     , Offset   :=  pPara^.aPara[0]$HINT
                     , Length   :=  pPara^.aPara[1]$USINT
                     , pWriteBuf:=  NIL) = 0 then        
        ret_code := READY;
      else
        ret_code := ERROR;
      end_if;    
    
    //**********************************************************************************************************************************************************
    _BUS_IF_WRITE_VIA_SDO:

      if AddSDORequest(pCmdSvr  :=  pPara^.aPara[3]$^SvrChCmd
                     , Command  :=  _BUS_IF_WRITE_VIA_SDO
                     , Offset   :=  pPara^.aPara[0]$HINT
                     , Length   :=  pPara^.aPara[1]$USINT
                     , pWriteBuf:=  pPara^.aPara[2]$^void) = 0 then        
        ret_code := READY;
      else
        ret_code := ERROR;
      end_if;    
    
    //**********************************************************************************************************************************************************
    _BUS_IF_WRITE_VIA_SDO_CTRL:
      
      if AddSDORequest(pCmdSvr  :=  pPara^.aPara[3]$^SvrChCmd
                     , Command  :=  _BUS_IF_WRITE_VIA_SDO_CTRL
                     , Offset   :=  pPara^.aPara[0]$HINT
                     , Length   :=  pPara^.aPara[1]$USINT
                     , pWriteBuf:=  pPara^.aPara[2]$^void) = 0 then        
        ret_code := READY;
      else
        ret_code := ERROR;
      end_if;
         
    //**********************************************************************************************************************************************************
    _BUS_IF_ADD_CALLBACK :         // Set Callbackpointer
      pResult^.uiLng    := 4;
      pBusIFAddCallback := (pPara^.aPara[0])$^t_BusIFAddCallback;
      
      if (SetOperatorClass(pBusIFAddCallback^.pthis)) then
        pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_ERROR_INVALID_POINTER;
        ret_code := ERROR;
      else
        pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_OK;
      end_if;
          
//**********************************************************************************************************************************************************
    _BUS_IF_ADD_DO :               // Add Data Object      
      MutexStart(pv_Mutex);      
      AddDO(pPara, pResult);
      if presult^.aData$t_AddDORet.retcode <> _BUS_IF_RETVAL_OK then
        ret_code := ERROR;      
      end_if;
      MutexStop(pv_Mutex);

//**********************************************************************************************************************************************************
    _BUS_IF_ADD_CTRL_DO :               // Add Data Object      
      MutexStart(pv_Mutex);      
      AddDO(pPara, pResult,TRUE);
      if presult^.aData$t_AddDORet.retcode <> _BUS_IF_RETVAL_OK then
        ret_code := ERROR;      
      end_if;
      MutexStop(pv_Mutex);

//**********************************************************************************************************************************************************
    _BUS_IF_UPDATE_DO :            // Update Data Object
      MutexStart(pv_Mutex);
      UpdateDO(pPara, pResult); 
      if pResult^.aData[0]$t_BusIFRetvalErrorcode <> _BUS_IF_RETVAL_OK then
        ret_code := ERROR;
      end_if;
      MutexStop(pv_Mutex);
          
//**********************************************************************************************************************************************************
    _BUS_IF_RESET_DO :             // Reset Data Object 
      MutexStart(pv_Mutex);
      ResetDO(pPara, pResult); 
      if pResult^.aData[0]$t_BusIFRetvalErrorcode <> _BUS_IF_RETVAL_OK then
        ret_code := ERROR;
      end_if;
      MutexStop(pv_Mutex);
     
//**********************************************************************************************************************************************************
    _BUS_IF_ADD_TASK :             // Add Varan Task
      AddTask(pPara, pResult); 
      if pResult^.aData[0]$t_BusIFRetvalErrorcode <> _BUS_IF_RETVAL_OK then
        ret_code := ERROR;
      end_if;

//**********************************************************************************************************************************************************
    _BUS_IF_RD_DA :                // Direct Access Read
      pResult^.uiLng    := 8;                                              
      pRDWRDOCfg := ((pPara^.aPara[0])$^t_RDWRDOCfg);

      if b_PayloadSupport then
        sd_retval := MULTI_VARAN_iExecuteDirectAccess(hNodeHandle := ud_HandleModule
                                                    , udCommand   := VARAN_CMD_MEMORY_READ
                                                    , udOffset    := pRDWRDOCfg^.ud_AddOffset
                                                    , udLength    := pRDWRDOCfg^.ud_length
                                                    , pusData     := (pRDWRDOCfg^.p_ud_data)$^USINT
                                                    , pudErrorInfo:= NIL);
      else
        sd_retval := VARAN_iReadMemoryDA( uiManager      := ud_VaranManagerNr
                                        , uiAddress      := DeviceAddress + pRDWRDOCfg^.ud_AddOffset  
                                        , uiLen          := pRDWRDOCfg^.ud_length
                                        , uiRetryTimeout := GetRetryTimeout( pRDWRDOCfg^.ud_length)
                                        , pvData         := pRDWRDOCfg^.p_ud_data
                                        , puiError       := NIL
                                        );
      end_if;

      if sd_retval = VARANMANAGER_OK then
        pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_OK;
      else
        pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_ERROR_DIRECT_ACCESS_FAILED;
        ret_code := ERROR;
      end_if;

//**********************************************************************************************************************************************************
    _BUS_IF_WR_DA :               // Direct Access Write
      pResult^.uiLng    := 8;
      pRDWRDOCfg := ((pPara^.aPara[0])$^t_RDWRDOCfg);
      
      if b_PayloadSupport then
        sd_retval := MULTI_VARAN_iExecuteDirectAccess(hNodeHandle := ud_HandleModule
                                                    , udCommand   := VARAN_CMD_MEMORY_WRITE
                                                    , udOffset    := pRDWRDOCfg^.ud_AddOffset
                                                    , udLength    := pRDWRDOCfg^.ud_length
                                                    , pusData     := (pRDWRDOCfg^.p_ud_data)$^USINT
                                                    , pudErrorInfo:= NIL);
      else
        sd_retval := VARAN_iWriteMemoryDA(uiManager       := ud_VaranManagerNr
                                        , uiAddress       := DeviceAddress + pRDWRDOCfg^.ud_AddOffset  
                                        , uiLen           := pRDWRDOCfg^.ud_length
                                        , uiRetryTimeout  := GetRetryTimeout( pRDWRDOCfg^.ud_length)
                                        , pvData          := pRDWRDOCfg^.p_ud_data
                                        , puiError        := NIL
                                        );
      end_if;

      if sd_retval = VARANMANAGER_OK then
        pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_OK;
      else
        pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_ERROR_DIRECT_ACCESS_FAILED;
        ret_code := ERROR;
      end_if;

//**********************************************************************************************************************************************************
    _BUS_IF_SET_RUN_STATE :       // Set the run State 
      MutexStart(pv_Mutex);
      SetRunState(pCmd:=pPara, presult:=pResult);
      if pResult^.aData[0]$t_BusIFRetvalErrorcode <> _BUS_IF_RETVAL_OK then
        ret_code := ERROR;
      end_if;
      MutexStop(pv_Mutex);
          
//**********************************************************************************************************************************************************
    _BUS_IF_SET_ONLINE:           // Sets the online Server
      ExtSetOnline := true;
      Online := pPara^.aPara[0];
      pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_OK;
          
//**********************************************************************************************************************************************************
    _BUS_IF_GET_BUSCYCLE_TIME :   // Get BusCycle time and Iso Startpoint 
      if udVaranTime = 0 then
        udVaranTime := VaranIn.GetVaranTime(p_ud_IsoStartPoint:=#udIsoStartPoint);   
      end_if;

      pResult^.aData[0]$t_GetBusCycleTime.retcode         := _BUS_IF_RETVAL_OK;
      pResult^.aData[0]$t_GetBusCycleTime.udBusCycleTime  := udVaranTime;
      pResult^.aData[0]$t_GetBusCycleTime.udIsoStartPoint := udIsoStartPoint;
      pResult^.aData[0]$t_GetBusCycleTime.udMainTimer     := _ClockTicks;

//**********************************************************************************************************************************************************
    _BUS_IF_GET_OBJECT_THIS_PTR:
      pResult^.aData[0]$UDINT := GetObjectThisp(p_us_ObjectPath := pPara^.aPara[0]$^USINT);
      
      if pResult^.aData[0]$UDINT = 0 then
        ret_code := ERROR;
        LogError("@018D (BusInterfaceVARAN::CallCommand::NewInst) Failed to get this pointer via hardware path");
      end_if;
      
//**********************************************************************************************************************************************************
    _BUS_IF_SET_DO_PRESCALER :    // Set DO Prescaler 
      MutexStart(pv_Mutex);
      SetDOPrescaler(pPara, pResult);
      if pResult^.aData[0]$t_BusIFRetvalErrorcode <> _BUS_IF_RETVAL_OK then
        ret_code := ERROR;
      end_if;
      MutexStop(pv_Mutex);
          
//**********************************************************************************************************************************************************
    _BUS_IF_SET_TASKS_PRESCALER : // Set Task Prescaler 
      SetTasksPrescaler(pPara, pResult);
      if pResult^.aData[0]$t_BusIFRetvalErrorcode <> _BUS_IF_RETVAL_OK then
        ret_code := ERROR;
      end_if;      
        
//**********************************************************************************************************************************************************
    _BUS_IF_SET_SYNC :            // Set the sync data 
      //use divider sync must be set to false as initalvalue.  
      pPara^.aPara[0]$^t_SyncData^.b_use_divider_sync := FALSE;
      SetSyncData(pPara, pResult);
      if pResult^.aData[0]$t_BusIFRetvalErrorcode <> _BUS_IF_RETVAL_OK then
        ret_code := ERROR;
      end_if; 
      
//**********************************************************************************************************************************************************
    _BUS_IF_SET_SYNC_DIVIDER :   // Set the sync data with divider
      SetSyncData(pPara, pResult);
      if pResult^.aData[0]$t_BusIFRetvalErrorcode = _BUS_IF_RETVAL_OK then
        //this value is for pll divider. as initial value it is set to zero (pll standard divider 1)
        us_PLLDivider := to_usint(pPara^.aPara[1]);
      else  
        ret_code := ERROR;        
      end_if; 
      
//**********************************************************************************************************************************************************
    _BUS_IF_WAIT_4_POST_INIT:
      tempCmd.uiCmd := VM_CMD_NEED_POST_INIT_CALL;
      tempCmd.aPara[0] := THIS$DINT;
      tempCmd.aPara[1] := pPara^.aPara[0];  // wait for DOs to be created
      ret_code := VaranIn.NewInst(#tempCmd, #_result);
      if (ret_code = READY) & (_result.uiLng = sizeof(UINT)) then
        ui_PostInitIndex := _result.aData[0]$UINT;
        pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_OK;
      else
        pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_ERROR_NOT_SUPPORTED;        
      end_if;
        
//**********************************************************************************************************************************************************
    _BUS_IF_POST_INIT_FINISHED:
      pPara^.uiCmd := VM_CMD_POST_INIT_FINISHED;
      pPara^.aPara[0] := THIS$DINT;
      pPara^.aPara[1] := to_dint(ui_PostInitIndex);
      pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_OK;
      ret_code := VaranIn.NewInst(pPara, pResult);

//**********************************************************************************************************************************************************
    _BUS_IF_DO_CREATION_FINISHED:
      pPara^.uiCmd := VM_CMD_DO_CREATION_FINISHED;
      pPara^.aPara[0] := THIS$DINT;
      pPara^.aPara[1] := to_dint(ui_PostInitIndex);
      pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_OK;
      ret_code := VaranIn.NewInst(pPara, pResult);

//**********************************************************************************************************************************************************
    _BUS_IF_MOVE_DO_CREATION_FINISHED:
      pPara^.uiCmd := VM_CMD_MOVE_DO_CREATION_FINISHED;
      pPara^.aPara[0] := THIS$DINT;
      pPara^.aPara[1] := to_dint(ui_PostInitIndex);
      pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_OK;
      ret_code := VaranIn.NewInst(pPara, pResult);

//**********************************************************************************************************************************************************
    _BUS_IF_RT_SYNC_READY:
      pPara^.uiCmd := VM_CMD_SYNC_SEND_READY;
      pPara^.aPara[0] := THIS$DINT;
      pPara^.aPara[1] := to_dint(ui_PostInitIndex);
      pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_OK;
      ret_code := VaranIn.NewInst(pPara, pResult);

//**********************************************************************************************************************************************************
    _BUS_IF_DO_MEM_READY:
      pPara^.uiCmd := VM_CMD_DO_MEM_READY;
      pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_OK;
      ret_code := VaranIn.NewInst(pPara, pResult);

//**********************************************************************************************************************************************************
    _BUS_IF_MOVE_DO_MEM_READY:
      pPara^.uiCmd := VM_CMD_MOVE_DO_MEM_READY;
      pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_OK;
      ret_code := VaranIn.NewInst(pPara, pResult);

//**********************************************************************************************************************************************************
    _BUS_IF_GET_HW_PATH:
      pTemp := GetPointer2ObjectPath();
      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_SET_REQUIRED_ERROR:
      //Set state of class
      State := _RequiredError;

    // if no callback installed so far => install one to create required error
      if b_CallBackInstalled = FALSE then
        if p_VaranPosition = NIL then
          //init the base class
          Varan_Base::Init();
        end_if;

        // install callback here, because in the first init the operator may set this object required
        sd_retval := VaranIn.SetObjectCallback( p_us_position_info  := p_VaranPosition
                                              , ud_action_ptr       := ( #Varan_CallBack() )$UDINT
                                              , ud_thisp            := this$UDINT
                                              , sd_required         := 1
                                              );

        if sd_retval = VARANMANAGER_OK then
          b_CallBackInstalled := TRUE;
        end_if;
      end_if;

      //Set VaranMaster off
      VaranIn.SetManagerOff( e_error := State );
      VaranIn.SetVaranError(p_Node:=p_VaranPosition);
      pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_OK;
      
      // crash is only allowed if UserAction is not zero
      if Varan_Base::UserAction.Write(input:=VARANMANAGER_CB_REQ_ERROR) <> 0 then  
        //if we're not crashed so far, it may be the first init and something went wrong => crash alternatively (no node information!)
        ToOSKernel.AddToServiceProvider(command:="exec climsg 45 A required module is not available!", immediatly:=1); 
      end_if;       
      
//**********************************************************************************************************************************************************
    _BUS_IF_SET_ERROR:
      pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_OK;

      State := pPara^.aPara[0]$t_e_VaranErrors;
      
      //Set VaranMaster off
      VaranIn.SetManagerOff( e_error := State );

      // if there is a pointer to a string => use it for service provider (should be like: "exec climsg 45 A required module is not available!")
      if pPara^.aPara[1] then
        // if a required module is not available or doesn't work properly, the system should crash
        ToOSKernel.AddToServiceProvider(command:=pPara^.aPara[1]$^CHAR, immediatly:=1);
      end_if;

//**********************************************************************************************************************************************************
    _BUS_IF_CREATE_MUTEX:
      pTemp := CreateMutex(pPara^.aPara[0]$^CHAR, pPara^.aPara[1]$pVirtualBase);
      if pTemp then
        pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_OK;
        pResult^.aData[4]$^void := pTemp;
        pResult^.aData[8]$^LSL_MT_TYPE := mt_api;
      else
        pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_ERROR_CREATE_MUTEX_FAILED;
        pResult^.aData[4]$^USINT := NIL;
        pResult^.aData[8]$^LSL_MT_TYPE := NIL;
        ret_code := ERROR;
      end_if;

//**********************************************************************************************************************************************************
    _BUS_IF_SET_REQUIRED:
      Required := 1;
      pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_OK;
    
//**********************************************************************************************************************************************************
    _BUS_IF_GET_DEACTIVATED_STATE:
      pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_OK;
      ManagerState := VaranIn.GetManagerState();
      pResult^.aData[4]$BOOL := (IsTransparent() <> FALSE) | (ManagerState = _NoVaranInterface);
      
//**********************************************************************************************************************************************************
    _BUS_IF_ADD_MOVE_DO:
      MutexStart(pv_Mutex);
      AddMoveDO(pPara, pResult);
      if presult^.aData$t_AddMoveDORet.retcode <> _BUS_IF_RETVAL_OK then
        ret_code := ERROR;
      end_if;
      MutexStop(pv_Mutex);
    
//**********************************************************************************************************************************************************
    _BUS_IF_UPDATE_MOVE_DO:
      MutexStart(pv_Mutex);
      UpdateMoveDO(pPara, pResult); 
      if pResult^.aData[0]$t_BusIFRetvalErrorcode <> _BUS_IF_RETVAL_OK then
        ret_code := ERROR;
      end_if;
      MutexStop(pv_Mutex);
      
//**********************************************************************************************************************************************************          
    _BUS_IF_GET_INTERFACE_TYPE:
      pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_OK;
      pResult^.aData[4]$t_BusIFType := _BUS_IF_TYPE_VARAN;

//**********************************************************************************************************************************************************          
    _BUS_IF_IS_VARAN_AVAILABLE:
      pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_OK;
      pResult^.aData[4]$BOOL := TRUE;      

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

//**********************************************************************************************************************************************************          
    _BUS_IF_GET_BUS_READY_AVAILABLE:
      pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_OK;
      if pVaran then
        pResult^.aData[4] := pVaran^.udVersion >= BUSIF_VARAN_BUS_READY_VER;      
      else
        pResult^.aData[4] := FALSE;
      end_if;
    
//**********************************************************************************************************************************************************          
    _BUS_IF_LOG_ERROR_MSG:
      pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_OK;
      
      if (pPara^.aPara[0]$t_LogErrorMsg.p_extThis1 = nil) then
        LogError(pPara^.aPara[0]$t_LogErrorMsg.e_msg);
      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;

//**********************************************************************************************************************************************************                
    _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;   
      end_if;
      
//**********************************************************************************************************************************************************      
    _BUS_IF_SET_CLASS_STATE:
      
      State := (pPara^.aPara[0])$t_e_VaranErrors;
      
      pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_OK;      

//**********************************************************************************************************************************************************      
    _BUS_IF_GET_CLASS_STATE:
    
      pResult^.aData[4]$t_e_VaranErrors        := State;      
      pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_OK;
  
//**********************************************************************************************************************************************************      
    _BUS_IF_SET_PARAM:            
      case pPara^.aPara[0]$UDINT of
      
        _BUS_IF_DEVICEID_DIAGNOSIS:
          DeviceIDDiagnosis := pPara^.aPara[1]$UDINT;
          ret_code := READY;
          
        _BUS_IF_DISABLE_DEVICE:
          ret_code$DINT := DisableDevice();
          
        _BUS_IF_ENABLE_DEVICE:
          ret_code$DINT := EnableDevice();          
          
      else
        //unknown command
        ret_code := ERROR;
      end_case;
          
//**********************************************************************************************************************************************************      
    _BUS_IF_GET_PARAM:
      case pPara^.aPara[0]$UDINT of
        
        _BUS_IF_DEVICEADDRESS: 
          pResult^.aData[4]$HDINT                  := DeviceAddress;      
          pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_OK;          
          
        _BUS_IF_DEVICEID: 
          pResult^.aData[4]$UDINT                  := DeviceID;      
          pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_OK;   
      
        _BUS_IF_VENDORID: 
          pResult^.aData[4]$UDINT                  := VendorID;      
          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                  := Release ;      
          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_DEVICEID_DIAGNOSIS:
          pResult^.aData[4]$UDINT                  := DeviceIDDiagnosis;      
          pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_OK;   
          
        _BUS_IF_DOLISTADD_AVAILABLE:
          pResult^.aData[4]$UDINT                  := bAddDOsToListSupport;      
          pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_OK;   
    
      else
        //unknown command
        ret_code := ERROR;
      end_case;

//**********************************************************************************************************************************************************
    _BUS_IF_GET_TRANSPARENT_STATE:
    
      pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_OK;
      pResult^.aData[4]$BOOL                   := IsTransparent();      

//**********************************************************************************************************************************************************
    CMD_EXTEND_POST_INIT_TIME,
    CMD_GET_HW_TIMESTAMP:
      // forward to HwControl (via VaranManager)
      VaranIn.NewInst(pPara, pResult);

//**********************************************************************************************************************************************************
    CMD_HWC_REQ_PLLNS_REGULATION:
      // forward to HwControl
      VaranIn.NewInst(pPara, pResult);  
      
//**********************************************************************************************************************************************************
    _BUS_IF_NEED_POST_INIT_TASK_DELAY:
      pPara^.uiCmd := VM_CMD_NEED_POST_INIT_TASK_DELAY;
      pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_OK;
      ret_code := VaranIn.NewInst(pPara, pResult);

//**********************************************************************************************************************************************************

  else
    //unknown command
    ret_code := ERROR;
  END_CASE;

END_FUNCTION


FUNCTION VIRTUAL GLOBAL BusInterfaceVARAN::CheckDeviceID
	VAR_INPUT
		ID2Check 	  : UDINT;
	END_VAR
	VAR_OUTPUT
		IsOK 	      : BOOL;
	END_VAR
  VAR
  	tempCmd     : CmdStruct;
    _result     : results;
  END_VAR

  // Check for 0 pointer
  if p_UserCalls.p_Callback then
  
    // Call the corrosponding function in the operator class
    tempCmd.uiCmd   := _BUS_IF_CHECK_DEVICE_ID;  
    tempCmd.aPara[0]:= ID2Check$DINT;
    
    p_UserCalls.p_Callback^.pSvrChCmd.NewInst(#tempCmd,#_result);
    
    if _result.aData[0] then
      IsOK         := TRUE;
    else
      IsOK         := FALSE;
    end_if;
  else
    IsOK := FALSE;
  end_if;

END_FUNCTION


FUNCTION VIRTUAL GLOBAL BusInterfaceVARAN::SetOperatorClass
	VAR_INPUT
		pOperator 	: pVirtualBase;
	END_VAR
	VAR_OUTPUT
		sd_retval 	: DINT;
	END_VAR
  
  sd_retval := 1;
      
  if pOperator then
    sd_retval               := 0;
    p_UserCalls.p_Callback  := pOperator;    
  end_if;

END_FUNCTION


FUNCTION VIRTUAL GLOBAL BusInterfaceVARAN::AddDO
	VAR_INPUT
		pCmd 	        : ^CmdStruct;
		presult 	    : ^results;
		bCtrlAcc 	: BOOL;(* := false *)
	END_VAR
  VAR
  	pADDDOCfg     : ^t_AddDOCfg;
    _ud_dol_type  : UDINT;
    sd_retval     : DINT;
    pCurrentDO    : ^t_DOCfg;
    _priority     : UDINT;
    udAddLaterFlag : UDINT;
    tmpDOType     : UDINT;
  END_VAR

  if bCtrlAcc = TRUE then
    tmpDOType := VM_CONTROL_ACCESS;
  else
    tmpDOType := VM_MEMORY_ACCESS;
  end_if;

  
  presult^.uiLng    := sizeof(t_AddDORet);
  
  if b_CallBackInstalled = FALSE then
    LogError("@018E (BusInterfaceVARAN::AddDO) Error: Varan Callback must be installed before DOs can be created!");
    pResult^.aData$t_AddDORet.retcode := _BUS_IF_RETVAL_ERROR_NO_CALLBACK_INSTALLED;
    return;
  end_if;
  
  if NrDO < BUSIF_VARAN_MAX_NR_DO then            
    pADDDOCfg := ((pCmd^.aPara[0])$^t_AddDOCfg);
    //reset flag
    udAddLaterFlag := 0;
    // Convert passed t_Priority to VARAN ud_dol_type
    if (pADDDOCfg^.Priority)$t_BusIFPriority  = _BUS_IF_ISO           | 
       (pADDDOCfg^.Priority)$t_BusIFPriority  = _BUS_IF_ISO_MOVE      | 
       (pADDDOCfg^.Priority)$t_BusIFPriority  = _BUS_IF_ISO_ADDLATER  then
      if (pADDDOCfg^.Priority)$t_BusIFPriority  = _BUS_IF_ISO_ADDLATER  then
        udAddLaterFlag := VARAN_DOL_NOT_INSERT_DO_INTO_DOL;
      end_if;
      _ud_dol_type := VARAN_DOL_ISO or udAddLaterFlag;
    else
      _ud_dol_type := VARAN_DOL_ASY or udAddLaterFlag;
    end_if;
    
    // Set Special prioritys for move source and destination DOs
    if (pADDDOCfg^.Priority)$t_BusIFPriority = _BUS_IF_ISO_MOVE |
       (pADDDOCfg^.Priority)$t_BusIFPriority = _BUS_IF_ASY_MOVE then
      
      if b_PayloadSupport then
        
        if (pADDDOCfg^.RdWr)$t_BusIFRDWR = _BUS_IF_READ then
          _priority := VM_PRIORITY_SAFETY_READ_DO;
        elsif (pADDDOCfg^.RdWr)$t_BusIFRDWR = _BUS_IF_WRITE then
          _priority := VM_PRIORITY_SAFETY_WRITE_DO;
        else
          _priority := VM_DO_PROPERTY_INVALID; // No Move DO with RDWR DO
        end_if;

      else
        
        if (pADDDOCfg^.RdWr)$t_BusIFRDWR = _BUS_IF_READ then
          _priority := VM_PRIORITY_1;
        elsif (pADDDOCfg^.RdWr)$t_BusIFRDWR = _BUS_IF_WRITE then
          _priority := VM_PRIORITY_3;
        else
          _priority := 0; // No Move DO with RDWR DO
        end_if;
        
      end_if;
      
    else
    
      if b_PayloadSupport then
        _priority := VM_DO_PROPERTY_INVALID;
      else
        _priority := 0;
      end_if;
    
    end_if;
    
    pCurrentDO := #DOList[NrDO];
    
    //set Flag to recognize if do should be installed into DO List later
    if (_ud_dol_type and VARAN_DOL_NOT_INSERT_DO_INTO_DOL) = VARAN_DOL_NOT_INSERT_DO_INTO_DOL
    & bAddDOsToListSupport then
      //do should be inserted later, store at do info structure
      pCurrentDO^.bsDoInsert := 1;
    end_if;
    
    if b_PayloadSupport then
      // Add read object
      if (pADDDOCfg^.RdWr)$t_BusIFRDWR = _BUS_IF_READ | (pADDDOCfg^.RdWr)$t_BusIFRDWR = _BUS_IF_READ_DYN then      
        
        sd_retval := AddRdPayloadDO(ud_dol_type        := _ud_dol_type
                                  , p_ud_handle        := (#pCurrentDO^.pHandle)$^UDINT
                                  , ud_offset_read     := pADDDOCfg^.ud_addressoff_read
                                  , ud_length_read     := pADDDOCfg^.ui_length_read
                                  , p_ud_data_read     := (#pCurrentDO^.pDataRead)$^UDINT
                                  , ud_type            := tmpDOType
                                  , ud_priority        := _priority
                                  , ud_WritePayloadType:= pADDDOCfg^.b_DOIsChangable);
      
      // Add write object
      elsif (pADDDOCfg^.RdWr)$t_BusIFRDWR = _BUS_IF_WRITE | (pADDDOCfg^.RdWr)$t_BusIFRDWR = _BUS_IF_WRITE_DYN then
        sd_retval := AddWrPayloadDO(ud_dol_type         := _ud_dol_type
                                  , p_ud_handle         := (#pCurrentDO^.pHandle)$^UDINT
                                  , ud_offset_write     := pADDDOCfg^.ud_addressoff_write
                                  , ud_length_write     := pADDDOCfg^.ui_length_write
                                  , p_ud_data_write     := (#pCurrentDO^.pDataWrite)$^UDINT
                                  , ud_type             := tmpDOType
                                  , ud_priority         := _priority
                                  , ud_WritePayloadType := pADDDOCfg^.b_DOIsChangable);
      
      // Add read/write object
      else
        sd_retval := AddRdWrPayloadDO(ud_dol_type         := _ud_dol_type
                                    , p_ud_handle         := (#pCurrentDO^.pHandle)$^UDINT
                                    , ud_offset_read      := pADDDOCfg^.ud_addressoff_read
                                    , ud_length_read      := pADDDOCfg^.ui_length_read
                                    , p_ud_data_read      := (#pCurrentDO^.pDataRead)$^UDINT
                                    , ud_offset_write     := pADDDOCfg^.ud_addressoff_write
                                    , ud_length_write     := pADDDOCfg^.ui_length_write
                                    , p_ud_data_write     := (#pCurrentDO^.pDataWrite)$^UDINT
                                    , ud_type             := tmpDOType
                                    , ud_WritePayloadType := pADDDOCfg^.b_DOIsChangable);
      end_if;    
    else        
      // Add read object
      if (pADDDOCfg^.RdWr)$t_BusIFRDWR = _BUS_IF_READ | (pADDDOCfg^.RdWr)$t_BusIFRDWR = _BUS_IF_READ_DYN then      
        
        sd_retval := VaranIn.AddRdDO( p_us_position_info  := p_VaranPosition
                                    , ud_dol_type         := _ud_dol_type
                                    , p_ud_handle         := (#pCurrentDO^.pHandle)$^UDINT
                                    , ud_address          := DeviceAddress + pADDDOCfg^.ud_addressoff_read
                                    , ud_length           := pADDDOCfg^.ui_length_read
                                    , p_ud_data           := (#pCurrentDO^.pDataRead)$^UDINT
                                    , ud_type             := tmpDOType or _priority);       
      
      // Add write object
      elsif (pADDDOCfg^.RdWr)$t_BusIFRDWR = _BUS_IF_WRITE | (pADDDOCfg^.RdWr)$t_BusIFRDWR = _BUS_IF_WRITE_DYN then
      
        sd_retval := VaranIn.AddWrDO( p_us_position_info  := p_VaranPosition
                                    , ud_dol_type         := _ud_dol_type
                                    , p_ud_handle         := (#pCurrentDO^.pHandle)$^UDINT
                                    , ud_address          := DeviceAddress + pADDDOCfg^.ud_addressoff_write
                                    , ud_length           := pADDDOCfg^.ui_length_write
                                    , p_ud_data           := (#pCurrentDO^.pDataWrite)$^UDINT
                                    , ud_type             := tmpDOType or _priority);
      
      // Add read/write object
      else
      
        sd_retval := VaranIn.AddRdWrDO( p_us_position_info  := p_VaranPosition
                                      , ud_dol_type         := _ud_dol_type
                                      , p_ud_handle         := (#pCurrentDO^.pHandle)$^UDINT
                                      , ud_address_read     := DeviceAddress + pADDDOCfg^.ud_addressoff_read
                                      , ud_length_read      := pADDDOCfg^.ui_length_read
                                      , p_ud_data_read      := (#pCurrentDO^.pDataRead)$^UDINT
                                      , ud_address_write    := DeviceAddress + pADDDOCfg^.ud_addressoff_write
                                      , ud_length_write     := pADDDOCfg^.ui_length_write
                                      , p_ud_data_write     := (#pCurrentDO^.pDataWrite)$^UDINT
                                      , ud_type             := tmpDOType);
      end_if;
    end_if;    
                              
    if sd_retval = 0 then          
      pCurrentDO^.pLocalRdMem := NIL;
      pCurrentDO^.pLocalWrMem := NIL;
    
      // 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^.maxLengthRead  := pADDDOCfg^.ui_length_read;
        pCurrentDO^.AddrOffsetRead := pADDDOCfg^.ud_addressoff_read;
        
        if (b_PayloadSupport = False) & pADDDOCfg^.ui_length_read > 128 then
          pCurrentDO^.IsLongDO := TRUE;
          pCurrentDO^.pLongDOSettings := pCurrentDO^.pHandle$^t_VaranDOSettingsLong + sizeof(LSL_VARANFRAME);
          pCurrentDO^.pDataRead       := pCurrentDO^.pLongDOSettings$^UDINT + sizeof(t_VaranDOSettingsLong);

          pCurrentDO^.pLongDOSettings^.ud_Address      := DeviceAddress + pADDDOCfg^.ud_addressoff_read; 
          pCurrentDO^.pLongDOSettings^.ui_ByteCount0   := pADDDOCfg^.ui_length_read;
          pCurrentDO^.pLongDOSettings^.us_ByteCount1   := 0;
          pCurrentDO^.pHandle^.usSendBufferLength      := 16#FFFF;
          pCurrentDO^.pHandle^.usLengthofExpAnswer     := 16#FFFF;          
        end_if;

        // we use local copy only if DMA is not active (DMA does the same)
        if pADDDOCfg^.b_UseLocalCopy & (b_DMAActive = FALSE) then
          pCurrentDO^.pLocalRdMem := To_StdLib.Malloc(size:=pCurrentDO^.maxLengthRead);
          
          if pCurrentDO^.pLocalRdMem = NIL then
            LogError("@018F (BusInterfaceVARAN::AddDO) Failed to allocate local memory for read DO");
          else
            _memset(dest:=pCurrentDO^.pLocalRdMem, usByte:=0, cntr:=pCurrentDO^.maxLengthRead);
          end_if;
          
          // return pointer to DPRAM in the input parameter
          pADDDOCfg^.ud_addressoff_read := pCurrentDO^.pDataRead$HDINT;
        end_if;

      elsif (pADDDOCfg^.RdWr)$t_BusIFRDWR = _BUS_IF_WRITE | (pADDDOCfg^.RdWr)$t_BusIFRDWR = _BUS_IF_WRITE_DYN then
        pCurrentDO^.lengthWrite    := pADDDOCfg^.ui_length_write;
        pCurrentDO^.maxLengthWrite := pADDDOCfg^.ui_length_write;
        pCurrentDO^.AddrOffsetWrite:= pADDDOCfg^.ud_addressoff_write;

        if (b_PayloadSupport = False) & pADDDOCfg^.ui_length_write > 128 then
          pCurrentDO^.IsLongDO := TRUE;
          pCurrentDO^.pLongDOSettings := pCurrentDO^.pHandle$^t_VaranDOSettingsLong + sizeof(LSL_VARANFRAME);
          pCurrentDO^.pDataWrite      := pCurrentDO^.pLongDOSettings$^UDINT + sizeof(t_VaranDOSettingsLong);

          pCurrentDO^.pLongDOSettings^.ud_Address      := DeviceAddress + pADDDOCfg^.ud_addressoff_write; 
          pCurrentDO^.pLongDOSettings^.ui_ByteCount0   := pADDDOCfg^.ui_length_write;
          pCurrentDO^.pLongDOSettings^.us_ByteCount1   := 0;
          pCurrentDO^.pHandle^.usSendBufferLength      := 16#FFFF;
          pCurrentDO^.pHandle^.usLengthofExpAnswer     := 16#FFFF;
        end_if;

        // we use local copy only if DMA is not active (DMA does the same)
        if pADDDOCfg^.b_UseLocalCopy & (b_DMAActive = FALSE) then
          pCurrentDO^.pLocalWrMem := To_StdLib.Malloc(size:=pCurrentDO^.maxLengthWrite);
          
          if pCurrentDO^.pLocalWrMem = NIL then
            LogError("@0190 (BusInterfaceVARAN::AddDO) Failed to allocate local memory for write DO");
          else
            _memset(dest:=pCurrentDO^.pLocalWrMem, usByte:=0, cntr:=pCurrentDO^.maxLengthWrite);
          end_if;

          // return pointer to DPRAM in the input parameter
          pADDDOCfg^.ud_addressoff_write := pCurrentDO^.pDataWrite$HDINT;
        end_if;
      else
        pCurrentDO^.lengthRead     := pADDDOCfg^.ui_length_read;
        pCurrentDO^.maxLengthRead  := pADDDOCfg^.ui_length_read;
        pCurrentDO^.AddrOffsetRead := pADDDOCfg^.ud_addressoff_read;
        pCurrentDO^.lengthWrite    := pADDDOCfg^.ui_length_write;
        pCurrentDO^.maxLengthWrite := pADDDOCfg^.ui_length_write;
        pCurrentDO^.AddrOffsetWrite:= pADDDOCfg^.ud_addressoff_write; 

        // we use local copy only if DMA is not active (DMA does the same)
        if pADDDOCfg^.b_UseLocalCopy & (b_DMAActive = FALSE) then
          pCurrentDO^.pLocalRdMem := To_StdLib.Malloc(size:=pCurrentDO^.maxLengthRead);
          
          if pCurrentDO^.pLocalRdMem = NIL then
            LogError("@0191 (BusInterfaceVARAN::AddDO) Failed to allocate local memory for read access of read/write DO");
          else
            _memset(dest:=pCurrentDO^.pLocalRdMem, usByte:=0, cntr:=pCurrentDO^.maxLengthRead);
          end_if;


          pCurrentDO^.pLocalWrMem := To_StdLib.Malloc(size:=pCurrentDO^.maxLengthWrite);
          
          if pCurrentDO^.pLocalWrMem = NIL then
            LogError("@0192 (BusInterfaceVARAN::AddDO) Failed to allocate local memory for write access of read/write DO");
          else
            _memset(dest:=pCurrentDO^.pLocalWrMem, usByte:=0, cntr:=pCurrentDO^.maxLengthWrite);
          end_if;
        end_if;
      end_if;
      
      pCurrentDO^.RdWr           := (pADDDOCfg^.RdWr)$t_BusIFRDWR;
      
      if pADDDOCfg^.Priority = _BUS_IF_ISO       |
         pADDDOCfg^.Priority = _BUS_IF_ISO_MOVE  | 
       (pADDDOCfg^.Priority)$t_BusIFPriority  = _BUS_IF_ISO_ADDLATER then
        pCurrentDO^.Priority := _BUS_IF_ISO;
      else
        pCurrentDO^.Priority := _BUS_IF_ASY;
      end_if;
      
      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 := sd_retval;
      pResult^.aData$t_AddDORet.Handle    := (#pCurrentDO^)$UDINT;
      
      if pCurrentDO^.pLocalRdMem then
        pResult^.aData$t_AddDORet.pDataRead := pCurrentDO^.pLocalRdMem;
        apLocalRdCopyDOs[LocalRdCopyNo].pSource := pCurrentDO^.pDataRead;
        apLocalRdCopyDOs[LocalRdCopyNo].pDest   := pCurrentDO^.pLocalRdMem;
        apLocalRdCopyDOs[LocalRdCopyNo].Length  := pCurrentDO^.maxLengthRead;
        LocalRdCopyNo += 1;
      else
        pResult^.aData$t_AddDORet.pDataRead := (pCurrentDO^.pDataRead);
      end_if;
        
      if pCurrentDO^.pLocalWrMem then
        pResult^.aData$t_AddDORet.pDataWrite:= pCurrentDO^.pLocalWrMem;      
        apLocalWrCopyDOs[LocalWrCopyNo].pSource := pCurrentDO^.pLocalWrMem;
        apLocalWrCopyDOs[LocalWrCopyNo].pDest   := pCurrentDO^.pDataWrite;
        apLocalWrCopyDOs[LocalWrCopyNo].Length  := pCurrentDO^.maxLengthWrite;
        LocalWrCopyNo += 1;
      else
        pResult^.aData$t_AddDORet.pDataWrite:= (pCurrentDO^.pDataWrite);
      end_if;

      // Return Handle if needed for a payload move DO
      if (pADDDOCfg^.Priority = _BUS_IF_ISO_MOVE 
      | pADDDOCfg^.Priority = _BUS_IF_ASY_MOVE) 
      & b_PayloadSupport then
        pResult^.aData$t_AddDORet.AccessHandle := (pCurrentDO^.pHandle)$UDINT;
      else
        pResult^.aData$t_AddDORet.AccessHandle := 0;
      end_if;

      NrDO += 1;
    else              
      if (b_LongDOsPossible = FALSE) & 
         ((((pADDDOCfg^.RdWr)$t_BusIFRDWR = _BUS_IF_READ)  & (pADDDOCfg^.ui_length_read  > 128)) | 
          (((pADDDOCfg^.RdWr)$t_BusIFRDWR = _BUS_IF_WRITE) & (pADDDOCfg^.ui_length_write > 128)))  then
        LogError("@0193 (BusInterfaceVARAN::AddDO) The FPGA of the VARAN Manager does not support Long DOs. Newer Version required!");
      else
        LogValue("@0194 (BusInterfaceVARAN::AddDO) Failed! sd_retval = -0x{0}", Value:=(0-sd_retval)$UDINT);
      end_if;
      pResult^.aData$t_AddDORet.retcode   := _BUS_IF_RETVAL_ERROR_CREATE_DO_FAILED;
      pResult^.aData$t_AddDORet.sd_retval := sd_retval; // Return sd_retval with info why DO creation failed.
    end_if;           
    
  else            
    pResult^.aData$t_AddDORet.retcode := _BUS_IF_RETVAL_ERROR_DO_LIST_FULL;
  end_if;

END_FUNCTION


FUNCTION VIRTUAL GLOBAL BusInterfaceVARAN::AddMoveDO
	VAR_INPUT
		pCmd 	          : ^CmdStruct;
		presult 	      : ^results;
	END_VAR
  VAR
  	pADDMOVEDOCfg   : ^t_AddMoveDOCfg;
    pCurrentDO      : ^t_DOMoveCfg;
    p_MoveSettings  : ^t_VaranDOSettingsMov;
    _ud_dol_type    : UDINT;    
    sd_retval       : DINT;
    i               : USINT;
    CopyLenOld      : UINT;
    CopyLenRest     : UINT;
    OldWrCopyNo     : USINT;
  END_VAR
  
  presult^.uiLng    := sizeof(t_AddMoveDORet);
  
  if b_CallBackInstalled = FALSE then
    LogError("@0195 (BusInterfaceVARAN::AddMoveDO) Error: Varan Callback must be installed before DOs can be created!");
    pResult^.aData$t_AddDORet.retcode := _BUS_IF_RETVAL_ERROR_NO_CALLBACK_INSTALLED;
    return;
  end_if;
  
  if NrDOMove < BUSIF_VARAN_MAX_NR_MOVEDO then
  
    pADDMOVEDOCfg := ((pCmd^.aPara[0])$^t_AddMoveDOCfg);  
    
    // Convert passed t_Priority to VARAN ud_dol_type
    if (pADDMOVEDOCfg^.Priority)$t_BusIFPriority  = _BUS_IF_ISO | 
       (pADDMOVEDOCfg^.Priority)$t_BusIFPriority  = _BUS_IF_ISO_MOVE then
      _ud_dol_type := VARAN_DOL_ISO;
    else    
      _ud_dol_type := VARAN_DOL_ASY;
    end_if;
    
    pCurrentDO := #DOListMove[NrDOMove];
    
    if b_PayloadSupport then
      sd_retval := AddMovePayloadDO(ud_dol_type                 := _ud_dol_type
                                  , p_ud_handle                 := (#pCurrentDO^.pHandle)$^UDINT
                                  , ud_SourceReadDOHandle       := pADDMOVEDOCfg^.ud_handle_source
                                  , ud_SourceReadOffset         := pADDMOVEDOCfg^.ud_addressoff_source
                                  , ud_DestinationWriteDOHandle := pADDMOVEDOCfg^.ud_handle_dest
                                  , ud_DestinationWriteOffset   := pADDMOVEDOCfg^.ud_addressoff_dest
                                  , ud_LengthMove               := pADDMOVEDOCfg^.ud_length_move
                                  , ud_Priority                 := VM_PRIORITY_SAFETY_MOVE_DO);
    else
      sd_retval := VaranIn.AddMovDO(ud_dol_type     := _ud_dol_type
                                  , p_ud_handle     := (#pCurrentDO^.pHandle)$^UDINT
                                  , p_ud_MovSettings:= (#p_MoveSettings)$^UDINT
                                  , ud_type         := VM_PRIORITY_2);
    end_if;

    if sd_retval = 0 then
      
      if b_PayloadSupport then
      
        pCurrentDO^.sourceDOHandle  := pADDMOVEDOCfg^.ud_handle_source;
        pCurrentDO^.pSourceDOData   := pADDMOVEDOCfg^.p_sourcedata;
        pCurrentDO^.sourceDOOffset  := pADDMOVEDOCfg^.ud_addressoff_source;
        pCurrentDO^.destDOHandle    := pADDMOVEDOCfg^.ud_handle_dest;
        pCurrentDO^.pDestDOData     := pADDMOVEDOCfg^.p_destdata;
        pCurrentDO^.DestDOOffset    := pADDMOVEDOCfg^.ud_addressoff_dest;
        pCurrentDO^.lengthMove      := pADDMOVEDOCfg^.ud_length_move;
        pCurrentDO^.lengthMoveMax   := pADDMOVEDOCfg^.ud_length_move;
        
        if pADDMOVEDOCfg^.Priority = _BUS_IF_ISO |
           pADDMOVEDOCfg^.Priority = _BUS_IF_ISO_MOVE then
          pCurrentDO^.Priority := _BUS_IF_ISO;
        else
          pCurrentDO^.Priority := _BUS_IF_ASY;
        end_if;
        
        pCurrentDO^.p_MovSettings   := nil; // Not used with payload
      
      else

        // check if we have to split a local copy (to save time)
        if LocalWrCopyNo then 
          for i := 0 to LocalWrCopyNo-1 do
            // check if the mov command is somewhere in the copy command of RT
            if (pADDMOVEDOCfg^.p_destdata >= apLocalWrCopyDOs[i].pDest) & 
               ((pADDMOVEDOCfg^.p_destdata + pADDMOVEDOCfg^.ud_length_move) <= (apLocalWrCopyDOs[i].pDest + apLocalWrCopyDOs[i].Length)) then
            
              // found it => split up the local copy command to skip the mov command
              
              // we have to modify the old in any case => prevent rt from copying anything while it's being modified
              OldWrCopyNo := LocalWrCopyNo;
              LocalWrCopyNo := 0;
              
              // if the mov is at the beginning of the copy command => we don't need an extra copy, just modify the actual
              if pADDMOVEDOCfg^.p_destdata = apLocalWrCopyDOs[i].pDest then
                apLocalWrCopyDOs[i].pSource += pADDMOVEDOCfg^.ud_length_move;
                apLocalWrCopyDOs[i].pDest   += pADDMOVEDOCfg^.ud_length_move;
                apLocalWrCopyDOs[i].Length  -= pADDMOVEDOCfg^.ud_length_move;
                
                // restore old number
                LocalWrCopyNo := OldWrCopyNo;
                
              // if the mov is at the end of the copy command => we don't need an extra copy, just modify the actual
              elsif (pADDMOVEDOCfg^.p_destdata + pADDMOVEDOCfg^.ud_length_move) = (apLocalWrCopyDOs[i].pDest + apLocalWrCopyDOs[i].Length) then
                apLocalWrCopyDOs[i].Length  -= pADDMOVEDOCfg^.ud_length_move;

                // restore old number
                LocalWrCopyNo := OldWrCopyNo;

              else
                // it's somewhere between and we need to modify the actual and create an extra copy

                // remember the old length
                CopyLenOld := apLocalWrCopyDOs[i].Length;

                // modify old one to copy the first block (pointers stay the same)                
                apLocalWrCopyDOs[i].Length  := (pADDMOVEDOCfg^.p_destdata$HDINT - apLocalWrCopyDOs[i].pDest$HDINT)$UINT;
                
                // get the rest-length for the new copy command (old length - length of modified copy - length of mov)
                CopyLenRest := CopyLenOld - apLocalWrCopyDOs[i].Length - pADDMOVEDOCfg^.ud_length_move;

                // create a new one for the rest (increase the old pointers by the length of the modified copy + length of mov)
                apLocalWrCopyDOs[OldWrCopyNo].pSource := apLocalWrCopyDOs[i].pSource + apLocalWrCopyDOs[i].Length + pADDMOVEDOCfg^.ud_length_move;
                apLocalWrCopyDOs[OldWrCopyNo].pDest   := apLocalWrCopyDOs[i].pDest   + apLocalWrCopyDOs[i].Length + pADDMOVEDOCfg^.ud_length_move;
                apLocalWrCopyDOs[OldWrCopyNo].Length  := CopyLenRest;

                // restore old number increased by 1
                LocalWrCopyNo := OldWrCopyNo + 1;
              end_if;
            
              us_SkippedWriteBlocks += 1;
              exit;
            end_if;
          end_for;
        end_if;

        pCurrentDO^.sourceDOHandle  := 0; // Not used
        pCurrentDO^.pSourceDOData   := pADDMOVEDOCfg^.p_sourcedata;
        pCurrentDO^.sourceDOOffset  := 0; // Not used
        pCurrentDO^.destDOHandle    := 0; // Not used
        pCurrentDO^.pDestDOData     := pADDMOVEDOCfg^.p_destdata;
        pCurrentDO^.DestDOOffset    := 0; // Not used
        pCurrentDO^.lengthMove      := pADDMOVEDOCfg^.ud_length_move;
        pCurrentDO^.lengthMoveMax   := pADDMOVEDOCfg^.ud_length_move;
        
        if pADDMOVEDOCfg^.Priority = _BUS_IF_ISO |
           pADDMOVEDOCfg^.Priority = _BUS_IF_ISO_MOVE then
          pCurrentDO^.Priority := _BUS_IF_ISO;
        else
          pCurrentDO^.Priority := _BUS_IF_ASY;
        end_if;
        
        p_MoveSettings^.ud_AddressDest  := (pCurrentDO^.pDestDOData)$UDINT;
        p_MoveSettings^.ud_AddressSrc   := (pCurrentDO^.pSourceDOData)$UDINT;
        p_MoveSettings^.ui_ByteCnt      := pCurrentDO^.lengthMove;
        
        pCurrentDO^.p_MovSettings   := p_MoveSettings;       
        
      end_if;
      
      // Return Values
      presult^.aData$t_AddMoveDORet.retcode   := _BUS_IF_RETVAL_OK;
      pResult^.aData$t_AddMoveDORet.sd_retval := sd_retval;
      pResult^.aData$t_AddMoveDORet.Handle    := (#pCurrentDO^)$UDINT;
      
      NrDOMove += 1;
    else
      pResult^.aData$t_AddDORet.retcode := _BUS_IF_RETVAL_ERROR_CREATE_MOVE_DO_FAILED;
    end_if;
  else
    pResult^.aData$t_AddDORet.retcode := _BUS_IF_RETVAL_ERROR_MOVE_DO_LIST_FULL;
  end_if;

END_FUNCTION


FUNCTION VIRTUAL GLOBAL BusInterfaceVARAN::UpdateDO
	VAR_INPUT
		pCmd 	            : ^CmdStruct;
		presult 	        : ^results;
	END_VAR
  VAR
    pUPDATEDOCfg      : ^t_UpdateDOCfg;
    pCurrentDO        : ^t_DOCfg;
    changed           : BOOL; 
    
    p_DOSettingsRd    : ^t_VaranDOSettingsRd;
    p_DOSettingsWr    : ^t_VaranDOSettingsWr;
    p_DOSettingsRdWr  : ^t_VaranDOSettingsRdWr;
  END_VAR
  
  changed := false;
  pUPDATEDOCfg := ((pCmd^.aPara[0])$^t_UpdateDOCfg); 
  
  pResult^.uiLng := 4;
  
  if CheckHandle(Handle:= pUPDATEDOCfg^.Handle) then
    
    pCurrentDO := (pUPDATEDOCfg^.Handle)$^t_DOCfg;
    
    // Check if parameters were changed
    // Read Object
    if pCurrentDO^.RDWR = _BUS_IF_READ then
    
      if pCurrentDO^.lengthRead <> pUPDATEDOCfg^.ud_length_read  then
        // Check that new DO length is smaller then max DO length
        if pCurrentDO^.maxLengthRead >= pUPDATEDOCfg^.ud_length_read  then
          pCurrentDO^.lengthRead := pUPDATEDOCfg^.ud_length_read;
          changed := true;
        else
          pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_ERROR_UPDATEDO_DOLENGTH;
          return;
        end_if;
      end_if;
      
      if pCurrentDO^.AddrOffsetRead <>  pUPDATEDOCfg^.ud_addressoff_read then
        pCurrentDO^.AddrOffsetRead := pUPDATEDOCfg^.ud_addressoff_read;
        changed := true;
      end_if;
    
    // Write Object
    elsif pCurrentDO^.RDWR = _BUS_IF_WRITE then
    
      if pCurrentDO^.lengthWrite <> pUPDATEDOCfg^.ud_length_write  then
        // Check that new DO length is smaller then max DO length
        if pCurrentDO^.maxLengthWrite >= pUPDATEDOCfg^.ud_length_write  then
          pCurrentDO^.lengthWrite := pUPDATEDOCfg^.ud_length_write;
          changed := true;
        else
          pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_ERROR_UPDATEDO_DOLENGTH;
          return;
        end_if;       
      end_if;      
      
      if pCurrentDO^.AddrOffsetWrite <>  pUPDATEDOCfg^.ud_addressoff_write then
        pCurrentDO^.AddrOffsetWrite := pUPDATEDOCfg^.ud_addressoff_write;
        changed := true;
      end_if;
    
    // Read Write Object
    else 
    
      if pCurrentDO^.lengthRead <> pUPDATEDOCfg^.ud_length_read  then
        // Check that new DO length is smaller then max DO length
        if pCurrentDO^.maxLengthRead >= pUPDATEDOCfg^.ud_length_read  then
          pCurrentDO^.lengthRead := pUPDATEDOCfg^.ud_length_read;
          changed := true;
        else
          pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_ERROR_UPDATEDO_DOLENGTH;
          return;
        end_if;
      end_if;      
      
      if pCurrentDO^.AddrOffsetRead <>  pUPDATEDOCfg^.ud_addressoff_read then
        pCurrentDO^.AddrOffsetRead := pUPDATEDOCfg^.ud_addressoff_read;
        changed := true;
      end_if;
      
      if pCurrentDO^.lengthWrite <> pUPDATEDOCfg^.ud_length_write  then
        // Check that new DO length is smaller then max DO length
        if pCurrentDO^.maxLengthWrite >= pUPDATEDOCfg^.ud_length_write  then
          pCurrentDO^.lengthWrite := pUPDATEDOCfg^.ud_length_write;
          changed := true;
        else
          pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_ERROR_UPDATEDO_DOLENGTH;
          return;
        end_if;
      end_if;      
      
      if pCurrentDO^.AddrOffsetWrite <>  pUPDATEDOCfg^.ud_addressoff_write then
        pCurrentDO^.AddrOffsetWrite := pUPDATEDOCfg^.ud_addressoff_write;
        changed := true;
      end_if;
    
    end_if;   

    if b_PayloadSupport then
      if changed then
        // Update Address and length
        // Read Object
        if pCurrentDO^.RDWR = _BUS_IF_READ then
        
          ChangeDOLengthOffset( ud_DOHandle     := pCurrentDO^.pHandle$UDINT
                              , ud_offset_read  := pCurrentDO^.AddrOffsetRead
                              , ud_length_read  := pCurrentDO^.lengthRead);
          
        // Write Object
        elsif pCurrentDO^.RDWR = _BUS_IF_WRITE then
        
          ChangeDOLengthOffset( ud_DOHandle     := pCurrentDO^.pHandle$UDINT
                              , ud_offset_write := pCurrentDO^.AddrOffsetWrite
                              , ud_length_write := pCurrentDO^.lengthWrite);
      
        // Read Write Object
        else
          ChangeDOLengthOffset( ud_DOHandle     := pCurrentDO^.pHandle$UDINT
                              , ud_offset_read  := pCurrentDO^.AddrOffsetRead
                              , ud_length_read  := pCurrentDO^.lengthRead
                              , ud_offset_write := pCurrentDO^.AddrOffsetWrite
                              , ud_length_write := pCurrentDO^.lengthWrite);
        end_if;
      end_if;
    elsif pCurrentDO^.IsLongDO = FALSE then
      
      // Update Address and length and Reset DO
      // Read Object
      if pCurrentDO^.RDWR = _BUS_IF_READ then
      
        p_DOSettingsRd    := pCurrentDO^.pDataRead$^t_VaranDOSettingsRd  - VM_DO_OFFSET_RD;
        
        p_DOSettingsRd^.ud_Address                := DeviceAddress + pCurrentDO^.AddrOffsetRead;
        p_DOSettingsRd^.us_ByteCnt                := pCurrentDO^.lengthRead$USINT;
        pCurrentDO^.pHandle^.usLengthofExpAnswer  := sizeof(t_VaranDOSettingsRd.us_Command) + pCurrentDO^.lengthRead;
          
        ResetDataObject(p_handleDO:=  pCurrentDO^.pHandle
                      , us_state  :=  pCurrentDO^.pHandle^.ucCtrlStat AND 3         // don't change run status, just recalculate the retry timeout here
                      , ud_bytes  :=  pCurrentDO^.lengthRead);
      
      // Write Object
      elsif pCurrentDO^.RDWR = _BUS_IF_WRITE then
        
        p_DOSettingsWr    := pCurrentDO^.pDataWrite$^t_VaranDOSettingsWr - VM_DO_OFFSET_WR;
        
        p_DOSettingsWr^.ud_Address              := DeviceAddress + pCurrentDO^.AddrOffsetWrite;
        p_DOSettingsWr^.us_ByteCnt              := pCurrentDO^.lengthWrite$USINT;
        pCurrentDO^.pHandle^.usSendBufferLength := sizeof(t_VaranDOSettingsWr) + pCurrentDO^.lengthWrite;
        
        ResetDataObject(p_handleDO:=  pCurrentDO^.pHandle
                      , us_state  :=  pCurrentDO^.pHandle^.ucCtrlStat AND 3         // don't change run status, just recalculate the retry timeout here
                      , ud_bytes  :=  pCurrentDO^.lengthWrite);
      
      // Read Write Object
      else 
        p_DOSettingsRdWr  := pCurrentDO^.pDataWrite$^t_VaranDOSettingsRdWr - VM_DO_OFFSET_RDWR;  
        
        p_DOSettingsRdWr^.ud_AddressRd := DeviceAddress + pCurrentDO^.AddrOffsetRead;        
        p_DOSettingsRdWr^.ud_AddressWr := DeviceAddress + pCurrentDO^.AddrOffsetWrite;
        
        p_DOSettingsRdWr^.us_ByteCntRd  := pCurrentDO^.lengthRead$USINT; 
        p_DOSettingsRdWr^.us_ByteCntWr  := pCurrentDO^.lengthWrite$USINT;      
        
        pCurrentDO^.pHandle^.usLengthofExpAnswer  := sizeof(t_VaranDOSettingsRdWr.us_Command) + pCurrentDO^.lengthRead;
        pCurrentDO^.pHandle^.usSendBufferLength   := sizeof(t_VaranDOSettingsRdWr) + pCurrentDO^.lengthWrite;
        
        ResetDataObject(p_handleDO:=  pCurrentDO^.pHandle
                      , us_state  :=  pCurrentDO^.pHandle^.ucCtrlStat AND 3         // don't change run status, just recalculate the retry timeout here
                      , ud_bytes  :=  pCurrentDO^.lengthRead + pCurrentDO^.lengthWrite);    
      
      end_if;
    else
      
      // change long DO
      
      // Update Address and length and Reset DO
      // Read Object
      if pCurrentDO^.RDWR = _BUS_IF_READ then
      
        pCurrentDO^.pLongDOSettings^.ud_Address      := DeviceAddress + pCurrentDO^.AddrOffsetRead; 
        pCurrentDO^.pLongDOSettings^.ui_ByteCount0   := pCurrentDO^.lengthRead;
        pCurrentDO^.pLongDOSettings^.us_ByteCount1   := 0;
        pCurrentDO^.pHandle^.usSendBufferLength      := 16#FFFF;
        pCurrentDO^.pHandle^.usLengthofExpAnswer     := 16#FFFF;
      
      // Write Object
      elsif pCurrentDO^.RDWR = _BUS_IF_WRITE then

        pCurrentDO^.pLongDOSettings^.ud_Address      := DeviceAddress + pCurrentDO^.AddrOffsetWrite; 
        pCurrentDO^.pLongDOSettings^.ui_ByteCount0   := pCurrentDO^.lengthWrite;
        pCurrentDO^.pLongDOSettings^.us_ByteCount1   := 0;
        pCurrentDO^.pHandle^.usSendBufferLength      := 16#FFFF;
        pCurrentDO^.pHandle^.usLengthofExpAnswer     := 16#FFFF;
        
      end_if;
    end_if;

    pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_OK;
  
  else
    pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_ERROR_INVALID_HANDLE;  
  end_if;  
  
END_FUNCTION


FUNCTION VIRTUAL GLOBAL BusInterfaceVARAN::UpdateMoveDO
	VAR_INPUT
		pCmd 	        : ^CmdStruct;
		presult 	    : ^results;
	END_VAR
  VAR
    pUPDATEDOCfg  : ^t_UpdateDOMoveCfg;
    pCurrentDO    : ^t_DOMoveCfg;  
    sd_retval     : DINT;
  END_VAR

  pUPDATEDOCfg := ((pCmd^.aPara[0])$^t_UpdateDOMoveCfg); 
  
  pResult^.uiLng := 4;
  
  if CheckMovHandle(Handle:= pUPDATEDOCfg^.Handle) then
  
    pCurrentDO := (pUPDATEDOCfg^.Handle)$^t_DOMoveCfg;
    
    // Check if length Parameter was passed
    // Length is used with Payload and without
    if (pUPDATEDOCfg^.ud_length_move <> 0) &
       pUPDATEDOCfg^.ud_length_move <> VM_DO_PROPERTY_INVALID  then
      // if the size is smaller than the maximum or if we don't have interrupted our own copy for the move command
      if (pUPDATEDOCfg^.ud_length_move <= pCurrentDO^.lengthMoveMax) | (us_SkippedWriteBlocks = 0) then
        pCurrentDO^.lengthMove := pUPDATEDOCfg^.ud_length_move;
      else
        pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_ERROR_UPDATEDO_DOLENGTH;  
        return;
      end_if;
    end_if;
    
    if b_PayloadSupport then
      
      if  pUPDATEDOCfg^.ud_handle_source <> 0 &
          pUPDATEDOCfg^.ud_handle_source <> VM_DO_PROPERTY_INVALID  then
        
        pCurrentDO^.sourceDOHandle := pUPDATEDOCfg^.ud_handle_source;
      end_if;
      
      if  pUPDATEDOCfg^.ud_addressoff_source <> VM_DO_PROPERTY_INVALID  then  // 0 is valid offset
        
        pCurrentDO^.sourceDOOffset := pUPDATEDOCfg^.ud_addressoff_source;
      end_if;
      
      if  pUPDATEDOCfg^.ud_handle_dest <> 0 &
          pUPDATEDOCfg^.ud_handle_dest <> VM_DO_PROPERTY_INVALID  then
        
        pCurrentDO^.destDOHandle := pUPDATEDOCfg^.ud_handle_dest;
      end_if;
      
      if  pUPDATEDOCfg^.ud_addressoff_dest <> VM_DO_PROPERTY_INVALID  then  // 0 is valid offset
        
        pCurrentDO^.destDOOffset := pUPDATEDOCfg^.ud_addressoff_dest;
      end_if;
      
      sd_retval := ChangeMovDOLengthOffset( ud_MovDOHandle              := pCurrentDO^.pHandle$UDINT
                                          , ud_SourceReadDOHandle       := pCurrentDO^.sourceDOHandle
                                          , ud_SourceReadOffset         := pCurrentDO^.sourceDOOffset
                                          , ud_DestinationWriteDOHandle := pCurrentDO^.destDOHandle
                                          , ud_DestinationWriteOffset   := pCurrentDO^.destDOOffset
                                          , ud_LengthMove               := pCurrentDO^.lengthMove);
                                          
      if sd_retval then
        pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_ERROR_UPDATE_MOVE_DO_FAILED;
      else   
        pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_OK;
      end_if;

    else
    
      if pUPDATEDOCfg^.p_sourcedata <> nil &
         pUPDATEDOCfg^.p_sourcedata <> VM_DO_PROPERTY_INVALID then
      
        pCurrentDO^.pSourceDOData := pUPDATEDOCfg^.p_sourcedata;
      end_if;

      if pUPDATEDOCfg^.p_destdata   <> nil &
         pUPDATEDOCfg^.p_destdata   <> VM_DO_PROPERTY_INVALID then
      
        pCurrentDO^.pDestDOData := pUPDATEDOCfg^.p_destdata;
      end_if;
      
      pCurrentDO^.p_MovSettings^.ud_AddressSrc  := pCurrentDO^.pSourceDOData$UDINT;
      pCurrentDO^.p_MovSettings^.ud_AddressDest := pCurrentDO^.pDestDOData$UDINT;
      pCurrentDO^.p_MovSettings^.ui_ByteCnt     := pCurrentDO^.lengthMove;
      
      pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_OK;
    end_if;
    
  else
    pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_ERROR_INVALID_HANDLE;  
  end_if;
  
END_FUNCTION


FUNCTION VIRTUAL GLOBAL BusInterfaceVARAN::SetDOPrescaler
	VAR_INPUT
		pCmd 	        : ^CmdStruct;
		presult 	    : ^results;
	END_VAR
  VAR
    pSetDOPreSCfg : ^t_SetDoPrescaler;
    pCurrentDO    : ^t_DOCfg;    
  END_VAR
  
  pSetDOPreSCfg := ((pCmd^.aPara[0])$^t_SetDoPrescaler); 
  
  pResult^.uiLng := 4;
  
  if CheckHandle(Handle:= pSetDOPreSCfg^.Handle) then
    
    pCurrentDO := (pSetDOPreSCfg^.Handle)$^t_DOCfg;
    
    if b_PayloadSupport then
    
      if SetPrescaler( ud_DOHandle   := pCurrentDO^.pHandle$UDINT
                     , Prescaler     := pSetDOPreSCfg^.Prescaler
                     , PrescalerCnt  := 0) = VARANMANAGER_OK then // Start at 0 = default We probably need to extend this functionality
      
        pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_OK;
      else
        pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_ERROR_INVALID_HANDLE;  
      end_if;
    else      
    
      pCurrentDO^.pHandle^.ucExePrescaler := pSetDOPreSCfg^.Prescaler;
      pCurrentDO^.PreScaler := pSetDOPreSCfg^.Prescaler;  // Saved as needed again as init value
    
      pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_OK;
    end_if;    
  else
  
    pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_ERROR_INVALID_HANDLE;  
  end_if;  

END_FUNCTION  

  
FUNCTION VIRTUAL GLOBAL BusInterfaceVARAN::SetTasksPrescaler
	VAR_INPUT
		pCmd 	            : ^CmdStruct;
		presult 	        : ^results;
	END_VAR
  VAR
  	pTaskPreScalerCfg : ^t_TaskPreScaler;
  END_VAR
  
  pTaskPreScalerCfg  := ((pCmd^.aPara[0])$^t_TaskPreScaler); 
  
  pResult^.uiLng := 4;
  
  // Check passed data
  if pTaskPreScalerCfg^.Prescaler > 0 & 
     pTaskPreScalerCfg^.Prescaler >= pTaskPreScalerCfg^.RtPreScanTrigger & 
     pTaskPreScalerCfg^.Prescaler >= pTaskPreScalerCfg^.RtPostScanTrigger & 
     pTaskPreScalerCfg^.Prescaler >= pTaskPreScalerCfg^.CyTrigger then
     
    TaskPrescaler.MaxCnt            := pTaskPreScalerCfg^.Prescaler;
    TaskPrescaler.RtPreScanTigger   := pTaskPreScalerCfg^.RtPreScanTrigger;
    TaskPrescaler.RtPostScanTrigger := pTaskPreScalerCfg^.RtPostScanTrigger;
    TaskPrescaler.CyTrigger         := pTaskPreScalerCfg^.CyTrigger;
  
    pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_OK;
  else  
    pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_ERROR_INVALID_DATA;
  end_if;


END_FUNCTION  


FUNCTION VIRTUAL GLOBAL BusInterfaceVARAN::ResetDO
	VAR_INPUT
		pCmd 	      : ^CmdStruct;
		presult 	  : ^results;
	END_VAR
  VAR
    pResetDOCfg : ^t_ResetDOCfg;
    pCurrentDO  : ^t_DOCfg;
  END_VAR

  pResult^.uiLng := 4;
  
  pResetDOCfg := ((pCmd^.aPara[0])$^t_ResetDOCfg);     

  if CheckHandle(Handle:= pResetDOCfg^.Handle) then
  
    // Paylaod DO auto calculate Timeout when the DO changes
    // Just return OK 
    if b_PayloadSupport = false then
    
      pCurrentDO := (pResetDOCfg^.Handle)$^t_DOCfg;
    
      // Reset DO
      // Read Object
      if (pCurrentDO^.RDWR = _BUS_IF_READ) then
        if pCurrentDO^.IsLongDO then
          ResetDataObject(p_handleDO :=  pCurrentDO^.pHandle
                          , us_state :=  VARAN_DO_NO_RUN         // No auto run, DO must be started by specific command
                          , ud_bytes :=  128);
        else
          ResetDataObject(p_handleDO :=  pCurrentDO^.pHandle
                          , us_state :=  VARAN_DO_NO_RUN         // No auto run, DO must be started by specific command
                          , ud_bytes :=  pCurrentDO^.lengthRead);
        end_if;

      // Write DO                      
      elsif pCurrentDO^.RDWR = _BUS_IF_WRITE then
        if pCurrentDO^.IsLongDO then
          ResetDataObject(p_handleDO :=  pCurrentDO^.pHandle
                          , us_state :=  VARAN_DO_NO_RUN         // No auto run, DO must be started by specific command
                          , ud_bytes :=  128);
        else
          ResetDataObject(p_handleDO :=  pCurrentDO^.pHandle
                          , us_state :=  VARAN_DO_NO_RUN         // No auto run, DO must be started by specific command
                          , ud_bytes :=  pCurrentDO^.lengthWrite);
        end_if;

                        
      // Read Write DO
      else
      
        ResetDataObject(p_handleDO:=  pCurrentDO^.pHandle
                        , us_state  :=  VARAN_DO_NO_RUN         // No auto run, DO must be started by specific command
                        , ud_bytes  :=  pCurrentDO^.lengthRead + pCurrentDO^.lengthWrite);
      
      end_if;
    
    end_if;
    
    pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_OK;
      
  else
    pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_ERROR_INVALID_HANDLE;  
  end_if;  
    
END_FUNCTION


FUNCTION VIRTUAL GLOBAL BusInterfaceVARAN::AddTask
	VAR_INPUT
		pCmd 	        : ^CmdStruct;
		presult       : ^results;
	END_VAR
  VAR
  	pTASKCfg      : ^t_TaskCfg;
    _ud_dol_type  : UDINT;
  END_VAR

  presult^.uiLng    := 4;
  
  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 
      p_UserCalls.p_UpdateRt := (pTASKCfg^.pthis)$pVirtualBase;
    elsif pTASKCfg^.callOptions = CALL_OPTION_RT_POSTSCAN then
      p_UserCalls.p_UpDateRtPostScan := (pTASKCfg^.pthis)$pVirtualBase;    
    elsif pTASKCfg^.callOptions = (CALL_OPTION_RT_PRESCAN or CALL_OPTION_RT_POSTSCAN) then
      p_UserCalls.p_UpdateRt := (pTASKCfg^.pthis)$pVirtualBase;
      p_UserCalls.p_UpDateRtPostScan := (pTASKCfg^.pthis)$pVirtualBase;    
    else
      p_UserCalls.p_UpdateCy := (pTASKCfg^.pthis)$pVirtualBase;
    end_if;
    
    //Install Varantask
    VaranIn.AddVaranTask( _ud_dol_type, 
                          p_this:=this,       // The callback pointer cannot be used directly because the class must be derived from VaranBase (p_VaranBase)
                          pTASKCfg^.callOptions);
    
    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 VIRTUAL GLOBAL BusInterfaceVARAN::SetRunState
	VAR_INPUT
		pCmd 	            : ^CmdStruct;
		presult 	        : ^results;
	END_VAR
  VAR
  	pSETRUNSTATECfg   : ^t_SetRunStateCfg;
    pCurrentDO        : ^t_DOCfg;
    pCurrentDOMove    : ^t_DOMoveCfg;
    sd_RetVal         : DINT;
  END_VAR
  
  presult^.uiLng  := 4;
  
  pSETRUNSTATECfg := ((pCmd^.aPara[0])$^t_SetRunStateCfg);
  
  // Standard DO -----------------------------------------------------------------------------
  if CheckHandle(Handle:= pSETRUNSTATECfg^.Handle) then
    
    pCurrentDO := (pSETRUNSTATECfg^.Handle)$^t_DOCfg;
    
    if b_PayloadSupport then
      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
        if EnableDO(ud_DOHandle := pCurrentDO^.pHandle$UDINT) = VARANMANAGER_OK then
        
          //check if do must be added to list
          if bAddDOsToListSupport 
          & pCurrentDO^.bsDoInsert.DOisInserted = FALSE
          & pCurrentDO^.bsDoInsert.RequestInsertLater = TRUE then
            sd_RetVal := MULTI_VARAN_IINSERTDOINTODOL(pCurrentDO^.pHandle$UDINT);
            pCurrentDO^.bsDoInsert.DOisInserted := TRUE;
          end_if;
          
          pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_OK;
        else
          pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_ERROR_INVALID_HANDLE;          
        end_if;
        pCurrentDO^.b_DOIsRunning         := 0; // Override any singlerun states
        pCurrentDO^.b_DOIsRunning.ContRun := true;
      else
        if DisableDO(ud_DOHandle := pCurrentDO^.pHandle$UDINT) = VARANMANAGER_OK then
          pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_OK;
        else
          pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_ERROR_INVALID_HANDLE;          
        end_if;
        pCurrentDO^.b_DOIsRunning         := 0;
      end_if;
    else
      if pSETRUNSTATECfg^.NewRunState = _BUS_IF_RUN_STATE_SINGLE_RUN then
        pCurrentDO^.pHandle^.ucCtrlStat := SetRunStatus(state:=VARAN_DO_SINGLE_RUN);
      elsif pSETRUNSTATECfg^.NewRunState = _BUS_IF_RUN_STATE_CONT_RUN then
        pCurrentDO^.pHandle^.ucCtrlStat := SetRunStatus(state:=VARAN_DO_CONT_RUN);
      else    
        pCurrentDO^.pHandle^.ucCtrlStat := SetRunStatus(state:=VARAN_DO_NO_RUN);
      end_if;
      
      pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_OK;
    end_if;    
  
  // Move DO ----------------------------------------------------------------------------------------
  elsif CheckMovHandle(Handle:= pSETRUNSTATECfg^.Handle) then
  
    pCurrentDOMove := (pSETRUNSTATECfg^.Handle)$^t_DOMoveCfg;
    
    if b_PayloadSupport then
      if pSETRUNSTATECfg^.NewRunState = _BUS_IF_RUN_STATE_SINGLE_RUN then
        pCurrentDOMove^.b_DOIsRunning.ContRun       := false; // Override cont run 
        pCurrentDOMove^.b_DOIsRunning.StartRequest  := true;
        pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_OK;
      elsif pSETRUNSTATECfg^.NewRunState = _BUS_IF_RUN_STATE_CONT_RUN then
        if EnableDO(ud_DOHandle := pCurrentDOMove^.pHandle$UDINT) = VARANMANAGER_OK then
          pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_OK;
        else
          pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_ERROR_INVALID_HANDLE;          
        end_if;
        pCurrentDOMove^.b_DOIsRunning         := 0; // Override any singlerun states
        pCurrentDOMove^.b_DOIsRunning.ContRun := true;
      else
        if DisableDO(ud_DOHandle := pCurrentDOMove^.pHandle$UDINT) = VARANMANAGER_OK then
          pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_OK;
        else
          pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_ERROR_INVALID_HANDLE;          
        end_if;
        pCurrentDOMove^.b_DOIsRunning         := 0;
      end_if;
    else
      if pSETRUNSTATECfg^.NewRunState = _BUS_IF_RUN_STATE_SINGLE_RUN then
        pCurrentDOMove^.pHandle^.ucCtrlStat := SetRunStatus(state:=VARAN_DO_SINGLE_RUN);
      elsif pSETRUNSTATECfg^.NewRunState = _BUS_IF_RUN_STATE_CONT_RUN then
        pCurrentDOMove^.pHandle^.ucCtrlStat := SetRunStatus(state:=VARAN_DO_CONT_RUN);
      else    
        pCurrentDOMove^.pHandle^.ucCtrlStat := SetRunStatus(state:=VARAN_DO_NO_RUN);
      end_if;
      
      pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_OK;
    end_if;
    
  else
    pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_ERROR_INVALID_HANDLE;
  end_if;
  
END_FUNCTION  

  
FUNCTION VIRTUAL GLOBAL BusInterfaceVARAN::SetSyncData
	VAR_INPUT
		pCmd 	        : ^CmdStruct;
		presult 	    : ^results;
	END_VAR
  VAR  	
    pSYNCDATACfg  :  ^t_SyncData;
    i             : USINT;
  END_VAR
  
  presult^.uiLng  := 4;
  
  pSYNCDATACfg    := ((pCmd^.aPara[0])$^t_SyncData);
  
  i := pSYNCDATACfg^.us_sync_nr;
  
  if  i >= 0 & 
      i <  4 then
      
    SyncData[i].us_sync_nr                := pSYNCDATACfg^.us_sync_nr;
    SyncData[i].sd_offset                 := pSYNCDATACfg^.sd_offset;
    SyncData[i].us_period_multiplier      := pSYNCDATACfg^.us_period_multiplier;
    SyncData[i].us_enable_frame_count     := pSYNCDATACfg^.us_enable_frame_count;
    SyncData[i].us_frame_count_threshold  := pSYNCDATACfg^.us_frame_count_threshold;
    SyncData[i].b_use_divider_sync        := pSYNCDATACfg^.b_use_divider_sync;
  
    bSetPll := TRUE;
  
    pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_OK;
  else
    pResult^.aData[0]$t_BusIFRetvalErrorcode := _BUS_IF_RETVAL_ERROR_INVALID_SYNC;
  end_if;
  
END_FUNCTION


FUNCTION VIRTUAL BusInterfaceVARAN::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 & NrDO then
    ListOffset := (Handle - (#DOList[0])$UDINT);
    if ((ListOffset MOD sizeof(t_DOCfg)) = 0) & ((ListOffset/sizeof(t_DOCfg)) < NrDO) then
      IsOk := true;
    end_if;
  end_if;

END_FUNCTION


FUNCTION VIRTUAL BusInterfaceVARAN::CheckMovHandle
	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 & NrDOMove then
    ListOffset := (Handle - (#DOListMove[0])$UDINT);
    if ((ListOffset MOD sizeof(t_DOMoveCfg)) = 0) & ((ListOffset/sizeof(t_DOMoveCfg)) < NrDOMove) then
      IsOk := true;
    end_if;
  end_if;

END_FUNCTION


FUNCTION VIRTUAL GLOBAL BusInterfaceVARAN::UpdateRetryCounter
  VAR
    i                 : USINT;  
	  tempRetryCounter  : USINT;
    pDOElement        : ^t_DOCfg;
  END_VAR

  // Standard DOs --------------------------------------------------------------------------
  if NrDO then
    pDOElement := #DOList[0];
    for i := 0 to (NrDO - 1) do
      
      tempRetryCounter := GetRetryCounter(ud_DOHandle := pDOElement^.pHandle$UDINT);
      
      if ( tempRetryCounter <> pDOElement^.OldRetryCounter) then
        RetryCounter += TO_USINT( tempRetryCounter - pDOElement^.OldRetryCounter );
        pDOElement^.OldRetryCounter := tempRetryCounter;
      end_if;
      
      pDOElement += sizeof(t_DOCfg);
    end_for;
  end_if;

END_FUNCTION


FUNCTION BusInterfaceVARAN::BusInterfaceVARAN
	VAR_OUTPUT
		ret_code 	: ConfStates;
	END_VAR

  ui_PostInitIndex := 16#FFFF;

  // initialize with 0xff for invalid
  _memset(dest:=#SyncData, usByte:=16#FF, cntr:=sizeof(SyncData));
  
  if OS_CILGet(INTERFACE_VARANMANAGER, #pVaran) <> SYS_ERR_NONE then
    LogError("@0196 (BusInterfaceVARAN::BusInterfaceVARAN) Failed to get VARAN-CIL (interface to OS)!");
  end_if;

  b_LongDOsPossible := GetLongDOsPossible();

	ret_code := C_OK;

END_FUNCTION


FUNCTION VIRTUAL GLOBAL BusInterfaceVARAN::Varan_HwInterrupt
	VAR_INPUT
		ud_reason 	: UDINT;
		ud_data 	  : ^t_CallBackInterrupt;
	END_VAR
	VAR_OUTPUT
		sd_retval 	: DINT;
	END_VAR
  VAR
  	tempCmd     : CmdStruct;
    _result     : results;
  END_VAR;
  
  // Turn off DO's
  SetDOsOff();
  
  // Check for 0 pointer
  if p_UserCalls.p_Callback then
    // Call the corrosponding function in the operator class
    tempCmd.uiCmd := _BUS_IF_HWINTERRUPT;  
    p_UserCalls.p_Callback^.pSvrChCmd.NewInst(#tempCmd,#_result);
  end_if;
  sd_retval := Varan_Base::Varan_HwInterrupt(ud_reason, ud_data);
  
END_FUNCTION


FUNCTION VIRTUAL BusInterfaceVARAN::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 VIRTUAL BusInterfaceVARAN::InstallCallbackObject
	VAR_OUTPUT
		sd_retval 	: DINT;
	END_VAR
  
  // we don't install the callback here (1st init). it's installed in the 2nd init, because in the first init the operator may set us to required
  sd_retval := VARANMANAGER_OK;

END_FUNCTION


FUNCTION VIRTUAL BusInterfaceVARAN::GetLongDOsPossible
	VAR_OUTPUT
		LongDOsPossible 	  : BOOL;
	END_VAR
  VAR
    pSPCIInfo           : ^LSL_SPCIINFO;
  	p_sigmatek_devinfo 	: ^PCICONFDATA;
    p_NodeInfo          : ^LSL_VARANNODEINFO;
    ManagerNodeString   : USINT;    
    ud_VMNodeHandle     : UDINT;
    s_NodeInfo          : LSL_VARANNODEINFO;
    sd_retval           : DINT;    
  END_VAR

  LongDOsPossible := FALSE;

  // check if long DOs are supported by VARAN Manager. Version of wb_varan_manager_control_status_info (Device Type x"0212" of info block) has to be >= 16#25.
  if OS_CILGET( "PCICONFIG", #pSPCIInfo ) =  SYS_ERR_NONE then
    p_sigmatek_devinfo 	:= SPCIINFO_FINDDEVICE(0x0212, 0);
    if p_sigmatek_devinfo = NIL then
      p_sigmatek_devinfo 	:= SPCIINFO_FINDDEVICE(0x0214, 0); //check for new varan interface 
    end_if;         
    // check if the Manager supports LongDOs
    if p_sigmatek_devinfo & (p_sigmatek_devinfo^.Version >= 16#25) then
      LongDOsPossible := TRUE;
    else
      // we don't get the device at a c-ipc, because it's a pci plug-in card
      if pVaran & (_WhoAmI = DESTPLC_C_IPC) then
        // now check the platform and the corresponding fpga version

        //get manager node info from os
        ManagerNodeString := 0;
        
        //call OS - function (must be OS-funciton because of error handling)
        if b_PayloadSupport then
          // Get the Handle of the VM
          sd_retval := MULTI_VARAN_iGetNodeHandle(udManagerNumber := ud_VaranManagerNr
                                                , pszHardwarePath := #ManagerNodeString
                                                , phNodeHandle    := #ud_VMNodeHandle);
                                                
          if sd_retval = VARANMANAGER_OK then
            p_NodeInfo := #s_NodeInfo;
            sd_retval := MULTI_VARAN_iGetNodeInformation( hNodeHandle := ud_VMNodeHandle
                                                        , psNodeInfo  := p_NodeInfo);     // Pass a pointer to the buffer into which the data will be written, instead of getting a pointer to te data
          end_if;
                                                
        else
          sd_retval := VARAN_iGetNodeInfo(uiManager	:= ud_VaranManagerNr
                                        , pucNode	  := #ManagerNodeString
                                        , pNodeInfo	:= #p_NodeInfo
                                        );
        end_if;

        if	( sd_retval = VARANMANAGER_OK ) & p_NodeInfo then
          case p_NodeInfo^.uiDeviceID of
            1000: // VM051    >= 1.6
              if p_NodeInfo^.ucFPGAVersion >= 16#16 then
                LongDOsPossible := TRUE;
              end_if;
              
            1030, // VM052    >= 1.4
            1150: // VM052-1  same fpga file
              if p_NodeInfo^.ucFPGAVersion >= 16#14 then
                LongDOsPossible := TRUE;
              end_if;
              
            1031: // VM052H   not necessary, this card doesn't work on a C-IPC (created for customer specific hardware)
            
            1044: // VMC052   >= 1.3
              if p_NodeInfo^.ucFPGAVersion >= 16#13 then
                LongDOsPossible := TRUE;
              end_if;

            1063, // VM052-3  >= 1.4
            1093: // VM053    same fpga file 
              if p_NodeInfo^.ucFPGAVersion >= 16#14 then
                LongDOsPossible := TRUE;
              end_if;
              
            1080: // VM052-4  no fpga available
            
          end_case;
        end_if;
      end_if;
    end_if;
  end_if;
  
END_FUNCTION


FUNCTION VIRTUAL GLOBAL BusInterfaceVARAN::Varan_HwSubBusReady
	VAR_INPUT
		ud_data 	  : UDINT;
	END_VAR
	VAR_OUTPUT
		sd_retval 	: DINT;
	END_VAR
  VAR
  	tempCmd     : CmdStruct;
    _result     : results;
  END_VAR    

  // Check for 0 pointer
  if p_UserCalls.p_Callback then
    // Call the corresponding function in the operator class
    tempCmd.uiCmd := _BUS_IF_HWSUB_BUS_READY;  
    p_UserCalls.p_Callback^.pSvrChCmd.NewInst(#tempCmd,#_result);
    
    sd_retval := _result.aData[0]$DINT;
  else
    sd_retval := 0;
  end_if;

END_FUNCTION


FUNCTION VIRTUAL GLOBAL BusInterfaceVARAN::State::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;    
    pStr_HWTreenEntry       : ^CHAR;
    ud_HWCRetcode           : t_HWCRetvalReturnCode;
    b_CallThisModule        : BOOL;    
  END_VAR
  
  pStr_HWTRequested         := NIL;
  us_HWTRequestedCurrIndex  := 0;    
  pStr_HWTreenEntry         := NIL;
  ud_HWCRetcode             := _HWC_RETVAL_ERROR;
  b_CallThisModule          := TRUE;

	ret_code := READY;

  CASE pPara^.uiCmd OF
//**********************************************************************************************************************************************************
    CMD_POST_INIT_RT_READY:
      // check if operator is ready
      tempCmd.uiCmd := _BUS_IF_POST_INIT_RT_READY;  
      ret_code := p_UserCalls.p_Callback^.pSvrChCmd.NewInst(#tempCmd, #_result);
      
      if bSimulateSDIASManager then
      
        // if we got an error => return it
        if eSdiasManagerInitSSW = _ErrorOccured then
          ret_code := ERROR;          
          
        //if we're not ready, return busy
        elsif eSdiasManagerInitSSW <> _InitFinished then
          ret_code := BUSY;
        end_if;            
      
      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      
        
        us_HWTRequestedCurrIndex  := pPara^.aPara[0]$t_HWCGetHardwareDiagnosisIn.us_current_index;

        // Check for any Escape sequence
        if (pStr_HWTRequested + us_HWTRequestedCurrIndex)^ and HWT_ESCAPE_SEQU then
          
          // Check if current index + 1 is valid, pStr_HWTRequested^ + 1 for extra byte of length
          if (us_HWTRequestedCurrIndex + 1) <= (pStr_HWTRequested$^UINT^ + 1) then
            // Update Current index to next position = Place of SDIAS Module
            pPara^.aPara[0]$t_HWCGetHardwareDiagnosisIn.us_current_index   += 1;
            pPara^.aPara[0]$t_HWCGetHardwareDiagnosisIn.us_current_length  -= 1;
            
            if p_UserCalls.p_Callback then 
              ret_code := p_UserCalls.p_Callback^.pSvrChCmd.NewInst(pPara,pResult); //Pass on command to connected extension module
            end_if;
            
          end_if;
                    
        else
          ret_code := Varan_Base::State.NewInst(pPara, pResult);  // Pass on command to base
          
          // Call conneceted Class for additional info            
          if p_UserCalls.p_Callback then            
                
            // Don't change retcode, may be not handled by extension modules.
            ud_HWCRetcode := pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.retcode;
            
            p_UserCalls.p_Callback^.pSvrChCmd.NewInst(pPara,pResult); //Pass on command to extension module 
            
            pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.retcode := ud_HWCRetcode;
            
          end_if;
        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;      
      
      b_CallThisModule    := TRUE;
      
      // Check HWT String
      if pStr_HWTRequested & p_ObjectPath then      
        
        // Compare string content        
        if _memcmp( ptr1 := pStr_HWTRequested + 2, 
                    ptr2 := p_ObjectPath +1, 
                    cntr := p_ObjectPath^) = 0 then
          
          
          //Check if last call was to Base itself, Compare string length
          if (pStr_HWTRequested$^USINT^ = p_ObjectPath^) then            
          
            //If last call was to base itself, don't call it this time
            b_CallThisModule := FALSE;
            
            // Last module called was the BusIF Object itself, next module is the 1st behind the extension module            
            pPara^.aPara[0]$t_HWCGetHardwareTreeEntryIn.pStr_LastHardewareTreeEntry := NIL;
            
            if p_UserCalls.p_Callback then    
              ret_code := p_UserCalls.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 := Varan_Base::State.NewInst(pPara,pResult); //Pass on command to base
              end_if;

            else
              pResult^.aData[0]$t_HWCGetHardwareTreeEntryOut.retcode := _HWC_RETVAL_OK_END_OF_LIST;
            end_if;
          
          elsif (pStr_HWTRequested$^USINT^ > p_ObjectPath^ + 1) then // Must be at least 2 Byte larger, ESCAPE Sequence + Place          
            
            // Check escape sequence
            if ( (pStr_HWTRequested + (p_ObjectPath^) + 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

              //If last call was to base itself, don't call it this time
              b_CallThisModule := FALSE;

              // Update index
              pPara^.aPara[0]$t_HWCGetHardwareTreeEntryIn.us_current_index  := p_ObjectPath^ + 3; // Second place after BUSIF Itself is place + 1 for addional length byte
              pPara^.aPara[0]$t_HWCGetHardwareTreeEntryIn.us_current_length := pStr_HWTRequested^ - p_ObjectPath^ - 1;
              
              //If we have a extension module
              if p_UserCalls.p_Callback then    
                ret_code := p_UserCalls.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;
          end_if;          
        end_if;        
      end_if;
      
      if b_CallThisModule then        
        
        ret_code := Varan_Base::State.NewInst(pPara, pResult);  // Pass on command to base            
        
        // Call conneceted Class for additional info            
        if p_UserCalls.p_Callback & 
           pResult^.aData[0]$t_HWCGetHardwareTreeEntryOut.pStr_NextHardewareTreeEntry then    
        
          // Update with Requested HWT String with the one returned from Varanbase
          pPara^.aPara[0]$t_HWCGetHardwareTreeEntryIn.pStr_LastHardewareTreeEntry := pResult^.aData[0]$t_HWCGetHardwareTreeEntryOut.pStr_NextHardewareTreeEntry;
              
          // Don't change retcode, may be not handled by extension modules.
          ud_HWCRetcode := pResult^.aData[0]$t_HWCGetHardwareTreeEntryOut.retcode;
          
          p_UserCalls.p_Callback^.pSvrChCmd.NewInst(pPara,pResult); //Pass on command to extension module 
          
          pResult^.aData[0]$t_HWCGetHardwareTreeEntryOut.retcode := ud_HWCRetcode;
        end_if;
      end_if;

//**********************************************************************************************************************************************************
 
   CMD_GET_HW_TIMESTAMP:
      // forward to VM
      ret_code := VaranIn.NewInst(pPara, pResult);

//**********************************************************************************************************************************************************
 
   CMD_HWC_REQ_PLLNS_REGULATION:
      // forward to VM
      ret_code := VaranIn.NewInst(pPara, pResult);

//**********************************************************************************************************************************************************

  ELSE
    // unknown commands are forwarded to the base
    ret_code := Varan_Base::State.NewInst(pPara, pResult);
  END_CASE;
  
END_FUNCTION


FUNCTION VIRTUAL GLOBAL BusInterfaceVARAN::GetDeviceID
	VAR_OUTPUT
		output 	: UDINT;
	END_VAR
  
  output := DeviceIDDiagnosis;

END_FUNCTION


FUNCTION VIRTUAL GLOBAL BusInterfaceVARAN::GetPayloadSupportState
	VAR_OUTPUT
		dRetCode 	: DINT;
	END_VAR
  
  dRetCode := b_PayloadSupport;
  
END_FUNCTION

FUNCTION VIRTUAL BusInterfaceVARAN::AddSDORequest
	VAR_INPUT
		pCmdSvr 	: ^SvrChCmd;
		Command 	: HINT;
		Offset 	: UDINT;
		Length 	: UDINT;
		pWriteBuf 	: ^void;
	END_VAR
	VAR_OUTPUT
		sd_retval 	: DINT;
	END_VAR

  // protect via mutex because this can be called from different task priorities
  OS_MT_WAIT(pv_MutexSDOs);

  // if the buffer is full, or the next element in the buffer is already in use
  if (SDOHandling.pWrite^.Command <> 0) then
    sd_retval := -2;
    OS_MT_SIGNAL(pv_MutexSDOs);
    return;
  end_if;
  
  if pCmdSvr = NIL then
    sd_retval := -3;
    return;
  end_if;
  
  if Length = 0 then
    sd_retval := -4;
  end_if;
  
  if Command =_BUS_IF_WRITE_VIA_SDO | Command = _BUS_IF_WRITE_VIA_SDO_CTRL then
    if pWriteBuf = NIL then
      sd_retval := -5;
      return;
    end_if;
  end_if;

  
  SDOHandling.pWrite^.pCallBackSvr  := pCmdSvr;
  SDOHandling.pWrite^.udLength      := Length;
  SDOHandling.pWrite^.udOffset      := Offset;
  SDOHandling.pWrite^.pWriteData    := pWriteBuf;
  // command is the last thing to store, because it indicates a complete entry
  SDOHandling.pWrite^.Command := Command;

  // we increment our used entries in the buffer (only for debugging)
  SDOHandling.EntriesUsed     += 1;

  // after we successfully added this SDO, set the write pointer to the next element
  if SDOHandling.pWrite = SDOHandling.pLastEntry then
    SDOHandling.pWrite := SDOHandling.pRingBufMemStart;
  else
    SDOHandling.pWrite += sizeof(t_SDORingBufEntry);
  end_if;

  sd_retval := 0;
  
  OS_MT_SIGNAL(pv_MutexSDOs);
  
END_FUNCTION


FUNCTION VIRTUAL BusInterfaceVARAN::CyclicSDOHandling
  VAR
		Length 	      : UDINT;
    pRingBufEntry : ^t_SDORingBufEntry;
    pCmdSvr       : ^SvrChCmd;
  	tempCmd       : CmdStruct;
    _result       : results;
    Offset : UDINT;
  END_VAR
  

  // protect via mutex because this can be called from different task priorities
  OS_MT_WAIT(pv_MutexSDOs);

  //If there is some work todo
  if SDOHandling.EntriesUsed then
  
    if SDOHandling.pActEntry & SDOHandling.pActEntry^.Command <> 0 then
    
      pRingBufEntry := SDOHandling.pActEntry;
    
      //State = 0 ... Start SDO access, 1 ... Get SDO access data and stop SDO
      if SDOHandling.pActEntry^.udState = 0 then
      
        Length := SDOHandling.pActEntry^.udLength;
        Offset := SDOHandling.pActEntry^.udOffset;
        
        case SDOHandling.pActEntry^.Command of
        
          _BUS_IF_READ_VIA_SDO:
          
            if ChangeAsyRd(Offset:=Offset$UINT, 
                           Length:=Length$USINT, 
                           RunState:=_BUS_IF_RUN_STATE_CONT_RUN,
                           bIsCtrlACC := FALSE) = FALSE then
              LogError("@009B (BusInterfaceVARAN::CyclicSDOHandling) Error occured at starting the MEM ReadDO");
            end_if;
            
            SDOHandling.pActEntry^.udState := 1;      
          
          _BUS_IF_READ_VIA_SDO_CTRL:
          
            if ChangeAsyRd(Offset:=Offset$UINT, 
                           Length:=Length$USINT, 
                           RunState:=_BUS_IF_RUN_STATE_CONT_RUN,
                           bIsCtrlACC := TRUE) = FALSE then
              LogError("@009B (BusInterfaceVARAN::CyclicSDOHandling) Error occured at starting the CTRL ReadDO");
            end_if;
            
            SDOHandling.pActEntry^.udState := 1;      
            
          _BUS_IF_WRITE_VIA_SDO:
          
            _memcpy(ptr1:=AsyMemWriteDO.pData, ptr2:=SDOHandling.pActEntry^.pWriteData, cntr:=SDOHandling.pActEntry^.udLength);
            
            if ChangeAsyWr(Offset:=Offset$UINT, 
                           Length:=Length$USINT, 
                           RunState:=_BUS_IF_RUN_STATE_CONT_RUN,
                           bIsCtrlACC := FALSE) = FALSE then
              LogError("@009B (BusInterfaceVARAN::CyclicSDOHandling) Error occured at starting the MEM WriteDO");
            end_if;
            
            SDOHandling.pActEntry^.udState := 1;
          
          _BUS_IF_WRITE_VIA_SDO_CTRL:
                      
            _memcpy(ptr1:=AsyCtrlWriteDO.pData, ptr2:=SDOHandling.pActEntry^.pWriteData, cntr:=SDOHandling.pActEntry^.udLength);
            
            if ChangeAsyWr(Offset:=Offset$UINT, 
                           Length:=Length$USINT, 
                           RunState:=_BUS_IF_RUN_STATE_CONT_RUN,
                           bIsCtrlACC := TRUE) = FALSE then
              LogError("@009B (BusInterfaceVARAN::CyclicSDOHandling) Error occured at starting the CTRL WriteDO");
            end_if;
            
            SDOHandling.pActEntry^.udState := 1;

          
        end_case;
      
      elsif SDOHandling.pActEntry^.udState = 1 then
      
        SDOHandling.EntriesUsed -= 1;
      
        // Call the corresponding function in the operator class
        tempCmd.uiCmd := _BUS_IF_SDO_RESPONSE;
        tempCmd.aPara[0] := SDOHandling.pActEntry^.Command$DINT;
        tempCmd.aPara[1] := SDOHandling.pActEntry^.udOffset$DINT;
        tempCmd.aPara[2] := SDOHandling.pActEntry^.udLength$DINT;
        
        tempCmd.aPara[3] := 0;
        
        case SDOHandling.pActEntry^.Command of
        
          _BUS_IF_READ_VIA_SDO:
          
            tempCmd.aPara[4] := AsyMemReadDO.pData$DINT;
            tempCmd.aPara[5] := AsyMemReadDO.Length;

          _BUS_IF_READ_VIA_SDO_CTRL:
          
            tempCmd.aPara[4] := AsyCtrlReadDO.pData$DINT;
            tempCmd.aPara[5] := AsyCtrlReadDO.Length;
            
          _BUS_IF_WRITE_VIA_SDO:
          
            tempCmd.aPara[4] := NIL$DINT;
            tempCmd.aPara[5] := 0;
          
          _BUS_IF_WRITE_VIA_SDO_CTRL:
          
            tempCmd.aPara[4] := NIL$DINT;
            tempCmd.aPara[5] := 0;
                    
        end_case;
        
        pCmdSvr := pRingBufEntry^.pCallBackSvr;
        
        if pCmdSvr$pVirtualBase^.NewInst(#tempCmd, #_result) <> READY then               
          LogError("@0099 (BusInterfaceVARAN::CyclicSDOHandling) SDO Error: Error of module at place 0x{0} while receiving the SDO reponse (which was an ErrorCode)");                              
        end_if;

        // the entry in the ringbuffer is free
        pRingBufEntry^.Command := 0;
        
        //Stop the DOs
        if ChangeAsyRd(Offset:=0, 
                       Length:=0, 
                       RunState:=_BUS_IF_RUN_STATE_NO_RUN,
                       bIsCtrlACC := TRUE) = FALSE then
          LogError("@0769 (BusInterfaceVARAN::CyclicSDOHandling) Error occured at starting the CTRL ReadDO");
        end_if;
        
        if ChangeAsyRd(Offset:=0, 
                       Length:=0, 
                       RunState:=_BUS_IF_RUN_STATE_NO_RUN,
                       bIsCtrlACC := FALSE) = FALSE then
          LogError("@076A (BusInterfaceVARAN::CyclicSDOHandling) Error occured at starting the MEM ReadDO");
        end_if;
        
        if ChangeAsyWr(Offset:=0, 
                       Length:=0, 
                       RunState:=_BUS_IF_RUN_STATE_NO_RUN,
                       bIsCtrlACC := TRUE) = FALSE then
          LogError("@076B (BusInterfaceVARAN::CyclicSDOHandling) Error occured at starting the CTRL WriteDO");
        end_if;
        
        if ChangeAsyWr(Offset:=0, 
                       Length:=0, 
                       RunState:=_BUS_IF_RUN_STATE_NO_RUN,
                       bIsCtrlACC := FALSE) = FALSE then
          LogError("@076D (BusInterfaceVARAN::CyclicSDOHandling) Error occured at starting the MEM WriteDO");
        end_if;
        
        SDOHandling.pActEntry^.udState := 0;
        
        // after we successfully added this SDO, set the read pointer to the next element
        if SDOHandling.pActEntry = SDOHandling.pLastEntry then
          SDOHandling.pActEntry := SDOHandling.pRingBufMemStart;
        else
          SDOHandling.pActEntry += sizeof(t_SDORingBufEntry);
        end_if;
        
      end_if;
    end_if;
  end_if;
  
  OS_MT_SIGNAL(pv_MutexSDOs);
  
END_FUNCTION


FUNCTION VIRTUAL BusInterfaceVARAN::ChangeAsyRd
	VAR_INPUT
		Offset 	: HINT;
		Length 	: USINT;
		RunState 	: t_BusIFRunState;
		bIsCtrlACC 	: BOOL;
	END_VAR
	VAR_OUTPUT
		Success 	: BOOL;
	END_VAR
  VAR
    dataUPDATEDO    : t_UpdateDOCfg;
  	tempCmd         : CmdStruct;
    _result         : results;
    dataSETRUNSTATE : t_SetRunStateCfg;
  END_VAR

  // if length = zero we may just want to stop the DO
  if Length then
    
    if bIsCtrlACC then
      AsyCtrlReadDO.Offset := Offset;
      AsyCtrlReadDO.Length := Length;

      dataUPDATEDO.Handle               := AsyCtrlReadDO.Handle;
      dataUPDATEDO.ud_addressoff_read   := AsyCtrlReadDO.Offset;
      dataUPDATEDO.ud_length_read       := AsyCtrlReadDO.Length;
    
    else
      AsyMemReadDO.Offset := Offset;
      AsyMemReadDO.Length := Length;

      dataUPDATEDO.Handle               := AsyMemReadDO.Handle;
      dataUPDATEDO.ud_addressoff_read   := AsyMemReadDO.Offset;
      dataUPDATEDO.ud_length_read       := AsyMemReadDO.Length;
    end_if;
    
    tempCmd.uiCmd         := _BUS_IF_UPDATE_DO;  
    tempCmd.aPara[0]      := (#dataUPDATEDO)$DINT;  

    CallCommand.NewInst(pPara:=#tempCmd, pResult:=#_result); 
    if _result.aData[0]$t_BusIFRetvalErrorcode <> _BUS_IF_RETVAL_OK then  
      LogError("@007C (BusInterfaceVARAN::ChangeAsyRd) Failed to change asynchron read access");
    end_if;
  end_if;
  
  // set runstate
  if bIsCtrlACC then
    dataSETRUNSTATE.Handle      := AsyCtrlReadDO.Handle;
  else
    dataSETRUNSTATE.Handle      := AsyMemReadDO.Handle;
  end_if;

  dataSETRUNSTATE.NewRunState := RunState;
  
  tempCmd.uiCmd         := _BUS_IF_SET_RUN_STATE;  
  tempCmd.aPara[0]      := (#dataSETRUNSTATE)$DINT; 
 
  CallCommand.NewInst(pPara:=#tempCmd, pResult:=#_result); 
  
  if _result.aData[0]$t_BusIFRetvalErrorcode <> _BUS_IF_RETVAL_OK then
    LogError("@007D (BusInterfaceVARAN::ChangeAsyRd) Error changing the run state of the asynchron read access!");
  end_if; 
    
  Success := TRUE;

END_FUNCTION


FUNCTION VIRTUAL BusInterfaceVARAN::ChangeAsyWr
	VAR_INPUT
		Offset 	: HINT;
		Length 	: USINT;
		RunState 	: t_BusIFRunState;
		bIsCtrlACC 	: BOOL;
	END_VAR
	VAR_OUTPUT
		Success 	: BOOL;
	END_VAR
  VAR
    dataUPDATEDO    : t_UpdateDOCfg;
  	tempCmd         : CmdStruct;
    _result         : results;
    dataSETRUNSTATE : t_SetRunStateCfg;
  END_VAR

  // if length = zero we may just want to stop the DO
  if Length then
  
    if bIsCtrlACC then
      AsyCtrlWriteDO.Offset := Offset;
      AsyCtrlWriteDO.Length := Length;

      dataUPDATEDO.Handle               := AsyCtrlWriteDO.Handle;
      dataUPDATEDO.ud_addressoff_write  := AsyCtrlWriteDO.Offset;
      dataUPDATEDO.ud_length_write      := AsyCtrlWriteDO.Length;
    
    else
      AsyMemWriteDO.Offset := Offset;
      AsyMemWriteDO.Length := Length;

      dataUPDATEDO.Handle               := AsyMemWriteDO.Handle;
      dataUPDATEDO.ud_addressoff_write  := AsyMemWriteDO.Offset;
      dataUPDATEDO.ud_length_write      := AsyMemWriteDO.Length;
      
    end_if;  

    tempCmd.uiCmd         := _BUS_IF_UPDATE_DO;  
    tempCmd.aPara[0]      := (#dataUPDATEDO)$DINT;  

    CallCommand.NewInst(pPara:=#tempCmd, pResult:=#_result); 
    if _result.aData[0]$t_BusIFRetvalErrorcode <> _BUS_IF_RETVAL_OK then  
      LogError("@007F (BusInterfaceVARAN::ChangeAsyWr) Failed to change asynchron write access");
    end_if;    
  end_if;

  // set runstate
  if bIsCtrlACC then
    dataSETRUNSTATE.Handle      := AsyCtrlWriteDO.Handle; 
  else
    dataSETRUNSTATE.Handle      := AsyMemWriteDO.Handle;
  end_if;

  dataSETRUNSTATE.NewRunState := RunState;
  
  tempCmd.uiCmd         := _BUS_IF_SET_RUN_STATE;  
  tempCmd.aPara[0]      := (#dataSETRUNSTATE)$DINT; 
 
  CallCommand.NewInst(pPara:=#tempCmd, pResult:=#_result); 
  
  if _result.aData[0]$t_BusIFRetvalErrorcode <> _BUS_IF_RETVAL_OK then
    LogError("@0080 (BusInterfaceVARAN::ChangeAsyWr) Error changing the run state of the asynchron write access!");
  end_if;  
    
  Success := TRUE;

END_FUNCTION


FUNCTION VIRTUAL BusInterfaceVARAN::SendPostInitFinished
	VAR_INPUT
		DisableThisObject 	: BOOL;(* := FALSE *)
	END_VAR
  VAR
  	tempCmd         : CmdStruct;
    _result         : results;
  END_VAR

  b_PostInitFinished := TRUE;
  tempCmd.uiCmd := _BUS_IF_POST_INIT_FINISHED;
  CallCommand.NewInst(pPara:=#tempCmd, pResult:=#_result);

  if _result.aData[0]$t_BusIFRetvalErrorcode <> _BUS_IF_RETVAL_OK then
    LogError("@00D8 (BusInterfaceVARAN::SendPostInitFinished) Failed to set the post init to finished via bus interface!");
  end_if;    


  if DisableThisObject then
    // tell the manager that we don't need to be called for rt syncing
    tempCmd.uiCmd := _BUS_IF_RT_SYNC_READY;
    CallCommand.NewInst(pPara:=#tempCmd, pResult:=#_result);
  
    if _result.aData[0]$t_BusIFRetvalErrorcode <> _BUS_IF_RETVAL_OK then
      LogError("@00D9 (BusInterfaceVARAN::CyWork) Failed to set rt sync ready via bus interface!");
    end_if;    
  end_if;
  

END_FUNCTION


FUNCTION VIRTUAL BusInterfaceVARAN::SimulateSDIASManagerCywork
VAR
	tempCmd           : CmdStruct; 
  _result           : results;    
  RetcodeIPR        : iprStates;
END_VAR  

  case eSdiasManagerInitSSW of
//**********************************************************************************************************************************************************
    t_SdiasManagerInitSSW::_StartInit:

      // remember when we started (for timeout and init time measure)
      InitStartTime := ops.tAbsolute;
    
      // check if we have a user class
      if p_UserCalls.p_Callback = NIL then
        // we already have a log entry from the constructor
        State := _CallBackError;
        LogError("@076E (BusInterfaceVARAN::SimulateSDIASManagerCywork) Pointer to user callback is invalid");        
        eErrorInitStep := eSdiasManagerInitSSW;
        eSdiasManagerInitSSW := _PrepareError;          
        return;
      end_if;
      
      //Go on with initialisation
      eSdiasManagerInitSSW := _InitAccesses;
      
//**********************************************************************************************************************************************************
    t_SdiasManagerInitSSW::_InitAccesses:
                 
      // call operator, who returns the init state (busy = call me again, error = error occured/cancel init, ready = init successfully finished)
      if p_UserCalls.p_Callback then
        // Call the corresponding function in the operator class
        tempCmd.uiCmd := _BUS_IF_INIT_ACCESSES;
        RetcodeIPR := p_UserCalls.p_Callback^.pSvrChCmd.NewInst(#tempCmd,#_result);
      else
        RetcodeIPR := READY;
      end_if;
      
      if RetcodeIPR = READY then
        eSdiasManagerInitSSW := t_SdiasManagerInitSSW::_FinishInitialisation;
      elsif RetcodeIPR = ERROR then
        eErrorInitStep := eSdiasManagerInitSSW;        
        eSdiasManagerInitSSW := t_SdiasManagerInitSSW::_PrepareError;
      end_if;
      
//**********************************************************************************************************************************************************
    t_SdiasManagerInitSSW::_FinishInitialisation:
    
      // tell the manager that we're finished with initializing, otherwise realtime will not be called
      if b_PostInitFinished = FALSE then
        SendPostInitFinished();
      end_if;
      
      //Enable the DOs in realtime
      eSdiasManagerInitSSW := _CallHwConnect;
      
      
//**********************************************************************************************************************************************************
    t_SdiasManagerInitSSW::_CallHwConnect:

      //Do nothing here, work is done in realtime (so that DOs will be started in the correct task
      
    
//**********************************************************************************************************************************************************
    t_SdiasManagerInitSSW::_ModuleInitialisation:
    
      // call operator, who returns the init state (busy = call me again, error = error occured/cancel init, ready = init successfully finished)
      if p_UserCalls.p_Callback then
        // Call the corresponding function in the operator class
        tempCmd.uiCmd := _BUS_IF_INIT_MODULE;
        RetcodeIPR := p_UserCalls.p_Callback^.pSvrChCmd.NewInst(#tempCmd,#_result);
      else
        RetcodeIPR := READY;
      end_if;
      
      if RetcodeIPR = READY then
        eSdiasManagerInitSSW := t_SdiasManagerInitSSW::_InitFinished;
        
        if bSendRtSyncReady = FALSE then
        
          bSendRtSyncReady := TRUE;
          //Finish init
          tempCmd.uiCmd := _BUS_IF_RT_SYNC_READY;
          CallCommand.NewInst(pPara:=#tempCmd, pResult:=#_result);
        
          if _result.aData[0]$t_BusIFRetvalErrorcode <> _BUS_IF_RETVAL_OK then
            LogError("@00D9 (BusInterfaceVARAN::CyWork) Failed to set rt sync ready via bus interface!");
          end_if;    
        end_if;        

      elsif RetcodeIPR = ERROR then
        eErrorInitStep := eSdiasManagerInitSSW;      
        eSdiasManagerInitSSW := t_SdiasManagerInitSSW::_PrepareError;
      end_if;
      
//**********************************************************************************************************************************************************
    t_SdiasManagerInitSSW::_InitFinished:

      p_UserCalls.p_UpdateCy^.CyWork(EAX:=0);

//**********************************************************************************************************************************************************
    t_SdiasManagerInitSSW::_PrepareError:

    // tell the manager that we're finished with initializing
    if b_PostInitFinished = FALSE then
      SendPostInitFinished(DisableThisObject:=TRUE);   
    end_if;
    
    //Sets a required error if the module is required
    SetRequiredError();

    eSdiasManagerInitSSW := _ErrorOccured;

//**********************************************************************************************************************************************************
    t_SdiasManagerInitSSW::_ErrorOccured:
      // do nothing here
      return;          
      
  end_case;
  
  //Always call SDO Handling
  CyclicSDOHandling();

END_FUNCTION


FUNCTION VIRTUAL BusInterfaceVARAN::SetRequiredError
  VAR
  	tempCmd         : CmdStruct;
    _result         : results;
  END_VAR

  if Required then
  
    // set required error
    tempCmd.uiCmd     := _BUS_IF_SET_REQUIRED_ERROR;
    
    CallCommand.NewInst(pPara:=#tempCmd, pResult:=#_result);
    if _result.aData[0]$t_BusIFRetvalErrorcode <> _BUS_IF_RETVAL_OK then
      LogError("@00A1 (BusInterfaceVARAN::SetRequiredError) Failed to set required error");
    end_if;    
  end_if;

END_FUNCTION


FUNCTION VIRTUAL BusInterfaceVARAN::SimulateSDIASManagerRtwork
VAR
	tempCmd     : CmdStruct;
  _result     : results;    
END_VAR
  
  case eSdiasManagerRTSSW of
  	t_SdiasManagerRtSSW::_RtIdle: // nothing
  	t_SdiasManagerRtSSW::_CreateAndModifyDOs: //nothing to do here
  	t_SdiasManagerRtSSW::_Wait4DOs:
  	t_SdiasManagerRtSSW::_Wait4PllSync:
  	t_SdiasManagerRtSSW::_Wait2Ticks:
  	t_SdiasManagerRtSSW::_CntDownSyncStart:
  	t_SdiasManagerRtSSW::_PreOperationalWait4DataReady:
  	t_SdiasManagerRtSSW::_PreOperational:
  	t_SdiasManagerRtSSW::_Operational:
  end_case;

  if eSdiasManagerInitSSW = _CallHwConnect then
  
    if bCallHwConnectInRT then
      bCallHwConnectInRT := FALSE;
      
      // Call the corresponding function in the operator class
      tempCmd.uiCmd := _BUS_IF_HWCONNECT;  
      p_UserCalls.p_Callback^.pSvrChCmd.NewInst(#tempCmd,#_result);
      
      eSdiasManagerInitSSW := _ModuleInitialisation;
      
      if _result.aData[0] then
        return;
      end_if;
    end_if;        
  end_if;

END_FUNCTION
