//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
#ifndef _T_VARANBASE_H
#define _T_VARANBASE_H

#define	VARAN_PLL_OFFSET		16#0140
#define VARAN_MULTIPLE_OFFSET	16#01AC

// version of serial number validation (16#10 = 1.0)
#define SERNO_VALIDATION_VERSION 16#10

#define IsTransparent_IS_AVAILABLE

// Defines for Mutex Generation
#define VARAN_STR_MUTEX_NAME_SEPERATOR ".."
#define VARAN_MUTEX_NAME_END_LENGTH 5
#define VARAN_MUTEX_NAME_MAX_LENGTH 32


#define VARAN_SPI_IDENT_LICENCENO_OFFSET    16#14
#define VARAN_SPI_IDENT_HARDWAREVER_OFFSET  16#18


#endif // _T_VARANBASE_H

//}}LSL_DEFINES

//{{LSL_DECLARATION
#include "..\..\Class\HwControl\HwControl.h"
#include "..\..\Source\interfaces\lsl_st_hardwaretree.h"

(*!
<Class
	Name               = "Varan_Base"
	Revision           = "2.21"
	GUID               = "{7213D447-AFAF-4410-B44D-60C992779DEC}"
	RealtimeTask       = "false"
	CyclicTask         = "false"
	BackgroundTask     = "false"
	Sigmatek           = "true"
	OSInterface        = "false"
	HighPriority       = "false"
	Automatic          = "false"
	UpdateMode         = "Prescan"
	IconPath           = ".\Class\Varan_Base\tool.ICO"
	SharedCommandTable = "true"
	Objectsize         = "(468,120)"
	Comment            = "baseclass of varan slave classes">
	<Channels>
		<Server Name="ConnectCounter" GUID="{954A88DF-0557-4623-ACCA-B5FBC5B7C60A}" Visualized="true" Initialize="false" WriteProtected="true" Retentive="false" Comment="Connects of Module"/>
		<Server Name="DeviceAddress" GUID="{A080B3C0-5C72-4786-821F-67B090196EE0}" Visualized="true" Initialize="false" WriteProtected="true" Retentive="false" Comment="device address of hardware module"/>
		<Server Name="DeviceID" GUID="{BC098D6A-D50F-4E69-B29E-2FD7BACEF5B7}" Visualized="true" Initialize="false" WriteProtected="true" Retentive="false" Comment="This server shows the device ID of the hardware module."/>
		<Server Name="DiagControl" GUID="{15B4CDDB-2E76-4EE5-9484-B9EAA0C04AC1}" Visualized="true" Initialize="false" WriteProtected="false" Retentive="false" Comment="Server to control Diagnose Function of module&#13;&#10;&#13;&#10;Read from Server&#13;&#10;-2..wrong FPGA for Diagnose&#13;&#10;-1..wrong OS for Diagnose&#13;&#10;0..Diagnose Function is deaktivated, not available&#13;&#10;1..Diagnose Function activated (additionally you need #define VARAN_DIAGNOSE)&#13;&#10;&#13;&#10;Write to Server&#13;&#10;0..to deactivate Diagnose&#13;&#10;1..to activate Diagnose&#13;&#10;2..to reset Counter (ConnectCounter, FaultCounter, RXLost, TXLost)"/>
		<Server Name="FaultCounter" GUID="{31800CFF-CF0C-4632-A8BF-FD586FC5A3D2}" Visualized="true" Initialize="false" WriteProtected="true" Retentive="false" Comment="PackageCounter for RXLost and TXLost were invalid"/>
		<Server Name="HardwareVersion" GUID="{3A157349-C799-4D08-BC21-1BB3A01BE1E2}" Visualized="true" Initialize="false" WriteProtected="true" Retentive="false" Comment="Shows the hardware version of the module in the format 16#HH MM LLLL where H stands for high revision, M for mid revision and L for low revision.&#13;&#10;&#13;&#10;e.g. 16#02 05 0000 is version 2.5.0"/>
		<Server Name="Online" GUID="{E1D79F53-53F1-4B06-90A0-A607940F73CE}" Visualized="true" Initialize="false" WriteProtected="true" Retentive="false" Comment="is class online or not"/>
		<Server Name="ProtocolVersion" GUID="{2C0EB127-FA92-4FF6-B57C-DBF97753C955}" Visualized="true" Initialize="false" WriteProtected="true" Retentive="false" Comment="Server shows the VARAN Protocol Version in the format xx.y.z&#13;&#10;e.g. 16#0130 means v01.3.0&#13;&#10;If this server is 16#0, then reading the VARAN Protocol Version is not supported by the OS-Interface."/>
		<Server Name="Release" GUID="{A28DDC77-1AC5-4E57-A42D-8741148B702E}" Visualized="true" Initialize="false" WriteProtected="true" Retentive="false" Comment="FPGA - Version"/>
		<Server Name="RetryCounter" GUID="{D16CA7CF-ABDD-407F-B021-9D2BF30F156D}" Visualized="true" Initialize="false" WriteProtected="false" Retentive="false" Comment="retry counter of varan module"/>
		<Server Name="RXLost" GUID="{0243B244-D646-4A4E-951E-A619B2FB83D2}" Visualized="true" Initialize="false" WriteProtected="true" Retentive="false" Comment="RX-Packages lost"/>
		<Server Name="SerialNo" GUID="{D1BF9B66-65D2-4212-8B5E-13E2E1A77915}" Class="String" Visualized="true" Initialize="false" WriteProtected="true" Retentive="false" Comment="use this channel to access the string functions"/>
		<Server Name="State" GUID="{E1B2C313-0B78-48A4-9E41-DECCCD6FD267}" Visualized="true" Initialize="false" WriteProtected="true" Retentive="false" Comment="This server shows the current status of the hardware class. For more information see: Varan hardware class status."/>
		<Server Name="TXLost" GUID="{14F6ED7F-C432-483B-B92B-7451C146827B}" Visualized="true" Initialize="false" WriteProtected="true" Retentive="false" Comment="TX-Packages lost"/>
		<Server Name="ValidateSerNo" GUID="{5B28FD6D-A4BE-419D-933F-49B93A7F83C2}" Visualized="true" Initialize="false" WriteProtected="false" Retentive="false" Comment="if the validation of the serial number is activated (SerNoValidation = 1)&#13;&#10;the serial number of the actual module can be validated by writing to this server&#13;&#10;&#13;&#10;this server shows also the state of validation:&#13;&#10;-2..validation not acivated&#13;&#10;-1..no module validated on this position&#13;&#10; 0..module is not the validated one&#13;&#10; 1..module is the validated one"/>
		<Server Name="VendorID" GUID="{9D8C5110-07EF-426A-B86A-743C5C7FC1E4}" Visualized="true" Initialize="false" WriteProtected="true" Retentive="false" Comment="This server contains the vendor ID of the hardware module."/>
		<Client Name="Required" Required="true" Internal="false" Comment="0 = module is not required&#13;&#10;1 = module is required (CPU will crash if module is missing)"/>
		<Client Name="SerialNoStr" Required="true" Internal="true"/>
		<Client Name="SerNoBackup" Required="true" Internal="true"/>
		<Client Name="SerNoValidation" Required="false" Internal="false" Comment="0..serial number of varan client does not matter&#13;&#10;1..serial number of varan client has to be validated, to use the module&#13;&#10;&#13;&#10;validation is done via write(1) to the ValidateSerNo Server"/>
		<Client Name="TimeBase" Required="false" Internal="false" DefValue="0"/>
		<Client Name="TimeBaseOffset" Required="false" Internal="false" DefValue="0"/>
		<Client Name="To_MultiTask" Required="false" Internal="false" Comment="This client is automatically connected to a OS interface class."/>
		<Client Name="To_StdLib" Required="false" Internal="false" Comment="This client is automatically connected to a OS interface class."/>
		<Client Name="Transparent" Required="false" Internal="false" DefValue="0" Comment="If this Client is set to 1 the module is not used for building the VARAN-Tree"/>
		<Client Name="UserAction" Required="false" Internal="false" Comment="optional, connect to server to get Varan states via write method.&#13;&#10;Fore more information check the documentation &quot;General Documentation to the VARAN Library&quot;."/>
		<Client Name="VaranIn" Required="true" Internal="false" Comment="This class must be connected to a VARAN port or a VaranOut_[x] server."/>
	</Channels>
	<Dependencies>
		<Files>
			<File Path=".\Class\VaranManager_Base\VaranManager_Base.h" Include="false"/>
			<File Path=".\Source\interfaces\lsl_st_pci.h" Include="false"/>
			<File Path=".\Class\HwControl\HwControl.h" Include="true"/>
			<File Path=".\Source\interfaces\lsl_st_hardwaretree.h" Include="true"/>
		</Files>
	</Dependencies>
	<RevDoku>
		<Owner Company="Sigmatek" Author="renste"/>
		<Dokumentation Revision="2.21" Date="13.12.2024" Author="LanSte" Company="Sigmatek" Description="Removed GetRequiredWaitTime.  Instead the wait time will be fetched from HWControl and apply to all required modules."/>
		<Dokumentation Revision="2.20" Date="03.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="2.19" 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="2.18" Date="18.12.2020" Author="RamAnd" Company="Sigmatek" Description="Removed CLI/STI occurances in internal time measurements"/>
		<Dokumentation Revision="2.17" Date="07.04.2020" Author="EisMic" Company="Sigmatek" Description="Changed comment of client &quot;UserAction&quot;."/>
		<Dokumentation Revision="2.16" Date="09.12.2019" Author="LanSte" Company="Sigmatek" Description="Added Server ProtocolVersion. InterframeGap is included in the resource calculation."/>
		<Dokumentation Revision="2.15" Date="16.03.2018" Author="EisMic" Company="Sigmatek" Description="Added support for 2nd VaranManager."/>
		<Dokumentation Revision="2.14" 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="2.13" Date="10.01.2018" Author="LanSte" Company="Sigmatek" Description="Added Support for default PostInit phase."/>
		<Dokumentation Revision="2.12" 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="2.11" Date="28.08.2017" Author="RamAnd" Company="Sigmatek" Description="The NewInst to get hardware diagnosis information doesn&apos;t set the returncode to SPI_ACCESS_FAILED if an optional entry of the type label is not available."/>
		<Dokumentation Revision="2.10" Date="29.11.2016" Author="PieSte" Company="Sigmatek" Description="Changed &quot;Online&quot; server behavior to set online first if cyclic data is valid."/>
		<Dokumentation Revision="2.9" 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="2.8" Date="17.02.2016" Author="EisMic" Company="Sigmatek" Description="Prescalersettings were not set correctly when Payload is active."/>
		<Dokumentation Revision="2.7" Date="28.08.2015" Author="PieSte" Company="Sigmatek" Description="Added support for up to 6 sync outs (e.g. CTMS031) in methode EnableSyncOut()."/>
		<Dokumentation Revision="2.6" Date="17.03.2015" Author="RamAnd" Company="Sigmatek" Description="Added support for Varan Mux."/>
		<Dokumentation Revision="2.5" Date="24.03.2015" Author="EisMic" 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="2.4" Date="28.08.2014" Author="EisMic" Company="Sigmatek" Description="Don&apos;t set states in GetHWInfoData. CMD_Get_Hardware_Diagnosis: Don&apos;t do a return when one spi access failed, try the other IDs too."/>
		<Dokumentation Revision="2.3" Date="24.06.2014" Author="LanSte" Company="Sigmatek" Description="Added support for reading hardware diagnosis."/>
		<Dokumentation Revision="2.2" 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="2.1" 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="2.0" Date="04.12.2013" Author="RamAnd&#13;&#10;FucHer&#13;&#10;LanSte" Company="Sigmatek" Description="Removed domain support&#13;&#10;Changed AWL code to Structured Text.&#13;&#10;Added Payload Support&#13;&#10;Added include for PCI accesses, which is necessary to find out if the Varan Manager supports LongDOs."/>
		<Dokumentation Revision="1.90" Date="30.08.2013" Author="RamAnd" Company="Sigmatek" Description="The class could have change the state to _DisableError after the disconnect from VARAN, even if there was no further problem."/>
		<Dokumentation Revision="1.80" Date="01.08.2013" Author="LanSte" Company="Sigmatek" Description="Added Support for changeable Payload DO&apos;s"/>
		<Dokumentation Revision="1.70" Date="18.07.2013" Author="LanSte&#13;&#10;ZoePat" Company="Sigmatek" Description="Added Payload Support&#13;&#10;Check if manager is on at function GetNodeInfo() to get different states for connected and disconnected modules if manager is turned off (e.g.: in case of required error that was handled by client UserAction)"/>
		<Dokumentation Revision="1.60" Date="07.03.2013" Author="RamAnd" Company="Sigmatek" Description="Improved comment of client UserAction (added new reasons)"/>
		<Dokumentation Revision="1.50" Date="05.11.2012" Author="RamAnd&#13;&#10;RamAnd" Company="Sigmatek" Description="Corrected time measurement for internal tests.&#13;&#10;Removed resetting of the FPGA retry counter in method ResetDataObject which could result in a wrong behavior of the RetryCounter server."/>
		<Dokumentation Revision="1.40" Date="18.09.2012" Author="RamAnd" Company="Sigmatek" Description="New State &quot;_NoCalibDataFound&quot; if a pointer to calibration data is fetched and there are no calibration data on the client."/>
		<Dokumentation Revision="1.39" Date="18.07.2012" Author="ObeChr" Company="Sigmatek" Description="Implemented time measurement for internal tests in methods UpdateRt, UpdateRtPostScan and UpdateCy&#13;&#10;Reduction of PCI Accesses in Methode GetRetryTimeout()"/>
		<Dokumentation Revision="1.38" Date="09.12.2011" Author="RamAnd" Company="Sigmatek" Description="The actual domain number is now added to the hardware path."/>
		<Dokumentation Revision="1.37" Date="19.09.2011" Author="RamAnd" Company="Sigmatek" Description="The client UserAction can now also be used to prevent a required error, if the write-method of the connected Server returns 0."/>
		<Dokumentation Revision="1.36" Date="13.07.2011" Author="RamAnd" Company="Sigmatek" Description="Added a dependency to class Hub_Base_Root, otherwise crashes can happen if only single VARAN-classes have been updated."/>
		<Dokumentation Revision="1.35" Date="14.04.2011" Author="BleErn" Company="Sigmatek" Description="Set complex object &quot;SerialNoStr&quot; to visualized"/>
		<Dokumentation Revision="1.34" Date="02.03.2011" Author="RamAnd" Company="Sigmatek" Description="Added new input parameter to method SetMultipleDataPointers to handle more than 1 multiple read write commands per VARAN client."/>
		<Dokumentation Revision="1.33" Date="04.01.2011" Author="BleErn" Company="Sigmatek" Description="Added Client Transparent that allows to disable a VARAN-HW-Class"/>
		<Dokumentation Revision="1.32" Date="17.01.2011" Author="RamAnd" Company="Sigmatek" Description="A required error on the first connect of the device can now be detected via the UserAction client"/>
		<Dokumentation Revision="1.31" Date="11.01.2011" Author="RamAnd" Company="Sigmatek" Description="Error fixed that Diagnostic functions stopped working after the first fault occured."/>
		<Dokumentation Revision="1.30" Date="14.12.2010" Author="RamAnd" Company="Sigmatek" Description="Set all servers to visualized, so that they can be used in visualisation"/>
		<Dokumentation Revision="1.29" Date="02.09.2010" Author="BleErn" Company="Sigmatek" Description="Server SerNoValidation was always set to 0 on disconnect of module"/>
		<Dokumentation Revision="1.28" Date="02.08.2010" Author="RamAnd" Company="Sigmatek" Description="Reworked serial number validation, because of problems with non-Sigmatek devices. Now the serial number is saved as a string instead of a number."/>
		<Dokumentation Revision="1.27" Date="22.07.2010" Author="WocPet / RamAnd" Company="Sigmatek" Description="Added functionality to forward a required error.&#13;&#10;Removed client UseRtPostScan (not needed, since it PostScan is always used)"/>
		<Dokumentation Revision="1.26" Date="06.04.2010" Author="RamAnd" Company="Sigmatek" Description="Added method &quot;FlexInit&quot; to initialize class if the position on VARAN has changed (FlexHub functionality)"/>
		<Dokumentation Revision="1.25" Date="10.03.2010" Author="RamAnd" Company="Sigmatek" Description="Added serial number validation and method CheckDeviceID for easier overloading"/>
		<Dokumentation Revision="1.24" Date="04.03.2010" Author="BleErn" Company="Sigmatek" Description="RtPostScan could be disabled at every CIV (took no notice of define!)"/>
		<Dokumentation Revision="1.23" Date="23.02.2010" Author="BleErn" Company="Sigmatek" Description="Changes in handling of VaranRtPostScan"/>
		<Dokumentation Revision="1.22" Date="17.05.2010" Author="RamAnd" Company="Sigmatek" Description="Changed defines to avoid compiler warning &quot;Identical Redefinition&quot;"/>
		<Dokumentation Revision="1.21" Date="09.10.2009" Author="ObeChr" Company="Sigmatek" Description="Added functions for VaranDiagnose"/>
		<Dokumentation Revision="1.20" Date="02.09.2009" Author="RamAnd" Company="Sigmatek" Description="Added functions for safety and hardwaretree."/>
		<Dokumentation Revision="1.19" Date="05.08.2009" Author="ObeChr" Company="Sigmatek" Description="When Client is required and no VaranInterface is available, VaranManager set application into reset"/>
		<Dokumentation Revision="1.18" Date="20.07.2009" Author="ObeChr" Company="Sigmatek" Description="Added function to set run state of do depending on required"/>
		<Dokumentation Revision="1.17" Date="16.07.2009" Author="ObeChr" Company="Sigmatek" Description="Added funktion to use VaranRtPostScan"/>
		<Dokumentation Revision="1.16" Date="18.06.2009" Author="EbnAnt" Company="Sigmatek" Description="Set Varan_CallBack() to virtual"/>
		<Dokumentation Revision="1.15" Date="16.04.2009" Author="RamAnd" Company="Sigmatek" Description="Added new method GetDocumentation to fetch pdf documentation of client.&#13;&#10;Added new Server SerialNo, to display the serial no of varan clients."/>
		<Dokumentation Revision="1.14" Date="01.12.2008" Author="RamAnd" Company="Sigmatek" Description="added new input variable b_use_divider_sync to function EnableSyncOut.&#13;&#10;Corrected SetNewPllData to new address mapping.&#13;&#10;improved client comments"/>
		<Dokumentation Revision="1.13" Date="03.09.2008" Author="renste" Company="Sigmatek" Description="add function for new pll"/>
	</RevDoku>
	<Network Name="Varan_Base">
		<!-- List of Components in this network -->
		<Components>
			<Object
				Name       = "SerialNoStr"
				GUID       = "{DBAA28A2-B730-4B3D-BE77-52A87CFBF0B0}"
				Class      = "String"
				Position   = "(180,480)"
				Visualized = "true">
				<Channels>
					<Server Name="Data"/>
					<Client Name="SingleRealloc" Value="1"/>
				</Channels>
			</Object>
			<Object
				Name       = "SerNoBackup"
				GUID       = "{7F2EEFF0-0F12-46DA-B0E6-9555A5C07FA2}"
				Class      = "RamFile"
				Position   = "(180,630)"
				Visualized = "true">
				<Channels>
					<Server Name="FileNameHex"/>
					<Server Name="m_udLength"/>
					<Server Name="SizeError"/>
					<Client Name="Alarm"/>
					<Client Name="MultiTask"/>
					<Client Name="Setup" Value="2#1101"/>
				</Channels>
			</Object>
		</Components>
		<Comments>
		</Comments>
		<!-- List of Connections in this network -->
		<Connections>
			<Connection Source="this.SerialNoStr" Destination="SerialNoStr.Data"/>
			<Connection Source="this.SerialNo" Destination="SerialNoStr.Data" Vertices="(818,630),(496,570),"/>
			<Connection Source="this.SerNoBackup" Destination="SerNoBackup.m_udLength"/>
		</Connections>
		<!-- Headerfiles -->
		<Options>
		</Options>
	</Network>
</Class>
*)
Varan_Base : CLASS
	TYPE
	  t_CallBack : STRUCT
	    ud_Counter : UDINT;
	    ud_ConnectCnt : UDINT;
	    ud_DisconnectCnt : UDINT;
	    ud_InterruptCnt : UDINT;
	    ud_SubBusReadyCnt : UDINT;
	    p_InterruptHandleDO : ^LSL_VARANFRAME;  //! <Type Comment="Warning:&#13;&#10;If the Interface &quot;IMULTIVARANMANAGER&quot; is used (b_PayloadSupport = true) this pointer those not point to the DO in the DPRAM!&#13;&#10;In this case this pointer holds the handle to the DO.&#13;&#10;" Name="t_CallBack.p_InterruptHandleDO"/>
	    ud_LastReason : UDINT;
	  END_STRUCT;
	  t_CycleWork :
	  (
	    _CycleInitIdle,
	    _CycleStartAsyDO,
	    _CycleStartIsoDO,
	    _CycleWaitforValidData,
	    _CyclePreOperational,
	    _CycleOperational
	  )$UDINT;
	  t_PllDataRead : STRUCT
	    us_State : BSINT
	    [
	      1 Pll_Locked,
	      2 Pll_Unlocked,
	      3 SyncOutputAvailable0,
	      4 SyncOutputAvailable1,
	      5 SyncOutputAvailable2,
	      6 IRQWatchdogEnable,
	      7 Pll_Enable,
	      8 PeriodeOverwriteAllowed,
	    ];
	  END_STRUCT;
	  t_PllDO : STRUCT
	    p_Handle : ^LSL_VARANFRAME;
	    p_DOSettings : ^t_VaranDOSettingsRd;
	    p_DataRead : ^t_PllDataRead;
	  END_STRUCT;
#pragma pack(push, 1)
	  t_PllSyncOut : STRUCT
	    sd_Offset : DINT;
	    us_PeriodMultiplier : USINT;
	    us_FrameCountTreshold : USINT;
	    us_Reserved1 : USINT;
	    us_ControlStatus : BSINT
	    [
	      1 SyncOutEnable,
	      2 FrameCountEnable,
	      3 SystemSync,  //! <Type Comment="0..divider sync&#13;&#10;1..system sync" Name="t_PllSyncOut.us_ControlStatus.SystemSync"/>
	    ];
	  END_STRUCT;
#pragma pack(pop)
	  t_RootDependency : ^Hub_Base_Root;
#pragma pack(push, 1)
	  t_SerNoValidateHeader : STRUCT
	    Version : HSINT;  //! <Type Comment="X.Y starting with 1.0 as first valid version&#13;&#10;&#13;&#10;X = Major&#13;&#10;Y = Minor" Name="t_SerNoValidateHeader.Version"/>
	    ZeroByte : USINT;
	    StringLength : UDINT;
	  END_STRUCT;
#pragma pack(pop)
	  t_SPI_CalibHeader : STRUCT
	    ud_Checksum : UDINT;
	    ud_ListVersion : UDINT;
	    ud_ListLength : UDINT;
	  END_STRUCT;
	  t_TempDataRead : STRUCT
	    si_Periode : INT;
	    ui_Prescaler : UINT;
	    ui_HiTimeRegister : UINT;
	  END_STRUCT;
	  t_TransparentInfo : BSINT
	  [
	    1 DeviceIsTransparent,
	    2 ClientTransparentRead,
	  ];
	END_TYPE
  //Servers:
	State 	: SvrChCmd_t_e_VaranErrors;
	Online 	: SvrCh_DINT;
	Release 	: SvrCh_HDINT;
	HardwareVersion 	: SvrCh_HDINT;
	DeviceAddress 	: SvrCh_HDINT;
	VendorID 	: SvrCh_UDINT;
	DeviceID 	: SvrCh_UDINT;
	SerialNo 	: SvrChCmd_UDINT;
	RetryCounter 	: SvrCh_UDINT;
	ValidateSerNo 	: SvrCh_DINT;
	DiagControl 	: SvrCh_DINT;
	ConnectCounter 	: SvrCh_UDINT;
	FaultCounter 	: SvrCh_UDINT;
	RXLost 	: SvrCh_UDINT;
	TXLost 	: SvrCh_UDINT;
	ProtocolVersion 	: SvrCh_HDINT;
  //Clients:
	VaranIn 	: CltChCmd_Hub_Base;
	Required 	: CltCh_DINT;
	UserAction 	: CltCh_DINT;
	SerNoValidation 	: CltCh_DINT;
	Transparent 	: CltCh_DINT;
	To_StdLib 	: CltChCmd__StdLib;
	To_MultiTask 	: CltChCmd__MultiTask;
	TimeBase 	: CltCh_UDINT;
	TimeBaseOffset 	: CltCh_UDINT;
	SerialNoStr 	: CltChCmd_String;
	SerNoBackup 	: CltChCmd_RamFile;
  //Variables:
		ud_VaranManagerNr 	: UDINT;
		pVaran 	: ^LSL_VARAN;			//! <Variable Comment="Pointer for the Varan interface" Name="pVaran"/>
		pMultiVaran 	: ^LSL_MULTI_VARAN;			//! <Variable Comment="Pointer for the MultiVaran/payload support interface" Name="pMultiVaran"/>
		mt_api 	: ^LSL_MT_TYPE;
		p_VaranPosition 	: ^USINT;
		p_NodeInfo 	: ^LSL_VARANNODEINFO;
		s_NodeInfo 	: LSL_VARANNODEINFO;
		ud_HandleModule 	: UDINT;
		ud_DeviceDelayTime 	: UDINT;
		s_CallBackSettings 	: t_CallBack;			//! <Variable Comment="settings of user callback function" Name="s_CallBackSettings"/>
		e_RequiredFaultState 	: t_e_VaranErrors;
		b_DisableDevice 	: BOOL;
		ud_DisableTime 	: UDINT;
		us_MulticastFilter 	: USINT;
		us_MultipleSequence 	: USINT;
		s_TimeRt 	: t_TimeMeasurementVaran;
		s_TimeRtPostScan 	: t_TimeMeasurementVaran;
		s_TimeCy 	: t_TimeMeasurementVaran;
		b_CyTask 	: BOOL;
		p_ObjectPath 	: ^USINT;
		s_Diagnose 	: t_s_VaranDiagnose;
		szSerNoStr : ARRAY [0..SERNO_STRING_SIZE-1] OF CHAR;

		b_ValidationInProgress 	: BOOL;
		SerNoHeader 	: t_SerNoValidateHeader;
		TransparentInfo 	: t_TransparentInfo;
		ud_ResponseTimeMax 	: UDINT;
		b_PayloadSupport 	: BOOL;			//! <Variable Comment="TRUE When Payload DOs are supporded by the OS Interface." Name="b_PayloadSupport"/>
		b_DMAactive 	: BOOL;			//! <Variable Comment="TRUE When Payload DOs are supporded by the OS Interface and the FPGA has an DMA Controller." Name="b_DMAactive"/>
		ud_OffestSPI 	: UDINT;
		bOnline 	: BOOL;
		eCycleWork 	: t_CycleWork;
		uiBasePostInitHandle 	: UINT;
		bPostInitNeeded 	: BOOL;
		_ParaBaseCy 	: CmdStruct;
		_ResultBaseCy 	: results;
  //Functions:
				//! <Function Comment="-------------------------------------------------------------------------------------------------&#13;&#10;[#ENGLISH]&#13;&#10;=================================================================================================&#13;&#10;Construct of Base class to set class not initialized&#13;&#10;=================================================================================================&#13;&#10;[server] State  :W  :State of class&#13;&#10;" Name="Varan_Base"/>
	FUNCTION Varan_Base
		VAR_OUTPUT
			ret_code 	: ConfStates;
		END_VAR;
				//! <Function Comment="Init for Varan Client" Name="Init"/>
	FUNCTION VIRTUAL GLOBAL Init;
				//! <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="get PDF-File from client, if it is available" Name="GetDocumentation"/>
	FUNCTION VIRTUAL GLOBAL GetDocumentation
		VAR_INPUT
			p_dpne 	: ^CHAR;			//! <Variable Comment="pass string of Drive/Path/Name/Extension (e.g. &quot;C:\mydoc.pdf&quot;)" Name="GetDocumentation.p_dpne"/>
		END_VAR
		VAR_OUTPUT
			sd_retval 	: DINT;			//! <Variable Comment=" 0..success&#13;&#10;-1..invalid parameters&#13;&#10;-2..failed to open file&#13;&#10;-3..os version must be 01.02.018 or higher&#13;&#10;-4..no documentation available on this client&#13;&#10;-5..failed to allocate memory for the file content&#13;&#10;-6..error in reading documentation from client&#13;&#10;-7..writing to file failed" Name="GetDocumentation.sd_retval"/>
		END_VAR;
				//! <Function Comment="Function returns pointer to node string of class" Name="GetPointer2NodeString"/>
	FUNCTION VIRTUAL GLOBAL GetPointer2NodeString
		VAR_OUTPUT
			p_us_node 	: ^USINT;			//! <Variable Comment="pointer to node string" Name="GetPointer2NodeString.p_us_node"/>
		END_VAR;
				//! <Function Comment="Function is called if a varan module is connected&#13;&#10;" Name="Varan_HwConnect"/>
	FUNCTION 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 Diagnose;
				//! <Function Comment="[#ENGLISH]&#13;&#10;=================================================================================================&#13;&#10;Function to set Pll settings of hardware module&#13;&#10;=================================================================================================&#13;&#10;[server] State    :W  :state of class&#13;&#10;[members] ud_DeviceDelayTime :W  :delay time of varan client for Pll&#13;&#10;   p_NodeInfo   :W  :pointer to varan client informations&#13;&#10;[locals] ud_data    :W/R :data for direct access&#13;&#10;" Name="SetPllData"/>
	FUNCTION SetPllData
		VAR_INPUT
			ud_delay_time 	: UDINT := 0;
		END_VAR
		VAR_OUTPUT
			sd_retval 	: DINT;
		END_VAR;
				//! <Function Comment="[#ENGLISH]&#13;&#10;=================================================================================================&#13;&#10;Function to get device address, Vendor ID and Device ID of varan module&#13;&#10;=================================================================================================&#13;&#10;[server] State   :W  :state of class&#13;&#10;   Release   :W  :FPGA - Version of varan client&#13;&#10;   DeviceAddress :W  :Device Address of client (from os)&#13;&#10;   VendorID  :W  :Vendor ID of varan client&#13;&#10;   DeviceID  :W  :Device ID of varan client&#13;&#10;[members] p_VaranPosition  :R  :node string of varan module&#13;&#10;   p_NodeInfo   :W  :pointer to varan client informations&#13;&#10;[locals] us_pll_time   :W/R :pll time from VaranMaster&#13;&#10;" Name="GetNodeInfo"/>
	FUNCTION GetNodeInfo
		VAR_OUTPUT
			sd_retval 	: DINT;
		END_VAR;
				//! <Function Comment="[#ENGLISH]&#13;&#10;=================================================================================================&#13;&#10;Callback Function is called from VaranManager&#13;&#10;=================================================================================================&#13;&#10;[server] Release   :W  :FPGA - Version of varan client&#13;&#10;   DeviceAddress :W  :Device Address of client (from os)&#13;&#10;   VendorID  :W  :Vendor ID of varan client&#13;&#10;   DeviceID  :W  :Device ID of varan client&#13;&#10;   State   :W  :state of class&#13;&#10;[client] Required  :R  :is class required for varan or not&#13;&#10;   UserAction  :R  :client for user actions&#13;&#10;[members] s_CallBackSettings  :W  :structure for settings of callback function&#13;&#10;   ud_DeviceDelayTime  :W  :delay time of varan client for Pll&#13;&#10;   e_RequiredFaultState :W  :Fault state of class in _RequiredError State&#13;&#10;" Name="Varan_CallBack"/>
	FUNCTION VIRTUAL Varan_CallBack
		VAR_INPUT
			ud_reason 	: UDINT;			//! <Variable Comment="reason of callback" Name="Varan_CallBack.ud_reason"/>
			ud_data 	: UDINT;
		END_VAR
		VAR_OUTPUT
			sd_retval (EAX) 	: DINT;
		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 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 reset settings of a data object" Name="ResetDataObject"/>
	FUNCTION VIRTUAL GLOBAL ResetDataObject
		VAR_INPUT
			p_handleDO 	: ^LSL_VARANFRAME;
			us_state 	: USINT;			//! <Variable Comment="state of DO (cont run, singl run, stop )" Name="ResetDataObject.us_state"/>
			ud_bytes 	: UDINT;			//! <Variable Comment="number of bytes" Name="ResetDataObject.ud_bytes"/>
		END_VAR;
				//! <Function Comment="=================================================================================================&#13;&#10;---------------------- Additional functions------------------------------------------------------&#13;&#10;=================================================================================================&#13;&#10;[#ENGLISH]&#13;&#10;=================================================================================================&#13;&#10;Function to Start time measurement&#13;&#10;=================================================================================================&#13;&#10;" Name="StartTimeMeasurement"/>
	FUNCTION StartTimeMeasurement
		VAR_INPUT
			usMode (EAX) 	: DINT;
		END_VAR;
				//! <Function Comment="[#ENGLISH]&#13;&#10;=================================================================================================&#13;&#10;Function to Stop time measurement&#13;&#10;=================================================================================================&#13;&#10;" Name="StopTimeMeasurement"/>
	FUNCTION StopTimeMeasurement
		VAR_INPUT
			usMode (EAX) 	: DINT;
		END_VAR;
				//! <Function Comment="Function to set a sync out" Name="GetDeviceAddress"/>
	FUNCTION VIRTUAL GLOBAL GetDeviceAddress
		VAR_OUTPUT
			ud_device_address 	: UDINT;			//! <Variable Comment="Device address of client" Name="GetDeviceAddress.ud_device_address"/>
		END_VAR;
				//! <Function Comment="[#ENGLISH]&#13;&#10;=================================================================================================&#13;&#10;Function to set a sync out&#13;&#10;=================================================================================================&#13;&#10;[server] State    :W  :state of class&#13;&#10;[locals] ud_offset    :W/R :address offset in pll&#13;&#10;   p_pll_output_data  :W/R :settings for pll sync output&#13;&#10;" Name="EnableSyncOut"/>
	FUNCTION EnableSyncOut
		VAR_INPUT
			us_sync_nr 	: USINT;			//! <Variable Comment="enable sync0-4 allowed" Name="EnableSyncOut.us_sync_nr"/>
			sd_offset 	: DINT;			//! <Variable Comment="Offset in 10ns time" Name="EnableSyncOut.sd_offset"/>
			us_period_multiplier 	: USINT;			//! <Variable Comment="periode multiplier" Name="EnableSyncOut.us_period_multiplier"/>
			us_frame_count_treshold 	: USINT;			//! <Variable Comment=" Frame Count Treshold" Name="EnableSyncOut.us_frame_count_treshold"/>
			us_enable_frame_count 	: USINT;			//! <Variable Comment=" enable frame count" Name="EnableSyncOut.us_enable_frame_count"/>
			b_use_divider_sync 	: BOOL := FALSE;
		END_VAR
		VAR_OUTPUT
			sd_retval 	: DINT;
		END_VAR;
				//! <Function Comment="Function to get pointer to node information" Name="GetPointer2NodeInfo"/>
	FUNCTION VIRTUAL GLOBAL GetPointer2NodeInfo
		VAR_OUTPUT
			p_node_info 	: ^LSL_VARANNODEINFO;			//! <Variable Comment="Pointer to Node information" Name="GetPointer2NodeInfo.p_node_info"/>
		END_VAR;
				//! <Function Comment="Function to set state of class" Name="SetState"/>
	FUNCTION VIRTUAL GLOBAL SetState
		VAR_INPUT
			sd_error 	: t_e_VaranErrors;			//! <Variable Comment="type of error" Name="SetState.sd_error"/>
		END_VAR;
				//! <Function Comment="Function to disable device" Name="DisableDevice"/>
	FUNCTION VIRTUAL GLOBAL DisableDevice
		VAR_OUTPUT
			sd_retval 	: DINT;
		END_VAR;
				//! <Function Comment="Function to enable device" Name="EnableDevice"/>
	FUNCTION VIRTUAL GLOBAL EnableDevice
		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 look if class is disabled" Name="IsDeviceDisabled"/>
	FUNCTION VIRTUAL GLOBAL IsDeviceDisabled
		VAR_OUTPUT
			b_disabled 	: BOOL;			//! <Variable Comment="TRUE -&gt; Device is disabled" Name="IsDeviceDisabled.b_disabled"/>
		END_VAR;
				//! <Function Comment="Function to set multiple memory read/write options" Name="SetMultipleSettings"/>
	FUNCTION VIRTUAL GLOBAL SetMultipleSettings
		VAR_INPUT
			us_filter 	: USINT;			//! <Variable Comment="filter of multicast write" Name="SetMultipleSettings.us_filter"/>
			us_sequence 	: USINT;			//! <Variable Comment="sequence number of device" Name="SetMultipleSettings.us_sequence"/>
		END_VAR
		VAR_OUTPUT
			sd_retval 	: DINT;
		END_VAR;
				//! <Function Comment="Function must be overwrite" Name="SetMultipleDataPointers"/>
	FUNCTION VIRTUAL GLOBAL SetMultipleDataPointers
		VAR_INPUT
			p_handle 	: ^LSL_VARANFRAME;			//! <Variable Comment="pointer to data object header" Name="SetMultipleDataPointers.p_handle"/>
			p_data_read 	: ^UDINT;			//! <Variable Comment="pointer to read data" Name="SetMultipleDataPointers.p_data_read"/>
			p_data_write 	: ^UDINT;			//! <Variable Comment="pointer to data write" Name="SetMultipleDataPointers.p_data_write"/>
			DOIndex 	: UDINT;
		END_VAR
		VAR_OUTPUT
			sd_retval 	: DINT;
		END_VAR;
				//! <Function Comment="[#ENGLISH]&#13;&#10;=================================================================================================&#13;&#10;Function to get pointer to calib data&#13;&#10;=================================================================================================&#13;&#10;" Name="GetCalibDataPointer"/>
	FUNCTION GetCalibDataPointer
		VAR_INPUT
			p_offset 	: ^UDINT;			//! <Variable Comment="pointer to variable to write offset" Name="GetCalibDataPointer.p_offset"/>
		END_VAR
		VAR_OUTPUT
			sd_retval 	: DINT;
		END_VAR;
				//! <Function Comment="[#ENGLISH]&#13;&#10;=================================================================================================&#13;&#10;Function to get pointer to calib data&#13;&#10;=================================================================================================&#13;&#10;" Name="ReadSPIData"/>
	FUNCTION ReadSPIData
		VAR_INPUT
			ud_offset 	: UDINT;			//! <Variable Comment="offset in SPI - Flash" Name="ReadSPIData.ud_offset"/>
			ud_length 	: UDINT;			//! <Variable Comment="length of data" Name="ReadSPIData.ud_length"/>
			p_data 	: ^USINT;			//! <Variable Comment="pointer to allocated data space" Name="ReadSPIData.p_data"/>
		END_VAR
		VAR_OUTPUT
			sd_retval 	: DINT;
		END_VAR;
				//! <Function Comment="Function to update module retry counter" Name="UpdateRetryCounter"/>
	FUNCTION VIRTUAL GLOBAL UpdateRetryCounter;
				//! <Function Comment="Function to get varan time" Name="GetVaranTime"/>
	FUNCTION VIRTUAL GLOBAL GetVaranTime
		VAR_INPUT
			p_ud_IsoStartPoint 	: ^UDINT := NIL;
		END_VAR
		VAR_OUTPUT
			ud_varan_time 	: UDINT;			//! <Variable Comment="varan time" Name="GetVaranTime.ud_varan_time"/>
		END_VAR;
				//! <Function Comment="Function to get retry timeout for a number of bytes" Name="GetRetryTimeout"/>
	FUNCTION VIRTUAL GLOBAL GetRetryTimeout
		VAR_INPUT
			ud_bytes 	: UDINT;
		END_VAR
		VAR_OUTPUT
			ud_timeout 	: UDINT;			//! <Variable Comment="retry timout time" Name="GetRetryTimeout.ud_timeout"/>
		END_VAR;
				//! <Function Comment="[#ENGLISH]&#13;&#10;=================================================================================================&#13;&#10;Function to disable Device in Rt (because VARAN_iSetNodeEnableStatus must not called in Realtime)&#13;&#10;=================================================================================================&#13;&#10;" Name="DisableDeviceRt"/>
	FUNCTION DisableDeviceRt
		VAR_OUTPUT
			sd_retval 	: DINT;
		END_VAR;
	
	FUNCTION SetNewPllData
		VAR_INPUT
			ud_delay_time 	: UDINT := 0;
			us_divider 	: USINT := 0;
		END_VAR
		VAR_OUTPUT
			sd_retval 	: DINT;
		END_VAR;
				//! <Function Comment="Function to set state depending on required" Name="SetRunStatus"/>
	FUNCTION GLOBAL SetRunStatus
		VAR_INPUT
			state 	: USINT;
		END_VAR
		VAR_OUTPUT
			us_retval 	: USINT;
		END_VAR;
	
	FUNCTION VIRTUAL GLOBAL GetPointer2ObjectPath
		VAR_OUTPUT
			p_us_ObjectPath 	: ^USINT;
		END_VAR;
	
	FUNCTION VIRTUAL GLOBAL SetObjectThisp
		VAR_INPUT
			p_us_ObjectPath 	: ^USINT;
			ud_thisp 	: UDINT;
		END_VAR
		VAR_OUTPUT
			sd_retval 	: DINT;
		END_VAR;
	
	FUNCTION VIRTUAL GLOBAL GetObjectThisp
		VAR_INPUT
			p_us_ObjectPath 	: ^USINT;
		END_VAR
		VAR_OUTPUT
			ud_Thisp 	: UDINT;
		END_VAR;
	
	FUNCTION SerNoValidationTask;
	
	FUNCTION GetHWInfoData
		VAR_INPUT
			p_offset 	: ^UDINT;
			ud_id 	: UDINT;
		END_VAR
		VAR_OUTPUT
			sd_retval 	: DINT;
		END_VAR;
	
	FUNCTION GetPllState
		VAR_OUTPUT
			pllstate 	: BSINT;
		END_VAR;
	
	FUNCTION VIRTUAL CheckCyclicPostInitFinished
		VAR_INPUT
			bForcePostInitEnd 	: BOOL;
		END_VAR;
				//! <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 GLOBAL FlexInit;
	
	FUNCTION GLOBAL AllowRequiredError;
	
	FUNCTION GLOBAL IsTransparent
		VAR_OUTPUT
			isTransparent 	: BOOL;
		END_VAR;
				//! <Function Comment="Method to add a read payload data object to varan manager.&#13;&#10;The parameters are passed on to the varan manager via a new inst call.&#13;&#10;" Name="AddRdPayloadDO"/>
	FUNCTION VIRTUAL GLOBAL AddRdPayloadDO
		VAR_INPUT
			ud_dol_type 	: UDINT;			//! <Variable Comment="DOL into witch the DO is to be inserted. &#13;&#10;VARAN_DOL_ASY or VARAN_DOL_ISO" Name="AddRdPayloadDO.ud_dol_type"/>
			p_ud_handle 	: ^UDINT;			//! <Variable Comment="Pointer to variable to set the DO handle.&#13;&#10;Value does not represent a valid address." Name="AddRdPayloadDO.p_ud_handle"/>
			ud_offset_read 	: UDINT;			//! <Variable Comment="Offset of read data within the module. &#13;&#10;(DeviceAddress is not included in this value.)" Name="AddRdPayloadDO.ud_offset_read"/>
			ud_length_read 	: UDINT;			//! <Variable Comment="Length of read data object." Name="AddRdPayloadDO.ud_length_read"/>
			p_ud_data_read 	: ^UDINT;			//! <Variable Comment="The pointer to the read data is written to this address." Name="AddRdPayloadDO.p_ud_data_read"/>
			ud_type 	: UDINT := VM_MEMORY_ACCESS;			//! <Variable Comment="0=control area, 1=memory area" Name="AddRdPayloadDO.ud_type"/>
			ud_priority 	: UDINT := VM_PRIORITY_INVALID;			//! <Variable Comment="Priority of the DO within the DOL. &#13;&#10;1000 highest priority&#13;&#10;9000 lowest priority&#13;&#10;Priority not dividable by 1000 cannot be used outside of the init phase.&#13;&#10;Optional." Name="AddRdPayloadDO.ud_priority"/>
			ud_WritePayloadType 	: UDINT := 0;			//! <Variable Comment="Changeable DO.&#13;&#10;Set this parameter if the DO length and or offset needs to be changed after creation.&#13;&#10;Optional." Name="AddRdPayloadDO.ud_WritePayloadType"/>
		END_VAR
		VAR_OUTPUT
			sd_retval 	: DINT;			//! <Variable Comment="Value &lt;&gt; 0 equal an error.&#13;&#10;See &#13;&#10;lsl_st_varan.h   // Ergebniscodes&#13;&#10;VaranManager_Base.h // Return Codes of the Control NewInst method&#13;&#10;for errorcodes." Name="AddRdPayloadDO.sd_retval"/>
		END_VAR;
				//! <Function Comment="Method to add a write payload data object to varan manager.&#13;&#10;The parameters are passed on to the varan manager via a new inst call.&#13;&#10;" Name="AddWrPayloadDO"/>
	FUNCTION VIRTUAL GLOBAL AddWrPayloadDO
		VAR_INPUT
			ud_dol_type 	: UDINT;			//! <Variable Comment="DOL into witch the DO is to be inserted. &#13;&#10;VARAN_DOL_ASY or VARAN_DOL_ISO" Name="AddWrPayloadDO.ud_dol_type"/>
			p_ud_handle 	: ^UDINT;			//! <Variable Comment="Pointer to variable to set the DO handle.&#13;&#10;Value does not represent a valid address." Name="AddWrPayloadDO.p_ud_handle"/>
			ud_offset_write 	: UDINT;			//! <Variable Comment="Offset of write data within the module. &#13;&#10;(DeviceAddress is not included in this value.)" Name="AddWrPayloadDO.ud_offset_write"/>
			ud_length_write 	: UDINT;			//! <Variable Comment="Length of write data object." Name="AddWrPayloadDO.ud_length_write"/>
			p_ud_data_write 	: ^UDINT;			//! <Variable Comment="The pointer to the read data is written to this address." Name="AddWrPayloadDO.p_ud_data_write"/>
			ud_type 	: UDINT;			//! <Variable Comment="0=control area, 1=memory area" Name="AddWrPayloadDO.ud_type"/>
			ud_priority 	: UDINT := VM_PRIORITY_INVALID;			//! <Variable Comment="Priority of the DO within the DOL. &#13;&#10;1000 highest priority&#13;&#10;9000 lowest priority&#13;&#10;Priority not dividable by 1000 cannot be used outside of the init phase.&#13;&#10;Optional." Name="AddWrPayloadDO.ud_priority"/>
			ud_WritePayloadType 	: UDINT := 0;			//! <Variable Comment="Changeable DO.&#13;&#10;Set this parameter if the DO length and or offset needs to be changed after creation.&#13;&#10;Optional." Name="AddWrPayloadDO.ud_WritePayloadType"/>
		END_VAR
		VAR_OUTPUT
			sd_retval 	: DINT;			//! <Variable Comment="Value &lt;&gt; 0 equal an error.&#13;&#10;See &#13;&#10;lsl_st_varan.h   // Ergebniscodes&#13;&#10;VaranManager_Base.h // Return Codes of the Control NewInst method&#13;&#10;for errorcodes." Name="AddWrPayloadDO.sd_retval"/>
		END_VAR;
				//! <Function Comment="Method to add a read/write payload data object to varan manager.&#13;&#10;The parameters are passed on to the varan manager via a new inst call.&#13;&#10;" Name="AddRdWrPayloadDO"/>
	FUNCTION VIRTUAL GLOBAL AddRdWrPayloadDO
		VAR_INPUT
			ud_dol_type 	: UDINT;			//! <Variable Comment="DOL into witch the DO is to be inserted. &#13;&#10;VARAN_DOL_ASY or VARAN_DOL_ISO" Name="AddRdWrPayloadDO.ud_dol_type"/>
			p_ud_handle 	: ^UDINT;			//! <Variable Comment="Pointer to variable to set the DO handle.&#13;&#10;Value does not represent a valid address." Name="AddRdWrPayloadDO.p_ud_handle"/>
			ud_offset_read 	: UDINT;			//! <Variable Comment="Offset of read data within the module. &#13;&#10;(DeviceAddress is not included in this value.)" Name="AddRdWrPayloadDO.ud_offset_read"/>
			ud_length_read 	: UDINT;			//! <Variable Comment="Length of read data object." Name="AddRdWrPayloadDO.ud_length_read"/>
			p_ud_data_read 	: ^UDINT;			//! <Variable Comment="The pointer to the read data is written to this address." Name="AddRdWrPayloadDO.p_ud_data_read"/>
			ud_offset_write 	: UDINT;			//! <Variable Comment="Offset of write data within the module. &#13;&#10;(DeviceAddress is not included in this value.)" Name="AddRdWrPayloadDO.ud_offset_write"/>
			ud_length_write 	: UDINT;			//! <Variable Comment="Length of write data object." Name="AddRdWrPayloadDO.ud_length_write"/>
			p_ud_data_write 	: ^UDINT;			//! <Variable Comment="The pointer to the read data is written to this address." Name="AddRdWrPayloadDO.p_ud_data_write"/>
			ud_type 	: UDINT;			//! <Variable Comment="0=control area, 1=memory area" Name="AddRdWrPayloadDO.ud_type"/>
			ud_priority 	: UDINT := VM_PRIORITY_INVALID;			//! <Variable Comment="Priority of the DO within the DOL. &#13;&#10;1000 highest priority&#13;&#10;9000 lowest priority&#13;&#10;Priority not dividable by 1000 cannot be used outside of the init phase.&#13;&#10;Optional." Name="AddRdWrPayloadDO.ud_priority"/>
			ud_WritePayloadType 	: UDINT := 0;			//! <Variable Comment="Changeable DO.&#13;&#10;Set this parameter if the DO length and or offset needs to be changed after creation.&#13;&#10;Optional." Name="AddRdWrPayloadDO.ud_WritePayloadType"/>
		END_VAR
		VAR_OUTPUT
			sd_retval 	: DINT;			//! <Variable Comment="Value &lt;&gt; 0 equal an error.&#13;&#10;See &#13;&#10;lsl_st_varan.h   // Ergebniscodes&#13;&#10;VaranManager_Base.h // Return Codes of the Control NewInst method&#13;&#10;for errorcodes." Name="AddRdWrPayloadDO.sd_retval"/>
		END_VAR;
				//! <Function Comment="Method to add a move payload data object to varan manager.&#13;&#10;The parameters are passed on to the varan manager via a new inst call.&#13;&#10;" Name="AddMovePayloadDO"/>
	FUNCTION VIRTUAL GLOBAL AddMovePayloadDO
		VAR_INPUT
			ud_dol_type 	: UDINT;			//! <Variable Comment="DOL into witch the DO is to be inserted. &#13;&#10;VARAN_DOL_ASY or VARAN_DOL_ISO" Name="AddMovePayloadDO.ud_dol_type"/>
			p_ud_handle 	: ^UDINT;			//! <Variable Comment="Pointer to variable to set the DO handle.&#13;&#10;Value does not represent a valid address." Name="AddMovePayloadDO.p_ud_handle"/>
			ud_SourceReadDOHandle 	: UDINT;			//! <Variable Comment="Handle of the source DO.&#13;&#10;" Name="AddMovePayloadDO.ud_SourceReadDOHandle"/>
			ud_SourceReadOffset 	: UDINT := 0;			//! <Variable Comment="Offset within the source DO from where to copy the data.&#13;&#10;This offset + the number of bytes to be copied must not exceed the size of the source DO." Name="AddMovePayloadDO.ud_SourceReadOffset"/>
			ud_DestinationWriteDOHandle 	: UDINT;			//! <Variable Comment="Handle of the destination DO.&#13;&#10;" Name="AddMovePayloadDO.ud_DestinationWriteDOHandle"/>
			ud_DestinationWriteOffset 	: UDINT := 0;			//! <Variable Comment="Offset within the destination DO from where to copy the data.&#13;&#10;This offset + the number of bytes to be copied must not exceed the size of the source DO." Name="AddMovePayloadDO.ud_DestinationWriteOffset"/>
			ud_LengthMove 	: UDINT;			//! <Variable Comment="Number of bytes to be copied." Name="AddMovePayloadDO.ud_LengthMove"/>
			ud_Priority 	: UDINT;			//! <Variable Comment="Priority of the DO within the DOL. &#13;&#10;1000 highest priority&#13;&#10;9000 lowest priority&#13;&#10;Priority not dividable by 1000 cannot be used outside of the init phase.&#13;&#10;This value must be set in correct relation with the source and destination DO." Name="AddMovePayloadDO.ud_Priority"/>
		END_VAR
		VAR_OUTPUT
			sd_retval 	: DINT;			//! <Variable Comment="Value &lt;&gt; 0 equal an error.&#13;&#10;See &#13;&#10;lsl_st_varan.h   // Ergebniscodes&#13;&#10;VaranManager_Base.h // Return Codes of the Control NewInst method&#13;&#10;for errorcodes." Name="AddMovePayloadDO.sd_retval"/>
		END_VAR;
				//! <Function Comment="Starts the passed data object " Name="EnableDO"/>
	FUNCTION VIRTUAL GLOBAL EnableDO
		VAR_INPUT
			ud_DOHandle 	: UDINT;			//! <Variable Comment="Starts the passed data object " Name="EnableDO.ud_DOHandle"/>
			ud_bytes 	: UDINT := 0;
		END_VAR
		VAR_OUTPUT
			sd_retval 	: DINT;
		END_VAR;
				//! <Function Comment="Stops the passed data object " Name="DisableDO"/>
	FUNCTION VIRTUAL GLOBAL DisableDO
		VAR_INPUT
			ud_DOHandle 	: UDINT;
			ud_bytes 	: UDINT := 0;
		END_VAR
		VAR_OUTPUT
			sd_retval 	: DINT;
		END_VAR;
				//! <Function Comment="Returns the retry counter of the passed data object." Name="GetRetryCounter"/>
	FUNCTION VIRTUAL GLOBAL GetRetryCounter
		VAR_INPUT
			ud_DOHandle 	: UDINT;
		END_VAR
		VAR_OUTPUT
			us_RetryCounter 	: USINT;
		END_VAR;
				//! <Function Comment="This method is used to change the offset and length of the DO. The method can only be used with the Interface &quot;IMULTIVARANMANAGER&quot; is active (if b_payload). Do not set parameters that are unused/should remain unchanged." Name="ChangeDOLengthOffset"/>
	FUNCTION VIRTUAL GLOBAL ChangeDOLengthOffset
		VAR_INPUT
			ud_DOHandle 	: UDINT;			//! <Variable Comment="Handle of the DO" Name="ChangeDOLengthOffset.ud_DOHandle"/>
			ud_offset_read 	: UDINT := VM_DO_PROPERTY_INVALID;			//! <Variable Comment="New read offset" Name="ChangeDOLengthOffset.ud_offset_read"/>
			ud_length_read 	: UDINT := VM_DO_PROPERTY_INVALID;			//! <Variable Comment="New read length" Name="ChangeDOLengthOffset.ud_length_read"/>
			ud_offset_write 	: UDINT := VM_DO_PROPERTY_INVALID;			//! <Variable Comment="New write offset" Name="ChangeDOLengthOffset.ud_offset_write"/>
			ud_length_write 	: UDINT := VM_DO_PROPERTY_INVALID;			//! <Variable Comment="New write length" Name="ChangeDOLengthOffset.ud_length_write"/>
		END_VAR
		VAR_OUTPUT
			sd_retval 	: DINT;
		END_VAR;
	
	FUNCTION VIRTUAL GLOBAL SetPrescaler
		VAR_INPUT
			ud_DOHandle 	: UDINT;
			Prescaler 	: UDINT;
			PrescalerCnt 	: UDINT := 0;
			b_MultipleTimeBase 	: BOOL := false;
		END_VAR
		VAR_OUTPUT
			sd_retval 	: DINT;
		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 CreateMutex
		VAR_INPUT
			MutexName 	: ^CHAR;
			pThis 	: ^VirtualBase := nil;
		END_VAR
		VAR_OUTPUT
			pv_RetMutex 	: pVoid;
		END_VAR;
	
	FUNCTION VIRTUAL GLOBAL MutexStart
		VAR_INPUT
			pMutex 	: pVoid;
		END_VAR;
	
	FUNCTION VIRTUAL GLOBAL MutexStop
		VAR_INPUT
			pMutex 	: pVoid;
		END_VAR;
				//! <Function Comment="Method simulates a SingleRun DO by En/Disabling the DO depending on p_b_DOIsRunning.&#13;&#10;To use this method t_SingleRunState^.StartRequest must be set where the singlerun is required&#13;&#10;and the Method must be called at the end of the task where the DO is used. (UpdatyCy, UpdateRt...)&#13;&#10;Only works with Varan DO (No with Mover)&#13;&#10;Method was made for Payload DO. Should work with standard DO&apos;s as well.&#13;&#10;(EnableDO, DisableDO does not equal ResetDO!)" Name="SingleRunSM"/>
	FUNCTION VIRTUAL GLOBAL SingleRunSM
		VAR_INPUT
			p_DOhandle 	: ^UDINT;
			p_b_DOIsRunning 	: ^t_SingleRunState;
		END_VAR;
	
	FUNCTION VIRTUAL GLOBAL ChangeMovDOLengthOffset
		VAR_INPUT
			ud_MovDOHandle 	: UDINT;
			ud_SourceReadDOHandle 	: UDINT := VM_DO_PROPERTY_INVALID;
			ud_SourceReadOffset 	: UDINT := VM_DO_PROPERTY_INVALID;
			ud_DestinationWriteDOHandle 	: UDINT := VM_DO_PROPERTY_INVALID;
			ud_DestinationWriteOffset 	: UDINT := VM_DO_PROPERTY_INVALID;
			ud_LengthMove 	: UDINT := VM_DO_PROPERTY_INVALID;
		END_VAR
		VAR_OUTPUT
			sd_retval 	: DINT;
		END_VAR;
	
	FUNCTION VIRTUAL GLOBAL GetDeviceID
		VAR_OUTPUT
			output 	: UDINT;
		END_VAR;
	
	FUNCTION VIRTUAL GetFWVersion
		VAR_INPUT
			pData 	: ^CHAR;
			length 	: UDINT;
		END_VAR;
				//! <Function Comment="Returns true if this class needs the postinitphase. &#13;&#10;Default in the base is false." Name="CheckPostInitNeeded"/>
	FUNCTION VIRTUAL GLOBAL CheckPostInitNeeded
		VAR_INPUT
			pbPostInitSettings 	: ^t_VM_CMD_NEED_POST_INIT_CALL_SETTINGS;
		END_VAR
		VAR_OUTPUT
			PostInitNeeded 	: BOOL;
		END_VAR;
	
	FUNCTION VIRTUAL LogError
		VAR_INPUT
			e_msg 	: ^CHAR;
		END_VAR;
	
	FUNCTION VIRTUAL LogValue
		VAR_INPUT
			pString 	: ^CHAR;
			Value 	: UDINT;
			Value2 	: UDINT := 16#FFFFFFFF;
			Value3 	: UDINT := 16#FFFFFFFF;
		END_VAR;
	
	FUNCTION VIRTUAL ConvertHwVersion
		VAR_INPUT
			OriginalHwVer 	: HDINT;
		END_VAR
		VAR_OUTPUT
			DisplayedHwVer 	: HDINT;
		END_VAR;
	
	FUNCTION VIRTUAL GLOBAL State::NewInst
		VAR_INPUT
			pPara 	: ^CmdStruct;
			pResult 	: ^results;
		END_VAR
		VAR_OUTPUT
			ret_code 	: iprStates;
		END_VAR;
	
	FUNCTION VIRTUAL GLOBAL ValidateSerNo::Write
		VAR_INPUT
			input (EAX) 	: DINT;
		END_VAR
		VAR_OUTPUT
			result (EAX) 	: DINT;
		END_VAR;
	
	FUNCTION VIRTUAL GLOBAL DiagControl::Write
		VAR_INPUT
			input (EAX) 	: DINT;
		END_VAR
		VAR_OUTPUT
			result (EAX) 	: DINT;
		END_VAR;
  //Tables:
	FUNCTION @STD
		VAR_OUTPUT
			ret_code	: CONFSTATES;
		END_VAR;
	FUNCTION GLOBAL TAB @CT_;
END_CLASS;

#pragma using RamFile
#pragma using String
#pragma usingLtd _MultiTask
#pragma usingLtd _StdLib
#pragma usingLtd Hub_Base


//}}LSL_DECLARATION


FUNCTION GLOBAL TAB Varan_Base::@CT_
0$UINT,
2#0100000000000000$UINT, //TY_VARAN_BASE
2$UINT, 21$UINT, (SIZEOF(::Varan_Base))$UINT, 
16$UINT, 11$UINT, 0$UINT, 
TO_UDINT(862125188), "Varan_Base", //Class
TO_UDINT(0), 0, 0$UINT, 0$UINT, //Baseclass
//Servers:
(::Varan_Base.State.pMeth)$UINT, _CH_CMD$UINT, 2#0000000000000000$UINT, TO_UDINT(1422331979), "State", 
(::Varan_Base.Online.pMeth)$UINT, _CH_SVR$UINT, 2#0000000000000000$UINT, TO_UDINT(1858763116), "Online", 
(::Varan_Base.Release.pMeth)$UINT, _CH_SVR$UINT, 2#0000000000000000$UINT, TO_UDINT(2701327623), "Release", 
(::Varan_Base.HardwareVersion.pMeth)$UINT, _CH_SVR$UINT, 2#0000000000000000$UINT, TO_UDINT(1421172680), "HardwareVersion", 
(::Varan_Base.DeviceAddress.pMeth)$UINT, _CH_SVR$UINT, 2#0000000000000000$UINT, TO_UDINT(19004412), "DeviceAddress", 
(::Varan_Base.VendorID.pMeth)$UINT, _CH_SVR$UINT, 2#0000000000000000$UINT, TO_UDINT(2218535187), "VendorID", 
(::Varan_Base.DeviceID.pMeth)$UINT, _CH_SVR$UINT, 2#0000000000000000$UINT, TO_UDINT(4261957967), "DeviceID", 
(::Varan_Base.SerialNo.pMeth)$UINT, _CH_SVR_OBJ$UINT, 2#0000000001000000$UINT, TO_UDINT(1856804640), "SerialNo", 
(::Varan_Base.RetryCounter.pMeth)$UINT, _CH_SVR$UINT, 2#0000000000000000$UINT, TO_UDINT(3383993698), "RetryCounter", 
(::Varan_Base.ValidateSerNo.pMeth)$UINT, _CH_SVR$UINT, 2#0000000000000000$UINT, TO_UDINT(1774120368), "ValidateSerNo", 
(::Varan_Base.DiagControl.pMeth)$UINT, _CH_SVR$UINT, 2#0000000000000000$UINT, TO_UDINT(3405391476), "DiagControl", 
(::Varan_Base.ConnectCounter.pMeth)$UINT, _CH_SVR$UINT, 2#0000000000000000$UINT, TO_UDINT(102302322), "ConnectCounter", 
(::Varan_Base.FaultCounter.pMeth)$UINT, _CH_SVR$UINT, 2#0000000000000000$UINT, TO_UDINT(1722935151), "FaultCounter", 
(::Varan_Base.RXLost.pMeth)$UINT, _CH_SVR$UINT, 2#0000000000000000$UINT, TO_UDINT(2943564375), "RXLost", 
(::Varan_Base.TXLost.pMeth)$UINT, _CH_SVR$UINT, 2#0000000000000000$UINT, TO_UDINT(2032851274), "TXLost", 
(::Varan_Base.ProtocolVersion.pMeth)$UINT, _CH_SVR$UINT, 2#0000000000000000$UINT, TO_UDINT(1757312337), "ProtocolVersion", 
//Clients:
(::Varan_Base.VaranIn.pCh)$UINT, _CH_CLT_OBJ$UINT, 2#0000000000000010$UINT, TO_UDINT(2999796184), "VaranIn", TO_UDINT(3238133653), "Hub_Base", 1$UINT, 21$UINT, 
(::Varan_Base.Required.pCh)$UINT, _CH_CLT_DATA$UINT, 2#0000000000000010$UINT, TO_UDINT(648558917), "Required", 
(::Varan_Base.UserAction.pCh)$UINT, _CH_CLT_DATA$UINT, 2#0000000000000000$UINT, TO_UDINT(615089769), "UserAction", 
(::Varan_Base.SerNoValidation.pCh)$UINT, _CH_CLT_DATA$UINT, 2#0000000000000000$UINT, TO_UDINT(2258645482), "SerNoValidation", 
(::Varan_Base.Transparent.pCh)$UINT, _CH_CLT_DATA$UINT, 2#0000000000000000$UINT, TO_UDINT(2239134692), "Transparent", 
(::Varan_Base.To_StdLib.pCh)$UINT, _CH_CLT_OBJ$UINT, 2#0000000000000000$UINT, TO_UDINT(2139173287), "To_StdLib", TO_UDINT(3689364044), "_StdLib", 2$UINT, 0$UINT, 
(::Varan_Base.To_MultiTask.pCh)$UINT, _CH_CLT_OBJ$UINT, 2#0000000000000000$UINT, TO_UDINT(2145650779), "To_MultiTask", TO_UDINT(2641766936), "_MultiTask", 1$UINT, 1$UINT, 
(::Varan_Base.TimeBase.pCh)$UINT, _CH_CLT_DATA$UINT, 2#0000000000000000$UINT, TO_UDINT(2439844029), "TimeBase", 
(::Varan_Base.TimeBaseOffset.pCh)$UINT, _CH_CLT_DATA$UINT, 2#0000000000000000$UINT, TO_UDINT(1524328294), "TimeBaseOffset", 
(::Varan_Base.SerialNoStr.pCh)$UINT, _CH_CLT_OBJ$UINT, 2#0000000000000010$UINT, TO_UDINT(321148131), "SerialNoStr", TO_UDINT(1850111279), "String", 1$UINT, 11$UINT, 
(::Varan_Base.SerNoBackup.pCh)$UINT, _CH_CLT_OBJ$UINT, 2#0000000000000010$UINT, TO_UDINT(1584581915), "SerNoBackup", TO_UDINT(3591333481), "RamFile", 1$UINT, 9$UINT, 
END_FUNCTION


#define USER_CNT_Varan_Base 49

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

FUNCTION Varan_Base::@STD
	VAR_OUTPUT
		ret_code	: CONFSTATES;
	END_VAR
	VAR
		vmt	: _LSL_STD_VMETH;
	END_VAR

	//Command Methods
	InitCmdTable (nCmd := nSTDCMD + USER_CNT_Varan_Base, pCmd := #vmt.CmdTable);
	vmt.CmdTable.NewInstr		:= #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[3]		:= #GetDocumentation();

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

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

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

#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[10]		:= #ResetDataObject();

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	IF SerialNo.pMeth THEN
		ret_code	:= C_OK;
	ELSE
		ret_code	:= C_OUTOF_NEAR;
		RETURN;
	END_IF;
	RetryCounter.pMeth			:= StoreMethod( #M_RD_DIRECT(), #M_WR_DIRECT() );
	IF RetryCounter.pMeth THEN
		ret_code	:= C_OK;
	ELSE
		ret_code	:= C_OUTOF_NEAR;
		RETURN;
	END_IF;
	ValidateSerNo.pMeth			:= StoreMethod( #M_RD_DIRECT(), #ValidateSerNo::Write() );
	IF ValidateSerNo.pMeth THEN
		ret_code	:= C_OK;
	ELSE
		ret_code	:= C_OUTOF_NEAR;
		RETURN;
	END_IF;
	DiagControl.pMeth			:= StoreMethod( #M_RD_DIRECT(), #DiagControl::Write() );
	IF DiagControl.pMeth THEN
		ret_code	:= C_OK;
	ELSE
		ret_code	:= C_OUTOF_NEAR;
		RETURN;
	END_IF;
	ret_code	:= Varan_Base();

END_FUNCTION

#pragma usingLtd Hub_Base_Root

//{{LSL_IMPLEMENTATION
(************************************************************************************
*
*	Baseclass for varan mastercontrolling
*	Created : Sigmatek	/	SR	/	March-April 2006
*	Changes :
*
*
*     FOR NEWER CHANGES SEE REVISION DOCUMENTATION IN CLASS PROPERTIES
*
*   1.11 => 1.12	/	26.05.2008
*			- [DB 863]: - add function to disable device in cyclic
*       1.10 => 1.11 /  18.04.2008
*			- [DB 852]: extend method GetVaranTime to get the IsoStartPoint
*		1.9 => 1.10	/	04.12.2007
*			- [DB 561]:	only call Init of this class (not virtual init)
*		1.8 => 1.9	/	18.07.2007
*			- [DB 561]:	Add function to read Varan time
*			- [DB 632]:	Ignore Execute Fault of Admin - Task with Disable - Function
*			- [DB 594]: set methode GetRetryTimout to global
*		1.7 => 1.8	/	11.07.2007
*			- [DB 620]:	Insert function to update module retry counters
*		1.6 => 1.7	/ 	04.04.2007
*			- [DB 541]: insert function to read SPI data
*			- [DB 536]: interrogation if Fault Boot - Image of FPGA is active
*		1.5 => 1.6	/	13.03.2007
*			- [DB 526]:	only search for position string if no string pointer is available
*		1.4 => 1.5	/	05.02.2007
*			- [DB 493]: changes in function GetDeviceAddress (do not request class state)
*			- Set DisableDevice Flag back if RTOS - Version <= 1.1.141
*		1.3 => 1.4	/	29.01.2007
*			- [DB 461]: add multiple read/write command
*		1.2 => 1.3	/	03.01.2007
*			- [DB 418]: insert functions to disable and enable port
*		1.1 => 1.2	/	14.12.2006
*			- [DB 441]: add function to set state of class
*		1.0 => 1.1	/	28.11.2006
*			first library version
*		0.2 => 1.0	/	05.10.2006
*			initial version
*		0.1 => 0.2	/	13.06.2006
*			second testversion 
*		0.0	=> 0.1	/	10.04.2006
*			first testversion for fair in Hannover
*
************************************************************************************)

VAR_PRIVATE

  // Private pointers to interface to avoid multiple OS_CILGet calls.
  pMultiVaranFetch : ^LSL_MULTI_VARAN;  
  mt_apiFetch      : ^LSL_MT_TYPE;
  
  p_this            : ^void;
  
  //Private Variables for CMD_GET_HARDWARE_DIAGNOSIS AND CMD_GET_HARDWARE_TREE_ENTRY
  a_HWTEntryStr     : ARRAY[0.. VARAN_MAX_DEPTH+1] OF CHAR;  // VaranMaxDepth +1 because length is 2 byte long
  a_VendorName			: ARRAY[0..99] OF CHAR;  
  a_DeviceName			: ARRAY[0..99] OF CHAR;
  a_OrderingNoId	  : ARRAY[0..99] OF CHAR;
  a_IdentList_LicenseNo_HwRev   : ARRAY[0..99] OF CHAR;    
  a_FWVersion           : ARRAY[0..99] OF CHAR;
  a_SerialNo			: ARRAY[0..31] OF CHAR;  
  
END_VAR


//[#ENGLISH]
//=================================================================================================
//Construct of Base class to set class not initialized
//=================================================================================================
//[server]	State		:W		:State of class
FUNCTION  Varan_Base::Varan_Base
  VAR_OUTPUT
    ret_code		: CONFSTATES;  
  END_VAR

  State			:= _NotInitialized;
  ret_code		:= C_OK;

#ifdef HWC_LogInit
  HWC_LogInit();
#endif
  
  pMultiVaranFetch := nil;
  mt_apiFetch := nil;

END_FUNCTION //  Varan_Base::Varan_Base
//[#ENGLISH]
//=================================================================================================
//Init for Varan Client
//=================================================================================================
//[server]	State				:W		:state of class
//[client]	Required			:R		:is class required for varan or not
//[members]	p_VaranPosition		:R/W	:node string of varan module
//			ud_VaranManagerNr	:W		:number of varan manager
//			p_Varan				:W		:pointer to varan OS - Functions
//[locals]	sd_retval			:W/R	:return value of called functions
FUNCTION VIRTUAL GLOBAL Varan_Base::Init
  VAR
    sd_retval	: DINT;
#ifdef VARAN_DIAGNOSE
    dummy     : UDINT;
#endif
    // For NewInst command 
    _Para 	            : CmdStruct;  
    _Result 	          : Results;
    ret_code            : IprStates;
    paraGetModuleHandel : t_VM_CMD_GetModuleHandle; 
    b_DummyCallback     : BOOL;
    bPostInitSettings   : t_VM_CMD_NEED_POST_INIT_CALL_SETTINGS;
    ud_DeviceDelayTime  : UDINT;
    bFirstLoop          : BOOL;
#ifdef VM_CLASS_TIME_MEASUREMENT
    dReqLogVal          : DINT;
#endif
  END_VAR

//=================================================================================================
#ifdef VM_CLASS_TIME_MEASUREMENT
    s_TimeRt.ud_MaximalTime := 0;
    s_TimeRt.ud_MinimalTime := 16#FFFF_FFFF;

    s_TimeRtPostScan.ud_MaximalTime := 0;
    s_TimeRtPostScan.ud_MinimalTime := 16#FFFF_FFFF;

    s_TimeCy.ud_MaximalTime := 0;
    s_TimeCy.ud_MinimalTime := 16#FFFF_FFFF; 
#endif
//=================================================================================================

  b_DummyCallback := false;
  
  //read required client
  Required := Required.read() and 1;

  //-----------------------------------------------------------------------------------------------
  // Check if Payload is supported by the VM
  
  _Para.uiCmd := VM_CMD_SET_MUX_THIS;
  _Para.aPara[0] := this$DINT;
  
  VaranIn.NewInst(#_Para, #_Result);

  //-----------------------------------------------------------------------------------------------
  // Check if Payload is supported by the VM  
  _Para.uiCmd := VM_CMD_IS_PAYLOAD_SUPPORTED;
  _Result.aData[0]$BOOL := 0;   // Set to 0 in case the NewInst Method is not Implemented
  
  if VaranIn.NewInst(#_Para, #_Result) = READY then
    b_PayloadSupport := _Result.aData[0]$BOOL;
  end_if;
  
  // Check if the FPGA has (and uses) an DMA Controller
  if b_PayloadSupport then    
    _Para.uiCmd := VM_CMD_IS_DMA_ACTIVE;
    _Result.aData[0]$BOOL := 0;   // Set to 0 in case the NewInst Method is not Implemented
    
    if VaranIn.NewInst(#_Para, #_Result) = READY then
      b_DMAactive := _Result.aData[0]$BOOL;   
    end_if;
  end_if;
    
  //-----------------------------------------------------------------------------------------------
  //get master number
  ud_VaranManagerNr := VaranIn.GetManagerNumber( p_varan := #pVaran );   

  //look for an error
  if ( pVaran = NIL ) &
     ( b_PayloadSupport = false ) then  // pVaran is only used without PayloadSupport
    State := _NoVaranInterface;
    if Required then
      VaranIn.AllowRequiredError();
    end_if;
    return;
  end_if;
  
  //-----------------------------------------------------------------------------------------------
  //get Varan position if we have no position yet
  if ( p_VaranPosition = NIL ) then

    //alloc memory to get position
    p_VaranPosition := ( To_StdLib.Malloc( size := VARAN_MAX_DEPTH + 1 ) )$^USINT;

    //look if an error occurs
    if ( p_VaranPosition = NIL ) then
      State := _RootError;
      return;
    end_if;

    //set length to 0
    p_VaranPosition^ := 0;		

    //get position
    sd_retval := VaranIn.GetVaranPosition( p_us_info := p_VaranPosition );
  
    //look if an error occurs
    if ( sd_retval <> VARANMANAGER_OK ) then
      State := _RootError;
      
      // if it's connected via flex hub, install a dummy callback before leaving the method
      if (VaranIn.Read() = VM_FLEXHUB_READ_ID) then
        //-----------------------------------------------------------------------------------------------
        //install callback function
        sd_retval := VaranIn.SetObjectCallback( p_us_position_info  := NIL
                                              , ud_action_ptr       := ( #Varan_CallBack() )$UDINT
                                              , ud_thisp            := this$UDINT
                                              , sd_required         := Required
                                              );

        //look if an error occurs
        if ( sd_retval <> VARANMANAGER_OK ) then
          return;      
        else
          // State := _NoHardware;
          State := _NotInitialized; // State to _NotInitialized, Otherwise the derived class will not create the DOs and abort the init.
          b_DummyCallback := true;
        end_if;
      else
        return;      
      end_if;    
    end_if;

    //alloc memory for position pointer
    p_VaranPosition :=  ( To_StdLib.ReAlloc	( mptr		:= p_VaranPosition
                                            , newsize	:= p_VaranPosition^ + 1
                                            ) 
                        )$^USINT;

    //look if an error occurs
    if ( p_VaranPosition = NIL ) then
      State := _RootError;
      return;
    end_if;  
    
    // Get Module Handle if supported
    if b_PayloadSupport then
    
      if pMultiVaranFetch = nil then
      
        // Get the pointer for the Payload inteface
        if ( OS_CILGet( INTERFACE_MULTIVARANMANAGER, #pMultiVaranFetch ) <> SYS_ERR_NONE) then
          // Should be impossible b_PayloadSupport is only set when this interface was already called succesfully
          LogError("@017C (Varan_Base::Init) No Multi_Varan Interface found");
          State 		:= _NoVaranInterface;
          return;
        end_if;
      
      end_if;

      pMultiVaran := pMultiVaranFetch;
    
      // Only read Module handle if it has not been read yet
      // May already be read be other classes with the same position string. (For example CDIAS behind CIV)
      if ud_HandleModule = 0 then
      
        _Para.uiCmd := VM_CMD_GET_MODULE_HANDLE;
      
        paraGetModuleHandel.p_us_position_info := p_VaranPosition;
        paraGetModuleHandel.p_ud_module_handle := #ud_HandleModule;
        
        _Para.aPara[0]  := (#paraGetModuleHandel)$DINT;
        
        if VaranIn.NewInst(#_Para, #_Result) = READY then 
          if _result.aData[0]$DINT <> VM_CMD_OK then
            State := _RootError;
            return;
          end_if;
        else
          State := _RootError;
          return;
        end_if;
      end_if;

    end_if;
    
    // Post Init Support --------------------------------------------------------------------------
    
    bPostInitSettings := 0; // Init with 0 incase derived classes forget to set parameter.
    bPostInitNeeded   := CheckPostInitNeeded(#bPostInitSettings);
    if bPostInitNeeded then
    
      _Para.uiCmd     := VM_CMD_NEED_POST_INIT_CALL;
      _Para.aPara[0]  := this$DINT;
      _Para.aPara[1]  := bPostInitSettings$DINT;
      
      ret_code        := VaranIn.NewInst(pPara:= #_Para, pResult:= #_Result);
      
      if ret_code = READY then
        uiBasePostInitHandle := _Result.aData[0];
      else
        // PostInit Flag zuruecksetzen da nicht von VM unterstuetzt.
        bPostInitNeeded := FALSE;
        // Keine Trace ausgabe, wird schon im VM gemacht        
      end_if;      
    end_if;
    
    // Delay Init while waiting for required Module -----------------------------------------------
    // must be done before InstallCallbackObject() to avoid issues with callback during waiting
    // already set callback to FlexHub (b_DummyCallback) is no problem, flexhub set callback in next init
    if Required then
    
      _Para.uiCmd     := CMD_HWC_GET_REQUIREDWAITTIME;
      _Para.aPara[0]  := 1; // Version
      _Result.aData[0]$UDINT := 0;   // Init Ret Version with 0 to check if newInst has been handled
      
      ret_code        := VaranIn.NewInst(pPara:= #_Para, pResult:= #_Result);
      
      ud_DeviceDelayTime := 0;
      if (ret_code = READY) & (_Result.aData[0]$UDINT = 1) then
        ud_DeviceDelayTime := _Result.aData[4]$UDINT;
      end_if;
    
      if ud_DeviceDelayTime then
        
#ifdef VM_CLASS_TIME_MEASUREMENT
        dReqLogVal$UDINT := ops.tAbsolute;
        HWC_LogPrintf(pThis:=this, format:="@DBG (Varan_Base::Init) Init delay start timeStamp %d ms", p0:=#dReqLogVal);
        dReqLogVal := 0;
#endif
        bFirstLoop := TRUE;
        // Use ops.tAbsolute because we want time since start of project
        while ops.tAbsolute < ud_DeviceDelayTime do
          
          if b_PayloadSupport then
            p_NodeInfo := #s_NodeInfo;  // No direct access to OS-memory with payload support, data will be stored to the passed pointer
          end_if;
          
          //get node info from os
          sd_retval := VaranIn.GetNodeInfo( p_us_position_info	:= p_VaranPosition
                                          , p_node_info			    := #p_NodeInfo
                                          );

          //look for an error
          if ( sd_retval = VARANMANAGER_OK ) then
            // Moudle found 
            if bFirstLoop = FALSE then
              // Delay so that Init does not overlap with connect call from varan task
              To_MultiTask.TASKDELAY(timeout0:=100);              
            end_if;
              // Do not delay if Moudle was found in first loop. It is asumed it was aleady here.
              
            Exit;      
          end_if;
          
          // Delay so that Varan task can search for module
          To_MultiTask.TASKDELAY(timeout0:=10);
          
          bFirstLoop := FALSE;

  #ifdef VM_CLASS_TIME_MEASUREMENT
          dReqLogVal += 1;
  #endif
        
        end_while;

  #ifdef VM_CLASS_TIME_MEASUREMENT
        HWC_LogPrintf(pThis:=this, format:="@DBG (Varan_Base::Init) Init delayed for %d cycles", p0:=#dReqLogVal);
        dReqLogVal$UDINT := ops.tAbsolute;
        HWC_LogPrintf(pThis:=this, format:="@DBG (Varan_Base::Init) Init delay end timeStamp %d ms", p0:=#dReqLogVal);
  #endif
      end_if;
    
    end_if;
  end_if;
  
  //-----------------------------------------------------------------------------------------------
  if b_DummyCallback = false then  // Only install if there is not dummy callback due to not connected module to Flexhub

    //install callback function
    sd_retval := InstallCallbackObject();  

    //look if an error occurs
    if ( sd_retval <> VARANMANAGER_OK ) then
      State := _CallBackError;
      return;
    end_if;
    
  end_if;
  
  //Get Object Path
  GetPointer2ObjectPath();
  

#ifdef VARAN_DIAGNOSE
  s_Diagnose.TimeCounter := 1000000 / VaranIn.GetVaranTime(p_ud_IsoStartPoint := #dummy); //value, when we increment every cycle after 1 sec
#endif

END_FUNCTION //VIRTUAL GLOBAL Varan_Base::Init
//[#ENGLISH]
//=================================================================================================
//Rt - Funktion of Varan class ( called bei VaranMaster )
//=================================================================================================
FUNCTION VIRTUAL GLOBAL Varan_Base::UpdateRt

  //disable Device if an error interrupt occures (not in interrupt because it takes to long)
  //if we have a Cy - Task disable Device in cylcic otherwise call special function (VaranManager disables Device in cyclic)
  //if DisableDevice is called in Rt a Timeslice Error can occure because OS uses ADMIN Task for this function!!!
  if (b_CyTask = FALSE) then
  
    if ( b_DisableDevice = TRUE) then
      DisableDeviceRt();
      SetDOsOff();
    end_if;

    // Check if Cylic Post Init needs to be finished  
    if bPostInitNeeded then
      CheckCyclicPostInitFinished(FALSE);
    end_if;

  end_if;

END_FUNCTION //VIRTUAL GLOBAL Varan_Base::UpdateRt
//[#ENGLISH]
//=================================================================================================
//Cy - Funktion of Varan class ( called bei VaranMaster )
//=================================================================================================
FUNCTION VIRTUAL GLOBAL Varan_Base::UpdateCy

  b_CyTask := TRUE;

#ifdef VARAN_DIAGNOSE
  if (s_Diagnose.Command <> Deactivate) & (s_Diagnose.Counter >= s_Diagnose.TimeCounter) & (DiagControl >= 0) then
    Diagnose();
    s_Diagnose.Counter  := 0;
  elsif (s_Diagnose.Command = Deactivate) then
    DiagControl         := 0;
    s_Diagnose.Counter  := 0;
  elsif (DiagControl >= 0) then
    s_Diagnose.Counter    += 1;
  end_if;
#endif

  //disable Device if an error interrupt occures (not in interrupt because it takes to long)
  if ( b_DisableDevice = TRUE ) then
    DisableDevice();
    SetDOsOff();
  end_if;

  // Check if Cylic Post Init needs to be finished  
  if bPostInitNeeded then
    CheckCyclicPostInitFinished(FALSE);
  end_if;

END_FUNCTION //VIRTUAL GLOBAL Varan_Base::UpdataCy
//[#ENGLISH]
//=================================================================================================
//Function returns pointer to node string of class
//=================================================================================================
//[members]	p_VaranPosition		:R		:Node string of varan module
//[<p_us_node]pointer to node string
FUNCTION VIRTUAL GLOBAL Varan_Base::GetPointer2NodeString
  VAR_OUTPUT
    p_us_node		: ^USINT;
  END_VAR

  if IsTransparent() then
    p_us_node := NIL; //We have no Nodestring: we do not exist!
  else

    //get Varan position if we have no position yet
    if ( p_VaranPosition = NIL ) then
      Varan_Base::Init();
    end_if;

    p_us_node := p_VaranPosition;

  end_if;

END_FUNCTION //VIRTUAL GLOBAL Varan_Base::GetPointer2NodeString
//[#ENGLISH]
//=================================================================================================
//Function is called if a varan interrupt occures
//=================================================================================================
//[server]	Online					:W		:set if class is ok and all data is valid
//			State					:W		:state of class
//[members]	s_CallBackSettings		:W		:structure for settings of callback function
//[>ud_reason]reason of interrupt
//[>ud_data]data of call back
//[<sd_retval]returnvalue of function
FUNCTION VIRTUAL GLOBAL Varan_Base::Varan_HwInterrupt
  VAR_INPUT
    ud_reason	: UDINT;
    ud_data		: ^t_CallBackInterrupt;
  END_VAR
  VAR_OUTPUT
    sd_retval	: DINT;
  END_VAR

  Online	:= 0;
  bOnline := FALSE;

  //look which type of interrupt
  case ( ud_reason ) of
    VARANMANAGER_CB_REQ_ERROR:		  
      State			:= _HardwareRequiredIRQ;
    
    VARANMANAGER_CB_NOT_REQ_ERROR:	
      State			:= _HardwareNotRequiredIRQ;
      b_DisableDevice := TRUE;
                                    
    VARANMANAGER_FATAL_ERROR:		    
      State			:= _HardwareFatalErrorIRQ;
      b_DisableDevice	:= TRUE;
      
  end_case;

  //get pointer to data object with error
  s_CallBackSettings.p_InterruptHandleDO := ( ud_data^.ud_Handle )$^LSL_VARANFRAME;
    
  sd_retval := VARANMANAGER_OK;

END_FUNCTION //VIRTUAL GLOBAL Varan_Base::Varan_HwInterrupt
//[#ENGLISH]
//=================================================================================================
//Function is called if a varan module is connected
//=================================================================================================
//[server]	Online		:W		:set if class is ok and all data is valid
//			State		:W		:state of class
//[>ud_data]data of call back
//[<sd_retval]returnvalue of function
#pragma warning(disable: 73)

FUNCTION VIRTUAL GLOBAL Varan_Base::Varan_HwConnect
  VAR_INPUT
    ud_data		: UDINT;
  END_VAR
  VAR_OUTPUT
    sd_retval	: DINT;
  END_VAR
  
  //set Online 1 first if cyclic data is valid
  Online    := 1;  
  bOnline   := TRUE;
  State     := _ClassOk;
  sd_retval := VARANMANAGER_OK;

END_FUNCTION //VIRTUAL GLOBAL Varan_Base::Varan_HwConnect
//[#ENGLISH]
//=================================================================================================
//Function is called if a varan module is disconnected
//=================================================================================================
//[server]	Online		:W		:set if class is ok and all data is valid
//			State		:W		:state of class
//[>ud_data]data of call back
//[<sd_retval]returnvalue of function
FUNCTION VIRTUAL GLOBAL Varan_Base::Varan_HwDisconnect
  VAR_INPUT
    ud_data		: UDINT;
  END_VAR
  VAR_OUTPUT
    sd_retval	: DINT;
  END_VAR

  Online		:= 0; 
  bOnline   := FALSE;
  State     := _NoHardware;  
  
  if bPostInitNeeded then

    CheckCyclicPostInitFinished(bForcePostInitEnd:=TRUE);   
    
  end_if;
  
  sd_retval := VARANMANAGER_OK;

END_FUNCTION //VIRTUAL GLOBAL Varan_Base::Varan_HwDisconnect
#pragma warning(default: 73)

//[#ENGLISH]
//=================================================================================================
//Callback Function is called from VaranManager
//=================================================================================================
//[server]	Release			:W		:FPGA - Version of varan client
//			DeviceAddress	:W		:Device Address of client (from os)
//			VendorID		:W		:Vendor ID of varan client
//			DeviceID		:W		:Device ID of varan client
//			State			:W		:state of class
//[client]	Required		:R		:is class required for varan or not
//			UserAction		:R		:client for user actions
//[members] s_CallBackSettings		:W		:structure for settings of callback function
//			ud_DeviceDelayTime		:W		:delay time of varan client for Pll
//			e_RequiredFaultState	:W		:Fault state of class in _RequiredError State
//[<sd_retval]0=Ok, VARANMANAGER_CALLBACK_NOT_HANDLED=VaranError
//[>ud_reason]reason of callback
//[>ud_data]data of callback function
FUNCTION VIRTUAL Varan_Base::Varan_CallBack
  VAR_INPUT
    ud_reason 	: UDINT;
    ud_data 	: UDINT;
  END_VAR
  VAR_OUTPUT
    sd_retval (EAX) 	: DINT;
  END_VAR

  //counter to count number of callback calls
  s_CallBackSettings.ud_Counter += 1;
  s_CallBackSettings.ud_LastReason := ud_reason;

  //switch case of callback
  case ( ud_reason ) of
//**********************************************************************************************************************************************************
    // Interrupt
    VARANMANAGER_CB_REQ_ERROR,
    VARANMANAGER_CB_NOT_REQ_ERROR,
    VARANMANAGER_FATAL_ERROR:		
                    sd_retval := Varan_HwInterrupt	( ud_reason := ud_reason
                                                    , ud_data := ud_data$^t_CallBackInterrupt
                                                    );
                                                    
                    s_CallBackSettings.ud_InterruptCnt += 1;

//**********************************************************************************************************************************************************
    // Connnect of a device
    VARANMANAGER_CB_CONNECT:		
                    sd_retval := Varan_HwConnect( ud_data := ud_data );
                    s_CallBackSettings.ud_ConnectCnt += 1;

#ifdef VARAN_DIAGNOSE                    
                    //Varan Diangose
                    //Init Struct
                    s_Diagnose.cmd_Input.ManagerNr       := ud_VaranManagerNr;               //number of manager
                    s_Diagnose.cmd_Input.BaseAddress     := DeviceAddress;                   //base-address of node
                    s_Diagnose.cmd_Input.CounterLength   := 20;                              //5 counter a 4 byte
                    s_Diagnose.cmd_Input.Counter1        := 0;                               //flags
                    s_Diagnose.cmd_Input.Counter2        := 1;                               //connect_count
                    s_Diagnose.cmd_Input.Counter3        := 2;                               //fault_count
                    s_Diagnose.cmd_Input.Counter4        := 3;                               //rx_lost
                    s_Diagnose.cmd_Input.Counter5        := 4;                               //tx_lost
                    s_Diagnose.InputSize                 := sizeof(s_Diagnose.cmd_Input); //size of input-struct
                    
                    if s_Diagnose.ActiveMerker = TRUE then
                      s_Diagnose.Command := Activate;
                    end_if;

#endif

//**********************************************************************************************************************************************************
    // Disconnect of a device
    VARANMANAGER_CB_DISCONNECT:		sd_retval := Varan_HwDisconnect( ud_data := ud_data );
                    s_CallBackSettings.ud_DisconnectCnt += 1;
                    
                    // reset the servers upon disconnect
                    Release           := 0;
                    HardwareVersion   := 0;
                    DeviceAddress     := 0;
                    VendorID          := 0;
                    DeviceID          := 0;                   
                    IF ValidateSerNo <> -2 THEN
                      ValidateSerNo := 0;
                    END_IF;
                    SerialNoStr.Clear();
                    ud_DeviceDelayTime:= 0;
                    
#ifdef VARAN_DIAGNOSE
                    if s_Diagnose.Command = Activate then
                      s_Diagnose.ActiveMerker := TRUE;
                    else
                      s_Diagnose.ActiveMerker := FALSE;
                    end_if;

                    s_Diagnose.Command := Deactivate;
#endif

//**********************************************************************************************************************************************************
    VARANMANAGER_CB_SUB_BUSES_INITIALIZED:
                    sd_retval := Varan_HwSubBusReady( ud_data := ud_data );
                    s_CallBackSettings.ud_SubBusReadyCnt += 1;
                    
//**********************************************************************************************************************************************************
  end_case;
  
  //------------------------------------------------------------------------------------------------
  //if class is required and state is error (because of first connect (called in Init))
  if 	( Required 
    & (State 	<> _ClassOk)
    & (State	<> _NotInitialized)
    & (State	<> _InvalidSerialNo)
    & (State	<> _ModuleFoundButManagerIsOff)
    )
  then
    
    //give an error back to VaranManager to shut down application
    sd_retval := VARANMANAGER_CALLBACK_NOT_HANDLED;
    //save fault state
    e_RequiredFaultState := State;
    //Set state of class
    State := _RequiredError;    
    
    //Set VaranMaster off
    VaranIn.SetManagerOff( e_error := State );
  
  else
    //if we have a negative return code but class is not required then we do nothing
    if ( sd_retval <> VARANMANAGER_OK ) then
      sd_retval := VARANMANAGER_OK;
    end_if;
  end_if;

  //----------------------------------User has last word -------------------------------------------
  //look if user client is connected
  if ( IsClientConnected( #UserAction ) = TRUE ) then

    //call user call back so that user has chance to change return value to VaranManager
    if (State = _RequiredError) & (sd_retval = VARANMANAGER_CALLBACK_NOT_HANDLED) then
      sd_retval := UserAction.write( VARANMANAGER_CB_REQ_ERROR );
    else
      sd_retval := UserAction.write( ud_reason$DINT );
    end_if;
    
    //look if user want other reaction
    if ( sd_retval ) then
      sd_retval := VARANMANAGER_CALLBACK_NOT_HANDLED;
    else
      sd_retval := VARANMANAGER_OK;
    end_if;
  end_if;

END_FUNCTION // Varan_Base::Varan_CallBack
//[#ENGLISH]
//=================================================================================================
//Function to get device address, Vendor ID and Device ID of varan module
//=================================================================================================
//[server]	State			:W		:state of class
//			Release			:W		:FPGA - Version of varan client
//			DeviceAddress	:W		:Device Address of client (from os)
//			VendorID		:W		:Vendor ID of varan client
//			DeviceID		:W		:Device ID of varan client
//[members]	p_VaranPosition		:R		:node string of varan module
//			p_NodeInfo			:W		:pointer to varan client informations
//[locals]	us_pll_time			:W/R	:pll time from VaranMaster
//[<sd_retval]0=OK, else varan manager error
FUNCTION Varan_Base::GetNodeInfo
  VAR_OUTPUT
    sd_retval	: DINT;
  END_VAR
  VAR
    szValidSerNo : ARRAY [0..SERNO_STRING_SIZE-1] OF CHAR;
    TempHwVer : HDINT;
    ManagerState  : t_e_VaranErrors;    

    // For NewInst command 
    _Para 	            : CmdStruct;  
    _Result 	          : Results;
  END_VAR
  
  if b_PayloadSupport then
    p_NodeInfo := #s_NodeInfo;  // No direct access with payload support, data will be stored to the passed pointer
  end_if;
  
  //get node info from os
  sd_retval := VaranIn.GetNodeInfo( p_us_position_info	:= p_VaranPosition
                                  , p_node_info			:= #p_NodeInfo
                                  );

  //look for an error
  if ( sd_retval <> VARANMANAGER_OK ) then
    State := _NoHardware;
    return;
  end_if;

  //set class servers
  Release			:= TO_UDINT( p_NodeInfo^.ucFPGAVersion );

  //check for Fault Boot Image version of FPGA
  if ( Release < 16#10 ) then
    State := _ErrorBootImageFPGA;
    sd_retval := -100;
    return;
  end_if;

  DeviceAddress	:= p_NodeInfo^.uiAddress;
  VendorID		:= p_NodeInfo^.uiVendorID;
  DeviceID		:= p_NodeInfo^.uiDeviceID;
  
  // Read VMClient Protocol version --------------------------------------------------------------
  if b_PayloadSupport then
    
    if (MULTI_VARAN_IGETNODEPROPERTY( hNodeHandle       := ud_HandleModule
                                    , udPropertyId      := ND_PROP_VARAN_PROTOCOL_VERSION
                                    , pudPropertyValue  := #ProtocolVersion
                                    ) <> VARANMANAGER_OK ) then // Do not set sd_retval, this error is ignored
      
      // Interface version 0x00001008/VM_MULTIVARAN_VERSION_INTERFRAME_GAP_TIME is not checked here intentionally
      // OS RTK may support this property without increasing the Interface version
      // No Error/Warning ProtocolVersion is additional information.
      ProtocolVersion := 0;
    end_if;
  
  end_if;  

  // check device ID before we continue with serial number check
  if CheckDeviceID(DeviceID) = FALSE then
    State := _WrongHardware;
    sd_retval := -101;
    return;
  end_if;

  // check if manager is on
  ManagerState := VaranIn.GetManagerState();
  if ManagerState <> _ClassOk then
    State := _ModuleFoundButManagerIsOff;
    sd_retval := -105;
    return;
  end_if;

  //-----------------------------------------------------------------------------------------------
  // Get the extended node info if available
  _Para.uiCmd := VM_CMD_GET_EXTENDED_NODE_INFO;
  
  // reset memory to set all pointers to 0
  _memset(dest:=#_Para.aPara[0], usByte:=0, cntr:=sizeof(t_VM_CMD_GetExtNodeInfo));
  _Para.aPara$t_VM_CMD_GetExtNodeInfo.ud_CmdVersion := VM_CMD_GET_EXTENDED_NODE_INFO_VER_1;
  _Para.aPara$t_VM_CMD_GetExtNodeInfo.p_PositionInfo:= p_VaranPosition;
  _Para.aPara$t_VM_CMD_GetExtNodeInfo.p_HwVersion   := #TempHwVer;
  _Para.aPara$t_VM_CMD_GetExtNodeInfo.p_SerNoStr    := #szSerNoStr[0];
  
  _Result.uiLng       := 0;   // Set to 0 in case the NewInst Method is not Implemented
  _Result.aData$DINT  := -1;  // initialize with error

  if VaranIn.NewInst(#_Para, #_Result) = READY then
    // if the return value has the right length and value
    if (_Result.uiLng = sizeof(DINT)) & (_Result.aData$DINT = VARANMANAGER_OK) then
      // show the Hardware version on the server
      HardwareVersion := ConvertHwVersion(TempHwVer);
    end_if;
  end_if;

  // if the extended node info is not supported or there was an error getting the info
  if _Result.aData$DINT <> VARANMANAGER_OK then 
    // get serial number of this client (from spi flash) via the old interface of the VaranManager
    VaranIn.GetSerialNo(p_us_position_info:=p_VaranPosition, p_SerialNo:=#szSerNoStr[0]);
  end_if;

  SerialNoStr.WriteDataOff(udLen:=_StrLen(#szSerNoStr[0]), udOff:=0, pData:=#szSerNoStr[0]);
  
  SerNoValidation := SerNoValidation.Read();
  if SerNoValidation then
  
    // get header out of ramfile
    if SerNoBackup.GetDataAt(p_us_data:=(#SerNoHeader)$^USINT, ud_size:=sizeof(SerNoHeader), ud_at:=0) = C_OK then
      
      // initialize local string
      _memset(#szValidSerNo[0], 0, SERNO_STRING_SIZE);
      
      // check data in header (string must be smaller than string size: 1 byte for termination) and get string out of ramfile
      if (SerNoHeader.Version = 16#10) & (SerNoHeader.ZeroByte = 0) & (SerNoHeader.StringLength < SERNO_STRING_SIZE) &
         (SerNoBackup.GetDataAt(p_us_data:=(#szValidSerNo[0])$^USINT, ud_size:=SerNoHeader.StringLength, ud_at:=sizeof(SerNoHeader)) = C_OK) then
                 
        // check if it's the correct serial number string
        if _strcmp(#szSerNoStr[0], #szValidSerNo[0]) = 0 then
        ValidateSerNo := 1;
      else
          // strings doesn't match
        ValidateSerNo := 0;
        State := _InvalidSerialNo;
          
          // return errorcode to prevent initialisation of the device
          sd_retval := -104;
      end_if;
    else
      ValidateSerNo := -1;
      State := _InvalidSerialNo;
        
        // header invalid or failed to read serno string
        sd_retval := -103;
      end_if;    
    else
      ValidateSerNo := -1;
      State := _InvalidSerialNo;
      
      // failed to read header of serno data
      sd_retval := -102;
    end_if;

  else
    ValidateSerNo := -2;
  end_if;

END_FUNCTION //VIRTUAL GLOBAL Varan_Base::GetNodeInfo
//[#ENGLISH]
//=================================================================================================
//Function to reset settings of a data object
//=================================================================================================
//[client]	Required		:R		:is class required for varan or not
//[>p_HandleDO]pointer to data object
//[>us_state]state of DO (cont run, singl run, stop )
//[>ud_bytes]number of bytes in DO
FUNCTION VIRTUAL GLOBAL Varan_Base::ResetDataObject
  VAR_INPUT
    p_handleDO		: ^LSL_VARANFRAME;
    us_state		: USINT;
    ud_bytes		: UDINT;
  END_VAR

  //look if we have a valid pointer
  if ( p_handleDO <> NIL ) then

    //set state of DO
    if ( Required ) then
      p_handleDO^.ucCtrlStat 		:= us_state or VARAN_DO_REQUIRED;
    else
      p_handleDO^.ucCtrlStat 		:= us_state;
    end_if;
    
    //reset retry counter
//		p_handleDO^.ucRetryCounter	:= 0;
    
    //set number of allowed retries
    p_handleDO^.ucRetrys		:= VM_ALLOWED_RETRIES;

    //set time for retry timeout
    p_handleDO^.uiRetryTimeout	:= GetRetryTimeout( ud_bytes := ud_bytes );
  end_if;

END_FUNCTION // Varan_Base::ResetDataObject

//[#ENGLISH]
//=================================================================================================
//Function to set Pll settings of hardware module
//=================================================================================================
//[server]	State				:W		:state of class
//[members]	ud_DeviceDelayTime	:W		:delay time of varan client for Pll
//			p_NodeInfo			:W		:pointer to varan client informations
//[locals]	ud_data				:W/R	:data for direct access
//[<sd_retval]0=OK, else varan manager error
FUNCTION Varan_Base::SetPllData
  VAR_INPUT
    ud_delay_time 	: UDINT;
  END_VAR
  VAR_OUTPUT
    sd_retval 	: DINT;
  END_VAR
  VAR
    ud_data			    : UDINT;
  END_VAR

  //calculate right register value (Response Time (in 10ns steps) / 2 - constant FPGA delay time
  ud_DeviceDelayTime := ( p_NodeInfo^.uiResponseTime ) / 20 + VM_CONST_FPGA_DELAY + ud_delay_time;
  
  //set device delay time and max. value of missing pll input sync
  ud_data := ( ud_DeviceDelayTime shl 8 ) or VM_MAX_PLL_SYNC_MISS;	
  
  // Payload Support
  if b_PayloadSupport then
    //write Pll time with direct access
    sd_retval := MULTI_VARAN_iExecuteDirectAccess(  hNodeHandle := ud_HandleModule
                                                  , udCommand   := VARAN_CMD_CONTROL_WRITE
                                                  , udOffset    := VARAN_PLL_OFFSET + 16#B
                                                  , udLength    := sizeof(ud_data)
                                                  , pusData     := ( #ud_data )$^USINT
                                                  , pudErrorInfo:= NIL);
  else
    //write Pll time with direct access
    sd_retval := VARAN_iWriteControlDA( uiManager		  := ud_VaranManagerNr
                                      , uiAddress		  := DeviceAddress + VARAN_PLL_OFFSET + 16#B
                                      , uiLen			    := sizeof(ud_data)
                                      , uiRetryTimeout:= GetRetryTimeout( ud_bytes := sizeof(ud_data) )
                                      , pvData		    := ( #ud_data )$^UDINT
                                      , puiError		  := NIL
                                      );
  end_if;

  

  //look if an error occurs
  if ( sd_retval <> VARANMANAGER_OK ) then
    State := _PllError;
    return;
  end_if;
  
END_FUNCTION //VIRTUAL GLOBAL Varan_Base::SetPllData
//[#ENGLISH]
//=================================================================================================
//Function to set a sync out
//=================================================================================================
//[server]	State				:W		:state of class
//[locals]	ud_offset				:W/R	:address offset in pll
//			p_pll_output_data		:W/R	:settings for pll sync output
//[>us_sync_nr]enable sync0-4 allowed
//[>sd_offset]Offset in 10ns time
//[>us_period_multiplier]periode multiplier
//[>us_frame_count_treshold] Frame Count Treshold
//[>us_enable_frame_count] enable frame count
//[<sd_retval]returnvalue of os
FUNCTION Varan_Base::EnableSyncOut
  VAR_INPUT
    us_sync_nr 	: USINT;
    sd_offset 	: DINT;
    us_period_multiplier 	: USINT;
    us_frame_count_treshold 	: USINT;
    us_enable_frame_count 	: USINT;
    b_use_divider_sync 	: BOOL;
  END_VAR
  VAR_OUTPUT
    sd_retval 	: DINT;
  END_VAR
  VAR
    ud_offset				: UDINT;
    p_pll_output_data		: t_PllSyncOut;
  END_VAR
  
  //look which sync out we have
  if ( us_sync_nr <= 5 ) then

    ud_offset := 16#10 + ( us_sync_nr * 16#8 );
    
    //set out data
    p_pll_output_data.sd_Offset 			:= sd_offset;
    p_pll_output_data.us_PeriodMultiplier	:= us_period_multiplier;
    p_pll_output_data.us_FrameCountTreshold	:= us_frame_count_treshold;
    p_pll_output_data.us_Reserved1			:= 0;
    
    p_pll_output_data.us_ControlStatus.SyncOutEnable 	:= TRUE;
    p_pll_output_data.us_ControlStatus.FrameCountEnable	:= us_enable_frame_count$BOOL;
    p_pll_output_data.us_ControlStatus.SystemSync       := NOT b_use_divider_sync;
    
    // Payload Support
    if b_PayloadSupport then
      //write Pll time with direct access
      sd_retval := MULTI_VARAN_iExecuteDirectAccess(  hNodeHandle := ud_HandleModule
                                                    , udCommand   := VARAN_CMD_CONTROL_WRITE
                                                    , udOffset    := VARAN_PLL_OFFSET + ud_offset
                                                    , udLength    := sizeof(t_PllSyncOut)
                                                    , pusData     := ( #p_pll_output_data )$^USINT
                                                    , pudErrorInfo:= NIL);
    else
      //write Pll time with direct access
      sd_retval := VARAN_iWriteControlDA	( uiManager		  := ud_VaranManagerNr
                                          , uiAddress		  := DeviceAddress + VARAN_PLL_OFFSET + ud_offset
                                          , uiLen			    := sizeof(t_PllSyncOut)
                                          , uiRetryTimeout:= GetRetryTimeout( ud_bytes := sizeof(t_PllSyncOut) )
                                          , pvData		    := ( #p_pll_output_data )$^UDINT
                                          , puiError		  := NIL
                                          );
    end_if;

    //look if an error occurs
    if ( sd_retval <> VARANMANAGER_OK ) then
      State := _PllError;
      return;
    end_if;
  
  else
    sd_retval := -100;
  end_if;

END_FUNCTION // Varan_Base::EnableSyncOut
//[#ENGLISH]
//=================================================================================================
//Function to set a sync out
//=================================================================================================
//[server]	DeviceAddress	:W		:Device Address of varan client
//[locals]	sd_retval		:W/R	:return value of called dfunctions
//[<ud_device_address]Device address of client
FUNCTION VIRTUAL GLOBAL Varan_Base::GetDeviceAddress
  VAR_OUTPUT
    ud_device_address	: UDINT;
  END_VAR
  VAR
    sd_retval			: DINT;
  END_VAR

  //look if we have a device address
  if ( DeviceAddress = 0 ) then

    //get node information
    sd_retval := GetNodeInfo();

    //look for an error
    if ( sd_retval <> VARANMANAGER_OK ) then
      return;
    end_if;
  end_if;

  //return Device Address of varan client
  ud_device_address := DeviceAddress;

END_FUNCTION //VIRTUAL GLOBAL Varan_Base::GetDeviceAddress
//[#ENGLISH]
//=================================================================================================
//Function to get pointer to node information
//=================================================================================================
//[members]	p_node_info	:R/W		:pointer to node information of client (from os)
//[locals]	sd_retval	:W/R		:retunr value of called functions
//[<p_node_info]Pointer to Node information
FUNCTION VIRTUAL GLOBAL Varan_Base::GetPointer2NodeInfo
  VAR_OUTPUT
    p_node_info		: ^LSL_VARANNODEINFO;
  END_VAR
  VAR
    sd_retval	: DINT;
  END_VAR

  //look if we have a correct pointer (we must call init and GetNodeInfo - Function)
  if ( p_NodeInfo = NIL ) then
    
    //if required error do nothing
    if ( State = _RequiredError ) then
      p_node_info := NIL;
      return;
    end_if;
    
    //call init function
    Varan_Base::Init();

    //get node info
    sd_retval := GetNodeInfo();

    //look for an error
    if ( sd_retval <> VARANMANAGER_OK ) then
      p_node_info := NIL;
      return;
    end_if;
  end_if;
  
  //return pointer
  p_node_info := p_NodeInfo;

END_FUNCTION //VIRTUAL GLOBAL Varan_Base::GetPointer2NodeInfo
//[#ENGLISH]
//=================================================================================================
//Function to get retry timeout for a number of bytes
//=================================================================================================
//[members]	p_NodeInfo		:R		:pointer to node information of client (from os)
//[>ud_bytes]number of bytes
//[<ud_timeout]retry timout time
FUNCTION GLOBAL Varan_Base::GetRetryTimeout
  VAR_INPUT
    ud_bytes		: UDINT;
  END_VAR
  VAR_OUTPUT
    ud_timeout		: UDINT;
  END_VAR

  //Got already ResponseTime?
  if ud_ResponseTimeMax = 0 then
    if p_NodeInfo then
      ud_ResponseTimeMax := p_NodeInfo^.uiResponseTimeMax;
    end_if;
  end_if;
  
  ud_timeout := ud_ResponseTimeMax + ud_bytes * VM_TIMEOUT_ONE_BYTE + VM_RETRY_TIMEOUT_STD_OFFSET;

END_FUNCTION // Varan_Base::GetRetryTimeout
//=================================================================================================
//---------------------- Additional functions------------------------------------------------------
//=================================================================================================

//[#ENGLISH]
//=================================================================================================
//Function to Start time measurement
//=================================================================================================
#pragma warning(disable:74)
#pragma warning(disable:73)
FUNCTION Varan_Base::StartTimeMeasurement
  VAR_INPUT
    usMode (EAX) 	: DINT;
  END_VAR
#ifdef VM_CLASS_TIME_MEASUREMENT
  VAR
    tmpTime : ^t_TimeMeasurementVaran;
  END_VAR

  case usMode of
  
    //-----------------------------------------------------------
    
    VARANTIME_RT:
      tmpTime := #s_TimeRt;
    
    //-----------------------------------------------------------
    
    VARANTIME_RTPOSTSCAN:
      tmpTime := #s_TimeRtPostScan;
    
    //-----------------------------------------------------------
    
    VARANTIME_CY:
      tmpTime := #s_TimeCy;
    
    //-----------------------------------------------------------
    
  end_case;
  
  if ( tmpTime^.us_Activate ) then
    tmpTime^.ud_Timemark := VaranIn.GetNsTime(); 
  end_if;

#endif

END_FUNCTION // Varan_Base::StartTimeMeasurement
//[#ENGLISH]
//=================================================================================================
//Function to Stop time measurement
//=================================================================================================
FUNCTION Varan_Base::StopTimeMeasurement
  VAR_INPUT
    usMode (EAX) 	: DINT;
  END_VAR
#ifdef VM_CLASS_TIME_MEASUREMENT
  VAR
    tmpTime : ^t_TimeMeasurementVaran;
  END_VAR

  case usMode of
  
    //-----------------------------------------------------------
    
    VARANTIME_RT:
      tmpTime := #s_TimeRt;
    
    //-----------------------------------------------------------
    
    VARANTIME_RTPOSTSCAN:
      tmpTime := #s_TimeRtPostScan;
    
    //-----------------------------------------------------------
    
    VARANTIME_CY:
      tmpTime := #s_TimeCy;
    
    //-----------------------------------------------------------
    
  end_case;

  if ( tmpTime^.us_Activate ) then

    //get actual time
    tmpTime^.ud_ActualTime := VaranIn.GetNsTime() - tmpTime^.ud_Timemark;

    //look for maximum time
    if ( tmpTime^.ud_ActualTime > tmpTime^.ud_MaximalTime ) then
      tmpTime^.ud_MaximalTime := tmpTime^.ud_ActualTime;
    end_if;

    //look for minimum time
    if ( tmpTime^.ud_ActualTime < tmpTime^.ud_MinimalTime ) then
      tmpTime^.ud_MinimalTime := tmpTime^.ud_ActualTime;
    end_if;

    //look for average time (100000 cycles)
    if ( tmpTime^.ud_AverageCounter = 100000 ) then

      tmpTime^.ud_AverageTime 	:= tmpTime^.ud_AverageSum / tmpTime^.ud_AverageCounter;
      tmpTime^.ud_AverageSum 	:= 0;
      tmpTime^.ud_AverageCounter := 0;

    else
      tmpTime^.ud_AverageSum += ( tmpTime^.ud_ActualTime / 100 );
      tmpTime^.ud_AverageCounter += 1;
    end_if;
  end_if;
  
#endif

END_FUNCTION // Varan_Base::StopTimeMeasurement
#pragma warning(default:74)
#pragma warning(default:73)

//[#ENGLISH]
//=================================================================================================
//Function to set state of class
//=================================================================================================
//[>sd_error]type of error
FUNCTION VIRTUAL GLOBAL Varan_Base::SetState
  VAR_INPUT
    sd_error		: t_e_VaranErrors;
  END_VAR

  //only set error if class is ok
  if ( State = _ClassOk ) then
  
    State := sd_error;

  else
    //only eeprom error can be cleared
    if ( State = _EEPromError & sd_error = _ClassOk ) then
      State := sd_error;
    end_if;
  end_if;

END_FUNCTION //VIRTUAL GLOBAL Varan_Base::SetState
//[#ENGLISH]
//=================================================================================================
//Function to disable device
//=================================================================================================
//[<sd_retval]0=ok, -17=Port no link, -30=client disabled, -31=client cant enable, -100 function not available with this os version, other return code of os
FUNCTION VIRTUAL GLOBAL Varan_Base::DisableDevice
  VAR_OUTPUT
    sd_retval	: DINT;
  END_VAR
  VAR
    nodeProperty    : LSL_PROPERTY_VALUE_PAIR;
  END_VAR

  //look if funtion is available with this os version
  if ( _RTOSVersion >= VM_DISABLE_DEVICE_AVAILABLE ) then

    if b_PayloadSupport then
      nodeProperty.udPropertyId    := ND_PROP_CONNECTION_STATE;
      nodeProperty.udPropertyValue := CN_STATE_DISCONNECTED;
      sd_retval := MULTI_VARAN_iSetNodeProperties(  hNodeHandle           := ud_HandleModule
                                                  , udPropertyCount       := 1
                                                  , psPropertyValuePairs  := #nodeProperty); 
    else
      //disable device
      sd_retval := VARAN_iSetNodeEnableStatus	( uiManager		:= ud_VaranManagerNr
                          , pucNode		:= p_VaranPosition
                          , uiNodeStatus	:= 0
                          );
    end_if;

    // if there was an error at disabling it was not caused by a disabled previous module
    if	( sd_retval <> VARANMANAGER_OK ) &
        ( sd_retval <> VARANMANAGER_CLIENT_DISABLED ) &
        ( sd_retval <> VARANMANAGER_ADMIN_DOL_EXECUTION_ERROR	) &	//because if device before is disabled, DA can't work
        ( VaranIn.IsDeviceDisabled() = FALSE ) then
        
      State := _DisableError;
            
      //Set VaranMaster off
      VaranIn.SetManagerOff( e_error := State );
    end_if;

    //port is disabled
    b_DisableDevice := FALSE;
    ud_DisableTime := ops.tAbsolute;
  else
    b_DisableDevice := FALSE;
    sd_retval := -100;
  end_if;

  // Force end of Cylic Post Init
  if bPostInitNeeded then
    CheckCyclicPostInitFinished(TRUE);
  end_if;

END_FUNCTION // Varan_Base::DisableDevice
//[#ENGLISH]
//=================================================================================================
//Function to enable device
//=================================================================================================
//[<sd_retval]0=ok, 1=device must disabled for more then 200ms, 2=-100 function not available with this os version, -17=Port no link, -30=client disabled, -31=client cant enable, other return code of os
FUNCTION VIRTUAL GLOBAL Varan_Base::EnableDevice
  VAR_OUTPUT
    sd_retval	: DINT;
  END_VAR
  VAR
    nodeProperty    : LSL_PROPERTY_VALUE_PAIR;
  END_VAR

  //look if funtion is available with this os
  if ( _RTOSVersion >= VM_DISABLE_DEVICE_AVAILABLE ) then

    //look if watchdog time is gone
    if ( ( ops.tAbsolute - ud_DisableTime ) < 200ms ) then
      sd_retval := 1;
      return;
    end_if;
    
    if b_PayloadSupport then
      nodeProperty.udPropertyId    := ND_PROP_CONNECTION_STATE;
      nodeProperty.udPropertyValue := CN_STATE_CONNECTED;
      sd_retval := MULTI_VARAN_iSetNodeProperties(  hNodeHandle           := ud_HandleModule
                                                  , udPropertyCount       := 1
                                                  , psPropertyValuePairs  := #nodeProperty); 
    else
      //enable device
      sd_retval := VARAN_iSetNodeEnableStatus	( uiManager		:= ud_VaranManagerNr
                          , pucNode		:= p_VaranPosition
                          , uiNodeStatus	:= 1
                          );
    end_if;

    
  
    //look for an error
    if ( sd_retval <> VARANMANAGER_OK ) then
      State := _EnableError;
    end_if;
  else
    sd_retval := 2;
  end_if;

END_FUNCTION // Varan_Base::EnableDevice
//[#ENGLISH]
//=================================================================================================
//Function to set all Data Objects off
//=================================================================================================
FUNCTION VIRTUAL GLOBAL Varan_Base::SetDOsOff

  //in base class we have no DO's

END_FUNCTION // Varan_Base::SetDOsOff
//[#ENGLISH]
//=================================================================================================
//Function to look if class is disabled
//=================================================================================================
//[<b_disabled]TRUE -> Device is disabled
FUNCTION VIRTUAL GLOBAL Varan_Base::IsDeviceDisabled
  VAR_OUTPUT
    b_disabled		: BOOL;
  END_VAR

  if 	( State = _NoHardware
    | State = _HardwareNotRequiredIRQ
    )
  then
    b_disabled := TRUE;
  else
    //look class above
    b_disabled := VaranIn.IsDeviceDisabled();
  end_if;

END_FUNCTION //VIRTUAL GLOBAL Varan_Base::IsDeviceDisabled
//[#ENGLISH]
//=================================================================================================
//Function to set multiple memory read/write options
//=================================================================================================
//[>us_filter]filter of multicast write
//[>us_sequence]sequence number of device
//[<sd_retval]error code
FUNCTION VIRTUAL GLOBAL Varan_Base::SetMultipleSettings
  VAR_INPUT
    us_filter		: USINT;
    us_sequence		: usint;
  END_VAR
  VAR_OUTPUT
    sd_retval		: DINT;
  END_VAR
  VAR
    a_data			: ARRAY[0..10] OF USINT;
  END_VAR

  //look if class is ok
  if ( State = _ClassOk ) then
    
    us_MulticastFilter 		:= us_filter;
    us_MultipleSequence		:= us_sequence;
    
    //set data for direct access
    a_data[ 0 ] := us_MulticastFilter;
    a_data[ 3 ] := us_sequence;
    a_data[ 10 ] := 16#6;					//to trigger watchdog only with watchdog command and multiple read/write command

    // Payload Support
    if b_PayloadSupport then
      //write data with direct access
      sd_retval := MULTI_VARAN_iExecuteDirectAccess(  hNodeHandle := ud_HandleModule
                                                    , udCommand   := VARAN_CMD_CONTROL_WRITE
                                                    , udOffset    := VARAN_MULTIPLE_OFFSET
                                                    , udLength    := sizeof(a_data)
                                                    , pusData     := ( #a_data )$^USINT
                                                    , pudErrorInfo:= NIL);
    else
      //write data with direct access
      sd_retval := VARAN_iWriteControlDA	( uiManager		  := ud_VaranManagerNr
                                          , uiAddress		  := DeviceAddress + VARAN_MULTIPLE_OFFSET
                                          , uiLen			    := sizeof(a_data)
                                          , uiRetryTimeout:= GetRetryTimeout( ud_bytes := sizeof(a_data) )
                                          , pvData		    := ( #a_data )$^UDINT
                                          , puiError		  := NIL
                                          );
    end_if;
    
    //look if an error occurs
    if ( sd_retval <> VARANMANAGER_OK ) then
      State := _MultipleError;
      return;
    end_if;
  end_if;

END_FUNCTION //VIRTUAL GLOBAL Varan_Base::SetMultipleSettings
//[#ENGLISH]
//=================================================================================================
//Function must be overwrite
//=================================================================================================
//[>p_handle]pointer to data object header
//[>p_data_read]pointer to read data
//[>p_data_write]pointer to data write
//[<sd_retval]error code
#pragma warning(disable: 73)
FUNCTION VIRTUAL GLOBAL Varan_Base::SetMultipleDataPointers
  VAR_INPUT
    p_handle		: ^LSL_VARANFRAME;
    p_data_read		: ^UDINT;
    p_data_write	: ^UDINT;
    DOIndex         : UDINT;
  END_VAR
  VAR_OUTPUT
    sd_retval		: DINT;
  END_VAR

  sd_retval := -1;
  
END_FUNCTION //VIRTUAL GLOBAL Varan_Base::SetMultipleDataPointers
#pragma warning(default: 73)
//[#ENGLISH]
//=================================================================================================
//Function to get pointer to calib data
//=================================================================================================
//[>p_offset]pointer to variable to write offset
//[<sd_retval]errorcode of os
FUNCTION  Varan_Base::GetCalibDataPointer
  VAR_INPUT
    p_offset	: ^UDINT;
  END_VAR
  VAR_OUTPUT
    sd_retval	: DINT;
  END_VAR
  VAR
    a_data			: ARRAY[0..31] OF UDINT;
    i				: UDINT;
  END_VAR

  //read SPI data
  sd_retval := VaranIn.ReadSPIData( p_us_position_info	:= p_VaranPosition
                  , ud_offset				:= 0
                  , ud_length				:= 128 or VM_SPI_IDENT_LIST 
                  , p_data				:= ( #a_data )$^USINT
                  );

  //look for an error
  if ( sd_retval <> VARANMANAGER_OK ) then
    State := _SPIError;
    return;
  end_if;

  //look for right Identifier
  if ( a_data[ 0 ] <> 16#12345678 ) then
    State := _SPIError;
    return;
  end_if;

  //look for valid length	(we only read 128 Byte at the moment [16Byte are header])
  if( a_data[ 3 ] > (128 - 16 ) ) then
    State := _SPIError;
    return;
  end_if;

  //search for calib data
  for i := 0 to a_data[ 3 ] / sizeof( UDINT ) do

    //look for calib id in 3rd byte
    if ( ( a_data[ i + 4 ] and 16#FF00_0000 ) = VM_SPI_CALIB_ID ) then
      p_offset^ := a_data[ i + 4 ] and 16#00FF_FFFF;
      return;
    end_if;
  end_for;

  //if no entry is found
  State := _NoCalibDataFound;
  sd_retval := -100;

END_FUNCTION // Varan_Base::GetCalibDataPointer
//[#ENGLISH]
//=================================================================================================
//Function to get pointer to calib data
//=================================================================================================
//[>ud_offset]offset in SPI - Flash
//[>ud_length]length of data
//[>p_data]pointer to allocated data space
//[<sd_retval]return value of OS
FUNCTION  Varan_Base::ReadSPIData
  VAR_INPUT
    ud_offset	: UDINT;
    ud_length	: UDINT;
    p_data		: ^USINT;
  END_VAR
  VAR_OUTPUT
    sd_retval	: DINT;
  END_VAR
  VAR
    ud_read_length	: UDINT;
  END_VAR

  //look if we have a length
  if ( ud_length = 0 ) then
    sd_retval := -100;
    return;
  end_if;

  //look if data is in one page
  while ( ud_length <> 0 ) do
    
    //if length is above page size
    if ( ( ud_offset and 16#FF ) + ud_length > 16#FF ) then
      //how many bytes are in this page available
      ud_read_length := 16#100 - ( ud_offset and 16#FF );
      //not more than 128 Bytes
      if ( ud_read_length > 128 ) then
        ud_read_length := 128;
      end_if;
    else
      //not more than 128 Bytes
      if ( ud_length > 128 ) then
        ud_read_length := 128;
      else
        ud_read_length := ud_length;
      end_if;
    end_if;

    //read data
    sd_retval := VaranIn.ReadSPIData( p_us_position_info	:= p_VaranPosition
                    , ud_offset				:= ud_offset
                    , ud_length				:= ud_read_length
                    , p_data				:= p_data
                    );
    //look for an error
    if ( sd_retval <> VARANMANAGER_OK ) then
      State := _SPIError;
      return;
    end_if;

    //correct length
    ud_length -= ud_read_length;
    ud_offset += ud_read_length;
    p_data += ud_read_length;
  end_while;

END_FUNCTION // Varan_Base::ReadSPIData

//[#ENGLISH]
//=================================================================================================
//Function to update module retry counter
//=================================================================================================
FUNCTION VIRTUAL GLOBAL Varan_Base::UpdateRetryCounter
  //function must be override 
END_FUNCTION //VIRTUAL GLOBAL Varan_Base::UpdateRetryCounter
//[#ENGLISH]
//=================================================================================================
//Function to get varan time
//=================================================================================================
//[<ud_varan_time]varan time
FUNCTION VIRTUAL GLOBAL Varan_Base::GetVaranTime
  VAR_INPUT
    p_ud_IsoStartPoint	: ^UDINT;
  END_VAR
  VAR_OUTPUT
    ud_varan_time		: UDINT;
  END_VAR

  ud_varan_time := VaranIn.GetVaranTime( p_ud_IsoStartPoint );

END_FUNCTION //VIRTUAL GLOBAL Varan_Base::GetVaranTime
//[#ENGLISH]
//=================================================================================================
//Function to disable Device in Rt (because VARAN_iSetNodeEnableStatus must not called in Realtime)
//=================================================================================================
FUNCTION  Varan_Base::DisableDeviceRt
  VAR_OUTPUT
    sd_retval		: DINT;
  END_VAR

  //look if funtion is available with this os version
  if ( _RTOSVersion >= VM_DISABLE_DEVICE_AVAILABLE ) then

      //disable device
    sd_retval := VaranIn.SetDisableDevice( p_us_position_info := p_VaranPosition );
    
    //check error
      if ( sd_retval = 0 ) then

        //port is disabled
        b_DisableDevice := FALSE;
        ud_DisableTime := ops.tAbsolute;
      end_if;
  else
    b_DisableDevice := FALSE;
    sd_retval := -100;
  end_if;

  // Force end of Cylic Post Init
  if bPostInitNeeded then
    CheckCyclicPostInitFinished(TRUE);
  end_if;

END_FUNCTION // Varan_Base::DisableDeviceRt


FUNCTION Varan_Base::SetNewPllData
  VAR_INPUT
    ud_delay_time 	: UDINT;
    us_divider 	    : USINT;
  END_VAR
  VAR_OUTPUT
    sd_retval 	    : DINT;
  END_VAR
  VAR
    ud_data			    : UDINT;
  END_VAR

  //calculate right register value (Response Time (in 10ns steps) / 2 - constant FPGA delay time
  ud_DeviceDelayTime := ( p_NodeInfo^.uiResponseTime ) / 20 + VM_CONST_FPGA_DELAY + ud_delay_time;
  
  // Payload support
  if b_PayloadSupport then
    //write Pll time with direct access
    sd_retval := MULTI_VARAN_iExecuteDirectAccess(  hNodeHandle := ud_HandleModule
                                                  , udCommand   := VARAN_CMD_CONTROL_WRITE
                                                  , udOffset    := VARAN_PLL_OFFSET + 16#C
                                                  , udLength    := 3
                                                  , pusData     := ( #ud_DeviceDelayTime )$^USINT
                                                  , pudErrorInfo:= NIL);
  else
    //write Pll time with direct access
    sd_retval := VARAN_iWriteControlDA( uiManager		  := ud_VaranManagerNr
                                      , uiAddress		  := DeviceAddress + VARAN_PLL_OFFSET + 16#C
                                      , uiLen			    := 3
                                      , uiRetryTimeout:= GetRetryTimeout( ud_bytes := 3 )
                                      , pvData		    := ( #ud_DeviceDelayTime )$^UDINT
                                      , puiError		  := NIL
                                      );
  end_if;

  //look if an error occurs
  if ( sd_retval <> VARANMANAGER_OK ) then
    State := _PllError;
    return;
  end_if;
  
  //set divider (only for new pll if function is available)
  if ( us_divider <> 0 ) then   
    
    
    if b_PayloadSupport then  //  -------------------------------------------------------------------------
      // disable divider
      ud_data := 0;
      
      sd_retval := MULTI_VARAN_iExecuteDirectAccess(  hNodeHandle := ud_HandleModule
                                                    , udCommand   := VARAN_CMD_CONTROL_WRITE
                                                    , udOffset    := VARAN_PLL_OFFSET + 16#A
                                                    , udLength    := 1
                                                    , pusData     := ( #ud_data )$^USINT
                                                    , pudErrorInfo:= NIL);
      
      
      //look if an error occurs
      if ( sd_retval <> VARANMANAGER_OK ) then
        State := _PllError;
        return;
      end_if;      
      
      // set divider value
      ud_data := us_divider;
      
      sd_retval := MULTI_VARAN_iExecuteDirectAccess(  hNodeHandle := ud_HandleModule
                                                    , udCommand   := VARAN_CMD_CONTROL_WRITE
                                                    , udOffset    := VARAN_PLL_OFFSET + 16#B
                                                    , udLength    := 1
                                                    , pusData     := ( #ud_data )$^USINT
                                                    , pudErrorInfo:= NIL);
      
      //look if an error occurs
      if ( sd_retval <> VARANMANAGER_OK ) then
        State := _PllError;
        return;
      end_if;
      
      // enable divider
      ud_data := 2#10010000;    //Defaultvalue = 0x80 + SyncDivider Eanble Bit (Bit4)
      
      sd_retval := MULTI_VARAN_iExecuteDirectAccess(  hNodeHandle := ud_HandleModule
                                                    , udCommand   := VARAN_CMD_CONTROL_WRITE
                                                    , udOffset    := VARAN_PLL_OFFSET + 16#A
                                                    , udLength    := 1
                                                    , pusData     := ( #ud_data )$^USINT
                                                    , pudErrorInfo:= NIL);
                                                    
      //look if an error occurs
      if ( sd_retval <> VARANMANAGER_OK ) then
        State := _PllError;
        return;
      end_if;
    
    else  // if b_PayloadSupport -------------------------------------------------------------------------
    
      // disable divider
      ud_data := 0;

      // write control register
      sd_retval := VARAN_iWriteControlDA( uiManager		  := ud_VaranManagerNr
                                        , uiAddress		  := DeviceAddress + VARAN_PLL_OFFSET + 16#A
                                        , uiLen			    := 1
                                        , uiRetryTimeout:= GetRetryTimeout( ud_bytes := 1 )
                                        , pvData		    := ( #ud_data )$^UDINT
                                        , puiError		  := NIL
                                        );
      
      //look if an error occurs
      if ( sd_retval <> VARANMANAGER_OK ) then
        State := _PllError;
        return;
      end_if;
      
      // set divider value
      ud_data := us_divider;
      
      //write Divider with direct access
      sd_retval := VARAN_iWriteControlDA( uiManager		  := ud_VaranManagerNr
                                        , uiAddress		  := DeviceAddress + VARAN_PLL_OFFSET + 16#B
                                        , uiLen			    := 1
                                        , uiRetryTimeout:= GetRetryTimeout( ud_bytes := 1 )
                                        , pvData		    := ( #ud_data )$^UDINT
                                        , puiError		  := NIL
                                        );

      //look if an error occurs
      if ( sd_retval <> VARANMANAGER_OK ) then
        State := _PllError;
        return;
      end_if;

      // enable divider
      ud_data := 2#10010000;    //Defaultvalue = 0x80 + SyncDivider Eanble Bit (Bit4)

      //write Divider with direct access
      sd_retval := VARAN_iWriteControlDA( uiManager		  := ud_VaranManagerNr
                                        , uiAddress		  := DeviceAddress + VARAN_PLL_OFFSET + 16#A
                                        , uiLen			    := 1
                                        , uiRetryTimeout:= GetRetryTimeout( ud_bytes := 1 )
                                        , pvData		    := ( #ud_data )$^UDINT
                                        , puiError		  := NIL
                                        );

      //look if an error occurs
      if ( sd_retval <> VARANMANAGER_OK ) then
        State := _PllError;
        return;
      end_if;
      
    end_if; // if b_PayloadSupport -------------------------------------------------------------------------
    
  end_if; // us_divider <> 0

END_FUNCTION


FUNCTION VIRTUAL GLOBAL Varan_Base::GetDocumentation
  VAR_INPUT
    p_dpne 	: ^CHAR;
  END_VAR
  VAR_OUTPUT
    sd_retval 	: DINT;
  END_VAR
  
  sd_retval := VaranIn.GetDocumentation(p_us_position_info:=p_VaranPosition, p_dpne:=p_dpne);

END_FUNCTION


FUNCTION VIRTUAL GLOBAL Varan_Base::UpdateRtPostScan

END_FUNCTION


FUNCTION GLOBAL Varan_Base::SetRunStatus
  VAR_INPUT
    state 	: USINT;
  END_VAR
  VAR_OUTPUT
    us_retval 	: USINT;
  END_VAR

  if Required then
    us_retval := state or VARAN_DO_REQUIRED;
  else
    us_retval := state;
  end_if;

END_FUNCTION


FUNCTION VIRTUAL GLOBAL Varan_Base::GetPointer2ObjectPath
  VAR_OUTPUT
    p_us_ObjectPath 	: ^USINT;
  END_VAR
  VAR
    i                       : USINT;
    udSystemVaranManagerCnt : UDINT;
    _Para 	                : CmdStruct;  
    _Result 	              : Results;
  END_VAR
 
  if ( p_ObjectPath = NIL ) then
  
    if ( p_VaranPosition = NIL ) then
      
      Varan_Base::Init();
    
      if ( p_VaranPosition = NIL ) then
        
        p_us_ObjectPath := NIL;
        return;
      
      end_if;
    end_if;
    
    if ( p_VaranPosition^ >= VARAN_MAX_DEPTH ) then
      p_us_ObjectPath := NIL;
      return;
    end_if;
    
    //alloc memory
    p_ObjectPath := ( To_StdLib.Malloc( size := p_VaranPosition^ + 5 ) )$^USINT;

    To_StdLib.MemCpy( dest 		:= p_ObjectPath
                    , source	:= p_VaranPosition
                    , size		:= p_VaranPosition^ + 1
                    );
   
    _Para.uiCmd := VM_CMD_GET_SYSTEM_MANAGER_CNT;
    _Result.aData[0]$UDINT  := 1;   // Set to 1 in case the NewInst Method is not Implemented
    udSystemVaranManagerCnt := 1;
    
    if VaranIn.NewInst(#_Para, #_Result) = READY then
      udSystemVaranManagerCnt := _Result.aData[0]$UDINT;
    end_if;


    //Check if we have to build the "new" hardware tree with the new escape sequence
    if udSystemVaranManagerCnt > 1 then
    
      //More than one manager --> new HW-Tree with new esacpe sequence
    
      //insert one byte after length
      for i := p_ObjectPath^ to 1 by -1 do 
        ( p_ObjectPath + i + 4 )^ := ( p_ObjectPath + i )^;
      end_for;
    
      // domain info byte
      ( p_ObjectPath + 1 )^ := 0;

      //insert escape sequence for varan
      ( p_ObjectPath + 2 )^ := HWT_ESCAPE_MULTIVARAN;
      
      //insert escape sequence for varan
      ( p_ObjectPath + 3 )^ := ud_VaranManagerNr$USINT;

      //insert escape sequence for varan
      ( p_ObjectPath + 4 )^ := HWT_ESCAPE_VARAN;
      
      //increase length
      p_ObjectPath^ += 4;
     
    else
      
      //Old HW-Tree (without Multivaran Escape sequence)
    
      //insert one byte after length
      for i := p_ObjectPath^ to 1 by -1 do 
        ( p_ObjectPath + i + 2 )^ := ( p_ObjectPath + i )^;
      end_for;
    
      // domain info byte
      ( p_ObjectPath + 1 )^ := 0;
      
      //insert escape sequence for varan
      ( p_ObjectPath + 2 )^ := HWT_ESCAPE_VARAN;
      
      //increase length
      p_ObjectPath^ += 2;
    
    end_if;
    
    
    //register object path in OS
    SetObjectThisp(p_us_ObjectPath:=p_ObjectPath, ud_thisp:=this$UDINT);
    
  end_if;
  
  p_us_ObjectPath := p_ObjectPath;
  
END_FUNCTION


FUNCTION VIRTUAL GLOBAL Varan_Base::SetObjectThisp
  VAR_INPUT
    p_us_ObjectPath 	: ^USINT;
    ud_thisp 	: UDINT;
  END_VAR
  VAR_OUTPUT
    sd_retval 	: DINT;
  END_VAR
  
  sd_retval := VaranIn.SetObjectThisp(p_us_ObjectPath,ud_thisp);
  
END_FUNCTION


FUNCTION VIRTUAL GLOBAL Varan_Base::GetObjectThisp
  VAR_INPUT
    p_us_ObjectPath : ^USINT;
  END_VAR
  VAR_OUTPUT
    ud_Thisp 	      : UDINT;
  END_VAR
  
  ud_thisp := VaranIn.GetObjectThisp(p_us_ObjectPath:=p_us_ObjectPath);
  
END_FUNCTION


FUNCTION Varan_Base::Diagnose
#ifdef VARAN_DIAGNOSE
  VAR
    os_retcode : DINT;
  END_VAR

  if State = _ClassOk then
    os_retcode := VARAN_IGETVARANDIAGNOSTICS(8, #s_Diagnose.cmd_Input, s_Diagnose.InputSize, #s_Diagnose.cmd_Output, #s_Diagnose.OutputSize);

    //reset counter
    if s_Diagnose.Command = Reset then
      ConnectCounter      := 0;
      FaultCounter        := 0;
      RXLost              := 0;
      TXLost              := 0;
      s_Diagnose.Command  := Activate;
    end_if;

    //OS doesn't support Diagnose
    if os_retcode <> 0 then
      DiagControl := -1;  
      return;
    end_if;

    //FPGA doesn't support Diagnose
    if s_Diagnose.cmd_Output.Flags.1 = 0 then  
      DiagControl := -2;
      return;  
    end_if;

    DiagControl     := 1;
    ConnectCounter  += s_Diagnose.cmd_Output.Counter1 - s_Diagnose.OldCounter.Counter1;
    FaultCounter    += s_Diagnose.cmd_Output.Counter2 - s_Diagnose.OldCounter.Counter2;
    RXLost          += s_Diagnose.cmd_Output.Counter3 - s_Diagnose.OldCounter.Counter3;
    TXLost          += s_Diagnose.cmd_Output.Counter4 - s_Diagnose.OldCounter.Counter4;   
    
    s_Diagnose.OldCounter.Counter1 := s_Diagnose.cmd_Output.Counter1;
    s_Diagnose.OldCounter.Counter2 := s_Diagnose.cmd_Output.Counter2;
    s_Diagnose.OldCounter.Counter3 := s_Diagnose.cmd_Output.Counter3;
    s_Diagnose.OldCounter.Counter4 := s_Diagnose.cmd_Output.Counter4;
  end_if;      
#endif
END_FUNCTION

#pragma warning(disable:73)
#pragma warning(disable:74)
#pragma warning(disable:76)
FUNCTION VIRTUAL GLOBAL Varan_Base::DiagControl::Write
  VAR_INPUT
    input (EAX) 	: DINT;
  END_VAR
  VAR_OUTPUT
    result (EAX) 	: DINT;
  END_VAR

#ifdef VARAN_DIAGNOSE

  if input >= 0 & input <= 2 then
    s_Diagnose.Command$DINT := input;
  end_if;
  
#endif

END_FUNCTION
#pragma warning(default:73)
#pragma warning(default:74)
#pragma warning(default:76)

FUNCTION VIRTUAL GLOBAL Varan_Base::ValidateSerNo::Write
  VAR_INPUT
    input (EAX) 	: DINT;
  END_VAR
  VAR_OUTPUT
    result (EAX) 	: DINT;
  END_VAR

  result := input;
  
  if (b_ValidationInProgress = FALSE) & SerNoValidation then
    
    To_MultiTask.CREATETHREAD(taskfunction0:=#SerNoValidationTask(), 
                              priority0:=14, 
                              stackSize0:=16#4000, 
                              flags0:=MT_TASK_SAVETHIS, 
                              parameter0:=this, 
                              name0:=#szSerNoStr[0]);

    b_ValidationInProgress := TRUE;
  end_if;

END_FUNCTION


FUNCTION Varan_Base::SerNoValidationTask

  // get length of string
  SerNoHeader.StringLength := _strlen(#szSerNoStr[0]);

  // reserve enough space in ramfile
  if SerNoBackup.SetSize(sizeof(SerNoHeader) + SerNoHeader.StringLength) <> C_OK then
      b_ValidationInProgress := FALSE;
      return;
    end_if;

  // initialize the rest of the header
  SerNoHeader.Version := SERNO_VALIDATION_VERSION;
  SerNoHeader.ZeroByte := 0;
  
  // write to ramfile
  if (SerNoBackup.SetDataAt((#SerNoHeader)$^USINT, sizeof(SerNoHeader), 0) = C_OK) & 
     (SerNoBackup.SetDataAt((#szSerNoStr[0])$^USINT, _strlen(#szSerNoStr[0]), sizeof(SerNoHeader)) = C_OK) then
    // if we had a problem with serial number before
    if State = _InvalidSerialNo then
      // try to reconnect
      Varan_HwConnect(0);
    end_if;

    ValidateSerNo := 1;
  else
    ValidateSerNo := 0;
  end_if;
  
  b_ValidationInProgress := FALSE;
  
END_FUNCTION

#pragma warning(disable:73)
FUNCTION VIRTUAL GLOBAL Varan_Base::CheckDeviceID
  VAR_INPUT
    ID2Check 	: UDINT;
  END_VAR
  VAR_OUTPUT
    IsOK 	: BOOL;
  END_VAR
#pragma warning(default:73)

  IsOK := TRUE;

END_FUNCTION


FUNCTION GLOBAL Varan_Base::FlexInit
  VAR
    sd_retval	: DINT;
  END_VAR

  //look for an error
  if ( pVaran = NIL ) then
    State := _NoVaranInterface;
    if Required then
      VaranIn.AllowRequiredError();
    end_if;
    return;
  end_if;
  
  //-----------------------------------------------------------------------------------------------
  //get Varan position if we have no position yet
  if ( p_VaranPosition = NIL ) then

    //alloc memory to get position
    p_VaranPosition := ( To_StdLib.Malloc( size := VARAN_MAX_DEPTH + 1 ) )$^USINT;
    //look if an error occurs
    if ( p_VaranPosition = NIL ) then
      State := _RootError;
      return;
    end_if;

  else
    
    //alloc memory for position pointer
    p_VaranPosition := 	( To_StdLib.ReAlloc	( mptr := p_VaranPosition , newsize	:= VARAN_MAX_DEPTH + 1))$^USINT;
    //look if an error occurs
    if ( p_VaranPosition = NIL ) then
      State := _RootError;
      return;
    end_if;
  
  end_if;

  //set length to 0
  p_VaranPosition^ := 0;		

  //get position
  sd_retval := VaranIn.GetVaranPosition( p_us_info := p_VaranPosition );

  //look if an error occurs
  if ( sd_retval <> VARANMANAGER_OK ) then
    State := _RootError;
    return;
  end_if;

  //alloc memory for position pointer
  p_VaranPosition := 	( To_StdLib.ReAlloc	( mptr		:= p_VaranPosition
                      , newsize	:= p_VaranPosition^ + 1
                      ) 
            )$^USINT;

  //look if an error occurs
  if ( p_VaranPosition = NIL ) then
    State := _RootError;
    return;
  end_if;

  //-----------------------------------------------------------------------------------------------
  //install callback function
  sd_retval := InstallCallbackObject();	

  //look if an error occurs
  if ( sd_retval <> VARANMANAGER_OK ) then
    State := _CallBackError;
    return;
  end_if;
  
END_FUNCTION


FUNCTION GLOBAL Varan_Base::AllowRequiredError
 
  VaranIn.AllowRequiredError();
 
END_FUNCTION


FUNCTION GLOBAL Varan_Base::IsTransparent
  VAR_OUTPUT
    isTransparent 	: BOOL;
  END_VAR

  IF TransparentInfo.ClientTransparentRead = FALSE THEN

    Transparent := Transparent.Read();
    IF Transparent | VaranIn.IsTransparent() THEN
      Transparent := 1;
      TransparentInfo.DeviceIsTransparent := TRUE;
      Required := 0;
    END_IF;
    
    TransparentInfo.ClientTransparentRead := TRUE;
  
  END_IF;

  isTransparent := TransparentInfo.DeviceIsTransparent;

END_FUNCTION


FUNCTION VIRTUAL GLOBAL Varan_Base::AddRdPayloadDO
  VAR_INPUT
    ud_dol_type 	: UDINT;
    p_ud_handle 	: ^UDINT;
    ud_offset_read 	: UDINT;
    ud_length_read 	: UDINT;
    p_ud_data_read 	: ^UDINT;
    ud_type 	: UDINT;
    ud_priority 	: UDINT;
    ud_WritePayloadType   : UDINT;
  END_VAR
  VAR_OUTPUT
    sd_retval 	: DINT;
  END_VAR
  VAR
      // For NewInst command 
    _Para 	        : CmdStruct;  
    _Result 	      : Results;    
    paraAddDO       : t_VM_CMD_AddDO;
    paraGetPointers : t_VM_CMD_GetDataPointers;
    dummy           : UDINT;
  END_VAR
  
  // Add DO Command ------------------------------------------------------------------------------------------
  _Para.uiCmd := VM_CMD_ADD_DO;
  
  if ud_HandleModule then
    paraAddDO.ud_ModuleHandle := ud_HandleModule;
  else
    sd_retval := VM_CMD_ERROR_MODULE_HANDLE;
    return;
  end_if;

  paraAddDO.p_ud_DoHandle   := p_ud_handle;
  paraAddDO.ud_b_DoRequired := Required$UDINT;
  paraAddDO.ud_DolType      := ud_dol_type;
  paraAddDO.ud_OffsetRead   := ud_offset_read;
  paraAddDO.ud_LengthRead   := ud_length_read;
  paraAddDO.ud_OffsetWrite  := 0;
  paraAddDO.ud_LengthWrite  := 0;  
  
  if TimeBase > 0 then
    paraAddDO.ud_PreScalerCounterThreshold   := TimeBase - 1;
  else
    paraAddDO.ud_PreScalerCounterThreshold   := 0;
  end_if;
  
  paraAddDO.ud_PreScalerCounterStartValue  := 0;
  
  if ud_priority = VM_PRIORITY_INVALID then
    // paraAddDO.ud_Priority := VM_PRIORITY_READ_DO;  // Only with Timesplit
    paraAddDO.ud_Priority := VM_PRIORITY_DEFAULT;
  else    
    paraAddDO.ud_Priority := ud_priority;
  end_if;  
  
  paraAddDO.ud_Filter   := 0;
  paraAddDO.ud_Slices   := 0;
  
  if ud_WritePayloadType then
    paraAddDO.ud_WritePayloadType := WR_PLD_TYPE_RD_ACCESS_CONFIGURABLE;
  else
    paraAddDO.ud_WritePayloadType := WR_PLD_TYPE_STANDARD;
  end_if;
  
  if ud_type = VM_CONTROL_ACCESS then
    paraAddDO.ud_Command  := VARAN_CMD_CONTROL_READ;
  else
    paraAddDO.ud_Command  := VARAN_CMD_MEMORY_READ;
  end_if;
  
  _Para.aPara[0]  := (#paraAddDO)$DINT;
  
  _result.aData[0]$DINT := VM_CMD_OK;
  
  // Add DO via NewInst 
  if VaranIn.NewInst(#_Para, #_Result) <> READY & 
     _result.aData[0]$DINT = VM_CMD_OK then
    // If NewInst failed but retcode is still OK
    sd_retval := VM_CMD_ERROR_NEW_INST;
  else    
    sd_retval := _result.aData[0]$DINT;
  end_if;
  
  if sd_retval <> VM_CMD_OK then    
    return;
  end_if;

  // Get Pointers Command ------------------------------------------------------------------------------------------
  _Para.uiCmd := VM_CMD_GET_DATA_POINTERS;  
  
  if p_ud_handle^ then
    paraGetPointers.ud_DoHandle     := p_ud_handle^;
  else    
    sd_retval := VM_CMD_ERROR_DO_HANDLE;
    return;
  end_if;  
  
  paraGetPointers.p_ud_ReadData   := p_ud_data_read;
  paraGetPointers.p_ud_WriteData  := #dummy;
  
  _Para.aPara[0]  := (#paraGetPointers)$DINT;
  _result.aData[0]$DINT := VM_CMD_OK;
  
  // Get Data Poiners via NewInst 
  if VaranIn.NewInst(#_Para, #_Result) <> READY & 
     _result.aData[0]$DINT = VM_CMD_OK then
    // If NewInst failed but retcode is still OK
    sd_retval := VM_CMD_ERROR_NEW_INST;
  else    
    sd_retval := _result.aData[0]$DINT;
  end_if;
  
END_FUNCTION


FUNCTION VIRTUAL GLOBAL Varan_Base::AddWrPayloadDO
  VAR_INPUT
    ud_dol_type 	: UDINT;
    p_ud_handle 	: ^UDINT;
    ud_offset_write 	: UDINT;
    ud_length_write 	: UDINT;
    p_ud_data_write 	: ^UDINT;
    ud_type 	: UDINT;
    ud_priority 	: UDINT;
    ud_WritePayloadType   : UDINT;
  END_VAR
  VAR_OUTPUT
    sd_retval 	: DINT;
  END_VAR
  VAR
      // For NewInst command 
    _Para 	        : CmdStruct;  
    _Result 	      : Results;    
    paraAddDO       : t_VM_CMD_AddDO;
    paraGetPointers : t_VM_CMD_GetDataPointers;
    dummy           : UDINT;
  END_VAR
  
  // Add DO Command ------------------------------------------------------------------------------------------
  _Para.uiCmd := VM_CMD_ADD_DO;
  
  if ud_HandleModule then
    paraAddDO.ud_ModuleHandle := ud_HandleModule;
  else
    sd_retval := VM_CMD_ERROR_MODULE_HANDLE;
    return;
  end_if;

  paraAddDO.p_ud_DoHandle   := p_ud_handle;
  paraAddDO.ud_b_DoRequired := Required$UDINT;
  paraAddDO.ud_DolType      := ud_dol_type;
  paraAddDO.ud_OffsetRead   := 0;
  paraAddDO.ud_LengthRead   := 0;
  paraAddDO.ud_OffsetWrite  := ud_offset_write;
  paraAddDO.ud_LengthWrite  := ud_length_write;  
  
  if TimeBase > 0 then
    paraAddDO.ud_PreScalerCounterThreshold   := TimeBase - 1;
  else
    paraAddDO.ud_PreScalerCounterThreshold   := 0;
  end_if;
  paraAddDO.ud_PreScalerCounterStartValue  := 0;
  
  if ud_priority = VM_PRIORITY_INVALID then
    // paraAddDO.ud_Priority := VM_PRIORITY_WRITE_DO;  // Only with Timesplit
    paraAddDO.ud_Priority := VM_PRIORITY_DEFAULT;
  else    
    paraAddDO.ud_Priority := ud_priority;
  end_if;  
  
  paraAddDO.ud_Filter   := 0;
  paraAddDO.ud_Slices   := 0;
  
  if ud_WritePayloadType then
    paraAddDO.ud_WritePayloadType := WR_PLD_TYPE_WR_ACCESS_CONFIGURABLE;
  else
    paraAddDO.ud_WritePayloadType := WR_PLD_TYPE_STANDARD;
  end_if;
  
  if ud_type = VM_CONTROL_ACCESS then
    paraAddDO.ud_Command  := VARAN_CMD_CONTROL_WRITE;
  else
    paraAddDO.ud_Command  := VARAN_CMD_MEMORY_WRITE;
  end_if;
  
  _Para.aPara[0]  := (#paraAddDO)$DINT;
  
  _result.aData[0]$DINT := VM_CMD_OK;
  
  // Add DO via NewInst 
  if VaranIn.NewInst(#_Para, #_Result) <> READY & 
     _result.aData[0]$DINT = VM_CMD_OK then
    // If NewInst failed but retcode is still OK
    sd_retval := VM_CMD_ERROR_NEW_INST;
  else    
    sd_retval := _result.aData[0]$DINT;
  end_if;
  
  if sd_retval <> VM_CMD_OK then    
    return;
  end_if;

  // Get Pointers Command ------------------------------------------------------------------------------------------
  _Para.uiCmd := VM_CMD_GET_DATA_POINTERS;  
  
  if p_ud_handle^ then
    paraGetPointers.ud_DoHandle     := p_ud_handle^;
  else    
    sd_retval := VM_CMD_ERROR_DO_HANDLE;
    return;
  end_if;  
  
  paraGetPointers.p_ud_ReadData   := #dummy;
  paraGetPointers.p_ud_WriteData  := p_ud_data_write;
  
  _Para.aPara[0]  := (#paraGetPointers)$DINT;
  _result.aData[0]$DINT := VM_CMD_OK;
  
  // Get Data Poiners via NewInst 
  if VaranIn.NewInst(#_Para, #_Result) <> READY & 
     _result.aData[0]$DINT = VM_CMD_OK then
    // If NewInst failed but retcode is still OK
    sd_retval := VM_CMD_ERROR_NEW_INST;
  else    
    sd_retval := _result.aData[0]$DINT;
  end_if;
  
END_FUNCTION


FUNCTION VIRTUAL GLOBAL Varan_Base::AddRdWrPayloadDO
  VAR_INPUT
    ud_dol_type 	: UDINT;
    p_ud_handle 	: ^UDINT;
    ud_offset_read 	: UDINT;
    ud_length_read 	: UDINT;
    p_ud_data_read 	: ^UDINT;
    ud_offset_write 	: UDINT;
    ud_length_write 	: UDINT;
    p_ud_data_write 	: ^UDINT;
    ud_type 	: UDINT;
    ud_priority 	: UDINT;
    ud_WritePayloadType   : UDINT;
  END_VAR
  VAR_OUTPUT
    sd_retval 	: DINT;
  END_VAR
  VAR
    // For NewInst command 
    _Para 	            : CmdStruct;  
    _Result 	          : Results;    
    paraAddDO           : t_VM_CMD_AddDO;
    paraGetPointers     : t_VM_CMD_GetDataPointers;
  END_VAR
  
  // Add DO Command ------------------------------------------------------------------------------------------
  _Para.uiCmd := VM_CMD_ADD_DO;
  
  if ud_HandleModule then
    paraAddDO.ud_ModuleHandle := ud_HandleModule;
  else
    sd_retval := VM_CMD_ERROR_MODULE_HANDLE;
    return;
  end_if;

  paraAddDO.p_ud_DoHandle   := p_ud_handle;
  paraAddDO.ud_b_DoRequired := Required$UDINT;
  paraAddDO.ud_DolType      := ud_dol_type;
  paraAddDO.ud_OffsetRead   := ud_offset_read;
  paraAddDO.ud_LengthRead   := ud_length_read;
  paraAddDO.ud_OffsetWrite  := ud_offset_write;
  paraAddDO.ud_LengthWrite  := ud_length_write;
  
  if TimeBase > 0 then
    paraAddDO.ud_PreScalerCounterThreshold   := TimeBase - 1;
  else
    paraAddDO.ud_PreScalerCounterThreshold   := 0;
  end_if;
  paraAddDO.ud_PreScalerCounterStartValue  := 0;
  
  if ud_priority = VM_PRIORITY_INVALID then
    // paraAddDO.ud_Priority := VM_PRIORITY_READ_DO; // Only with Timesplit
    paraAddDO.ud_Priority := VM_PRIORITY_DEFAULT;
  else    
    paraAddDO.ud_Priority := ud_priority;
  end_if;  
  
  paraAddDO.ud_Filter   := 0;
  paraAddDO.ud_Slices   := 0;  
  
  if ud_WritePayloadType then
    // Check if only the read or write part of the Payload DO needs to be changed
    if (ud_WritePayloadType = WR_PLD_TYPE_RD_ACCESS_CONFIGURABLE$UDINT) |
       (ud_WritePayloadType = WR_PLD_TYPE_WR_ACCESS_CONFIGURABLE$UDINT) then
      paraAddDO.ud_WritePayloadType := ud_WritePayloadType;
    else
      paraAddDO.ud_WritePayloadType := WR_PLD_TYPE_RW_ACCESS_CONFIGURABLE;
    end_if;
  else
    paraAddDO.ud_WritePayloadType := WR_PLD_TYPE_STANDARD;
  end_if;
  
  if ud_type = VM_CONTROL_ACCESS then
    paraAddDO.ud_Command  := VARAN_CMD_CONTROL_READ_WRITE;
  else
    paraAddDO.ud_Command  := VARAN_CMD_MEMORY_READ_WRITE;
  end_if;
  
  _Para.aPara[0]  := (#paraAddDO)$DINT;
  
  _result.aData[0]$DINT := VM_CMD_OK;
  
  // Add DO via NewInst 
  if VaranIn.NewInst(#_Para, #_Result) <> READY & 
     _result.aData[0]$DINT = VM_CMD_OK then
    // If NewInst failed but retcode is still OK
    sd_retval := VM_CMD_ERROR_NEW_INST;
  else    
    sd_retval := _result.aData[0]$DINT;
  end_if;
  
  if sd_retval <> VM_CMD_OK then    
    return;
  end_if;

  // Get Pointers Command ------------------------------------------------------------------------------------------
  _Para.uiCmd := VM_CMD_GET_DATA_POINTERS;  
  
  if p_ud_handle^ then
    paraGetPointers.ud_DoHandle     := p_ud_handle^;
  else    
    sd_retval := VM_CMD_ERROR_DO_HANDLE;
    return;
  end_if;  
  
  paraGetPointers.p_ud_ReadData   := p_ud_data_read;
  paraGetPointers.p_ud_WriteData  := p_ud_data_write;
  
  _Para.aPara[0]  := (#paraGetPointers)$DINT;
  _result.aData[0]$DINT := VM_CMD_OK;
  
  // Get Data Poiners via NewInst 
  if VaranIn.NewInst(#_Para, #_Result) <> READY & 
     _result.aData[0]$DINT = VM_CMD_OK then
    // If NewInst failed but retcode is still OK
    sd_retval := VM_CMD_ERROR_NEW_INST;
  else    
    sd_retval := _result.aData[0]$DINT;
  end_if;
  
END_FUNCTION


FUNCTION VIRTUAL GLOBAL Varan_Base::AddMovePayloadDO
  VAR_INPUT
    ud_dol_type 	: UDINT;
    p_ud_handle 	: ^UDINT;
    ud_SourceReadDOHandle 	: UDINT;
    ud_SourceReadOffset 	: UDINT;
    ud_DestinationWriteDOHandle 	: UDINT;
    ud_DestinationWriteOffset 	: UDINT;
    ud_LengthMove 	: UDINT;
    ud_Priority 	: UDINT;
  END_VAR
  VAR_OUTPUT
    sd_retval 	: DINT;
  END_VAR
  VAR
      // For NewInst command 
    _Para 	            : CmdStruct;  
    _Result 	          : Results;    
    paraMovDO           : t_VM_CMD_AddMovDo;    
  END_VAR
  
   // Add Move DO Command ------------------------------------------------------------------------------------------
  _Para.uiCmd := VM_CMD_ADD_MOV_DO; 
  
  paraMovDO.p_ud_DoHandle               := p_ud_handle;
  paraMovDO.ud_b_DoRequired             := Required$UDINT;
  paraMovDO.ud_DolType                  := ud_dol_type;
  paraMovDO.ud_SourceReadDoHandle       := ud_SourceReadDOHandle;
  paraMovDO.ud_SourceReadOffset         := ud_SourceReadOffset;
  paraMovDO.ud_DestinationWriteDoHandle := ud_DestinationWriteDOHandle;
  paraMovDO.ud_DestinationWriteOffset   := ud_DestinationWriteOffset;
  paraMovDO.ud_LengthMove               := ud_LengthMove;
  
  if TimeBase > 0 then
    paraMovDO.ud_PreScalerCounterThreshold   := TimeBase - 1;
  else
    paraMovDO.ud_PreScalerCounterThreshold   := 0;
  end_if;

  paraMovDO.ud_PreScalerCounterStartValue  := 0;
  
  if ud_priority = VM_PRIORITY_INVALID then
    paraMovDO.ud_Priority := VM_PRIORITY_READ_DO;
  else    
    paraMovDO.ud_Priority := ud_priority;
  end_if;    
  
  _Para.aPara[0]  := (#paraMovDO)$DINT;
  
  _result.aData[0]$DINT := VM_CMD_OK;
  
  // Add DO via NewInst via NewInst 
  if VaranIn.NewInst(#_Para, #_Result) <> READY & 
     _result.aData[0]$DINT = VM_CMD_OK then
    // If NewInst failed but retcode is still OK
    sd_retval := VM_CMD_ERROR_NEW_INST;
  else    
    sd_retval := _result.aData[0]$DINT;
  end_if;   
  
END_FUNCTION


FUNCTION VIRTUAL GLOBAL Varan_Base::EnableDO
  VAR_INPUT
    ud_DOHandle 	: UDINT;
    ud_bytes 	: UDINT;
  END_VAR
  VAR_OUTPUT
    sd_retval 	: DINT;
  END_VAR   
  
  // LanSte 12.04.2013 09:11 Use IMULTIVARANMANAGER,
  if b_PayloadSupport then      
    sd_retval := MULTI_VARAN_iEnableDo(ud_DOHandle);    
  else
    if ud_DOHandle then  
      ResetDataObject(p_handleDO:=  ud_DOHandle$PLSL_VARANFRAME,
                      us_state  :=  VARAN_DO_CONT_RUN  , 
                      ud_bytes  :=  ud_bytes);
      
      sd_retval := VARANMANAGER_OK;
    else
      sd_retval := VARANMANAGER_DO_HANDLE_INVALID;
    end_if;
  end_if;    
  
END_FUNCTION


FUNCTION VIRTUAL GLOBAL Varan_Base::DisableDO
	VAR_INPUT
		ud_DOHandle 	: UDINT;
		ud_bytes 	: UDINT;(* := 0 *)
	END_VAR
	VAR_OUTPUT
		sd_retval 	: DINT;
	END_VAR
  
  // LanSte 12.04.2013 09:11 Use IMULTIVARANMANAGER,
  if b_PayloadSupport then    
    sd_retval := MULTI_VARAN_iDisableDo(ud_DOHandle);    
  else  
    if ud_DOHandle then     
      ResetDataObject	( p_handleDO	:= ud_DOHandle$PLSL_VARANFRAME
                      , us_state		:= VARAN_DO_NO_RUN
                      , ud_bytes		:= ud_bytes
                      );
      //ud_DOHandle$PLSL_VARANFRAME^.ucCtrlStat := VARAN_DO_NO_RUN;        
      sd_retval := VARANMANAGER_OK;
    else
      sd_retval := VARANMANAGER_DO_HANDLE_INVALID;
    end_if;    
  end_if; 
  
END_FUNCTION


FUNCTION VIRTUAL GLOBAL Varan_Base::GetRetryCounter
  VAR_INPUT
    ud_DOHandle 	: UDINT;
  END_VAR
  VAR_OUTPUT
    us_RetryCounter 	: USINT;
  END_VAR
  VAR
    sd_retval 	: DINT;
  END_VAR
  
   // LanSte 12.04.2013 09:11 Use IMULTIVARANMANAGER,
  if b_PayloadSupport then  
    us_RetryCounter := 16#FF;  // Set Value so that we notice a Problem if the Valeu remains unchanged
    sd_retval := MULTI_VARAN_iGetDoProperty(ud_DOHandle, DO_PROP_FAILED_ACCESS_COUNTER, #us_RetryCounter$UDINT);      
    
  else
    if ud_DOHandle then
      us_RetryCounter := ud_DOHandle$PLSL_VARANFRAME^.ucRetryCounter;
      sd_retval := VARANMANAGER_OK;
    else
      sd_retval := VARANMANAGER_DO_HANDLE_INVALID;
    end_if;
  end_if;  
  
END_FUNCTION


FUNCTION VIRTUAL GLOBAL Varan_Base::ChangeDOLengthOffset
  VAR_INPUT
    ud_DOHandle 	: UDINT;
    ud_offset_read 	: UDINT;
    ud_length_read 	: UDINT;
    ud_offset_write 	: UDINT;
    ud_length_write 	: UDINT;
  END_VAR
  VAR_OUTPUT
    sd_retval 	: DINT;
  END_VAR
  VAR  	    
    ud_PropertyCount    : UDINT;
    s_PropertyValuePair : ARRAY [0..4] of LSL_PROPERTY_VALUE_PAIR;  
  END_VAR
  
  if b_PayloadSupport = false then
    sd_retval := VM_CMD_WRONG_OS;
    return;    
  end_if;
  
  ud_PropertyCount := 0;
  
  if (ud_offset_read <> VM_DO_PROPERTY_INVALID) then    
    
    s_PropertyValuePair[ud_PropertyCount].udPropertyId    := DO_PROP_READ_OFFSET;
    s_PropertyValuePair[ud_PropertyCount].udPropertyValue := ud_offset_read;
    
    ud_PropertyCount += 1;
  end_if;
  
  if ud_length_read <> VM_DO_PROPERTY_INVALID then
  
    s_PropertyValuePair[ud_PropertyCount].udPropertyId    := DO_PROP_READ_LENGTH;
    s_PropertyValuePair[ud_PropertyCount].udPropertyValue := ud_length_read;
    
    ud_PropertyCount += 1;
    
  end_if;  
  
  if ud_offset_write <> VM_DO_PROPERTY_INVALID then
    s_PropertyValuePair[ud_PropertyCount].udPropertyId    := DO_PROP_WRITE_OFFSET;
    s_PropertyValuePair[ud_PropertyCount].udPropertyValue := ud_offset_write;
    
    ud_PropertyCount += 1;
  end_if;
  
  if ud_length_write <> VM_DO_PROPERTY_INVALID then
    s_PropertyValuePair[ud_PropertyCount].udPropertyId    := DO_PROP_WRITE_LENGTH;
    s_PropertyValuePair[ud_PropertyCount].udPropertyValue := ud_length_write;
    
    ud_PropertyCount += 1;    
  end_if;
  
  if ud_PropertyCount then
    sd_retval := MULTI_VARAN_iSetDoProperties(ud_DOHandle, ud_PropertyCount, #s_PropertyValuePair[0] );
  else
    // Data undefined
    sd_retval := VM_CMD_ERROR_NO_PROPERTY;
  end_if;
  
END_FUNCTION


FUNCTION VIRTUAL GLOBAL Varan_Base::ChangeMovDOLengthOffset
  VAR_INPUT
    ud_MovDOHandle 	: UDINT;
    ud_SourceReadDOHandle 	: UDINT;
    ud_SourceReadOffset 	: UDINT;
    ud_DestinationWriteDOHandle 	: UDINT;
    ud_DestinationWriteOffset 	: UDINT;
    ud_LengthMove 	: UDINT;
  END_VAR
  VAR_OUTPUT
    sd_retval 	: DINT;
  END_VAR  
  VAR  	    
    ud_PropertyCount    : UDINT;
    s_PropertyValuePair : ARRAY [0..5] of LSL_PROPERTY_VALUE_PAIR;  
  END_VAR
  
  ud_PropertyCount := 0;
  
  if (ud_sourceReadDOHandle <> VM_DO_PROPERTY_INVALID) then 
    
    s_PropertyValuePair[ud_PropertyCount].udPropertyId    := DO_PROP_SOURCE_READ_DO;
    s_PropertyValuePair[ud_PropertyCount].udPropertyValue := ud_SourceReadDOHandle;
    
    ud_PropertyCount += 1;
  end_if;
  
  if (ud_SourceReadOffset <> VM_DO_PROPERTY_INVALID) then 
    
    s_PropertyValuePair[ud_PropertyCount].udPropertyId    := DO_PROP_READ_OFFSET;
    s_PropertyValuePair[ud_PropertyCount].udPropertyValue := ud_SourceReadOffset;
    
    ud_PropertyCount += 1;
  end_if;
  
  if (ud_destinationWriteDOHandle <> VM_DO_PROPERTY_INVALID) then 
    
    s_PropertyValuePair[ud_PropertyCount].udPropertyId    := DO_PROP_DESTINATION_WRITE_DO;
    s_PropertyValuePair[ud_PropertyCount].udPropertyValue := ud_DestinationWriteDOHandle;
    
    ud_PropertyCount += 1;
  end_if;
  
  if (ud_DestinationWriteOffset <> VM_DO_PROPERTY_INVALID) then 
    
    s_PropertyValuePair[ud_PropertyCount].udPropertyId    := DO_PROP_WRITE_OFFSET;
    s_PropertyValuePair[ud_PropertyCount].udPropertyValue := ud_DestinationWriteOffset;
    
    ud_PropertyCount += 1;
  end_if;
  
  if (ud_lengthmove <> VM_DO_PROPERTY_INVALID) then 
    
    s_PropertyValuePair[ud_PropertyCount].udPropertyId    := DO_PROP_MOVE_DATA_LENGTH;
    s_PropertyValuePair[ud_PropertyCount].udPropertyValue := ud_LengthMove;
    
    ud_PropertyCount += 1;
  end_if;
  if ud_PropertyCount then
    sd_retval := MULTI_VARAN_iSetDoProperties(ud_MovDOHandle, ud_PropertyCount, #s_PropertyValuePair[0] );
  else
    // Data undefined
    sd_retval := VM_CMD_ERROR_NO_PROPERTY;
  end_if;
  
END_FUNCTION


FUNCTION VIRTUAL GLOBAL Varan_Base::SetPrescaler
  VAR_INPUT
    ud_DOHandle 	: UDINT;
    Prescaler 	: UDINT;
    PrescalerCnt 	: UDINT;
    b_MultipleTimeBase 	: BOOL;
  END_VAR
  VAR_OUTPUT
    sd_retval 	: DINT;
  END_VAR
  VAR
    ud_PropertyCount    : UDINT;
    s_PropertyValuePair : ARRAY [0..1] of LSL_PROPERTY_VALUE_PAIR;
  END_VAR
  
  ud_PropertyCount := 0;
  
  s_PropertyValuePair[0].udPropertyId := DO_PROP_PRESCALER_COUNTER_THRESHOLD;
  ud_PropertyCount += 1;  
  
  if b_MultipleTimeBase then
  
    // Ensure that there is no Multiplication with 0 
    if Prescaler & TimeBase > 1 then
      s_PropertyValuePair[0].udPropertyValue := ((Prescaler + 1) * TimeBase) - 1;
    elsif TimeBase > 1 then
      s_PropertyValuePair[0].udPropertyValue := TimeBase-1;
    else
      // No Prescaler and no Timebase 
      // Why was this Method called again?
      s_PropertyValuePair[0].udPropertyValue := 0;
    end_if;
    
  else
  
    // Set Prescaler 
    s_PropertyValuePair[0].udPropertyValue := Prescaler;
    
    // Set PrescalerCnt (Optional)
    if PrescalerCnt then
      s_PropertyValuePair[1].udPropertyId := DO_PROP_PRESCALER_COUNTER_INIT_VALUE;
      ud_PropertyCount += 1;
      
      s_PropertyValuePair[1].udPropertyValue := PrescalerCnt;  
    end_if;

  end_if;
  
  sd_retval := MULTI_VARAN_iSetDoProperties(ud_DOHandle, ud_PropertyCount, #s_PropertyValuePair[0] );
  
END_FUNCTION


FUNCTION VIRTUAL Varan_Base::InstallCallbackObject
  VAR_OUTPUT
    sd_retval 	: DINT;
  END_VAR
  
  //-----------------------------------------------------------------------------------------------
  // install callback function
  sd_retval := VaranIn.SetObjectCallback( p_us_position_info  := p_VaranPosition
                                        , ud_action_ptr       := ( #Varan_CallBack() )$UDINT
                                        , ud_thisp            := this$UDINT
                                        , sd_required         := Required
                                        );
END_FUNCTION


FUNCTION VIRTUAL GLOBAL Varan_Base::CreateMutex
  VAR_INPUT
    MutexName 	: ^CHAR;
    pThis 	: ^VirtualBase;
  END_VAR
  VAR_OUTPUT
    pv_RetMutex 	: pVoid;
  END_VAR
  VAR
    str_ObjName : array[0..255] of char;
    str_ObjNamePart1 : array[0..VARAN_MUTEX_NAME_MAX_LENGTH-1] of char;
    str_ObjNamePart2 : array[0..VARAN_MUTEX_NAME_END_LENGTH] of char; // +1 for 0 Termination
    str_CombinedName : array[0..VARAN_MUTEX_NAME_MAX_LENGTH-1] of char; 
    str_this : array[0..11] of char; // 2 byty %m, 8 byte Address, 1 byte for 0 Termination
    
    ud_LenObjName  : UDINT;    
    ud_LenStr  : UDINT;    
    ud_SepLenStr : UDINT;
    ud_LenCombObjName : UDINT;  
    ud_LenThis : UDINT;

  END_VAR
  
  pv_RetMutex := Nil; // Error OS_CILGetv failed
  
  if pThis = nil then
    pthis := this;
  end_if;  
  
  if (mt_api = nil) then
  
    if (mt_apiFetch = nil) then 
    
      if(OS_CILGet("LSL_MULTITASK", #mt_apiFetch$void)) THEN
        mt_apiFetch := NIL;
      end_if;
      
    end_if;
    
    mt_api := mt_apiFetch;
    
  end_if;
  
  if mt_api then
  
    _memset(dest:=#str_ObjName[0], usByte:=0, cntr:=sizeof(str_ObjName) );
    _memset(dest:=#str_ObjNamePart1[0], usByte:=0, cntr:=sizeof(str_ObjNamePart1) );
    _memset(dest:=#str_ObjNamePart2[0], usByte:=0, cntr:=sizeof(str_ObjNamePart2) );
    _memset(dest:=#str_CombinedName[0], usByte:=0, cntr:=sizeof(str_CombinedName) );
    _memset(dest:=#str_this[0], usByte:=0, cntr:=sizeof(str_this) );
    
  
    ud_LenStr := _strlen(MutexName);    

    ud_SepLenStr := _strlen(VARAN_STR_MUTEX_NAME_SEPERATOR);
    ud_LenObjName := _GetObjName(pThis:=pthis, pName:=#str_ObjName[0]);
  
    if (ud_LenStr < VARAN_MUTEX_NAME_MAX_LENGTH) then
      _strcpy(dest:=#str_CombinedName[0], src:=MutexName);
    else
      _strncpy(dest:=#str_CombinedName[0], src:=MutexName, max:=VARAN_MUTEX_NAME_MAX_LENGTH-1);
    end_if;
    
    if (ud_LenObjName + ud_LenStr) < VARAN_MUTEX_NAME_MAX_LENGTH then      
      _strcat(dest:=#str_CombinedName[0], src:=#str_ObjName[0]); 
    else
      _strncpy(dest:=#str_ObjNamePart1[0], src:= #str_ObjName[0], max:= VARAN_MUTEX_NAME_MAX_LENGTH - ud_LenStr - ud_SepLenStr - VARAN_MUTEX_NAME_END_LENGTH - 1);    // Copy Beginning of str_ObjName
      _strncpy(dest:=#str_ObjNamePart2[0], src:= #str_ObjName[ud_LenObjName-VARAN_MUTEX_NAME_END_LENGTH-1], max:=VARAN_MUTEX_NAME_END_LENGTH);  // Copy Last MUTEX_NAME_END_LENGTH Char of str_ObjName
      
      // Put the Mutex String together
      _strcat(dest:=#str_CombinedName[0], src:= #str_ObjNamePart1[0]);
      _strcat(dest:=#str_CombinedName[0], src:= VARAN_STR_MUTEX_NAME_SEPERATOR);
      _strcat(dest:=#str_CombinedName[0], src:= #str_ObjNamePart2[0]);      
    end_if;

    pv_RetMutex := OS_MT_CreateSemaphore(MTSEMATYPE_MUTEX, 1, 0, #str_CombinedName[0]);   
    
    if pv_RetMutex = nil then
    
      // If Create Mutex failed: Insert the this pointer into the string
      ud_LenCombObjName := _strlen(#str_CombinedName[0]);
      
      str_this[0] := '0';
      str_this[1] := 'x';
      _itoa(udNumber:=pthis$UDINT, pString:=#str_this[2]);
      ud_LenThis  := _strlen(src:=#str_this[0]);
      
      _strcpy(dest:=#str_CombinedName[ud_LenCombObjName-ud_LenThis], src:=#str_this[0]);      
      
      pv_RetMutex := OS_MT_CreateSemaphore(MTSEMATYPE_MUTEX, 1, 0, #str_CombinedName[0]); 
    
    end_if;

  end_if;    
  
END_FUNCTION


FUNCTION VIRTUAL GLOBAL Varan_Base::MutexStart
  VAR_INPUT
    pMutex 	: pVoid;
  END_VAR

  if(pMutex <> NIL) then
    OS_MT_WAIT(pMutex); 
  end_if;

END_FUNCTION


FUNCTION VIRTUAL GLOBAL Varan_Base::MutexStop
  VAR_INPUT
    pMutex 	: pVoid;
  END_VAR

  if(pMutex <> NIL) then
    OS_MT_SIGNAL(pMutex); 
  end_if;

END_FUNCTION


FUNCTION VIRTUAL GLOBAL Varan_Base::SingleRunSM
  VAR_INPUT
    p_DOhandle 	: ^UDINT;
    p_b_DOIsRunning 	: ^t_SingleRunState;
  END_VAR
  
  // xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
  case p_b_DOIsRunning^ of
  
    SR_STATE_ENABLE_ME :  // DO is not running and start request is set ----------------------------------------
      EnableDO(ud_DOHandle := p_DOhandle^);        
      p_b_DOIsRunning^ := SR_STATE_DISABLE_ME;
      
    SR_STATE_DISABLE_ME : // DO is running and start request is not set ----------------------------------------
      DisableDO(ud_DOHandle:= p_DOhandle^);
      p_b_DOIsRunning^ := SR_STATE_NOTHING;
      
    SR_STATE_LEAVE_ME_ENABLED : // DO is running and another start request is set ------------------------------
      p_b_DOIsRunning^ := SR_STATE_DISABLE_ME;
      
  end_case;
  
END_FUNCTION


FUNCTION VIRTUAL GLOBAL Varan_Base::State::NewInst
  VAR_INPUT
    pPara 	: ^CmdStruct;
    pResult 	: ^Results;
  END_VAR
  VAR_OUTPUT
    ret_code 	: IprStates;
  END_VAR
  VAR
    p_paraGetModuleHandel : ^t_VM_CMD_GetModuleHandle;
    sd_retval             : dint;

    ud_StrSize : UDINT;
    ud_MaxStrSize : UDINT;
    
  END_VAR
  
  p_paraGetModuleHandel:= NIL;
  sd_retval            := VARANMANAGER_FATAL_ERROR;

  ud_StrSize    := 0;
  ud_MaxStrSize := 0;

  ret_code := READY;
  
  CASE pPara^.uiCmd OF
//**********************************************************************************************************************************************************
    VM_CMD_GET_MODULE_HANDLE :  
      p_paraGetModuleHandel := (pPara^.aPara[0])$^t_VM_CMD_GetModuleHandle;
      
      // Check if the passed position string is the same as this class => same module handle
      // For example CDIAS modules behind a CIV
      if (p_paraGetModuleHandel^.p_us_position_info^ = p_VaranPosition^) &  // Lengths of the pos strings are equal
          (_memcmp(ptr1 := p_paraGetModuleHandel^.p_us_position_info+1, ptr2 := p_VaranPosition+1, cntr := p_VaranPosition^) = 0) then  // Contend of the strings are equal
        
        
        if ud_HandleModule then // Check if Module handle has been read. May not be read yet because of init order.
          p_paraGetModuleHandel^.p_ud_module_handle^ := ud_HandleModule;
          pResult^.aData[0]$DINT := VM_CMD_OK;
        else
          // Passes on the NewInst command
          ret_code := VaranIn.NewInst(pPara, pResult);
          
          if pResult^.aData[0]$DINT = VM_CMD_OK & 
             ret_code = READY then
            // Safe the Module Handle to this class as well to avoid unnessary OS Calls
            ud_HandleModule := p_paraGetModuleHandel^.p_ud_module_handle^;
          end_if;
          // Else Let calling class deal with the error
        end_if;

      else
        // Passes on the NewInst command
        ret_code := VaranIn.NewInst(pPara, pResult);
      end_if;
//**********************************************************************************************************************************************************
    CMD_GET_HARDWARE_TREE_ENTRY :
      
      
      ret_code := ERROR;
      pResult^.aData$t_HWCGetHardwareTreeEntryOut.retcode := _HWC_RETVAL_ERROR;
      pResult^.aData[0]$t_HWCGetHardwareTreeEntryOut.pStr_NextHardewareTreeEntry := NIL;
      
      // Don't check for State = _ClassOk, method will be used to compare Real HWT with placed classes
      
      if p_ObjectPath then
        a_HWTEntryStr[0] := p_ObjectPath^$USINT;
        a_HWTEntryStr[1] := 0;
        //a_HWTEntryStr + 2 because first 2 bytes are length, ObjectPath 1st byte is length, 
        _memcpy(ptr1:=#a_HWTEntryStr+2, ptr2:=p_ObjectPath+1, cntr:= a_HWTEntryStr[0]);   
        
        pResult^.aData[0]$t_HWCGetHardwareTreeEntryOut.pStr_NextHardewareTreeEntry := #a_HWTEntryStr[0];
        
        ret_code := READY;
        pResult^.aData$t_HWCGetHardwareTreeEntryOut.retcode := _HWC_RETVAL_OK_HWTSTR_RETURNED;
        
        // Compare Module string with passed string
        if pPara^.aPara[0]$t_HWCGetHardwareDiagnosisIn.pStr_HardewareTreeEntry then 
        
          if pPara^.aPara[0]$t_HWCGetHardwareDiagnosisIn.pStr_HardewareTreeEntry$^USINT^ =
             pResult^.aData[0]$t_HWCGetHardwareTreeEntryOut.pStr_NextHardewareTreeEntry$^USINT^ then // Compare Length
             
            if _memcmp( ptr1:= pPara^.aPara[0]$t_HWCGetHardwareDiagnosisIn.pStr_HardewareTreeEntry // Compare Data
                      , ptr2:= pResult^.aData[0]$t_HWCGetHardwareTreeEntryOut.pStr_NextHardewareTreeEntry
                      , cntr:= pResult^.aData[0]$t_HWCGetHardwareTreeEntryOut.pStr_NextHardewareTreeEntry$^USINT^ + 2) = 0 then  // + 2 for 2 Byte Length
                      
              pResult^.aData$t_HWCGetHardwareTreeEntryOut.retcode :=  _HWC_RETVAL_OK_MODULE_FOUND; 
            end_if;
          end_if;
        end_if;
        
      end_if;
    
//**********************************************************************************************************************************************************
    CMD_GET_HARDWARE_DIAGNOSIS :

//      //search escape sequence, maybe there is a copple module
////      if (ptmpStr+pPara^.aPara[0]$t_HWCGetHardwareDiagnosisIn.us_current_index)^$USINT  = HWT_ESCAPE_VARAN | HWT_ESCAPE_SDIAS | HWT_ESCAPE_CDIAS | HWT_ESCAPE_DIAS  then 
//      if (ptmpStr + pPara^.aPara[0]$t_HWCGetHardwareDiagnosisIn.us_current_index)^$USINT  = HWT_ESCAPE_VARAN (*| HWT_ESCAPE_SDIAS | HWT_ESCAPE_CDIAS | HWT_ESCAPE_DIAS*)  then 
//        pPara^.aPara[0]$t_HWCGetHardwareDiagnosisIn.us_current_index += 1;
//        //Call SDIAS Manager New Inst
//        ret_code := p_UserCalls.p_Callback^.pSvrChCmd.NewInst(pPara,pResult);
//        return;
//      end_if; 

      pResult^.aData$t_HWCGetHardwareDiagnosisOut.retcode := _HWC_RETVAL_ERROR_CLASS_NOT_ONLINE;
      ret_code := ERROR;
      
      //Return State and Device ID and set retcode ----------------------------------------------------------
      pResult^.aData$t_HWCGetHardwareDiagnosisOut.ClassState := State;
      pResult^.aData$t_HWCGetHardwareDiagnosisOut.ud_DeviceID := GetDeviceID();
      
      if State = _NoHardware then
        pResult^.aData$t_HWCGetHardwareDiagnosisOut.retcode := _HWC_RETVAL_ERROR_NO_HARDWARE;
      elsif State = _WrongHardware then
        pResult^.aData$t_HWCGetHardwareDiagnosisOut.retcode := _HWC_RETVAL_ERROR_WRONG_HARDWARE;
      elsif State = _NoCalibDataFound then
        pResult^.aData$t_HWCGetHardwareDiagnosisOut.retcode := _HWC_RETVAL_ERROR_NO_CALIB_DATA_FOUND;
      end_if;
      //------------------------------------------------------------------------------------------------------
      
      if State = _ClassOk then      
      
        // Set Retcodes --------------------------------------------------------------------------------------------        
        pResult^.aData$t_HWCGetHardwareDiagnosisOut.retcode := _HWC_RETVAL_OK;
        ret_code := READY;
        
        //Data which is already in HWK available
        pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.ud_DeviceID := DeviceID;
        pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.ud_VendorID := VendorID;
        
        // Get Serialno -----------------------------------------------------------------------------------------
        pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.pStr_SerialNo     := #a_SerialNo[0];  // Will be overwritten if this pointer is not equal 
        
        if (this <> p_this) then

          ud_StrSize := SerialNoStr.GetLength() ;              
          pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.pStr_SerialNo     := NIL;
          
          if ud_StrSize then

            if (ud_StrSize < sizeof(a_SerialNo)) then // < to account for 0 termination
              // Copy complete string
              SerialNoStr.GetDataAt(pData:=#a_SerialNo[0], udSize:=ud_StrSize, udAt:=0);
              a_SerialNo[ud_StrSize] := 0; // 0 termination
            else
              // Copy part string
              SerialNoStr.GetDataAt(pData:=#a_SerialNo[0], udSize:=sizeof(a_SerialNo)-1, udAt:=0);
              a_SerialNo[sizeof(a_SerialNo)-1] := 0; // 0 termination                
            end_if;             

            pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.pStr_SerialNo     := #a_SerialNo[0];
          end_if;         
        end_if;
        
        // FPGA Version ----------------------------------------------------------------------------------------------------------          
        pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.hd_FPGAVersion := Release;
        
        // FW Version --------------------------------------------------------------------------------------------        
        GetFWVersion(pData:=#a_FWVersion[0],sizeof(a_FWVersion));
        pResult^.aData$t_HWCGetHardwareDiagnosisOut.pStr_FWVersion := #a_FWVersion[0];
        
        // Ordering Version ----------------------------------------------------------------------------------------------------------          
        pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.pStr_OrderingNo := (#a_OrderingNoId + sizeof(t_SPI_CalibHeader))$^CHAR;   // Will be overwritten if this pointer is not equal 
        if (this <> p_this) then          
          
          sd_retval := GetHWInfoData(p_offset:=#ud_OffestSPI, ud_id:=VM_SPI_ORDERING_NO_ID);        
          //look for an error
          if ( sd_retval = VARANMANAGER_OK ) then   
          
            sd_retval := ReadSPIData( ud_offset := ud_OffestSPI
                                    , ud_length	:= sizeof(a_OrderingNoId)
                                    , p_data	:= ( #a_OrderingNoId )$^USINT
                                    );
            //look for an error
            if ( sd_retval = VARANMANAGER_OK ) then

              //t_SPI_CalibHeader ist gleich groß wie der Header von Ordering No Id
              pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.pStr_OrderingNo := (#a_OrderingNoId + sizeof(t_SPI_CalibHeader))$^CHAR; 
            
              // Null Termination
              ud_StrSize    := a_OrderingNoId[0]$t_SPI_CalibHeader.ud_ListLength;
              ud_MaxStrSize := sizeof(a_OrderingNoId) - sizeof(t_SPI_CalibHeader);  
              
              (pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.pStr_OrderingNo + ud_MaxStrSize)^ := 0;
              if ud_StrSize < ud_MaxStrSize then
                (pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.pStr_OrderingNo + ud_StrSize)^ := 0;  
              end_if;
            else
              pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.pStr_OrderingNo := NIL;
// optional, therefore no reason to set the returncode              pResult^.aData$t_HWCGetHardwareDiagnosisOut.retcode := _HWC_RETVAL_ERROR_VARAN_SPI_ACCESS_FAILED;
            end_if;
          else
            pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.pStr_OrderingNo := NIL;
// optional, therefore no reason to set the returncode            pResult^.aData$t_HWCGetHardwareDiagnosisOut.retcode := _HWC_RETVAL_ERROR_VARAN_SPI_ACCESS_FAILED;
          end_if;
        end_if;

        // Device Name ----------------------------------------------------------------------------------------
        pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.pStr_DeviceName     := (#a_DeviceName + sizeof(t_SPI_CalibHeader))$^CHAR;  // Will be overwritten if this pointer is not equal 
        
        if (this <> p_this) then
          sd_retval := GetHWInfoData(p_offset:=#ud_OffestSPI, ud_id:=VM_SPI_DEVICE_NAME_ID);        
          //look for an error
          if ( sd_retval = VARANMANAGER_OK ) then
          
            sd_retval := ReadSPIData( ud_offset := ud_OffestSPI
                                    , ud_length	:= sizeof(a_DeviceName)
                                    , p_data	:= ( #a_DeviceName )$^USINT
                                    );

            //look for an error
            if ( sd_retval = VARANMANAGER_OK ) then
              //t_SPI_CalibHeader ist gleich groß wie der Header von spi device name id
              pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.pStr_DeviceName := (#a_DeviceName + sizeof(t_SPI_CalibHeader))$^CHAR;

              // Null Termination
              ud_StrSize    := a_DeviceName[0]$t_SPI_CalibHeader.ud_ListLength;
              ud_MaxStrSize := sizeof(a_DeviceName) - sizeof(t_SPI_CalibHeader);  
              
              (pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.pStr_DeviceName + ud_MaxStrSize)^ := 0;
              if ud_StrSize < ud_MaxStrSize then
                (pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.pStr_DeviceName + ud_StrSize)^ := 0;  
              end_if;
                      
            else
              pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.pStr_DeviceName := NIL;
// optional, therefore no reason to set the returncode              pResult^.aData$t_HWCGetHardwareDiagnosisOut.retcode := _HWC_RETVAL_ERROR_VARAN_SPI_ACCESS_FAILED;
            end_if;
          else
            pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.pStr_DeviceName := NIL;
// optional, therefore no reason to set the returncode            pResult^.aData$t_HWCGetHardwareDiagnosisOut.retcode := _HWC_RETVAL_ERROR_VARAN_SPI_ACCESS_FAILED;
          end_if;
        end_if;
        
        // Vendor Name -----------------------------------------------------------------------------------------
        pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.pStr_VendorName     := (#a_VendorName + sizeof(t_SPI_CalibHeader))$^CHAR;  // Will be overwritten if this pointer is not equal 
        
        if (this <> p_this) then

          sd_retval := GetHWInfoData(p_offset:=#ud_OffestSPI, ud_id:=VM_SPI_VENDOR_NAME_ID);
          //look for an error
          if ( sd_retval = VARANMANAGER_OK ) then
          
            sd_retval := ReadSPIData( ud_offset := ud_OffestSPI
                                    , ud_length	:= sizeof(a_VendorName)
                                    , p_data	:= ( #a_VendorName )$^USINT
                                    );
            //look for an error
            if ( sd_retval = VARANMANAGER_OK ) then
              
              //t_SPI_CalibHeader ist gleich groß wie der Header von spi vendor name id
              pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.pStr_VendorName := (#a_VendorName + sizeof(t_SPI_CalibHeader))$^CHAR;
              
              // Null Termination
              ud_StrSize    := a_VendorName[0]$t_SPI_CalibHeader.ud_ListLength;
              ud_MaxStrSize := sizeof(a_VendorName) - sizeof(t_SPI_CalibHeader); 
              
              (pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.pStr_VendorName + ud_MaxStrSize)^ := 0;
              if ud_StrSize < ud_MaxStrSize then
                (pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.pStr_VendorName + ud_StrSize)^ := 0;  
              end_if;
            
            else
              pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.pStr_VendorName := NIL;
// optional, therefore no reason to set the returncode              pResult^.aData$t_HWCGetHardwareDiagnosisOut.retcode := _HWC_RETVAL_ERROR_VARAN_SPI_ACCESS_FAILED;
            end_if;
          else
            pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.pStr_VendorName := NIL;
// optional, therefore no reason to set the returncode            pResult^.aData$t_HWCGetHardwareDiagnosisOut.retcode := _HWC_RETVAL_ERROR_VARAN_SPI_ACCESS_FAILED;

          end_if;
        end_if;
        
        // Hardware Veriosn and LiceseNo ----------------------------------------------------------------------------------------------
        pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.ud_LicenseNo := a_IdentList_LicenseNo_HwRev[VARAN_SPI_IDENT_LICENCENO_OFFSET]$UDINT;    // Will be overwritten if this pointer is not equal 
        pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.hd_HWVersion := a_IdentList_LicenseNo_HwRev[VARAN_SPI_IDENT_HARDWAREVER_OFFSET]$UDINT;  // Will be overwritten if this pointer is not equal 
        
        if (this <> p_this) then
        
          sd_retval := GetHWInfoData(p_offset:=#ud_OffestSPI, ud_id:=VM_SPI_IDENTIFICATION_LIST);
          
          //look for an error
          if ( sd_retval = VARANMANAGER_OK ) then
          
            sd_retval := ReadSPIData( ud_offset := ud_OffestSPI
                                    , ud_length	:= sizeof(a_IdentList_LicenseNo_HwRev )                
                                    , p_data	:= ( #a_IdentList_LicenseNo_HwRev )$^USINT
                                    );
            //look for an error
            if ( sd_retval = VARANMANAGER_OK ) then
              pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.ud_LicenseNo := a_IdentList_LicenseNo_HwRev[VARAN_SPI_IDENT_LICENCENO_OFFSET]$UDINT;
              pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.hd_HWVersion := a_IdentList_LicenseNo_HwRev[VARAN_SPI_IDENT_HARDWAREVER_OFFSET]$UDINT;         
            else
            
              pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.ud_LicenseNo := 0;
              pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.hd_HWVersion := 0;
              pResult^.aData$t_HWCGetHardwareDiagnosisOut.retcode := _HWC_RETVAL_ERROR_VARAN_SPI_ACCESS_FAILED; // mandatory entry => set return value
            end_if;
          else
          
            pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.ud_LicenseNo := 0;
            pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.hd_HWVersion := 0;
            pResult^.aData$t_HWCGetHardwareDiagnosisOut.retcode := _HWC_RETVAL_ERROR_VARAN_SPI_ACCESS_FAILED; // mandatory entry => set return value
          end_if;
        end_if;
  
        
        p_this := this;  // Safe this pointer, if method is called with for same class that private variables are still valid, don't need to read again
      
      end_if; // if State = _ClassOk then
      
//**********************************************************************************************************************************************************
    CMD_POST_INIT_RT_READY :
      
      // End PostInit if module is online or module has not been found
      if ((Online = 1) | (bOnline = 0)) then      
        ret_code := READY;
      else      
        ret_code := BUSY;
      end_if;
    
//**********************************************************************************************************************************************************
    else
      // Passes on the NewInst command
      ret_code := VaranIn.NewInst(pPara, pResult);	
  END_CASE;

END_FUNCTION

#pragma warning(disable: 73)
FUNCTION VIRTUAL GLOBAL Varan_Base::Varan_HwSubBusReady
  VAR_INPUT
    ud_data 	: UDINT;
  END_VAR
  VAR_OUTPUT
    sd_retval 	: DINT;
  END_VAR

  sd_retval := VARANMANAGER_OK;

END_FUNCTION
#pragma warning(default: 73)


FUNCTION Varan_Base::GetHWInfoData
	VAR_INPUT
		p_offset 	: ^UDINT;
    ud_id        : UDINT;
	END_VAR
	VAR_OUTPUT
		sd_retval 	: DINT;
	END_VAR

  VAR
    a_data			: ARRAY[0..31] OF UDINT;
    i				: UDINT;
  END_VAR   
  
 //read SPI data
  sd_retval := VaranIn.ReadSPIData( p_us_position_info	:= p_VaranPosition
                  , ud_offset				:= 0
                  , ud_length				:= 128 or VM_SPI_IDENT_LIST 
                  , p_data				:= ( #a_data )$^USINT
                  );

  //look for an error
  if ( sd_retval <> VARANMANAGER_OK ) then
    return;
  end_if;
      
  //look for right Identifier
  if ( a_data[ 0 ] <> 16#12345678 ) then
    return;
  end_if;

  //look for valid length	(we only read 128 Byte at the moment [16Byte are header])
  if( a_data[ 3 ] > (128 - 16 ) ) then
    return;
  end_if;

  //search for input data
  for i := 0 to a_data[ 3 ] / sizeof( UDINT ) do

    //look for input id in 3rd byte
    if ( ( a_data[ i + 4 ] and 16#FF00_0000 ) = ud_id ) then
      p_offset^ := a_data[ i + 4 ] and 16#00FF_FFFF;
      return;
    end_if;
  end_for;

  //if no entry is found
  sd_retval := -100;


END_FUNCTION


FUNCTION VIRTUAL GLOBAL Varan_Base::GetDeviceID
	VAR_OUTPUT
		output 	: UDINT;
	END_VAR
  //Overwrite this method in derived class

 output := HWC_INVALID_DEVICE_ID;


END_FUNCTION


FUNCTION VIRTUAL Varan_Base::GetFWVersion
	VAR_INPUT
		pData 	: ^CHAR;
		length 	: UDINT;
	END_VAR
  
  //Overwrite in derived Classes    
  if pData then
    if Length >= 1 then
      pData^ := 0;    // Set first byte  to 0 termination = invalid string
    end_if;
  end_if;
  
END_FUNCTION


FUNCTION Varan_Base::GetPllState
	VAR_OUTPUT
		pllstate 	: BSINT;
	END_VAR
  VAR
  	us_data : BSINT;
    sd_retval		: DINT;
  END_VAR

  pllstate := 0;
  
  if b_PayloadSupport then  //  -------------------------------------------------------------------------
    // get pll state
    us_data := 0;
    
    sd_retval := MULTI_VARAN_iExecuteDirectAccess(  hNodeHandle := ud_HandleModule
                                                  , udCommand   := VARAN_CMD_CONTROL_READ
                                                  , udOffset    := VARAN_PLL_OFFSET + 16#A
                                                  , udLength    := 1
                                                  , pusData     := ( #us_data )$^USINT
                                                  , pudErrorInfo:= NIL);
    
    
    //look if an error occurs
    if ( sd_retval <> VARANMANAGER_OK ) then
      return;
    end_if;      
  
  else  // if b_PayloadSupport -------------------------------------------------------------------------
    // get pll state
    us_data := 0;

    // write control register
    sd_retval := VARAN_iReadControlDA( uiManager		  := ud_VaranManagerNr
                                      , uiAddress		  := DeviceAddress + VARAN_PLL_OFFSET + 16#A
                                      , uiLen			    := 1
                                      , uiRetryTimeout:= GetRetryTimeout( ud_bytes := 1 )
                                      , pvData		    := ( #us_data )$^UDINT
                                      , puiError		  := NIL
                                      );
    
    //look if an error occurs
    if ( sd_retval <> VARANMANAGER_OK ) then
      return;
    end_if;
    
  end_if;

#pragma warning(disable:74);
  pllstate.1 := us_data.7; // enabled
  pllstate.2 := us_data.1; // locked
  pllstate.3 := us_data.3; // delay compensated
#pragma warning(default:74);

END_FUNCTION


FUNCTION VIRTUAL GLOBAL Varan_Base::CheckPostInitNeeded
	VAR_INPUT
		pbPostInitSettings 	: ^t_VM_CMD_NEED_POST_INIT_CALL_SETTINGS;
	END_VAR
	VAR_OUTPUT
		PostInitNeeded 	: BOOL;
	END_VAR
  
  if pbPostInitSettings <> NIL then
    pbPostInitSettings^ := 0;
  end_if;
  
  PostInitNeeded 	:= FALSE;

END_FUNCTION


FUNCTION VIRTUAL Varan_Base::CheckCyclicPostInitFinished
	VAR_INPUT
		bForcePostInitEnd 	: BOOL;
	END_VAR
  
  if ((eCycleWork >= _CycleStartIsoDO) | (bOnline = FALSE) | (bForcePostInitEnd)) then
    _ParaBaseCy.uiCmd   := VM_CMD_POST_INIT_FINISHED;
    _ParaBaseCy.aPara[0]:= this$DINT;
    _ParaBaseCy.aPara[1]:= uiBasePostInitHandle;
    
    if VaranIn.NewInst(pPara:= #_ParaBaseCy, pResult:= #_ResultBaseCy) <> READY then
      LogError("@017D (Varan_Base::CheckCyclicPostInitFinished) Failed to end PostInit.");
    end_if;

    bPostInitNeeded := FALSE;
  end_if;

END_FUNCTION

#pragma warning(disable: 73);
FUNCTION VIRTUAL Varan_Base::LogError
	VAR_INPUT
		e_msg 	: ^CHAR;
	END_VAR
  
#ifdef HWC_LogError
  HWC_LogError(this, e_msg);
#endif

END_FUNCTION


FUNCTION VIRTUAL Varan_Base::LogValue
	VAR_INPUT
		pString 	: ^CHAR;
		Value 	: UDINT;
		Value2 	: UDINT;(* := 16#FFFFFFFF *)
		Value3 	: UDINT;(* := 16#FFFFFFFF *)
	END_VAR
  
#ifdef HWC_LogValue3
  HWC_LogValue3(this, pString, Value, Value2, Value3);
#endif

END_FUNCTION
#pragma warning(default: 73);


FUNCTION VIRTUAL Varan_Base::ConvertHwVersion
	VAR_INPUT
		OriginalHwVer 	: HDINT;
	END_VAR
	VAR_OUTPUT
		DisplayedHwVer 	: HDINT;
	END_VAR
  
  // if it's a sigmatek device
  if VendorID = VM_VENDOR_ID_SIGMATEK then
    // convert the version info to comply with the module print
    DisplayedHwVer := ((OriginalHwVer AND 16#FF000000) SHR 16) OR // high version
                      ((OriginalHwVer AND 16#000F0000) SHR 12) OR // middle version
                       (OriginalHwVer AND 16#0000000F);           // low version
  else
    // use the original
    DisplayedHwVer := OriginalHwVer;
  end_if;

END_FUNCTION
