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

//{{LSL_DEFINES

#define SIZE_PAYLOAD_FRAME_HEADER_DO      16#38  // Const because datasize is in the Payload DOs
#define SIZE_PAYLOAD_IRQ_FRAME_HEADER_DO  16#40  // Const because datasize is in the Payload DOs

#define VM_MAX_POST_INIT_MODULES  1000

#define VM_OBJECT_PATH            16#81000002   // Object Path for Varanmanager Length = 2 (First 2byte), Domain = 0 (3rd byte), Escape Sequence Varan (4th byte) 
//}}LSL_DEFINES

//{{LSL_DECLARATION
#include "..\..\Class\VaranManager\VaranManager.h"
#include "..\..\Class\SafetyManager\SafetyManager.h"
#include "..\..\Source\interfaces\lsl_st_kernel.h"

(*!
<Class
	Name               = "VaranManager"
	Revision           = "3.8"
	GUID               = "{2CF568E9-025C-4CAE-9A6D-3802AC2DB447}"
	RealtimeTask       = "false"
	CyclicTask         = "false"
	BackgroundTask     = "false"
	Sigmatek           = "true"
	OSInterface        = "false"
	HighPriority       = "false"
	Automatic          = "false"
	UpdateMode         = "Prescan"
	IconPath           = ".\Class\VaranManager\VaranManager.ico"
	SharedCommandTable = "true"
	Objectsize         = "(628,120)"
	Comment            = "class to handle a VaranManager component">
	<Channels>
		<Server Name="Act_RtCallTime" GUID="{86C8821F-08C9-4A88-B684-C7584BB5E1BB}" Visualized="true" Initialize="false" WriteProtected="true" Retentive="false" Comment="actual realtime call time [us]"/>
		<Server Name="Act_RtTime" GUID="{210878FF-5568-4CFA-BD03-CBAB5B1C1C27}" Visualized="true" Initialize="false" WriteProtected="true" Retentive="false" Comment="actaual Rt - Time [us]&#13;&#10;measurement starts with call of first realtime-object and stops with last call of RtPostScan-Object"/>
		<Server Name="AsyVaranTime" GUID="{C1D6D199-88EA-4EFF-B4C4-3E5B075159E9}" Visualized="true" Initialize="false" WriteProtected="true" Retentive="false" Comment="Asynchronous time of varan task [ns]"/>
		<Server Name="Control">
		</Server>
		<Server Name="IsoVaranTime" GUID="{A21FDC9A-2A45-4D32-9D9F-16268E6DA2F3}" Visualized="true" Initialize="false" WriteProtected="true" Retentive="false" Comment="Isochronous time of varan task [ns]"/>
		<Server Name="IsoVaranTimeMax" GUID="{D5EB16BB-6777-4076-8550-4754E7E31E6E}" Visualized="true" Initialize="false" WriteProtected="false" Retentive="false" Comment="maximal isochronous time of varan task [ns]"/>
		<Server Name="ManagerOn" GUID="{3D57A698-3E86-4812-9F57-BCFA7179418A}" Visualized="true" Initialize="false" WriteProtected="true" Retentive="false" Comment="0=Manager is off, 1=Manager is running; -1=VARAN not available or OS version too old"/>
		<Server Name="ManagerProtocolVersion" GUID="{0D8AB714-B3BB-4F11-BE12-24EEB39635D1}" Visualized="true" Initialize="false" WriteProtected="true" Retentive="false" Comment="Server shows the VARAN Manager 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="Max_RtCallTime" GUID="{2EC877A1-3026-425A-A66B-F95D4EBC7A94}" Visualized="true" Initialize="false" WriteProtected="false" Retentive="false" Comment="maximal realtime call time [us]"/>
		<Server Name="Max_RtTime" GUID="{A5565D8C-B6E2-4559-BC3D-FDD908F37782}" Visualized="true" Initialize="false" WriteProtected="false" Retentive="false" Comment="maximum of realtime time [us]&#13;&#10;measurement starts with call of first realtime-object and stops with last call of RtPostScan-Object"/>
		<Server Name="Min_RtCallTime" GUID="{EC5C52D8-64B5-4BFE-8297-4B42F3C4FB12}" Visualized="true" Initialize="false" WriteProtected="false" Retentive="false" Comment="minimal call time of realtime methode [us]"/>
		<Server Name="Min_RtTime" GUID="{6C3D2B3C-0907-45F7-9C81-AEFDFF92C841}" Visualized="true" Initialize="false" WriteProtected="false" Retentive="false" Comment="minimal realtime time [us]&#13;&#10;measurement starts with call of first realtime-object and stops with last call of RtPostScan-Object"/>
		<Server Name="Release" GUID="{B0FAF2D9-DA3F-4F0E-93DE-130D37732570}" Visualized="true" Initialize="false" WriteProtected="true" Retentive="false" Comment="FPGA version of manager"/>
		<Server Name="RetryCounter" GUID="{E3E8AAA9-2CC2-4B74-AAFE-F03CBA5D574B}" Visualized="true" Initialize="false" WriteProtected="false" Retentive="false" Comment="global Retry Counter"/>
		<Server Name="State" GUID="{A82B4B9F-AB6D-423E-97B9-D67D4AE9D9BE}" Visualized="true" Initialize="false" WriteProtected="true" Retentive="false" Comment="state of varan manager class"/>
		<Server Name="SuperiorSystemOK" GUID="{B2A1DA64-5A8A-47AC-89AD-B2EAB631558D}" Visualized="true" Initialize="false" WriteProtected="true" Retentive="false" Comment="0 = alive counter of superior system not ok, 1 = superior system works, -1 = varan manager client is not used"/>
		<Client Name="ASCII_BIN1" Required="true" Internal="true"/>
		<Client Name="CoreSelect" Required="false" Internal="false" DefValue="0" Comment="The desired CPU core on which the realtime/cyclic task of the manager runs can be selected here.&#13;&#10;0 ... VaranManager Realtime/Cyclic runs on CPU core 0.&#13;&#10;1 ... VaranManager Realtime/Cyclic runs on CPU core 1. (Only if supported by CPU)"/>
		<Client Name="InterframeGap" Required="true" Internal="false" DefValue="0" Comment="Interframe gap time of the VARAN frames [ns].&#13;&#10;Important! The client value must be set as the initialization value. It must not be connected to a server.&#13;&#10;The internal resolution of this value is [20ns]. Configuration outside the resolution will be rounded up.&#13;&#10;The minimum value is 120ns&#13;&#10;The maximum value is 5220ns&#13;&#10;If a value outside of valid range is configured, the value from the autoexe.lsl will be used."/>
		<Client Name="IsAlsoClient" Required="false" Internal="false" Comment="set if manager is also a client (VMC)"/>
		<Client Name="IsoStartPoint" Required="false" Internal="false" Comment="Time of the isochronous VARAN task as a percentage of the VaranManager time. &#13;&#10;defines the offset between start of realtime-task and start of isochronous VARAN data transfer&#13;&#10;&#13;&#10;Value range between 1 and 99 % (default: 50)&#13;&#10;&#13;&#10;e.g.: IsoStartPoint = 70 and VaranManagerTime = 1000000 -&gt; Isochronous VARAN task gets 300 µs, the hardware classes (real time of the controller) get 700 µs. &#13;&#10;As an initialization value&#13;&#10;"/>
		<Client Name="PayloadFrame" Required="false" Internal="false" DefValue="0" Comment="This client specifies whether the Varanmanager uses payload frames or not.&#13;&#10;&#10;Important! The client value must be set as the initialization value. It must not be connected to a server.&#13;&#10;0... Payload frames are not used unless the multiple VaranManager support for payload is already implemented in the operating system. If this is the case, despite payload frames are used.&#13;&#10;1... Payload frames are used (if supported by the OS)&#13;&#10;2... Payload frames are not used, even if the multiple VaranManager support for payload is already implemented in the operating system.&#13;&#10;Payload frames can only be used if they are supported by the OS Version.&#13;&#10;A warning will be shown in debugger trace if the OS Version doesn&apos;t support it."/>
		<Client Name="PreventManagerError" Required="false" Internal="false" Comment="0 = normal triggering of a manager error &#13;&#10;1 = prevents a manager error "/>
		<Client Name="SafetyAsyMemRead" Required="false" Internal="false" Comment="This Client defines the size of the asynchronous Read Data.&#13;&#10;The data is given in Byte and as the Init Value. The Write Data on the other side( Client: SafetyAsyMemWrite) has to be the same size.&#13;&#10;&#13;&#10;The ideal size of the Data, is seen on the Server &quot;SafetyAsyReadMemUsed&quot;&#13;&#10;&#13;&#10;Additional functions of this Client:&#13;&#10; 0...Transfer not active&#13;&#10;-1...use maximal possible size, to determine the actual usage"/>
		<Client Name="SafetyAsyMemWrite" Required="false" Internal="false" Comment="This Client defines the size of the asynchronous Write Data.&#13;&#10;The data is given in Byte and as the Init Value. The Read Data on the other side( Client: SafetyAsyMemRead) has to be the same size.&#13;&#10;&#13;&#10;The ideal size of the Data, is seen on the Server &quot;SafetyAsyWriteMemUsed&quot;&#13;&#10;&#13;&#10;Additional functions of this Client:&#13;&#10; 0...Transfer not active&#13;&#10;-1...use maximal possible size, to determine the actual usage"/>
		<Client Name="SafetyIsoMemRead" Required="false" Internal="false" Comment="This Client defines the size of the isochronous Read Data.&#13;&#10;The data is given in Byte and as the Init Value. The Write Data on the other side (Client: SafetyIsoMemWrite) has to be the same size.&#13;&#10;&#13;&#10;The ideal size of the Data, is seen on the Server &quot;SafetyIsoReadMemUsed&quot;&#13;&#10;&#13;&#10;Additional functions of this Client:&#13;&#10; 0...Transfer not active&#13;&#10;-1...use maximal possible size, to determine the actual usage&#13;&#10; &#13;&#10;"/>
		<Client Name="SafetyIsoMemWrite" Required="false" Internal="false" Comment="This Client defines the size of the isochronous Write Data.&#13;&#10;The data is given in Byte and as the Init Value. The Read Data on the other side( Client: SafetyIsoMemRead) has to be the same size.&#13;&#10;&#13;&#10;The ideal size of the Data, is seen on the Server &quot;SafetyIsoWriteMemUsed&quot;&#13;&#10;&#13;&#10;Additional functions of this Client:&#13;&#10; 0...Transfer not active&#13;&#10;-1...use maximal possible size, to determine the actual usage"/>
		<Client Name="SuperiorSystemTime" Required="false" Internal="false" Comment="varan time of superior system in ns, has to be a multiple of VaranManagerTime"/>
		<Client Name="To_HwControl" Required="true" Internal="false" Comment="connect to server &quot;Control&quot; of HwControl class"/>
		<Client Name="To_Multitask" Required="false" Internal="false" Comment="is connected automatically to os class"/>
		<Client Name="VaranManagerNr" Required="false" Internal="false" Comment="The VaranManager number is set here (if there are several VaranManagers in the system).&#13;&#10;Default value: 0        &#13;&#10;As an initialization value&#13;&#10;&#13;&#10;e.g. &#13;&#10;0 .. First VaranManager&#13;&#10;1 .. Second VaranManager"/>
		<Client Name="VaranManagerTime" Required="false" Internal="false" DefValue="1000000" Comment="The real-time of the VaranManager hardware classes and the VARAN Isochronous DataObjectList is set here.&#13;&#10;Unit: ns&#13;&#10;Default value: 1000000 (=1ms)        &#13;&#10;As an initialization value"/>
	</Channels>
	<Dependencies>
		<Files>
			<File Path=".\Source\interfaces\lsl_st_pci.h" Include="false"/>
			<File Path=".\Class\VaranManager\VaranManager.h" Include="true"/>
			<File Path=".\Class\SafetyManager\SafetyManager.h" Include="true"/>
			<File Path=".\Source\interfaces\lsl_st_kernel.h" Include="true"/>
		</Files>
	</Dependencies>
	<RevDoku>
		<Owner Company="Sigmatek" Author="renste"/>
		<Dokumentation Revision="3.8" Date="13.12.2024" Author="LanSte" Company="Sigmatek" Description="Added support for Get Required Wait Time"/>
		<Dokumentation Revision="3.7" Date="16.06.2023" Author="EisMic" Company="Sigmatek" Description="Added functionality to allow modules to give time to the OS during the post init phase (e.g. for safety SDO handling).&#13;&#10;Fixed the debug VARAN memory calculation when the flag VARAN_DOL_NOT_INSERT_DO_INTO_DOL is set."/>
		<Dokumentation Revision="3.6" Date="18.04.2023" Author="EisMic" Company="Sigmatek" Description="Fixed an access exception when more than 1 Flexhub object were used on CPUs with no VaranInterface available."/>
		<Dokumentation Revision="3.5" Date="15.06.2022" Author="RamAnd" Company="Sigmatek" Description="Added an interface for the VARAN Client classes to get their hardware version."/>
		<Dokumentation Revision="3.4" Date="27.11.2020" Author="FurDom" Company="Sigmatek" Description="Forwarded the CMD_HWC_REQ_PLLNS_REGULATION NewInst cmd to the businterface class."/>
		<Dokumentation Revision="3.3" Date="09.12.2019" Author="LanSte" Company="Sigmatek" Description="Added Server ProtocolVersion. InterframeGap is included in the resource calculation.&#13;&#10;Added Client InterframeGap."/>
		<Dokumentation Revision="3.2" Date="25.01.2019" Author="EisMic" Company="Sigmatek" Description="Added functionality to give the OS the information which VaranManager runs on which processor core"/>
		<Dokumentation Revision="3.1" Date="29.05.2018" Author="EisMic" Company="Sigmatek" Description="Fixed an error that the VaranManager did not work on CPUs with a maintimer with 2ms or higher."/>
		<Dokumentation Revision="3.0" Date="16.03.2018" Author="EisMic" Company="Sigmatek" Description="Added support for 2nd VaranManager.&#13;&#10;Corrected an error that the CyWork is executed if ManagerOn &lt;&gt; 1.&#13;&#10;Removed VARANMANAGER_PROFILER define from source code.&#13;&#10;Removed client IRQTaskTime."/>
		<Dokumentation Revision="2.36" Date="10.01.2018" Author="EisMic&#13;&#10;&#13;&#10;&#13;&#10;ZoePat" Company="Sigmatek" Description="Cywork will no longer be called if there are no VaranClient objects connected to the manager.&#13;&#10;The hardware will now be turned off in the method SetVaranDOError.&#13;&#10;Attached header files no longer point to the installation directory of LASAL but instead now point to the the source/interfaces folder.&#13;&#10;Fixed an error that when starting a project the time for the hardware on the Varan, i. e. after IsoStartPoint is too short, the status is not TimeSliceError but TimeSliceErrorIRQ."/>
		<Dokumentation Revision="2.35" Date="18.01.2018" Author="EisMic" Company="Sigmatek" Description="Corrected an error that all connected clients were called at the end of the post init phase, instead of just the ones which should be called."/>
		<Dokumentation Revision="2.34" 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.33" Date="29.08.2017" Author="RamAnd" Company="Sigmatek" Description="The VaranManager can now tell the HwControl if it doesn&apos;t have any clients connected. In this case the HwControl is in charge of triggering the internal watchdog."/>
		<Dokumentation Revision="2.32" Date="03.07.2017" Author="ZoePat" Company="Sigmatek" Description="The VaranManager is no longer disabled, if IsAlsoClient is enabled."/>
		<Dokumentation Revision="2.31" Date="11.04.2017" Author="RamAnd" Company="Sigmatek" Description="Required error at missing modules is now also provided with payload option active."/>
		<Dokumentation Revision="2.30" Date="31.03.2017" Author="EisMic" Company="Sigmatek" Description="Corrected error that required data objects were not started sometimes if payload was used.&#13;&#10;Corrected error with VaranMux if payload was used."/>
		<Dokumentation Revision="2.29" Date="14.02.2017" Author="ZoePat" Company="Sigmatek" Description="SdiasModules can now request to increase the PostInit timeout."/>
		<Dokumentation Revision="2.28" Date="07.12.2016" Author="ZoePat" Company="Sigmatek" Description="VaranManager is now disabled if there are no VaranClient objects connected. Can be enabled again by setting bEnableManagerWithNoModules=TRUE in first init run."/>
		<Dokumentation Revision="2.27" Date="24.02.2016" Author="EisMic" Company="Sigmatek" Description="CAN behind VARAN works now on Edge2 CPUs."/>
		<Dokumentation Revision="2.26" Date="28.09.2015" Author="ZoePat" Company="Sigmatek" Description="New function to set a VaranManagerError."/>
		<Dokumentation Revision="2.25" Date="29.06.2015" Author="EisMic" Company="Sigmatek" Description="- Prevented access exception if a varanmanagertime greater 32ms was set at the client.&#13;&#10;- CyWork, RtWork, UpdateRTPostScan: Free Mutex if there are returns in the methods.&#13;&#10;- Electronic Typelabel: Supported more information at varanmanager module (eg. Vendorname, DeviceName, SerialNo, LicenseNo, OrderingNo,...)"/>
		<Dokumentation Revision="2.24" Date="21.05.2015" Author="EisMic" Company="Sigmatek" Description="Corrected handling of SyncFrameCounter in RtWork which could lead to a problem at isochrone CAN behind varan (e.g. CIV 521)."/>
		<Dokumentation Revision="2.23" Date="12.05.2015" Author="EisMic" Company="Sigmatek" Description="Added support for calculating resources for graphical hardware editor."/>
		<Dokumentation Revision="2.22" Date="14.05.2015" Author="RamAnd" Company="Sigmatek" Description="Added another step in initialisation to prevent watchdog error."/>
		<Dokumentation Revision="2.21" Date="15.04.2015" Author="RamAnd" Company="Sigmatek" Description="Added support for VaranMux."/>
		<Dokumentation Revision="2.20" Date="23.03.2015" Author="RamAnd" Company="Sigmatek" Description="Prevent crash if the user calls public methods and the VARAN interface is not available (e.g. on LARS)"/>
		<Dokumentation Revision="2.19" Date="24.01.2015" Author="RamAnd" Company="Sigmatek" Description="If a post init object is finished (completed or error) than it&apos;s still called during the post init phase to allow triggering of watchdogs.&#13;&#10;Furthermore this module is removed from the list of modules to wait for (creating DOs and Move-DOs)."/>
		<Dokumentation Revision="2.18" Date="25.11.2014" Author="LanSte" Company="Sigmatek" Description="Corrected IsoVaranTime calcualtion with MultivaranInterface.&#13;&#10;Corrected Trace Message when an unknown NewInst command was recieved."/>
		<Dokumentation Revision="2.17" Date="11.08.2014" Author="EisMic" Company="Sigmatek" Description="Deactivated Varan Error when running a programm in LARS."/>
		<Dokumentation Revision="2.16" Date="01.08.2014" Author="RamAnd" Company="Sigmatek" Description="Asynchron VARAN DOs may not have been started on ARM CPUs, because the image of the DOs wasn&apos;t copied correctly to the VM DPRAM."/>
		<Dokumentation Revision="2.15" Date="30.07.2014" Author="RamAnd" Company="Sigmatek" Description="Added flag for every post init object, so it is only called if it hasn&apos;t finished post init work yet."/>
		<Dokumentation Revision="2.14" Date="24.06.2014" Author="LanSte" Company="Sigmatek" Description="Added support for reading hardware diagnosis."/>
		<Dokumentation Revision="2.13" Date="19.05.2014" Author="LanSte" Company="Sigmatek" Description="Added support for INTERFACE_MULTIVARANMANAGER dol timing Methods. Removed PayloadMEM clients as they are not supported."/>
		<Dokumentation Revision="2.12" Date="15.04.2014" Author="RamAnd" Company="Sigmatek" Description="Changed initialisation:&#13;&#10; - Asynchron work is now independent of isochronous initialisation state machine&#13;&#10; - Removed thread for sorting DOs. This is now done in a seperate init step called by the HwControl"/>
		<Dokumentation Revision="2.11" Date="11.03.2014" Author="EisMic" Company="Sigmatek" Description="Added Server IsoVaranTimeMax"/>
		<Dokumentation Revision="2.10" Date="12.02.2014" Author="RamAnd&#13;&#10;PieSte&#13;&#10;ZoePat" Company="Sigmatek" Description="Thread for sorting DOs is now created in init to prevent errors in task handling on Salamander systems.&#13;&#10;Changed min/max value for IsoStartPoint to get more flexibilty.&#13;&#10;Corrected AccessException if no VaranInterface is avaliable."/>
		<Dokumentation Revision="2.0" Date="22.01.2014" Author="RamAnd&#13;&#10;LanSte&#13;&#10;&#13;&#10;PieSte&#13;&#10;LanSte&#13;&#10;LanSte" Company="Sigmatek" Description="Initialisation of VaranManager and SdiasManager has been reworked for cases where multiple Safety cpus are connected via VI021.&#13;&#10;Corrected Type Spelling.&#13;&#10;Updated Total DOCounter and DPRAM_Used for MultipleRDWRDOs.&#13;&#10;Fixed free FileDate before use.&#13;&#10;Added support for user IOImage with ARM CPUs.&#13;&#10;Ended Postinit Phase if Varanmanger is set off."/>
		<Dokumentation Revision="1.90" Date="04.12.2013" Author="LanSte&#13;&#10;RamAnd&#13;&#10;FucHer" Company="Sigmatek" Description="Added NewInst Method to allow force endeing PostInit on timeout.&#13;&#10;Fixed call to end VM own PostInit Phase.&#13;&#10;Added postinit call to prevent user classes being called before the Varanmanager has finished its config.&#13;&#10;Fixed case dureing startup where the ISO DOL was started twice in one cycle.&#13;&#10;The manager has added himself to the internal client list, which lead to writing 68 to the control server if a required error occured.&#13;&#10;Fixed crash if no VARAN interface was available, but objects of VARAN module classes were placed.&#13;&#10;Added payload support&#13;&#10;GetVaranPosition(): keyword AWL removed.  Mutex replaces CLI, STI."/>
		<Dokumentation Revision="1.80" Date="01.08.2013" Author="RamAnd" Company="Sigmatek" Description="Fixed crash if no VARAN interface was available, which was caused by the last change (removed checks for ManagerOn)"/>
		<Dokumentation Revision="1.70" Date="18.07.2013" Author="RamAnd&#13;&#10;ZoePat&#13;&#10;&#13;&#10;RamAnd&#13;&#10;RamAnd" Company="Sigmatek" Description="Last Init now waits until the SDIAS modules are finished with initialisation (like it is done for intelligent master)&#13;&#10;Don&apos;t return negative retcode at functions like GetNodeInfo() if manager is off.&#13;&#10;If the Manager is turned off the state _ModuleFoundButManagerIsOff is set to modules that was _ClassOk before.&#13;&#10;Check parameters of GetNodeInfo before calling the OS interface. Could have lead to a crash.&#13;&#10;Added the possibility to measure the cyclic time of every VARAN module just by defining VARAN_TIME_MEASUREMENT_SINGLE_OBJECTS in VaranManager_Base.h"/>
		<Dokumentation Revision="1.60" Date="07.03.2013" Author="RamAnd" Company="Sigmatek" Description="Changed range of the safety NewInst commands. Range for HW-Classes: 0x8000-0x8FFF; Range for Safety HW-Classes: 0x8100-0x81FF"/>
		<Dokumentation Revision="1.50" Date="22.01.2013" Author="RamAnd" Company="Sigmatek" Description="Changed types for safety data handling."/>
		<Dokumentation Revision="1.45" Date="27.09.2012" Author="SeiJan" Company="Sigmatek" Description="If no VARAN interface is available in LARS and a module is set to required, set the right error if the LARS version supports it."/>
		<Dokumentation Revision="1.44" Date="23.12.2011" Author="RamAnd" Company="Sigmatek" Description="Added support for the SafetyManager"/>
		<Dokumentation Revision="1.43" Date="12.12.2011" Author="RamAnd" Company="Sigmatek" Description="Methode UpdateRtPostScan is now virtual to allow overloading."/>
		<Dokumentation Revision="1.42" Date="29.02.2012" Author="SvePau" Company="Sigmatek" Description="Changed Asy data handling to Client DPRAM (for VMC) via PCI. Read and Write on first Asy data address is now performed last."/>
		<Dokumentation Revision="1.41" Date="30.01.2012" Author="ZoePat" Company="Sigmatek" Description="If a VARAN-Module is required but no VARAN interface is avaliable, instead of resetting the PLC on OS versions 01.02.150 or higer a required error is triggered and a message is shown in CLI."/>
		<Dokumentation Revision="1.40" Date="09.11.2011" Author="RamAnd" Company="Sigmatek" Description="After sorting the DOs it was not possible that adding DOs during runtime (Dias Drive) causes some DOs to stop working."/>
		<Dokumentation Revision="1.39" Date="03.11.2011" Author="RamAnd" Company="Sigmatek" Description="Sorting of VARAN-Commands is now done in Cyclic priority instead of Realtime priority because it could take a few hundred µs depending on the number of VARAN accesses in the project which would lead to a TimeSliceErrorIRQ or Runtime Error."/>
		<Dokumentation Revision="1.38" Date="27.06.2011" Author="RamAnd" Company="Sigmatek" Description="Support of sorting VARAN commands by priority added (needed for communication between safety-modules)."/>
		<Dokumentation Revision="1.37" Date="07.09.2011" Author="RamAnd" Company="Sigmatek" Description="Corrected check of filenhandle after trying to open a file."/>
		<Dokumentation Revision="1.36" Date="11.08.2011" Author="PibPet" Company="Sigmatek" Description="To Minimize the Jitter on the VARAN-Bus, Manager need 2 Commands before it&apos;s free again (Prefetch + actual Command) SA:19275"/>
		<Dokumentation Revision="1.35" Date="20.06.2011" Author="RamAnd" Company="Sigmatek" Description="Reset of time measurement is now done later in initialisation phase to avoid invalid measured values."/>
		<Dokumentation Revision="1.34" Date="25.05.2011" Author="RamAnd" Company="Sigmatek" Description="PostScan-Calls in Init-Phase are now done in HwControl instead of VaranManager."/>
		<Dokumentation Revision="1.33" Date="12.01.2011" Author="BleErn" Company="Sigmatek" Description="Class revision is now fetched from class-properties for logfile."/>
		<Dokumentation Revision="1.32" Date="11.01.2011" Author="RamAnd" Company="Sigmatek" Description="Corrected calculation of asynchronous VARAN load."/>
		<Dokumentation Revision="1.31" Date="17.11.2010" Author="WocPet" Company="Sigmatek" Description="Manager error triggered if a DIAS Error occures on a required modul"/>
		<Dokumentation Revision="1.30" Date="14.10.2010" Author="RamAnd" Company="Sigmatek" Description="Added method AddMovDO for the move command in the VM.&#13;&#10;The time shown on the servers IsoVaranTime and AsyVaranTime now also contain the time for commands like direct access and the new added move command."/>
		<Dokumentation Revision="1.29" Date="13.08.2010" Author="BleErn" Company="Sigmatek" Description="VaranManager crashed if the master was shut-down when the master was not started (eg. _NoVaranInterface on LARS)&#13;&#10;Read-Method of clients is now always called before using a value.&#13;&#10;Trace-Messages now only appear once&#13;&#10;Act_RtTime showed incorrect values if no hardware was connected&#13;&#10;Comment of Server ManagerOn was not complete&#13;&#10;Server SuperiorSystemOK now shows if VaranManagerClient functionality is not used&#13;&#10;Time-Measurement of VaranManager did not stop if Manager was set off but rest of system was still alive"/>
		<Dokumentation Revision="1.28" Date="22.07.2010" Author="WocPet" Company="Sigmatek" Description="Function to display CDIAS/DIAS required error"/>
		<Dokumentation Revision="1.27" Date="19.07.2010" Author="RamAnd" Company="Sigmatek" Description="Added new method GetNsTimeBPLLTicks for easier internal time measurements.&#13;&#10;Added new methods AddDAClientRdData and SendDAClientWrData to access new direct access alternating buffer on VMC hardware."/>
		<Dokumentation Revision="1.26" Date="30.06.2010" Author="RamAnd" Company="Sigmatek" Description="Corrected RtPostScan modification"/>
		<Dokumentation Revision="1.25" Date="13.04.2010" Author="RamAnd" Company="Sigmatek" Description="Used memory of VARAN Manager DPRAM is now shown (counted) in the private variable DPRAM_Used and the number of data objects is stored in the private variable DOCounter"/>
		<Dokumentation Revision="1.24" Date="06.04.2010" Author="RamAnd" Company="Sigmatek" Description="Added new method &quot;TopologyChangeLogin&quot; for login of FlexHub objects"/>
		<Dokumentation Revision="1.23" Date="23.02.2010" Author="BleErn" Company="Sigmatek" Description="New method &quot;UpdateRtPostScan&quot;.&#13;&#10;IRQ Task could cause an error if there are no data objects defined.&#13;&#10;Watchdog on VARAN Clients are now triggered during the synchronisation of VMC."/>
		<Dokumentation Revision="1.22" Date="16.11.2009" Author="RamAnd" Company="Sigmatek" Description="Manager could have shown a _SPIError, even if everything was OK."/>
		<Dokumentation Revision="1.21" Date="20.10.2009" Author="RamAnd" Company="Sigmatek" Description="Manager Switch Off in error case has been corrected. Isochronous Task is stopped now."/>
		<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 using a VaranManager without VaranInterface and one client is required, application gets into reset&#13;&#10;Syncs are done before HW-Classes start&#13;&#10;Improved description of server/clients/methods"/>
		<Dokumentation Revision="1.18" Date="16.07.2009" Author="ObeChr" Company="Sigmatek" Description="Now Time-Measurement can be deactivated with #define VARAN_TIME_MEASUREMENT_DEACTIVATE&#13;&#10;Added Methods and Change in RT-Work for VaranRtPostscan"/>
		<Dokumentation Revision="1.17" Date="16.04.2009" Author="RamAnd" Company="Sigmatek" Description="Added new method GetSerialNo&#13;&#10;Suppressed VMC error message, if VMC is not used"/>
		<Dokumentation Revision="1.16" Date="22.01.2009" Author="RamAnd" Company="Sigmatek" Description="Improved VMC synchronity check.&#13;&#10;New Method FrameCounterChanged (only to be called by HW_Control)&#13;&#10;New Method GetDocumentation to fetch .pdf-file from Varan-Client"/>
		<Dokumentation Revision="1.15" Date="01.12.2008" Author="RamAnd" Company="Sigmatek" Description="Added VMC communication (ISO/ASY alternating buffer) and synchronisation"/>
		<Dokumentation Revision="1.14" Date="21.07.2008" Author="renste" Company="Sigmatek" Description="DB901: insert IRQ Task function"/>
	</RevDoku>
	<Network Name="VaranManager">
		<!-- List of Components in this network -->
		<Components>
			<Object
				Name       = "_base"
				GUID       = "{D32EA40A-247A-4A46-B103-304F62B74DD1}"
				Class      = "VaranManager_Base"
				Position   = "(420,210)"
				Visualized = "true">
				<Channels>
					<Server Name="Control"/>
					<Client Name="To_FileSys"/>
					<Client Name="To_OSKernel"/>
					<Client Name="To_StdLib"/>
				</Channels>
			</Object>
			<Object
				Name       = "ASCII_BIN1"
				GUID       = "{8C265742-AE37-41F3-9FFC-79C0C2DE41AA}"
				Class      = "ASCII_BIN"
				Position   = "(420,510)"
				Visualized = "true"
				Remotely   = "true">
				<Channels>
					<Server Name="Obj_channel"/>
				</Channels>
			</Object>
		</Components>
		<Comments>
		</Comments>
		<!-- List of Connections in this network -->
		<Connections>
			<Connection Source="this.Control" Destination="_base.Control" Vertices="(986,210),(720,300),"/>
			<Connection Source="this.ASCII_BIN1" Destination="ASCII_BIN1.Obj_channel"/>
		</Connections>
		<!-- Headerfiles -->
		<Options>
		</Options>
	</Network>
</Class>
*)
#pragma using VaranManager_Base

VaranManager : CLASS
: VaranManager_Base
	TYPE
	  p_VaranBase : ^Varan_Base;
	  t_s_OneHandle : STRUCT
	    p_This : p_VaranBase;
	    TimeMeasuring : t_s_SingleObjTimeMeasurement;
	  END_STRUCT;
	  t_a_Handles : ARRAY [0..199] OF t_s_OneHandle;
#pragma pack(push, 1)
	  t_AlternatingBuffer : STRUCT
	    us_SwitchBuffer : USINT;
	    us_Status : BSINT
	    [
	      1 Pll_Locked,
	    ];
	    ui_AliveCounter : UINT;
	    a_Data : ARRAY [0..254] OF UDINT;
	  END_STRUCT;
#pragma pack(pop)
#pragma pack(push, 1)
	  t_ASYAlternatingBuffer : STRUCT
	    a_data : ARRAY [0..255] OF DINT;
	  END_STRUCT;
#pragma pack(pop)
#pragma pack(push, 1)
	  t_DaBufferHeader : STRUCT
	    MsgCounter : USINT;
	    aReserved : ARRAY [0..2] OF USINT;
	  END_STRUCT;
#pragma pack(pop)
#pragma pack(push, 1)
	  t_DataRead : STRUCT
	    Varan1_SysPeriodTimeMeas : UDINT;
	    Varan2_SysPeriodTimeMeas : UDINT;
	    DeltaPhaseMeasured : INT;
	    Varan1_SyncFrameCnt : USINT;
	    Varan2_SyncFrameCnt : USINT;
	  END_STRUCT;
#pragma pack(pop)
#pragma pack(push, 1)
	  t_DO_RD : STRUCT
	    p_Handle : ^LSL_VARANFRAME;
	    p_DOSettings : ^t_VaranDOSettingsRd;
	    p_DataRead : ^t_DataRead;
	    us_OldRetryCounter : DINT;
	  END_STRUCT;
#pragma pack(pop)
#pragma pack(push, 1)
	  t_DOCounter : STRUCT
	    ISO_Rd : UDINT;
	    ISO_Wr : UDINT;
	    ISO_RdWr : UDINT;
	    ISO_Mov : DINT;
	    ASY_Rd : UDINT;
	    ASY_Wr : UDINT;
	    ASY_RdWr : UDINT;
	    ASY_Mov : DINT;
	    DA_Rd : UDINT;
	    DA_Wr : UDINT;
	    DA_RdWr : UDINT;
	    Admin_Rd : UDINT;
	    Admin_Wr : UDINT;
	    Admin_RdWr : UDINT;
	    IRQ_Rd : UDINT;
	    IRQ_Wr : UDINT;
	    IRQ_RdWr : UDINT;
	    Total : UDINT;
	  END_STRUCT;
#pragma pack(pop)
#pragma pack(push, 1)
	  t_DOCounterPayload : STRUCT
	    ISO_Rd : UDINT;
	    ISO_Wr : UDINT;
	    ISO_RdWr : UDINT;
	    ISO_Mov : DINT;
	    ASY_Rd : UDINT;
	    ASY_Wr : UDINT;
	    ASY_RdWr : UDINT;
	    ASY_Mov : DINT;
	    DA_Rd : UDINT;
	    DA_Wr : UDINT;
	    DA_RdWr : UDINT;
	    Admin_Rd : UDINT;
	    Admin_Wr : UDINT;
	    Admin_RdWr : UDINT;
	    IRQ_Rd : UDINT;
	    IRQ_Wr : UDINT;
	    IRQ_RdWr : UDINT;
	    Total : UDINT;
	    Payload_Header : UDINT;
	    Payload_Read : UDINT;
	    Payload_Write : UDINT;
	  END_STRUCT;
#pragma pack(pop)
	  t_e_SPISSW :
	  (
	    _GetVendorName,
	    _GetSerialNo,
	    _GetDeviceName,
	    _GetOrderingNo,
	    _GetLicenseNoHWVersion,
	    _SPIDataReady
	  )$UDINT;
#pragma pack(push, 1)
	  t_VMC_Header : STRUCT
	    us_SwitchBuffer : USINT;
	    us_Status : BSINT
	    [
	      1 Pll_Locked,
	    ];
	    ui_AliveCounter : UINT;
	  END_STRUCT;
#pragma pack(pop)
#pragma pack(push, 1)
	  t_VMC_Safety_Header : STRUCT
	    WriteCnt : UINT;
	    StateInfo : BSINT
	    [
	      1 TimeSyncToken,
	      2 TDOInside,
	      3 InterfaceFramesPossible,
	      5 Initialize,
	      7 TDOAck,
	      8 TokenAck,
	    ];
	    Length : USINT;
	  END_STRUCT;
#pragma pack(pop)
#pragma pack(push, 1)
	  t_Iso_data : STRUCT
	    VMC_Header : t_VMC_Header;
	    Safety_Header : t_VMC_Safety_Header;
	    TDO : ARRAY [0..23] OF USINT;
	    PDO : ARRAY [0..991] OF USINT;
	  END_STRUCT;
#pragma pack(pop)
#pragma pack(push, 1)
	  t_PrioHandleList : STRUCT
	    pHandle : ^LSL_VARANFRAME;
	    pNext : ^t_PrioHandleList;
	  END_STRUCT;
#pragma pack(pop)
#pragma pack(push, 1)
	  t_PrioListList : STRUCT
	    Prio : HDINT;
	    pList : ^t_PrioHandleList;
	    pNext : ^t_PrioListList;
	  END_STRUCT;
#pragma pack(pop)
	  t_RtLog : BDINT
	  [
	    1 WatchdogTriggerFailed,
	    2 TimeSliceError,
	  ];
	  t_RtSSW :
	  (
	    _Nothing,
	    _Wait4Sync:=10,
	    _InitVaranManager:=20,
	    _Wait4RtWork:=25,
	    _RtWork:=30
	  )$UDINT;
	  t_s_DirectDO : STRUCT
	    ud_DOHandle : ^LSL_VARANFRAME;
	    p_ud_DOWrite : ^UDINT;
	  END_STRUCT;
#pragma pack(push, 1)
	  t_s_FlexHub : STRUCT
	    pServer : ^DINT;
	    pNext : ^t_s_FlexHub;
	  END_STRUCT;
#pragma pack(pop)
	  t_s_Handles : STRUCT
	    ud_NrOfHandles : UDINT;
	    ud_MaxHandles : UDINT;
	    b_ExecuteDOL : BOOL;
	    p_HandleList : ^t_a_Handles;
	  END_STRUCT;
#pragma pack(push, 1)
	  t_s_ModuleList : STRUCT
	    ud_NrOfModules : UDINT;
	    ud_MaxModules : UDINT;
	    p_ModuleList : ^p_VaranBase;
	    p_PositionList : ^pVoid;
	  END_STRUCT;
#pragma pack(pop)
#pragma pack(push, 1)
	  t_s_PostInitList : STRUCT
	    p_This : p_VaranBase;
	    Settings : BSINT
	    [
	      1 Wait4DOCreation,
	      2 Wait4MoveDOCreation,
	      3 Wait4SyncSend,
	    ];
	    b_CallMe : BOOL;
	  END_STRUCT;
#pragma pack(pop)
#pragma pack(push, 1)
	  t_s_PostScanElement : STRUCT
	    No : UDINT;
	    Thisp : DINT;
	  END_STRUCT;
#pragma pack(pop)
#pragma pack(push, 1)
	  t_s_SPIIDListContent : STRUCT
	    VendorID : DINT;
	    DeviceID : DINT;
	    LicenseNo : UDINT;
	    HwVersion : HDINT;
	  END_STRUCT;
#pragma pack(pop)
#pragma pack(push, 1)
	  t_s_SPIListHeader : STRUCT
	    CheckSum : UDINT;
	    ListVersion : UDINT;
	    ListLength : UDINT;
	  END_STRUCT;
#pragma pack(pop)
	  t_s_VaranErrors : STRUCT
	    ud_ErrorCounter : UDINT;
	    f_AddRdDO : t_e_VaranErrors;
	    f_AddWrDO : t_e_VaranErrors;
	    f_AddRdWrDO : t_e_VaranErrors;
	    f_ExecuteDOL : t_e_VaranErrors;
	    f_ClearDOL : t_e_VaranErrors;
	    f_GetNodeInfo : t_e_VaranErrors;
	    f_TriggerWd : t_e_VaranErrors;
	    f_RdDO : t_e_VaranErrors;
	    f_WrDO : t_e_VaranErrors;
	    f_SetObjectCallback : t_e_VaranErrors;
	    f_SetVaranError : t_e_VaranErrors;
	    f_AddFoPaReq : t_e_VaranErrors;
	  END_STRUCT;
	  t_s_VaranSettings : STRUCT
	    us_InitCounter : USINT;
	    b_TimeMeasureActive : BOOL;
	    us_OldRetryCounter : USINT;
	    us_NoCyclicUpdateCnt : USINT;
	    ud_WatchdogTimemark : UDINT;
	    sd_LastError : DINT;
	    b_LogError : BOOL;
	    us_Wait4Sync : USINT;
	    us_FilterNumber : USINT;
	    us_Wait4RtWork : USINT;
	  END_STRUCT;
#pragma pack(push, 1)
	  t_SyncData : STRUCT
	    us_FrameCounter : USINT;
	    ui_Periode : UINT;
	    us_Periode : USINT;
	  END_STRUCT;
#pragma pack(pop)
#pragma pack(push, 1)
	  t_TimeMeasurement : STRUCT
	    ud_AverageCounter : UDINT;
	    ud_AverageSum : UDINT;
	    ud_AverageTime : UDINT;
	    ud_ActualTime : UDINT;
	  END_STRUCT;
#pragma pack(pop)
#pragma pack(push, 1)
	  t_VM_ControlData : STRUCT
	    ud_IsoStartPoint : UDINT;
	    ud_MaxTimeCmdExecution : UDINT;
	  END_STRUCT;
#pragma pack(pop)
#pragma pack(push, 1)
	  t_VMC_Safety_Header_TDO : STRUCT
	    SafetyHeader : t_VMC_Safety_Header;
	    TDO : ARRAY [0..23] OF USINT;
	  END_STRUCT;
#pragma pack(pop)
	  t_VMFunctions : STRUCT
	    p_This : pVoid;
	    ud_VaranTime : UDINT;
	    b_IsAlsoClient : BOOL;
	    ud_SuperiorTime : UDINT;
	    b_HWClassSynchron : BOOL;
	    b_OverrideFrameCheck : BOOL;
	    SafetyManagerThisPointer : ^pVirtualBase;
	    Reserved1 : DINT;
	    Reserved2 : DINT;
	  END_STRUCT;
	END_TYPE
  //Servers:
	State 	: SvrCh_t_e_VaranErrors;
	ManagerOn 	: SvrCh_DINT;
	Release 	: SvrCh_HDINT;
	RetryCounter 	: SvrCh_DINT;
	IsoVaranTime 	: SvrCh_DINT;
	IsoVaranTimeMax 	: SvrCh_UDINT;
	AsyVaranTime 	: SvrCh_DINT;
	Act_RtTime 	: SvrCh_UDINT;
	Min_RtTime 	: SvrCh_UDINT;
	Max_RtTime 	: SvrCh_UDINT;
	Act_RtCallTime 	: SvrCh_UDINT;
	Min_RtCallTime 	: SvrCh_UDINT;
	Max_RtCallTime 	: SvrCh_UDINT;
	SuperiorSystemOK 	: SvrCh_DINT;
	ManagerProtocolVersion 	: SvrCh_HDINT;
  //Clients:
	To_HwControl 	: CltChCmd_HwControl;
	VaranManagerTime 	: CltCh_UDINT;
	VaranManagerNr 	: CltCh_UDINT;
	PreventManagerError 	: CltCh_DINT;
	IsoStartPoint 	: CltCh_UDINT;
	IsAlsoClient 	: CltCh_DINT;
	SuperiorSystemTime 	: CltCh_UDINT;
	To_Multitask 	: CltChCmd__MultiTask;
	SafetyIsoMemRead 	: CltCh_DINT;
	SafetyIsoMemWrite 	: CltCh_DINT;
	SafetyAsyMemRead 	: CltCh_DINT;
	SafetyAsyMemWrite 	: CltCh_DINT;
	PayloadFrame 	: CltCh_DINT;
	CoreSelect 	: CltCh_UDINT;
	InterframeGap 	: CltCh_UDINT;
	ASCII_BIN1 	: CltChCmd_ASCII_BIN;
  //Variables:
		ui_AliveCounterOld 	: UINT;
		p_ManagerPll 	: ^LSL_VARANPLL;
		p_ManagerStructure 	: ^LSL_CONTROLBLOCK;
		s_ManagerControlData 	: t_VM_ControlData;			//! <Variable Comment="Buffer for Certain elements of the Varanmanager Controlblock. The data is saved in here so that it needn&apos;t be read back again.&#13;&#10;Pll sync out info data. There is no direct access to this data with payload support." Name="s_ManagerControlData"/>
		p_SyncOut 	: ^LSL_VARANPLLSYNCOUT;
		s_SyncOut 	: LSL_VARANPLLSYNCOUT;			//! <Variable Comment="Buffer for Pll sync out info data. There is no direct access to this data with payload support." Name="s_SyncOut"/>
		p_SyncAndWdDO 	: ^LSL_VARANFRAME;
		p_NodeInfo 	: ^LSL_VARANNODEINFO;
		s_NodeInfo 	: LSL_VARANNODEINFO;			//! <Variable Comment="Buffer for node info data. There is no direct access to this data with payload support." Name="s_NodeInfo"/>
		p_SyncData 	: ^t_SyncData;
		s_VaranManagerSettings 	: t_s_VaranSettings;			//! <Variable Comment="structure for different varan settings" Name="s_VaranManagerSettings"/>
		s_ErrorVaranManager 	: t_s_VaranErrors;
		s_RtHandles 	: t_s_Handles;			//! <Variable Comment="structure to save Handles and thisp for realtime update methodes" Name="s_RtHandles"/>
		s_RtPostScanHandles 	: t_s_Handles;
		s_CyHandles 	: t_s_Handles;			//! <Variable Comment="structure to save Handles and thisp for cyclic update methodes" Name="s_CyHandles"/>
		s_VaranTimes 	: t_VaranManagerTimes;			//! <Variable Comment="structure for varan time measurement" Name="s_VaranTimes"/>
		s_DirectAccessDO 	: t_s_DirectDO;
		s_VMFunctions 	: t_VMFunctions;			//! <Variable Comment="structure for HwControl class" Name="s_VMFunctions"/>
		pVaran 	: ^LSL_VARAN;			//! <Variable Comment="pointer to varan interface" Name="pVaran"/>
		ud_SystemPeriod 	: UDINT;
		p_SemaHandle 	: ^void;			//! <Variable Comment="semaphore handle for rd or wr do" Name="p_SemaHandle"/>
		us_RtStep 	: t_RtSSW;
		b_RtDebug 	: BOOL;
		b_DisableDevice 	: BOOL;
		p_DisablePath 	: ^USINT;
		p_ManagerClientSpace 	: ^DINT;
		ISORdVaranPackages 	: USINT;
		ISOWrVaranPackages 	: USINT;
		ISOLastPackageWrSize 	: USINT;
		ISOLastPackageRdSize 	: USINT;
		ASYRdVaranPackages 	: USINT;
		ASYWrVaranPackages 	: USINT;
		ASYLastPackageWrSize 	: USINT;
		ASYLastPackageRdSize 	: USINT;
		VMC_ModValue 	: UDINT;
		p_SyncOutISOSwitch 	: ^LSL_VARANPLLSYNCOUT;
		s_SyncOutISOSwitch 	: LSL_VARANPLLSYNCOUT;
		SyncCheck 	: USINT;
		ucIsoSwitchTemp 	: USINT;
		ucVaranManagerTemp 	: USINT;
		MainTimer 	: UDINT;			//! <Variable Comment="maintimer of OS in ns" Name="MainTimer"/>
		UnSyncCounter 	: DINT;
		OldFrameCounter 	: USINT;
		ud_SPI_Offset 	: UDINT;
		ud_SPI_Docu_Length 	: UDINT;
		SetRequiredError 	: BOOL;
		pHardwareTree 	: ^LSL_HARDWARETREE;
		DPRAM_Used 	: t_DOCounter;
		DPRAM_Used_Payload 	: t_DOCounterPayload;
		DOCounter 	: t_DOCounter;
		TriggerClientWD 	: BOOL;
		pFlexHubs 	: ^t_s_FlexHub;
		DA_IRQ_pFunc 	: ^void;
		DA_IRQ_pThis 	: ^void;
		DA_IRQ_pData 	: ^void;
		DA_IRQ_Length 	: UDINT;
		DAIRQTime 	: UDINT;
		pPriorityList 	: ^t_PrioListList;
		SafetyManagerThis 	: pVirtualBase;
		VaranManagerRevision 	: HDINT;
		bFirstInitDone 	: BOOL;
		bExternalInit 	: BOOL;
		pIsoReadSafetyData 	: ^t_Iso_data;
		pIsoWriteSafetyData 	: ^t_Iso_data;
		bPdoCopyDisable 	: BOOL;
		UserObjectData 	: t_s_user_object_data;
		p_ASYDataWrite 	: ^t_ASYAlternatingBuffer;
		p_ASYDataRead 	: ^t_ASYAlternatingBuffer;
		AsyWriteData 	: t_AsyMemXChange;
		AsyReadData 	: t_AsyMemXChange;
		us_InitCounter 	: USINT;
		s_ModuleList 	: t_s_ModuleList;
		bPostInitActive 	: BOOL;
		aPostInitList : ARRAY [0..VM_MAX_POST_INIT_MODULES-1] OF t_s_PostInitList;

		PostInitModuleCnt 	: UINT;
		PostInitModuleReadyCnt 	: UINT;
		bPostInitModulesReady 	: BOOL;
		WaitForPostInitObjectsCnt 	: UINT;
		WaitForPostInitMoveObjectsCnt 	: UINT;
		WaitForSyncSendObjectsCnt 	: UINT;
		PostInitOSWaitObjectsCnt 	: UINT;
		pMutex 	: pVoid;
		mt_api 	: ^LSL_MT_TYPE;
		b_PayloadSupport 	: BOOL;
		pMultiVaran 	: ^LSL_MULTI_VARAN;
		vmNodeHandle 	: UDINT;
		b_IOImage 	: BOOL;			//! <Variable Comment="If this Varaiable is set IO Image is surpported by the OS. Only available for ARM CPUs." Name="b_IOImage"/>
		b_IOImageWritten 	: BOOL;
		ud_VaranPosition 	: HDINT;			//! <Variable Comment="Mem space to store the VARAN Positionstring for the VM. Only need max 4 Byte because the Posiionsring is constant for the VM.&#13;&#10;Must be a Variable because we need to return a pointer to to it." Name="ud_VaranPosition"/>
		b_PostInitRtSyncReady 	: BOOL;
		eSPISSW 	: t_e_SPISSW;
		pVaranSave 	: ^DINT;
		bEnableManagerWithNoModules 	: BOOL;
		bd_RtLog 	: t_RtLog;
		bd_RtLogged 	: t_RtLog;
		bDisableCyTaskNoModules 	: DINT;			//! <Variable Comment="Flag to disable the cywork method if no modules are connected to the manager." Name="bDisableCyTaskNoModules"/>
		MyPara 	: CmdStruct;
		MyResult 	: results;
		udSystemVaranManagerCnt 	: UDINT;
		bSetSystemProperties 	: BOOL;
  //Functions:
				//! <Function Comment="Init for VaranManager" Name="Init"/>
	FUNCTION VIRTUAL GLOBAL Init;
				//! <Function Comment="This function is called in PostScan by VaranManagerPostScan" Name="CyWork"/>
	FUNCTION VIRTUAL GLOBAL CyWork
		VAR_INPUT
			EAX 	: UDINT := EAX;
		END_VAR
		VAR_OUTPUT
			state (EAX) 	: UDINT;
		END_VAR;
				//! <Function Comment="Normal Rt - Funktion for VaranManager_Base" Name="RtWork"/>
	FUNCTION VIRTUAL GLOBAL RtWork
		VAR_INPUT
			EAX 	: UDINT := EAX;
		END_VAR
		VAR_OUTPUT
			state (EAX) 	: UDINT;
		END_VAR;
				//! <Function Comment="[#ENGLISH]&#13;&#10;=================================================================================================&#13;&#10;VaranManager Constructor&#13;&#10;=================================================================================================&#13;&#10;[globals] _RTOSVersion   :R  :OS-Version&#13;&#10;[server] ManagerOn    :W  :state of Manager (On/Off)&#13;&#10;   State     :W  :State of class&#13;&#10;[members] s_RtHandles    :W  :structure to save Handles and thisp for realtime update methodes&#13;&#10;   s_CyHandles    :W  :structure to save Handles and thisp for cyclic update methodes&#13;&#10;   pVaran     :W  :pointer to varan interface&#13;&#10;[local] p_SSR     :W/R :pointer to get pointer to kernel log function&#13;&#10;" Name="VaranManager"/>
	FUNCTION VaranManager
		VAR_OUTPUT
			ret_code 	: ConfStates;
		END_VAR;
				//! <Function Comment="Function to add a realtime or cyclic task to VaranManager" Name="AddVaranTask"/>
	FUNCTION VIRTUAL GLOBAL AddVaranTask
		VAR_INPUT
			ud_dol_type 	: UDINT;			//! <Variable Comment=" Type of DOL (see lsl_st_varan.h)" Name="AddVaranTask.ud_dol_type"/>
			p_this 	: ^void;			//! <Variable Comment=" Thispointer of connected varan class" Name="AddVaranTask.p_this"/>
			callOptions 	: USINT := CALL_OPTION_RT_PRESCAN;
		END_VAR;
				//! <Function Comment="Function to add a read data object to varan Manager and install a varan task" Name="AddRdDO"/>
	FUNCTION VIRTUAL GLOBAL AddRdDO
		VAR_INPUT
			p_us_position_info 	: ^USINT;			//! <Variable Comment="pointer to position info( first byte is length)" Name="AddRdDO.p_us_position_info"/>
			ud_dol_type 	: UDINT;
			p_ud_handle 	: ^UDINT;			//! <Variable Comment="pointer to variable to set right handle" Name="AddRdDO.p_ud_handle"/>
			ud_address 	: UDINT;			//! <Variable Comment=" Address of data object" Name="AddRdDO.ud_address"/>
			ud_length 	: UDINT;			//! <Variable Comment="length of data (max. 128Byte)" Name="AddRdDO.ud_length"/>
			p_ud_data 	: ^UDINT;			//! <Variable Comment="pointer to data should be written" Name="AddRdDO.p_ud_data"/>
			ud_type 	: UDINT;			//! <Variable Comment="0=control area, 1=memory area" Name="AddRdDO.ud_type"/>
		END_VAR
		VAR_OUTPUT
			sd_retval 	: DINT;
		END_VAR;
				//! <Function Comment="Function to add a write data object to varan Manager and install a varan task" Name="AddWrDO"/>
	FUNCTION VIRTUAL GLOBAL AddWrDO
		VAR_INPUT
			p_us_position_info 	: ^USINT;
			ud_dol_type 	: UDINT;
			p_ud_handle 	: ^UDINT;
			ud_address 	: UDINT;
			ud_length 	: UDINT;
			p_ud_data 	: ^UDINT;
			ud_type 	: UDINT;
		END_VAR
		VAR_OUTPUT
			sd_retval 	: DINT;
		END_VAR;
				//! <Function Comment="Function to add a read/write data object to varan manager and install a varan task" Name="AddRdWrDO"/>
	FUNCTION VIRTUAL GLOBAL AddRdWrDO
		VAR_INPUT
			p_us_position_info 	: ^USINT;
			ud_dol_type 	: UDINT;
			p_ud_handle 	: ^UDINT;
			ud_address_read 	: UDINT;			//! <Variable Comment=" Address of read data object" Name="AddRdWrDO.ud_address_read"/>
			ud_length_read 	: UDINT;			//! <Variable Comment=" Length of read data object" Name="AddRdWrDO.ud_length_read"/>
			p_ud_data_read 	: ^UDINT;			//! <Variable Comment=" pointer to variable to get pointer to data" Name="AddRdWrDO.p_ud_data_read"/>
			ud_address_write 	: UDINT;			//! <Variable Comment=" Address of write data object" Name="AddRdWrDO.ud_address_write"/>
			ud_length_write 	: UDINT;			//! <Variable Comment=" Length of write data object" Name="AddRdWrDO.ud_length_write"/>
			p_ud_data_write 	: ^UDINT;			//! <Variable Comment=" pointer to variable to get pointer to data" Name="AddRdWrDO.p_ud_data_write"/>
			ud_type 	: UDINT;
		END_VAR
		VAR_OUTPUT
			sd_retval 	: DINT;
		END_VAR;
	
	FUNCTION AWL VIRTUAL GLOBAL AddMovDO
		VAR_INPUT
			ud_dol_type 	: UDINT;
			p_ud_handle 	: ^UDINT;
			p_ud_MovSettings 	: ^UDINT;
			ud_type 	: UDINT;			//! <Variable Comment="access type is always memory, but we may want to have some priority for this access" Name="AddMovDO.ud_type"/>
		END_VAR
		VAR_OUTPUT
			sd_retval 	: DINT;
		END_VAR;
				//! <Function Comment="Function executes a data object list of VaranManager" Name="ExecuteDOL"/>
	FUNCTION VIRTUAL GLOBAL ExecuteDOL
		VAR_INPUT
			ud_dol_type 	: UDINT;
		END_VAR
		VAR_OUTPUT
			sd_retval 	: DINT;
		END_VAR;
				//! <Function Comment="Function clears a data object list of VaranManager" Name="ClearDOL"/>
	FUNCTION VIRTUAL GLOBAL ClearDOL
		VAR_INPUT
			ud_dol_type 	: UDINT;
		END_VAR
		VAR_OUTPUT
			sd_retval 	: DINT;
		END_VAR;
				//! <Function Comment="Function to read a direct access data object" Name="RdDO"/>
	FUNCTION VIRTUAL GLOBAL RdDO
		VAR_INPUT
			p_us_position_info 	: ^USINT;
			ud_address 	: UDINT;
			ud_length 	: UDINT;
			p_ud_data 	: ^UDINT;
			ud_type 	: UDINT;
		END_VAR
		VAR_OUTPUT
			sd_retval 	: DINT;
		END_VAR;
				//! <Function Comment="Function to write a direct access data object" Name="WrDO"/>
	FUNCTION VIRTUAL GLOBAL WrDO
		VAR_INPUT
			p_us_position_info 	: ^USINT;
			ud_address 	: UDINT;
			ud_length 	: UDINT;
			p_ud_data 	: ^UDINT;
			ud_type 	: UDINT;
		END_VAR
		VAR_OUTPUT
			sd_retval 	: DINT;
		END_VAR;
				//! <Function Comment="Function to get Pll - Time of VaranManager" 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 in ns" Name="GetVaranTime.ud_varan_time"/>
		END_VAR;
				//! <Function Comment="Function to get Varan class position in a string" Name="GetVaranPosition"/>
	FUNCTION VIRTUAL GLOBAL GetVaranPosition
		VAR_INPUT
			p_us_info 	: ^USINT;			//! <Variable Comment=" pointer to save position info (first byte is length)" Name="GetVaranPosition.p_us_info"/>
		END_VAR
		VAR_OUTPUT
			sd_retval 	: DINT;
		END_VAR;
				//! <Function Comment="Function to install callback function for hot plug and play" Name="SetObjectCallback"/>
	FUNCTION VIRTUAL GLOBAL SetObjectCallback
		VAR_INPUT
			p_us_position_info 	: ^USINT;
			ud_action_ptr 	: UDINT;			//! <Variable Comment="pointer to function" Name="SetObjectCallback.ud_action_ptr"/>
			ud_thisp 	: UDINT;			//! <Variable Comment="thispointer" Name="SetObjectCallback.ud_thisp"/>
			sd_required 	: DINT;			//! <Variable Comment="is class required" Name="SetObjectCallback.sd_required"/>
		END_VAR
		VAR_OUTPUT
			sd_retval 	: DINT;
		END_VAR;
				//! <Function Comment="Function sets Manager off" Name="SetManagerOff"/>
	FUNCTION VIRTUAL GLOBAL SetManagerOff
		VAR_INPUT
			e_error 	: t_e_VaranErrors;			//! <Variable Comment="reason why varan Manager is set off" Name="SetManagerOff.e_error"/>
		END_VAR;
				//! <Function Comment="Function set a varan error" Name="SetVaranError"/>
	FUNCTION VIRTUAL GLOBAL SetVaranError
		VAR_INPUT
			p_Node 	: ^USINT;			//! <Variable Comment="pointer to Node string" Name="SetVaranError.p_Node"/>
		END_VAR;
				//! <Function Comment="Function give back a nano second counter value of VaranManager" Name="GetNsTime"/>
	FUNCTION VIRTUAL GLOBAL GetNsTime
		VAR_OUTPUT
			ud_ns_counter 	: UDINT;			//! <Variable Comment="nano second counter value" Name="GetNsTime.ud_ns_counter"/>
		END_VAR;
				//! <Function Comment="Functions give back the nano second counter value of VaranManager between the PLL ticks (time since last tick)" Name="GetNsTimeBPLLTicks"/>
	FUNCTION VIRTUAL GLOBAL GetNsTimeBPLLTicks
		VAR_OUTPUT
			ud_ns_counter 	: UDINT;			//! <Variable Comment="time since last tick" Name="GetNsTimeBPLLTicks.ud_ns_counter"/>
		END_VAR;
				//! <Function Comment="Function to get pointer to node information" Name="GetNodeInfo"/>
	FUNCTION VIRTUAL GLOBAL GetNodeInfo
		VAR_INPUT
			p_us_position_info 	: ^USINT;
			p_node_info 	: ^PLSL_VARANNODEINFO;			//! <Variable Comment="pointer to node info" Name="GetNodeInfo.p_node_info"/>
		END_VAR
		VAR_OUTPUT
			sd_retval 	: DINT;
		END_VAR;
				//! <Function Comment="Function to get Varan Manager number" Name="GetManagerNumber"/>
	FUNCTION VIRTUAL GLOBAL GetManagerNumber
		VAR_INPUT
			p_varan 	: ^pVoid;			//! <Variable Comment="address of pointer to varan" Name="GetManagerNumber.p_varan"/>
		END_VAR
		VAR_OUTPUT
			ud_manager_number 	: UDINT;
		END_VAR;
				//! <Function Comment="Function returns state of Varan manger class" Name="GetManagerState"/>
	FUNCTION VIRTUAL GLOBAL GetManagerState
		VAR_OUTPUT
			e_state 	: t_e_VaranErrors;			//! <Variable Comment="error of varan manager" Name="GetManagerState.e_state"/>
		END_VAR;
				//! <Function Comment="Function to read SPI data" Name="ReadSPIData"/>
	FUNCTION VIRTUAL GLOBAL ReadSPIData
		VAR_INPUT
			p_us_position_info 	: ^USINT;			//! <Variable Comment="nodestring of varan client" Name="ReadSPIData.p_us_position_info"/>
			ud_offset 	: UDINT;			//! <Variable Comment="offset in SPI flash" Name="ReadSPIData.ud_offset"/>
			ud_length 	: UDINT;			//! <Variable Comment="length of data to read (if MSB is set, access is done on the last page in SPI)" Name="ReadSPIData.ud_length"/>
			p_data 	: ^USINT;			//! <Variable Comment="pointer to allocated memory for read data" Name="ReadSPIData.p_data"/>
		END_VAR
		VAR_OUTPUT
			sd_retval 	: DINT;			//! <Variable Comment="0...success&#13;&#10;or else negative errorcode is returned" Name="ReadSPIData.sd_retval"/>
		END_VAR;
				//! <Function Comment="Function to get sync frame counter" Name="GetSyncFrameCounter"/>
	FUNCTION VIRTUAL GLOBAL GetSyncFrameCounter
		VAR_OUTPUT
			us_frame_counter 	: USINT;			//! <Variable Comment=" sync frame counter" Name="GetSyncFrameCounter.us_frame_counter"/>
		END_VAR;
				//! <Function Comment="Function to set disable device in cyclic" Name="SetDisableDevice"/>
	FUNCTION VIRTUAL GLOBAL SetDisableDevice
		VAR_INPUT
			p_us_position_info 	: ^USINT;
		END_VAR
		VAR_OUTPUT
			sd_retval 	: DINT;
		END_VAR;
				//! <Function Comment="Method to fetch .pdf-file from Varan-Client" Name="GetDocumentation"/>
	FUNCTION VIRTUAL GLOBAL GetDocumentation
		VAR_INPUT
			p_us_position_info 	: ^USINT;
			p_dpne 	: ^CHAR;
		END_VAR
		VAR_OUTPUT
			sd_retval 	: DINT;
		END_VAR;
				//! <Function Comment="Method to get Serial Number from Varan-Client" Name="GetSerialNo"/>
	FUNCTION VIRTUAL GLOBAL GetSerialNo
		VAR_INPUT
			p_us_position_info 	: ^USINT;
			p_SerialNo 	: ^CHAR;
		END_VAR
		VAR_OUTPUT
			sd_retval 	: DINT;
		END_VAR;
				//! <Function Comment="If a connected VaranClient is Required, VaranManager occurs a ManagerError if no interface is available" Name="AllowRequiredError"/>
	FUNCTION VIRTUAL GLOBAL AllowRequiredError
		VAR_OUTPUT
			sd_retval 	: DINT;
		END_VAR;
	
	FUNCTION AWL VIRTUAL GLOBAL SetObjectThisp
		VAR_INPUT
			p_us_ObjectPath 	: ^USINT;
			ud_thisp 	: UDINT;
		END_VAR
		VAR_OUTPUT
			sd_retval 	: DINT;
		END_VAR;
	
	FUNCTION AWL VIRTUAL GLOBAL GetObjectThisp
		VAR_INPUT
			p_us_ObjectPath 	: ^USINT;
		END_VAR
		VAR_OUTPUT
			ud_thisp 	: UDINT;
		END_VAR;
				//! <Function Comment="[#ENGLISH]&#13;&#10;=================================================================================================&#13;&#10;Function to send Sync and trigger Watchdog of Varan Bus&#13;&#10;=================================================================================================&#13;&#10;" Name="TriggerWatchdog"/>
	FUNCTION TriggerWatchdog
		VAR_OUTPUT
			sd_retval 	: DINT;			//! <Variable Comment=" 0=OK, negative=error (look lsl_st_varan.h)" Name="TriggerWatchdog.sd_retval"/>
		END_VAR;
				//! <Function Comment="[#ENGLISH]&#13;&#10;=================================================================================================&#13;&#10;Function to extend Handle List&#13;&#10;=================================================================================================&#13;&#10;[servers] ManagerOn    :W  :marks VaranManager as valid / ok&#13;&#10;[members] s_RtHandles    :W  :structure to save Handles and thisp for realtime update methodes&#13;&#10;   s_CyHandles    :W  :structure to save Handles and thisp for cyclic update methodes&#13;&#10;   e_ErrorVaranManager  :W  :enum for Error State&#13;&#10;" Name="ExtendHandleList"/>
	FUNCTION ExtendHandleList
		VAR_INPUT
			ud_dol_type 	: UDINT;			//! <Variable Comment=" type of DOL list( 1=direct access, 2=IRQ, 3=realtime, 4=cyclic )" Name="ExtendHandleList.ud_dol_type"/>
			callOptions 	: USINT := CALL_OPTION_RT_PRESCAN;
		END_VAR;
				//! <Function Comment="[#ENGLISH]&#13;&#10;=================================================================================================&#13;&#10;Function to call Realtime update methode of a varan class&#13;&#10;=================================================================================================&#13;&#10;" Name="CallUpdateRt"/>
	FUNCTION CallUpdateRt
		VAR_INPUT
			p_this 	: p_VaranBase;			//! <Variable Comment="Thispointer of Varan_Base class" Name="CallUpdateRt.p_this"/>
		END_VAR;
				//! <Function Comment="[#ENGLISH]&#13;&#10;=================================================================================================&#13;&#10;Function to call Cyclic update methode of a varan class&#13;&#10;=================================================================================================&#13;&#10;" Name="CallUpdateCy"/>
	FUNCTION CallUpdateCy
		VAR_INPUT
			p_this 	: p_VaranBase;
		END_VAR;
				//! <Function Comment="[#ENGLISH]&#13;&#10;=================================================================================================&#13;&#10;Function to set Error in VaranManager&#13;&#10;=================================================================================================&#13;&#10;[members] e_ErrorVaranManager  :W  :Enum for Error State&#13;&#10;[&gt;sd_Error]Error of VaranManager&#13;&#10;" Name="SetVaranDOError"/>
	FUNCTION SetVaranDOError
		VAR_INPUT
			sd_error 	: DINT;
			b_manager_off 	: BOOL;			//! <Variable Comment="0=run, 1=set VaranManagerOff" Name="SetVaranDOError.b_manager_off"/>
			b_log 	: BOOL;			//! <Variable Comment="0=no logging, 1=log fault" Name="SetVaranDOError.b_log"/>
		END_VAR
		VAR_OUTPUT
			sd_enum_error 	: t_e_VaranErrors;
		END_VAR;
				//! <Function Comment="[#ENGLISH]&#13;&#10;=================================================================================================&#13;&#10;Function to get µs time&#13;&#10;=================================================================================================&#13;&#10;" Name="GetMuSec"/>
	FUNCTION GetMuSec
		VAR_OUTPUT
			ud_us_sec (EAX) 	: UDINT;
		END_VAR;
				//! <Function Comment="[#ENGLISH]&#13;&#10;=================================================================================================&#13;&#10;Function trace a Realtime Overlap fault&#13;&#10;=================================================================================================&#13;&#10;[server] ManagerOn    :W  :state of Manager (On/Off)&#13;&#10;   State     :R  :State of class&#13;&#10;[members] s_VaranManagerSettings :W  :structure for different varan settings&#13;&#10;" Name="TRACE_RtOverlap"/>
	FUNCTION TRACE_RtOverlap;
				//! <Function Comment="[#ENGLISH]&#13;&#10;=================================================================================================&#13;&#10;Function to get watchdog or timeslice error&#13;&#10;=================================================================================================&#13;&#10;[server] ManagerOn    :W  :state of Manager (On/Off)&#13;&#10;   State     :R  :State of class&#13;&#10;[members] s_VaranManagerSettings :W  :structure for different varan settings&#13;&#10;" Name="Varan_CallBack"/>
	FUNCTION Varan_CallBack
		VAR_INPUT
			ud_reason 	: UDINT;			//! <Variable Comment="reason of callback" Name="Varan_CallBack.ud_reason"/>
		END_VAR;
				//! <Function Comment="[#ENGLISH]&#13;&#10;=================================================================================================&#13;&#10;Function to log faults in cyclic (to prevent an error 67)&#13;&#10;=================================================================================================&#13;&#10;[server] State     :W  :State of class&#13;&#10;[members] s_VaranManagerSettings :W  :structure for different varan settings&#13;&#10;" Name="LogError"/>
	FUNCTION LogError;
				//! <Function Comment="Function to get an actual filter number" Name="GetFilterNumber"/>
	FUNCTION GLOBAL GetFilterNumber
		VAR_OUTPUT
			us_filter 	: USINT;			//! <Variable Comment="number of filter" Name="GetFilterNumber.us_filter"/>
		END_VAR;
				//! <Function Comment="Function to add a multiple read/write register" Name="AddMultipleRdWr"/>
	FUNCTION GLOBAL AddMultipleRdWr
		VAR_INPUT
			p_us_position_info 	: ^USINT;
			ud_dol_type 	: UDINT;
			p_ud_handle 	: ^UDINT;
			ud_address_read 	: UDINT;
			ud_length_read 	: UDINT;
			p_ud_data_read 	: ^UDINT;
			ud_address_write 	: UDINT;
			ud_length_write 	: UDINT;
			p_ud_data_write 	: ^UDINT;
			us_filter 	: USINT;			//! <Variable Comment=" number of filter" Name="AddMultipleRdWr.us_filter"/>
			ui_number_of_slices 	: UINT;			//! <Variable Comment="maximal number of slices" Name="AddMultipleRdWr.ui_number_of_slices"/>
		END_VAR
		VAR_OUTPUT
			sd_retval 	: DINT;
		END_VAR;
				//! <Function Comment="Function to write a direct access data object" Name="MultipleRdWrDO"/>
	FUNCTION GLOBAL MultipleRdWrDO
		VAR_INPUT
			p_us_position_info 	: ^USINT;
			ud_address_read 	: UDINT;
			ud_length_read 	: UDINT;
			p_ud_data_read 	: ^UDINT;
			ud_address_write 	: UDINT;
			ud_length_write 	: UDINT;
			p_ud_data_write 	: ^UDINT;
			us_filter 	: USINT;
			us_slices 	: USINT;			//! <Variable Comment=" max number of slices" Name="MultipleRdWrDO.us_slices"/>
			p_handle 	: ^PLSL_VARANFRAME;			//! <Variable Comment="pointer to varan header" Name="MultipleRdWrDO.p_handle"/>
		END_VAR
		VAR_OUTPUT
			sd_retval 	: DINT;
		END_VAR;
				//! <Function Comment="Function add a foreign package request" Name="AddForeignPackRequest"/>
	FUNCTION VIRTUAL GLOBAL AddForeignPackRequest
		VAR_INPUT
			p_us_position_info 	: ^USINT;
			ud_dol_type 	: UDINT;
			p_ud_handle 	: ^UDINT;
			ud_address 	: UDINT;
		END_VAR
		VAR_OUTPUT
			sd_retval 	: DINT;
		END_VAR;
				//! <Function Comment="Method to get IsoStartPoint in %" Name="GetIsoStartPoint"/>
	FUNCTION VIRTUAL GLOBAL GetIsoStartPoint
		VAR_OUTPUT
			retval 	: UDINT;			//! <Variable Comment="ISO start point [ns]" Name="GetIsoStartPoint.retval"/>
		END_VAR;
	
	FUNCTION GetISOStartTime;
				//! <Function Comment="=================================================================================================&#13;&#10;Function to disable device in cyclic&#13;&#10;=================================================================================================&#13;&#10;" Name="DisableDevice"/>
	FUNCTION DisableDevice
		VAR_OUTPUT
			sd_retval 	: DINT;
		END_VAR;
				//! <Function Comment="Function to read waiting time before sync(time where no varan accesses are allowed)" Name="ReadWaitingTimeBeforeSync"/>
	FUNCTION GLOBAL ReadWaitingTimeBeforeSync
		VAR_OUTPUT
			ud_waitingtime 	: UDINT;
		END_VAR;
				//! <Function Comment="Function to set waiting time before sync(time where no varan accesses are allowed)" Name="SetWaitingTimeBeforeSync"/>
	FUNCTION GLOBAL SetWaitingTimeBeforeSync
		VAR_INPUT
			ud_waitingtime 	: UDINT;
		END_VAR;
				//! <Function Comment="Method to get change of FrameCounter (only to be called by HW_Control)" Name="FrameCounterChanged"/>
	FUNCTION GLOBAL FrameCounterChanged
		VAR_INPUT
			pOld 	: ^USINT := NIL;
			pAct 	: ^USINT := NIL;
		END_VAR
		VAR_OUTPUT
			retcode 	: BOOL;
		END_VAR;
				//! <Function Comment="With this method, a memory area can be read in realtime from the alternating VMC buffer in the isochronous task.&#13;&#10;&#13;&#10;ATTENTION: Must be called before 5th init" Name="AddIsoClientRdData"/>
	FUNCTION VIRTUAL GLOBAL AddIsoClientRdData
		VAR_INPUT
			ud_length 	: UDINT;			//! <Variable Comment="length of data (max. 1020 Byte)" Name="AddIsoClientRdData.ud_length"/>
			p_pdata 	: ^void;			//! <Variable Comment="pointer on memory, where to save the read out data" Name="AddIsoClientRdData.p_pdata"/>
		END_VAR
		VAR_OUTPUT
			sd_retval 	: DINT;			//! <Variable Comment=" 0..OK&#13;&#10;-1..function called too late (after 6th init cycle)&#13;&#10;-2..invalid length&#13;&#10;-3..invalid pointer&#13;&#10;-4..already added data&#13;&#10;-5..allocating memory failed&#13;&#10;-6..no manager client installed (clients of VaranManager class!)" Name="AddIsoClientRdData.sd_retval"/>
		END_VAR;
				//! <Function Comment="With this method, a memory area can be written cyclically in the alternating VMC buffer in the isochronous task.&#13;&#10;&#13;&#10;ATTENTION: Must be called before 5th init" Name="AddIsoClientWrData"/>
	FUNCTION VIRTUAL GLOBAL AddIsoClientWrData
		VAR_INPUT
			ud_length 	: UDINT;			//! <Variable Comment="length of data (max. 1020 Byte)" Name="AddIsoClientWrData.ud_length"/>
			p_pdata 	: ^void;			//! <Variable Comment="pointer on memory, which should be written" Name="AddIsoClientWrData.p_pdata"/>
		END_VAR
		VAR_OUTPUT
			sd_retval 	: DINT;			//! <Variable Comment=" 0..OK&#13;&#10;-1..function called too late (after 6th init cycle)&#13;&#10;-2..invalid length&#13;&#10;-3..invalid pointer&#13;&#10;-4..already added data&#13;&#10;-5..allocating memory failed&#13;&#10;-6..no manager client installed (clients of VaranManager class!)" Name="AddIsoClientWrData.sd_retval"/>
		END_VAR;
				//! <Function Comment="With this method, a memory area can be read from the VMC alternating buffer in the asychronous task.&#13;&#10;&#13;&#10;ATTENTION: Must be called before 5th init" Name="AddAsyClientRdData"/>
	FUNCTION VIRTUAL GLOBAL AddAsyClientRdData
		VAR_INPUT
			ud_length 	: UDINT;			//! <Variable Comment="length of data (max. 1024 Byte)" Name="AddAsyClientRdData.ud_length"/>
			p_pdata 	: ^void;			//! <Variable Comment="pointer on memory, where to save the read out data" Name="AddAsyClientRdData.p_pdata"/>
		END_VAR
		VAR_OUTPUT
			sd_retval 	: DINT;			//! <Variable Comment=" 0..OK&#13;&#10;-1..function called too late (after 6th init cycle)&#13;&#10;-2..invalid length&#13;&#10;-3..invalid pointer&#13;&#10;-4..already added data&#13;&#10;-5..allocating memory failed&#13;&#10;-6..no manager client installed (clients of VaranManager class!)" Name="AddAsyClientRdData.sd_retval"/>
		END_VAR;
				//! <Function Comment="With this method, a memory area can be written cyclically in the VMC alternating buffer in the asynchronous task.&#13;&#10;&#13;&#10;ATTENTION: Must be called before 5th init" Name="AddAsyClientWrData"/>
	FUNCTION VIRTUAL GLOBAL AddAsyClientWrData
		VAR_INPUT
			ud_length 	: UDINT;			//! <Variable Comment="length of data (max. 1024 Byte)" Name="AddAsyClientWrData.ud_length"/>
			p_pdata 	: ^void;			//! <Variable Comment="pointer on memory, which should be written" Name="AddAsyClientWrData.p_pdata"/>
		END_VAR
		VAR_OUTPUT
			sd_retval 	: DINT;			//! <Variable Comment=" 0..OK&#13;&#10;-1..function called too late (after 6th init cycle)&#13;&#10;-2..invalid length&#13;&#10;-3..invalid pointer&#13;&#10;-4..already added data&#13;&#10;-5..allocating memory failed&#13;&#10;-6..no manager client installed (clients of VaranManager class!)" Name="AddAsyClientWrData.sd_retval"/>
		END_VAR;
				//! <Function Comment="With this method, a callback will be installed to receive data from direct access buffer via interrupt.&#13;&#10;&#13;&#10;Your method (given via pointer pFunction) should look like this:&#13;&#10;&#13;&#10;FUNCTION YourClassName::IRQMethod&#13;&#10;  VAR_INPUT&#13;&#10;    pThis  : UDINT;&#13;&#10;  END_VAR&#13;&#10;&#13;&#10;  ESI := pThis;&#13;&#10;&#13;&#10;  //some other stuff to do in irq&#13;&#10;&#13;&#10;END_FUNCTION&#13;&#10;&#13;&#10;Notice: When the method is called, the actual receive data are already in the memory area you pass by with parameter &quot;p_pdata&quot; of this method (AddDAClientRdData)." Name="AddDAClientRdData"/>
	FUNCTION GLOBAL AddDAClientRdData
		VAR_INPUT
			ud_length 	: UDINT;			//! <Variable Comment="length of data (max. 1020 Byte)" Name="AddDAClientRdData.ud_length"/>
			p_pdata 	: ^void;			//! <Variable Comment="pointer on memory, where to save the read out data" Name="AddDAClientRdData.p_pdata"/>
			pThis 	: ^void;			//! <Variable Comment="Pointer to calling object (this)" Name="AddDAClientRdData.pThis"/>
			pFunction 	: ^void;			//! <Variable Comment="pointer on IRQ method (method to be called, when irq occurs)" Name="AddDAClientRdData.pFunction"/>
		END_VAR
		VAR_OUTPUT
			sd_retval 	: DINT;			//! <Variable Comment=" 0..OK&#13;&#10;-1..no manager client installed (clients of VaranManager class!)&#13;&#10;-2..invalid length&#13;&#10;-3..invalid pointer&#13;&#10;-4..direct access buffer not supported by fpga (must be &gt;= 1.4)&#13;&#10;-5..direct access buffer not supported by os (must be &gt;= 01.02.106)&#13;&#10;-6..newer lsl_st_varan.h file necessary to install IRQ Callback" Name="AddDAClientRdData.sd_retval"/>
		END_VAR;
	
	FUNCTION GLOBAL SendDAClientWrData
		VAR_INPUT
			ud_length 	: UDINT;
			p_pdata 	: ^void;
		END_VAR
		VAR_OUTPUT
			sd_retval 	: DINT;			//! <Variable Comment=" 0..OK&#13;&#10;-1..no manager client installed (clients of VaranManager class!)&#13;&#10;-2..invalid length&#13;&#10;-3..invalid pointer&#13;&#10;-4..direct access buffer not supported by fpga (must be &gt;= 1.4)&#13;&#10;&#13;&#10;" Name="SendDAClientWrData.sd_retval"/>
		END_VAR;
	
	FUNCTION ActISOReadLength
		VAR_INPUT
			loop 	: USINT;
		END_VAR
		VAR_OUTPUT
			length 	: UDINT;
		END_VAR;
	
	FUNCTION ActISOWriteLength
		VAR_INPUT
			loop 	: USINT;
		END_VAR
		VAR_OUTPUT
			length 	: UDINT;
		END_VAR;
	
	FUNCTION ActASYReadLength
		VAR_INPUT
			loop 	: USINT;
		END_VAR
		VAR_OUTPUT
			length 	: UDINT;
		END_VAR;
	
	FUNCTION ActASYWriteLength
		VAR_INPUT
			loop 	: USINT;
		END_VAR
		VAR_OUTPUT
			length 	: UDINT;
		END_VAR;
	
	FUNCTION InitMulDivVMC
		VAR_OUTPUT
			sd_retval 	: DINT;
		END_VAR;
	
	FUNCTION SearchSPIList
		VAR_INPUT
			p_us_position_info 	: ^USINT;
			SearchID 	: UDINT;
			p_BaseListAddress 	: ^UDINT;
		END_VAR
		VAR_OUTPUT
			sd_retval 	: DINT;
		END_VAR;
	
	FUNCTION GetDocuFileInfo
		VAR_INPUT
			p_us_position_info 	: ^USINT;
			ud_listOffset 	: UDINT;
		END_VAR
		VAR_OUTPUT
			sd_retval 	: DINT;
		END_VAR;
	
	FUNCTION ReadSPIDataComfort
		VAR_INPUT
			p_us_position_info 	: ^USINT;
			ud_offset 	: UDINT;
			ud_length 	: UDINT;
			p_data 	: ^USINT;
		END_VAR
		VAR_OUTPUT
			sd_retval 	: DINT;
		END_VAR;
	
	FUNCTION VIRTUAL GLOBAL UpdateRtPostScan;
				//! <Function Comment="With this method, you can login to a mechanism, which tells you when there is a connect or disconnect on the varan topology.&#13;&#10;" Name="TopologyChangeLogin"/>
	FUNCTION GLOBAL TopologyChangeLogin
		VAR_INPUT
			pServer 	: ^DINT;
		END_VAR;
	
	FUNCTION AddToDOPriorityList
		VAR_INPUT
			pHandle 	: ^LSL_VARANFRAME;
			ud_Priority 	: HDINT;
		END_VAR;
	
	FUNCTION SortCmdsByPriority;
	
	FUNCTION IsInPriorityList
		VAR_INPUT
			pHandle 	: ^LSL_VARANFRAME;
		END_VAR
		VAR_OUTPUT
			retcode 	: BOOL;
		END_VAR;
	
	FUNCTION FirstInit;
	
	FUNCTION ExtendModuleList
		VAR_OUTPUT
			sd_retval 	: DINT;
		END_VAR;
				//! <Function Comment="Switch off isochronous task" Name="TurnOffIsoTask"/>
	FUNCTION TurnOffIsoTask;
	
	FUNCTION AddPayloadDO
		VAR_INPUT
			p_ud_DoHandle 	: ^UDINT;
			ud_NodeHandle 	: UDINT;
			ud_DoRequired 	: UDINT;
			ud_DolType 	: UDINT;
			ud_Command 	: UDINT;
			ud_Priority 	: UDINT;
			ud_PrescalerCounterThreshold 	: UDINT;
			ud_PrescalerCounterStartValue 	: UDINT;
			ud_ReadOffset 	: UDINT;
			ud_ReadLength 	: UDINT;
			ud_WriteOffset 	: UDINT;
			ud_WriteLength 	: UDINT;
			ud_Filter 	: UDINT;
			ud_Slices 	: UDINT;
			ud_WritePayloadType 	: UDINT;
		END_VAR
		VAR_OUTPUT
			sd_retval 	: DINT;
		END_VAR;
	
	FUNCTION AddPayloadMoveDO
		VAR_INPUT
			p_ud_DoHandle 	: ^UDINT;
			ud_bDoRequired 	: UDINT;
			ud_DolType 	: UDINT;
			ud_Priority 	: UDINT;
			ud_PrescalerCounterThreshold 	: UDINT;
			ud_PrescalerCounterStartValue 	: UDINT;
			ud_hSourceReadDoHandle 	: UDINT;
			ud_ReadOffset 	: UDINT;
			ud_hDestinationWriteDoHandle 	: UDINT;
			ud_WriteOffset 	: UDINT;
			ud_MoveDataLength 	: UDINT;
		END_VAR
		VAR_OUTPUT
			sd_retval 	: DINT;
		END_VAR;
	
	FUNCTION GetDataPointers
		VAR_INPUT
			ud_hDoHandle 	: UDINT;
			pp_ReadData 	: ^pVoid;
			pp_WriteData 	: ^pVoid;
		END_VAR
		VAR_OUTPUT
			sd_retval 	: DINT;
		END_VAR;
	
	FUNCTION GetModuleHandle
		VAR_INPUT
			p_us_PositionInfo 	: ^USINT;
			p_ud_ModuleHandle 	: ^UDINT;
		END_VAR
		VAR_OUTPUT
			sd_retval 	: DINT;
		END_VAR;
	
	FUNCTION AddObjectCallback
		VAR_INPUT
			p_us_position_info 	: ^USINT;
			ud_action_ptr 	: UDINT;
			ud_thisp 	: UDINT;
			sd_required 	: DINT;
		END_VAR
		VAR_OUTPUT
			sd_retval 	: DINT;
		END_VAR;
	
	FUNCTION GLOBAL CreateMutex
		VAR_INPUT
			MutexName 	: ^CHAR;
			pThis 	: ^VirtualBase;
		END_VAR
		VAR_OUTPUT
			pv_RetMutex 	: pVoid;
		END_VAR;
	
	FUNCTION GLOBAL MutexStart
		VAR_INPUT
			pMutex 	: pVoid;
		END_VAR;
	
	FUNCTION GLOBAL MutexStop
		VAR_INPUT
			pMutex 	: pVoid;
		END_VAR;
	
	FUNCTION GetSPIDataFromID
		VAR_INPUT
			p_us_position_info 	: ^USINT;
			udListID 	: UDINT;
			pData 	: ^CHAR;
			udRequDataLength 	: UDINT;
			pIDHeader 	: ^t_s_SPIListHeader;
			udOffset 	: UDINT := 16#00;
		END_VAR
		VAR_OUTPUT
			sd_retval 	: DINT;
		END_VAR;
	
	FUNCTION GLOBAL RaiseManagerError
		VAR_INPUT
			udReason 	: UDINT;
		END_VAR;
	
	FUNCTION GetExtNodeInfoDirectly
		VAR_INPUT
			pPara 	: ^t_VM_CMD_GetExtNodeInfo;
		END_VAR
		VAR_OUTPUT
			sd_retval 	: DINT;
		END_VAR;
	
	FUNCTION VIRTUAL GLOBAL Control::NewInst
		VAR_INPUT
			pPara 	: ^CmdStruct;
			pResult 	: ^results;
		END_VAR
		VAR_OUTPUT
			ret_code 	: iprStates;
		END_VAR;
  //Tables:
	FUNCTION @STD
		VAR_OUTPUT
			ret_code	: CONFSTATES;
		END_VAR;
	FUNCTION GLOBAL TAB @CT_;
END_CLASS;

#pragma using ASCII_BIN
#pragma usingLtd _MultiTask
#pragma usingLtd HwControl


//}}LSL_DECLARATION


FUNCTION GLOBAL TAB VaranManager::@CT_
0$UINT,
2#0100000000000000$UINT, //TY_VARANMANAGER
3$UINT, 8$UINT, (SIZEOF(::VaranManager))$UINT, 
15$UINT, 16$UINT, 0$UINT, 
TO_UDINT(2940693151), "VaranManager", //Class
TO_UDINT(4035182347), "VaranManager_Base", 1$UINT, 26$UINT, //Baseclass
//Servers:
(::VaranManager.State.pMeth)$UINT, _CH_SVR$UINT, 2#0000000000000000$UINT, TO_UDINT(1422331979), "State", 
(::VaranManager.ManagerOn.pMeth)$UINT, _CH_SVR$UINT, 2#0000000000000000$UINT, TO_UDINT(863440053), "ManagerOn", 
(::VaranManager.Release.pMeth)$UINT, _CH_SVR$UINT, 2#0000000000000000$UINT, TO_UDINT(2701327623), "Release", 
(::VaranManager.RetryCounter.pMeth)$UINT, _CH_SVR$UINT, 2#0000000000000000$UINT, TO_UDINT(3383993698), "RetryCounter", 
(::VaranManager.IsoVaranTime.pMeth)$UINT, _CH_SVR$UINT, 2#0000000000000000$UINT, TO_UDINT(1397046043), "IsoVaranTime", 
(::VaranManager.IsoVaranTimeMax.pMeth)$UINT, _CH_SVR$UINT, 2#0000000000000000$UINT, TO_UDINT(564557542), "IsoVaranTimeMax", 
(::VaranManager.AsyVaranTime.pMeth)$UINT, _CH_SVR$UINT, 2#0000000000000000$UINT, TO_UDINT(2147073098), "AsyVaranTime", 
(::VaranManager.Act_RtTime.pMeth)$UINT, _CH_SVR$UINT, 2#0000000000000000$UINT, TO_UDINT(2240558418), "Act_RtTime", 
(::VaranManager.Min_RtTime.pMeth)$UINT, _CH_SVR$UINT, 2#0000000000000000$UINT, TO_UDINT(3890573985), "Min_RtTime", 
(::VaranManager.Max_RtTime.pMeth)$UINT, _CH_SVR$UINT, 2#0000000000000000$UINT, TO_UDINT(3874088981), "Max_RtTime", 
(::VaranManager.Act_RtCallTime.pMeth)$UINT, _CH_SVR$UINT, 2#0000000000000000$UINT, TO_UDINT(2476536522), "Act_RtCallTime", 
(::VaranManager.Min_RtCallTime.pMeth)$UINT, _CH_SVR$UINT, 2#0000000000000000$UINT, TO_UDINT(1696137308), "Min_RtCallTime", 
(::VaranManager.Max_RtCallTime.pMeth)$UINT, _CH_SVR$UINT, 2#0000000000000000$UINT, TO_UDINT(3695156013), "Max_RtCallTime", 
(::VaranManager.SuperiorSystemOK.pMeth)$UINT, _CH_SVR$UINT, 2#0000000000000000$UINT, TO_UDINT(298279974), "SuperiorSystemOK", 
(::VaranManager.ManagerProtocolVersion.pMeth)$UINT, _CH_SVR$UINT, 2#0000000000000000$UINT, TO_UDINT(1336107588), "ManagerProtocolVersion", 
//Clients:
(::VaranManager.To_HwControl.pCh)$UINT, _CH_CLT_OBJ$UINT, 2#0000000000000010$UINT, TO_UDINT(1012711711), "To_HwControl", TO_UDINT(2471641665), "HwControl", 5$UINT, 24$UINT, 
(::VaranManager.VaranManagerTime.pCh)$UINT, _CH_CLT_DATA$UINT, 2#0000000000000000$UINT, TO_UDINT(3386702), "VaranManagerTime", 
(::VaranManager.VaranManagerNr.pCh)$UINT, _CH_CLT_DATA$UINT, 2#0000000000000000$UINT, TO_UDINT(4059623800), "VaranManagerNr", 
(::VaranManager.PreventManagerError.pCh)$UINT, _CH_CLT_DATA$UINT, 2#0000000000000000$UINT, TO_UDINT(1977854530), "PreventManagerError", 
(::VaranManager.IsoStartPoint.pCh)$UINT, _CH_CLT_DATA$UINT, 2#0000000000000000$UINT, TO_UDINT(102048672), "IsoStartPoint", 
(::VaranManager.IsAlsoClient.pCh)$UINT, _CH_CLT_DATA$UINT, 2#0000000000000000$UINT, TO_UDINT(2433351523), "IsAlsoClient", 
(::VaranManager.SuperiorSystemTime.pCh)$UINT, _CH_CLT_DATA$UINT, 2#0000000000000000$UINT, TO_UDINT(254125562), "SuperiorSystemTime", 
(::VaranManager.To_Multitask.pCh)$UINT, _CH_CLT_OBJ$UINT, 2#0000000000000000$UINT, TO_UDINT(2145650779), "To_Multitask", TO_UDINT(2641766936), "_MultiTask", 1$UINT, 1$UINT, 
(::VaranManager.SafetyIsoMemRead.pCh)$UINT, _CH_CLT_DATA$UINT, 2#0000000000000000$UINT, TO_UDINT(3608963762), "SafetyIsoMemRead", 
(::VaranManager.SafetyIsoMemWrite.pCh)$UINT, _CH_CLT_DATA$UINT, 2#0000000000000000$UINT, TO_UDINT(2968729575), "SafetyIsoMemWrite", 
(::VaranManager.SafetyAsyMemRead.pCh)$UINT, _CH_CLT_DATA$UINT, 2#0000000000000000$UINT, TO_UDINT(2115965674), "SafetyAsyMemRead", 
(::VaranManager.SafetyAsyMemWrite.pCh)$UINT, _CH_CLT_DATA$UINT, 2#0000000000000000$UINT, TO_UDINT(3588943193), "SafetyAsyMemWrite", 
(::VaranManager.PayloadFrame.pCh)$UINT, _CH_CLT_DATA$UINT, 2#0000000000000000$UINT, TO_UDINT(793372747), "PayloadFrame", 
(::VaranManager.CoreSelect.pCh)$UINT, _CH_CLT_DATA$UINT, 2#0000000000000000$UINT, TO_UDINT(2631154307), "CoreSelect", 
(::VaranManager.InterframeGap.pCh)$UINT, _CH_CLT_DATA$UINT, 2#0000000000000010$UINT, TO_UDINT(1688721570), "InterframeGap", 
(::VaranManager.ASCII_BIN1.pCh)$UINT, _CH_CLT_OBJ$UINT, 2#0000000000000010$UINT, TO_UDINT(1288358665), "ASCII_BIN1", TO_UDINT(2897291062), "ASCII_BIN", 1$UINT, 21$UINT, 
END_FUNCTION


#define USER_CNT_VaranManager 35

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

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

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

	_memcpy((#vmt.CmdTable)$^USINT, VaranManager_Base::Control.pMeth, nCmdSize);
	vmt.CmdTable.nCmds		:= nSTDCMD + USER_CNT_VaranManager;
	vmt.CmdTable.NewInstr		:= #Control::NewInst();
	vmt.CmdTable.Init		:= #Init();
	vmt.CmdTable.CyWork		:= #CyWork();
	vmt.CmdTable.RtWork		:= #RtWork();
#pragma warning (disable : 74)
	vmt.UserFcts[0]		:= #AddVaranTask();

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	IF VaranManager_Base::Control.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;
	IsoVaranTimeMax.pMeth			:= StoreMethod( #M_RD_DIRECT(), #M_WR_DIRECT() );
	IF IsoVaranTimeMax.pMeth THEN
		ret_code	:= C_OK;
	ELSE
		ret_code	:= C_OUTOF_NEAR;
		RETURN;
	END_IF;
	Min_RtTime.pMeth			:= StoreMethod( #M_RD_DIRECT(), #M_WR_DIRECT() );
	IF Min_RtTime.pMeth THEN
		ret_code	:= C_OK;
	ELSE
		ret_code	:= C_OUTOF_NEAR;
		RETURN;
	END_IF;
	Max_RtTime.pMeth			:= StoreMethod( #M_RD_DIRECT(), #M_WR_DIRECT() );
	IF Max_RtTime.pMeth THEN
		ret_code	:= C_OK;
	ELSE
		ret_code	:= C_OUTOF_NEAR;
		RETURN;
	END_IF;
	Min_RtCallTime.pMeth			:= StoreMethod( #M_RD_DIRECT(), #M_WR_DIRECT() );
	IF Min_RtCallTime.pMeth THEN
		ret_code	:= C_OK;
	ELSE
		ret_code	:= C_OUTOF_NEAR;
		RETURN;
	END_IF;
	Max_RtCallTime.pMeth			:= StoreMethod( #M_RD_DIRECT(), #M_WR_DIRECT() );
	IF Max_RtCallTime.pMeth THEN
		ret_code	:= C_OK;
	ELSE
		ret_code	:= C_OUTOF_NEAR;
		RETURN;
	END_IF;
	ret_code	:= VaranManager();

END_FUNCTION

#pragma usingLtd Varan_Base

//{{LSL_IMPLEMENTATION
#pragma using Varan_Base

(************************************************************************************
*
*	Baseclass for varan Managercontrolling
*	Created : Sigmatek	/	SR	/	March-April 2006
*	Changes : 
*
*
*     FOR NEWER CHANGES SEE REVISION DOCUMENTATION IN CLASS PROPERTIES
*
*
*   1.12 => 1.13 /  26.05.2008
*			- [DB 863]: - add function to disable device in cyclic
*   1.11 => 1.12 /  18.04.2008
*			- [DB 852]: - extend method GetVaranTime to get the IsoStartPoint
*						- correct trace-message for missing varan interface
*		1.10 => 1.11 /  07.04.2008
*			- [DB 825]: add client to control the ISO start point
*		1.9 => 1.10	/	29.02.2008
*			- [DB 770]:	add function to log messages and log device error
*		1.8 => 1.9	/	17.12.2007
*			- [DB 713]:	add function to log messages and log device error
*		1.7 => 1.8	/	03.10.2007
*			- add function to get "SyncFrame Counter" 
*		1.6 => 1.7	/	11.07.2007
*			- [DB 620]:	Insert function to update module retry counters
*		1.5 => 1.6	/	09.07.2007
*			- [DB 619]: Insert time measurement for Rt - Jitter
*		1.4 => 1.5	/	31.05.2007
*			- [DB 581]:	only execut cy if realtime is ready
*			- [DB 590]: save function "RdDO" and "WrDO" with semaphore
*		1.3 => 1.4	/ 	04.04.2007
*			- [DB 541]: insert function to read SPI data
*		1.2 => 1.3	/	06.02.2007
*			- [DB 495]: always update Retry Counter
*		1.1 => 1.2	/	29.01.2007
*			- [DB 461]: add multiple read/write command functions
*		1.0 => 1.1	/	28.11.2006
*			first library version
*		0.2 => 1.0	/	09.10.2006	/	no Mark
*			initial version
*		0.1 => 0.2	/	13.06.2006	/	no Mark
*			second testversion 
*		0.0	=> 0.1	/	10.04.2006	/	no Mark
*			first testversion for fair in Hannover
*
************************************************************************************)

VAR_PRIVATE
  p_this                        : ^void;
  a_VendorName                  : ARRAY[0..99] OF CHAR;
  a_SerialNo			              : ARRAY[0..43] OF CHAR;
  a_DeviceName                  : ARRAY[0..99] OF CHAR;
  a_OrderingNo                  : ARRAY[0..99] OF CHAR;
  udHWVersion                   : UDINT;
  udLicenseNo                   : UDINT;
  bDiagnosisDataAvailableFlags  : BSINT
  [
    1 HWVersion,
    2 VendorName,
    3 DeviceName,
    4 OrderingNo,
    5 LicenseNo,
    6 SerialNo,
  ];
END_VAR

#pragma warning(disable: 73)
FUNCTION IRQMethodDummy
  VAR_INPUT
    pThis : ^void;
  END_VAR
END_FUNCTION
#pragma warning(default: 73)

//[#ENGLISH]
//=================================================================================================
//VaranManager Constructor
//=================================================================================================
//[globals]	_RTOSVersion			:R		:OS-Version
//[server]	ManagerOn				:W		:state of Manager (On/Off)
//			State					:W		:State of class
//[members]	s_RtHandles				:W		:structure to save Handles and thisp for realtime update methodes
//			s_CyHandles				:W		:structure to save Handles and thisp for cyclic update methodes
//			pVaran					:W		:pointer to varan interface
//[local]	p_SSR					:W/R	:pointer to get pointer to kernel log function
FUNCTION  VaranManager::VaranManager
  VAR_OUTPUT
    ret_code		      : CONFSTATES;
  END_VAR
  VAR
    p_Obj                   : ^Obj;
    p_ClsHdr                : ^ClsHdr;
    p_VMHeader              : ^ClsHdr;
    b_Varan                 : BOOL;
    ManagerNodeString       : USINT;
    ud_WFESupport           : UDINT;  // Wait for event support
    sd_retval               : DINT;
    sysProperty             : ARRAY [0..2] of LSL_PROPERTY_VALUE_PAIR;
    nodeProperty            : LSL_PROPERTY_VALUE_PAIR;
    bChangeInterframeGap    : BOOL;
    bOSInterframeGapSupport : BOOL;
    InterframeGapOS         : UDINT;
  END_VAR

  //no error for VaranManager at beginning
  State := _ClassOk;

  //set VaranManager not on
  ManagerOn := -1;

  // if there are no post init modules, we're ready instantly (otherwise this variable will get resetted)
  bPostInitModulesReady := TRUE;

  OldFrameCounter := 16#FF;
  
  // Will be set if we get an interface
  b_Varan := false;

#ifdef HWC_LogInit
  HWC_LogInit();
#else
  #pragma message("Warning! Log and trace messages of this class require a newer version of class HwControl. Please update for full functionality!")
#endif

  // Display Warning if client is connected dispite the client comment,
  if IsClientConnected(#PayloadFrame) then
#ifdef HWC_LogError
    HWC_LogError(this, "@0012 (VaranManager::VaranManager) Warning: Client PayloadFrame does not work with a connected server! Set this client as initvalue instead.");
#endif
  end_if;
  
  //always try to get multivaran interface
  if OS_CILGet(INTERFACE_MULTIVARANMANAGER, #pMultiVaran) <> SYS_ERR_NONE then
    pMultiVaran := NIL;
  end_if;

  //Check if the user wants to activate payloadframe
  if PayloadFrame = 1 & (pMultiVaran = nil) then
    PayloadFrame := 0;
#ifdef HWC_LogError
    HWC_LogError(this,"@0197 (VaranManager::VaranManager) Warning: Payload Frames are not supported, a newer OS is required.");
#endif
  end_if;
      
  //Initialize system varan manager count with 1 (if the HW/OS supports more manager we will get the exact number via system property)
  udSystemVaranManagerCnt := 1;
  
  //Check if the new VARAN-OS-Interface should be used 
  
  //Customer wants PayloadFrame by himself and multivaran interface is valid
  if ( PayloadFrame = 1 ) |
    // Multivaran Interface version is high enough for MultivaranManager (CP731-K) -> just use the new interface if PayloadFrame <> 2 --> user wants the old interface
     ( PayloadFrame <> 2 & pMultiVaran & pMultiVaran^.udVersion >= VM_MULTIVARAN_VERSION_GET_SYSTEM_PROPERTY_AVAILABLE) then 
      
      //Show on client that payload is used, will be set to zero if not available
      PayloadFrame := 1;
      
      sysProperty[0].udPropertyId    := SYS_PROP_OPERATIONAL_STATE;
      sysProperty[0].udPropertyValue := OP_STATE_LEGACY_INIT;
      sd_retval := MULTI_VARAN_iSetSystemProperties(  udPropertyCount       := 1
                                                   ,  psPropertyValuePairs  := #sysProperty[0]);
      
      if sd_retval = VARANMANAGER_PROPERTY_VALUE_INVALID then
        sd_retval := VARANMANAGER_OK;
        bSetSystemProperties := FALSE; //Set flag, that this object of varanmanager sets the system properties (so not all objects of varanmanagers sets system properties)
      else
        bSetSystemProperties := TRUE; //Set flag, that this object of varanmanager sets the system properties (so not all objects of varanmanagers sets system properties)      
      end_if;

    //Check 
    if (sd_retval <> VARANMANAGER_OK ) then
        // Because of the use of MULTI_VARAN_iGetNodeHandle we are already forced into the MULTI_VARAN_IF
#ifdef HWC_LogError
        HWC_LogError(this, "@0013 (VaranManager::VaranManager) Failed to set the init state!");
#endif
        State     := _NoVaranInterface;
        ManagerOn := 0;
      else
        // Get the Node handle of the VM Module
        ManagerNodeString := 0;
        sd_retval := MULTI_VARAN_iGetNodeHandle(  udManagerNumber := VaranManagerNr
                                                , pszHardwarePath := #ManagerNodeString
                                                , phNodeHandle    := #vmNodeHandle
                                                );
                                                
        if sd_retval <> VARANMANAGER_OK then  
          // Because of the use of MULTI_VARAN_iGetNodeHandle we are already forced into the MULTI_VARAN_IF
#ifdef HWC_LogError
          HWC_LogError(this, "@0014 (VaranManager::VaranManager) Failed to retrieve Varanmanager Handle!");
#endif
          State     := _NoVaranInterface;
          ManagerOn := 0;
        else
          // check if the FPGA supports the wait for event command (indicator for payload frames)
          sd_retval := MULTI_VARAN_iGetNodeProperty( hNodeHandle      := vmNodeHandle
                                                   , udPropertyId     := VM_PROP_PAYLOAD_WFE_SUPPORT_AVAILABLE
                                                   , pudPropertyValue := #ud_WFESupport
                                                   );
          
          if sd_retval <> VARANMANAGER_OK |
             ud_WFESupport = 0 then
            // Payload Requested but not supported by FPGA. MULTI_VARAN_IF is used!!
#ifdef HWC_LogError
            HWC_LogError(this, "@0015 (VaranManager::VaranManager) Payload Frames are not supported by the Hardware, a newer FPGA is required!");
#endif
            PayloadFrame := 0;  // Constructor! Cannot use client write()
          end_if;

          b_PayloadSupport  := true;
          
          //DMA Configuration for OS (Activate and deactivate DMA Channels)
          //**************************************************************************************************************************************
          if pMultiVaran^.udVersion >= VM_MULTIVARAN_VERSION_DMA_CHANNEL_ENABLE then
            //Property ID of DMA Channel Enable
            nodeProperty.udPropertyId    := VM_PROP_PAYLOAD_DMA_CHANNEL_ENABLE;
            
            //Here we define which channels should be used by the DMA from the OS 
            //Use DMA for everey direction
            nodeProperty.udPropertyValue := VM_MULTIVARAN_DMA_CHANNEL_ENABLE_ISO_RD OR
                                            VM_MULTIVARAN_DMA_CHANNEL_ENABLE_ISO_WR OR
                                            VM_MULTIVARAN_DMA_CHANNEL_ENABLE_ASY_RD OR
                                            VM_MULTIVARAN_DMA_CHANNEL_ENABLE_ASY_WR; 
                                            //Do not use defines from lsl_st_varan.h file because they have a wrong format (<< instead of shl)

            sd_retval := MULTI_VARAN_iSetNodeProperties( hNodeHandle           := vmNodeHandle
                                                       , udPropertyCount       := 1
                                                       , psPropertyValuePairs  := #nodeProperty
                                                       ); 
                                                       
            if sd_retval <> VARANMANAGER_OK then
#ifdef HWC_LogError
              HWC_LogError(this, "@0198 (VaranManager::VaranManager) Failed to set DMA Configuration for OS (activate channels)!");
#endif
            end_if;
          end_if;
        
        //Get amount of VARAN Manager
        //**************************************************************************************************************************************
#ifdef MULTI_VARAN_iGetSystemProperty
        if pMultiVaran^.udVersion >= VM_MULTIVARAN_VERSION_GET_SYSTEM_PROPERTY_AVAILABLE then
          sd_retval := MULTI_VARAN_iGetSystemProperty(SYS_PROP_MANAGER_COUNT,#udSystemVaranManagerCnt);
      
          if sd_retval <> VARANMANAGER_OK then
#ifdef HWC_LogError
            HWC_LogError(this, "@0199 (VaranManager::VaranManager) Failed to get system property SYS_PROP_MANAGER_COUNT");
#endif
            udSystemVaranManagerCnt := 1;
          end_if;
        end_if;
#else
  #pragma message("Warning! Multivaran does not work with this version of lsl_st_varan.h file. A newer lsl_st_varan.h file is needed");
#endif
        
          if pMultiVaran^.udVersion >= VM_MULTIVARAN_VERSION_FULL_PAYLOAD_AVAILABLE then 
            b_Varan := true;
            PayloadFrame := 1;
          end_if;
          // else both interfaces are needed
      end_if;
    end_if;
  end_if;
  
  // If we havn't got an interface yet try the old one
  if b_Varan = false then
    
      //get pointer to varan interface
    if	( OS_CILGet( INTERFACE_VARANMANAGER, #pVaran ) 
      | _RTOSVersion < 16#1184                          //because older has different function variables
      ) 
    then
        
      //if interface not found give out TRACE and set Manager off
      pVaran    := NIL;
      State     := _NoVaranInterface;
      ManagerOn := 0;
      if ( _RTOSVersion < 16#1184 ) then
#ifdef HWC_LogError
        HWC_LogError(this, "@0017 (VaranManager::VaranManager) No Varan Interface, a newer OS is required to use Varan - Bus!");
#endif
      else
#ifdef HWC_LogError
        HWC_LogError(this, "@0018 (VaranManager::VaranManager) No Varan Interface found");
#endif
      end_if;
    else
    
      //Check if we have a node information of the manager
      if b_PayloadSupport then
      
        //-----------------------------------------------------------------------------------------------   
        //get manager node info from os
        p_NodeInfo := #s_NodeInfo;
        
        sd_retval := MULTI_VARAN_iGetNodeInformation( hNodeHandle := vmNodeHandle
                                                    , psNodeInfo  := p_NodeInfo
                                                    );
        
        if	( sd_retval <> VARANMANAGER_OK 
          | p_NodeInfo = NIL
          )
        then
          //if interface not found give out TRACE and set Manager off
          pVaranSave := pMultiVaran$^DINT; //Save pointer to set varan error later
          pMultiVaran := NIL;
          State     := _NoVaranInterface;
          ManagerOn := 0;
#ifdef HWC_LogError
          HWC_LogError(this, "@0019 (VaranManager::VaranManager) Manager Node Information not found");
#endif
        end_if;
      
      //Without Payload support
      else
      
        //get manager node info from os
        ManagerNodeString := 0;
        
        //call OS - function (must be OS-funciton because of error handling)
        sd_retval := VARAN_iGetNodeInfo	( uiManager	:= VaranManagerNr
                                        , pucNode	  := #ManagerNodeString
                                        , pNodeInfo	:= #p_NodeInfo
                                        );

        if	( sd_retval <> VARANMANAGER_OK 
          | p_NodeInfo = NIL
          )
        then
          //if interface not found give out TRACE and set Manager off
          pVaranSave  := pVaran$^DINT; //Save pointer to set varan error later
          pVaran    := NIL;
          State     := _NoVaranInterface;
          ManagerOn := 0;
#ifdef HWC_LogError
          HWC_LogError(this, "@0019 (VaranManager::VaranManager) Manager Node Information not found");
#endif
        end_if;
      end_if;
    
      //If we do have an interface here, we have a varanmanager
      if pVaran then
        b_Varan := true;
      end_if;

#ifdef _LSL_TARGETARCH_ARM  // IO Image only needed for ARM  CPUs
#ifdef VARAN_iDisableOSGetSetInputImage
      if pVaran then
        if pVaran^.udVersion >= 16#00001108 then
          if VARAN_iDisableOSGetSetInputImage(VaranManagerNr) = 0 then
            b_IOImage := TRUE;
          else
#ifdef HWC_LogError
            HWC_LogError(this, "@001A (VaranManager::VaranManager) IO Image not available. Interface call failed.");
#endif
          end_if;
        else
#ifdef HWC_LogError
          HWC_LogError(this, "@001B (VaranManager::VaranManager) IO Image not available. A newer OS is needed.");
#endif
        end_if;
      end_if;
#else 
#ifdef HWC_LogError
      HWC_LogError(this, "@001C (VaranManager::VaranManager) IO Image not available. A newer lsl_st_varan.h file is needed.");
#endif
#endif
#endif
    
    end_if;
  end_if;  

  if b_Varan then
  
    // Read Manager Protocol version --------------------------------------------------------------
    if b_PayloadSupport then

      sd_retval := MULTI_VARAN_IGETNODEPROPERTY(hNodeHandle       := vmNodeHandle
                                              , udPropertyId      := ND_PROP_VARAN_PROTOCOL_VERSION
                                              , pudPropertyValue  := #ManagerProtocolVersion
                                               );
      bOSInterframeGapSupport := TRUE;
      if ( sd_retval <> VARANMANAGER_OK ) then
        // 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.
        ManagerProtocolVersion  := 0;
        bOSInterframeGapSupport := FALSE; // Remember that OS those not support INTERFRAME_GAP_TIME for logging
      end_if;
    end_if;
    
    // Handle InterframeGap -----------------------------------------------------------------------
    bChangeInterframeGap := FALSE;
    if (InterframeGap >= VM_MIN_INTERFRAMEGAPTIME) & 
       (InterframeGap <= VM_MAX_INTERFRAMEGAPTIME) then
      // User wants to change the interframegap time
      bChangeInterframeGap := TRUE;
    else
      InterframeGap := 0; // Set to 0 in case it cannot be read from OS
    end_if;
      
    if b_PayloadSupport then
      
      // Check if property is supported
      if (bOSInterframeGapSupport = TRUE) then
        
        // Check VM FPGA property is supported
        if ManagerProtocolVersion >= VM_PROTOCOLVERSION_INTERFRAME_GAP_TIME then
          
          // Compare with InterframeGap in OS
          sd_retval := MULTI_VARAN_IGETNODEPROPERTY(hNodeHandle       := vmNodeHandle
                                                  , udPropertyId      := VM_PROP_INTERFRAME_GAP_TIME
                                                  , pudPropertyValue  := #InterframeGapOS
                                                   );
                                                   
          if sd_retval <> VARANMANAGER_OK then
            // Should be impossible because bOSInterframeGapSupport = True
            HWC_LogPrintf(pThis:=this, format:= "@0675 (VaranManager::VaranManager) Failed to get property VM_PROP_INTERFRAME_GAP_TIME. Returncode: %d.",
                          p0:=#sd_retval);
            InterframeGap := 0;
          else

            if bChangeInterframeGap then
              
              // Check Interframe Gap resolution
              if (InterframeGap mod 20) <> 0 then
                InterframeGap := ((InterframeGap / 20) + 1) * 20;
              end_if;
              
              if InterframeGap <> InterframeGapOS then
              
                // Set Interframe Gap
                nodeProperty.udPropertyId    := VM_PROP_INTERFRAME_GAP_TIME;
                nodeProperty.udPropertyValue := InterframeGap;
                sd_retval := MULTI_VARAN_iSetNodeProperties(hNodeHandle           := vmNodeHandle
                                                          , udPropertyCount       := 1
                                                          , psPropertyValuePairs  := #nodeProperty
                                                           );
                if sd_retval <> VARANMANAGER_OK then
                  // Should be impossible because bOSInterframeGapSupport = True (On salamder)
                  // True on RTK because setting is not possible.
                  HWC_LogPrintf(pThis:=this, format:= "@0676 (VaranManager::VaranManager) Failed to set property VM_PROP_INTERFRAME_GAP_TIME. Returncode: %d.", 
                                p0:=#sd_retval);
                  
                  // Display version from OS/autoexe
                  InterframeGap := InterframeGapOS;
                  
                end_if;
              end_if;
            else
              // InterframeGap not set in HWK, display version from OS/autoexec
              InterframeGap := InterframeGapOS;
            end_if;
          end_if;
        
        else
          if bChangeInterframeGap then
            InterframeGap := 0;
#ifdef HWC_Logerror
            HWC_Logerror(this, "@0677 (VaranManager::VaranManager) Setting the interframegap time not supported with this VaranManager FPGA Version.");
#endif
          end_if;
        end_if;
      
      else
        if bChangeInterframeGap then
          InterframeGap := 0;
#ifdef HWC_Logerror
          HWC_Logerror(this, "@0678 (VaranManager::VaranManager) Setting the interframegap time not supported with this OS-Version.");
#endif
        end_if;
      end_if;
    else
      if bChangeInterframeGap then
        InterframeGap := 0;
#ifdef HWC_Logerror
        HWC_Logerror(this, "@0679 (VaranManager::VaranManager) Setting the interframegap time not supported with this VARAN Interface. Check the client PayloadFrame.");
#endif
      end_if;
    end_if;
    // end Handle InterframeGap -------------------------------------------------------------------

    // fetch class revision of VaranManager; We need to go down until one layer above VaranManager_Base
    p_Obj       := LSL_GetHdr(this);
    p_ClsHdr    := p_Obj^.pClsHdr;
    p_VMHeader  := NIL;
    WHILE p_clsHdr^.pBaseCls <> NIL DO // go down until there is no base - we might be derived by the user....
      p_VMHeader := p_ClsHdr; //--> VaranManager has always VaranManager_Base as Base Class; If not something went terribly wrong!
      p_ClsHdr := p_ClsHdr^.pBaseCls;
    END_WHILE;    
    
    //Log Version of VaranManager
    if InterframeGap then
      HWC_LogPrintf(pThis:=this, format:= "@0640 (VaranManager::VaranManager) VaranManager %u: Started with Version %V2.%V2. Interframe gap time: %u ns.", 
                    p0:=#VaranManagerNr, p1:=#p_VMHeader^.pDsc^.udRev.Hi, p2:=#p_VMHeader^.pDsc^.udRev.Lo, p3:=#InterframeGap);
    else
#ifdef HWC_LogValue3
      HWC_LogValue3(this, "@0640 (VaranManager::VaranManager) VaranManager {0}: Started with Version {1}.{2}", VaranManagerNr, p_VMHeader^.pDsc^.udRev.Hi, p_VMHeader^.pDsc^.udRev.Lo);
#endif
    end_if;
    
    // lower and higher revision is limited to 2 byte, so we merge 'em into 1 HDINT
    VaranManagerRevision := (p_VMHeader^.pDsc^.udRev.Hi SHL 16) OR (p_VMHeader^.pDsc^.udRev.Lo AND 16#FFFF);

    //--------------------------------------------------------------------------------------------------------------------
    //allocate memory for realtime handles
    s_RtHandles.ud_MaxHandles       := VM_START_HANDLES;
    s_RtHandles.p_HandleList$^void  := To_StdLib.Malloc( size := s_RtHandles.ud_MaxHandles * sizeof( t_s_OneHandle ) );

    //set memory to 0 (for better diagnostics)
    if ( s_RtHandles.p_HandleList ) then
  
      To_StdLib.MemSet( dest  := s_RtHandles.p_HandleList
                      , value := 0
                      , size  := s_RtHandles.ud_MaxHandles * sizeof( t_s_OneHandle ) 
                      );

    else
      //we got no memory (set Manager off and log the error)
      State     := _MemoryFault;    //set Varan error
      ManagerOn := 0;

      //Log entry
#ifdef HWC_LogValue1
      HWC_LogValue1(this, "@067C (VaranManager::VaranManager) No Memory for Varan Manager available! (Make Rt - Handles: {0})", s_RtHandles.ud_MaxHandles);
#endif
    end_if;

    //we always execute realtime DOL list because of triggering the pll of varan modules
    s_RtHandles.b_ExecuteDOL := TRUE;


    //allocate memory for realtime-postscan handles
    s_RtPostScanHandles.ud_MaxHandles       := VM_START_HANDLES;
    s_RtPostScanHandles.p_HandleList$^void  := To_StdLib.Malloc( size := s_RtPostScanHandles.ud_MaxHandles * sizeof( t_s_OneHandle ) );

    //set memory to 0 (for better diagnostics)
    if ( s_RtPostScanHandles.p_HandleList ) then
  
      To_StdLib.MemSet( dest  := s_RtPostScanHandles.p_HandleList
                      , value := 0
                      , size  := s_RtPostScanHandles.ud_MaxHandles * sizeof( t_s_OneHandle ) 
                      );

    else
      //we got no memory (set Manager off and log the error)
      State     := _MemoryFault;    //set Varan error
      ManagerOn := 0;

      //Log entry
#ifdef HWC_LogValue1
      HWC_LogValue1(this, "@001D (VaranManager::VaranManager) No Memory for Varan Manager available! (Make RtPostScan - Handles: {0})", s_RtPostScanHandles.ud_MaxHandles);
#endif
    end_if;

    //--------------------------------------------------------------------------------------------------------------------
    //allocate memory for cyclic handles
    s_CyHandles.ud_MaxHandles       := VM_START_HANDLES;
    s_CyHandles.p_HandleList$^void  := To_StdLib.Malloc( size := s_CyHandles.ud_MaxHandles * sizeof( t_s_OneHandle ) );

    //set memory to 0 (for better diagnostics)
    if ( s_CyHandles.p_HandleList ) then
  
      To_StdLib.MemSet( dest  := s_CyHandles.p_HandleList
                      , value := 0
                      , size  := s_CyHandles.ud_MaxHandles * sizeof( t_s_OneHandle ) 
                      );

    else
      //we got no memory (give out TRACE, set off memory)
      State     := _MemoryFault;    //set varan error
      ManagerOn := 0;

      //Log entry
#ifdef HWC_LogValue1
      HWC_LogValue1(this, "@0686 (VaranManager::VaranManager) No Memory for Varan Manager available! (Make Cy - Handles: {0})", s_CyHandles.ud_MaxHandles);
#endif
    end_if;

    //--------------------------------------------------------------------------------------------------------------------
    //allocate memory for Module list
    s_ModuleList.ud_MaxModules        := VM_START_HANDLES;
    s_ModuleList.p_ModuleList$^void   := To_StdLib.Malloc( size := s_ModuleList.ud_MaxModules * sizeof( p_VaranBase ) );
    s_ModuleList.p_PositionList$^void := To_StdLib.Malloc(size:= s_ModuleList.ud_MaxModules * sizeof(pVoid));

    //set memory to 0 (for better diagnostics)
    if ( s_ModuleList.p_ModuleList ) then
  
      To_StdLib.MemSet( dest  := s_ModuleList.p_ModuleList
                      , value := 0
                      , size  := s_ModuleList.ud_MaxModules * sizeof( p_VaranBase ) 
                      );

    else
      //we got no memory (give out TRACE, set off memory)
      State     := _MemoryFault;    //set Varan error
      ManagerOn := 0;

      //Log entry
#ifdef HWC_LogValue1
      HWC_LogValue1(this, "@001E (VaranManager::VaranManager) No Memory for Varan Manager available! (Make Module List: {0})", s_ModuleList.ud_MaxModules);
#endif
    end_if;
    
    //set memory to 0 (for better diagnostics)
    if ( s_ModuleList.p_PositionList ) then

      To_StdLib.MemSet( dest  := s_ModuleList.p_PositionList
                      , value := 0
                      , size  := s_ModuleList.ud_MaxModules * sizeof( pVoid ) 
                      );

    else
      //we got no memory (give out TRACE, set off memory)
      State     := _MemoryFault;    //set Varan error
      ManagerOn := 0;

      //Log entry
#ifdef HWC_LogValue1
      HWC_LogValue1(this, "@001F (VaranManager::VaranManager) No Memory for Varan Manager available! (Make Position List: {0})", s_ModuleList.ud_MaxModules);
#endif
    end_if;

    //get interface for hardwaretree functions
    if ( OS_CILGET(INTERFACE_HARDWARETREE, #pHardwareTree)) then
      pHardwareTree := NIL;

#ifdef HWC_LogError
      HWC_LogError(this, "@0020 (VaranManager::VaranManager) Hardwaretree-Interface not found. A newer OS is required for Safety-Modules");
#endif
    end_if;
  end_if;
  
  ret_code := C_OK;    //Construction ok

END_FUNCTION //  VaranManager::VaranManager

//[#ENGLISH]
//=================================================================================================
//Init for VaranManager
//=================================================================================================
//[server]	ManagerOn				:W		:state of Manager (On/Off)
//			State					:W		:State of class
//			Release					:W		:FPGA - version
//[clients]	VaranManagerNr			:R		:number of varan manager
//			VaranManagerTime		:R		:time of varan manager
//[members]	s_VaranManagerSettings	:W		:structure for different varan settings
//			s_VaranTimes			:W		:structure for varan time measurement
//			s_VMFunctions			:W		:structure for HwControl class
//			p_NodeInfo				:W/R	:pointer to node info for master (from OS)
//			p_ManagerStructure		:W/R	:pointer for manager structure (from OS)
//			ud_SystemPeriode		:W		:variable for system period
//			p_ManagerPll			:W/R	:pointer to Varan pll (from OS)
//			p_SyncOut				:W/R	:pointer to right sync out
//			p_SyncData				:W/R	:pointer to sync data object
//[locals]	us_pos			:W		:to get node information for master
FUNCTION VIRTUAL GLOBAL VaranManager::Init

  
  //look if varan interface is ok
  if ( State = _NoVaranInterface ) then
  
    if ( s_VaranManagerSettings.us_InitCounter = 7 ) then
      
      PreventManagerError := PreventManagerError.Read();
      if SetRequiredError = TRUE & PreventManagerError <> 1 then   
#ifdef HWC_LogError
        HWC_LogError(this, "@0021 (VaranManager::Init) No VaranInterface for Required Module");
#endif
        
        case _WhoAmI of
          DESTPLC_WINPC_98,    // LARS, Standard PC, Win98/ME
          DESTPLC_WINPC_NT,    // LARS, Standard PC, WinNT/Win2000/WinXP
          DESTPLC_WINIPC_98,   // LARS, IPC, Win98/ME
          DESTPLC_WINIPC_NT:   // LARS, IPC, WinNT/Win2000/WinXP
          
          //LARS 
          //EisMic: Don't execute a varan error when target platform is lars due to SA 28840
          
          else
          //--- rtk-os
            if _rtosversion >= 16#1296 then
              To_OSKernel.AddToServiceProvider(command:="exec climsg 45 A VARAN module is set required, but there is no VARAN Interface", immediatly:=1);  //stop application
            else
              To_OSKernel.Reset();  //stop application, because this OS doesn't support the message and the CPU state
            end_if;
            
            //if We reach this code here, stop of application has not worked, try to set varan error in other ways
            
            //State is no interface -> look if we can get pVaran or pMultiVaran Pointer, is reset if cpu has no VARAN, but interface could be available
            if pVaranSave then
            
              pMultiVaran := pVaranSave$^LSL_MULTI_VARAN;
              pVaran := pVaranSave$^LSL_VARAN;

              if b_PayloadSupport & pMultiVaran^.udVersion >= VM_MULTIVARAN_VERSION_FULL_PAYLOAD_AVAILABLE  then
              
                MULTI_VARAN_iReportVaranError( diErrorNumber := VM_ERROR_REQUIRED
                                             , hErrorNode    := vmNodeHandle
                                             );

              elsif pVaran & (pVaran^.udVersion >= 16#00001104 ) then
              
                VARAN_iSetManagerError( VaranManagerNr, VM_ERROR_REQUIRED );
              end_if;
            end_if;
                      
        end_case;
      end_if;  
    end_if;  
  else
  
    case s_VaranManagerSettings.us_InitCounter of
    
      0 : // must be in first init phase
          if bFirstInitDone = false then
            FirstInit();
          end_if;      

      7 : // all Varan_Base are ready with init
          if (s_ModuleList.ud_NrOfModules = 0) & (bEnableManagerWithNoModules = FALSE) then
            // penultimate call: if there are no clients => tell the hwcontrol to disable this 
            To_HwControl.DisableVaranManager( ud_manager_number := VaranManagerNr
                                            , p_function_list   := #s_VMFunctions
                                            );
            State 		:= _NotInitialized;
          	ManagerOn := 0;                   //Disables Rt Task
          	bDisableCyTaskNoModules := TRUE;  //Disables Cy Task
          end_if;

    end_case;	


    //trigger watchdog in init
    TriggerWatchdog();

  end_if;
  
  //increment our initcounter
  s_VaranManagerSettings.us_InitCounter += 1;
  
END_FUNCTION //VIRTUAL GLOBAL VaranManager::Init

//[#ENGLISH]
//=================================================================================================
//This function is called in PostScan by VaranManagerPostScan
//=================================================================================================
//[servers]	ManagerOn				:R		:state of Manager (On/Off)
//			RetryCounter			:W		:server counts retries 
//			AsyVaranTime			:W		:time of asynchronous varan task
//[members]	s_CyHandles				:R		:structure to save Handles and thisp for cyclic update methodes
//			s_VaranTimes			:W		:structure for varan time measurement
//			us_UpdateOkCy			:R/W	:if variable = 1 then varan classes are called
//			p_ManagerStructure		:R		:pointer for manager structure (from OS)
//			s_VaranManagerSettings	:R/W	:structure for different varan settings
FUNCTION VIRTUAL GLOBAL VaranManager::CyWork
  VAR_INPUT
    EAX		              : UDINT;
  END_VAR
  VAR_OUTPUT
    state	    	        : UDINT;
  END_VAR
  VAR
    us_retry_counter	  : USINT;
    pHelp               : ^t_s_OneHandle;
    asyState            : UDINT;
    asyTimestamp        : UDINT;
  #ifndef VARAN_TIME_MEASUREMENT_DEACTIVATE
    ud_time				      : UDINT;
  #endif
    i				          	: UDINT;  
    AsyReady            : BOOL;
    pHelpPostInit       : ^t_s_PostInitList;
  #ifdef VARAN_TIME_MEASUREMENT_SINGLE_OBJECTS
    ud_SingleTimeMark1  : UDINT;
    ud_SingleTimeMark2  : UDINT;  
  #endif
  END_VAR

  //look if structur is ok, also check if cywork should be disabled due to no connected modules  
  if ( p_ManagerStructure = NIL & b_PayloadSupport = false) | ( bDisableCyTaskNoModules = TRUE ) then
    return;
  end_if;

  //look if cyclic task is ready (executed)
  if b_PayloadSupport &
     pMultiVaran^.udVersion >= VM_MULTIVARAN_DOL_TIMING_AVAILABLE then

    MULTI_VARAN_iGetNodeProperty( hNodeHandle       := vmNodeHandle
                                , udPropertyId      := VM_PROP_TASK_STATE_ASY
                                , pudPropertyValue  := #asyState
                                );                                  
    
    if asyState = TK_STATE_EXECUTING then
      AsyReady := FALSE;
    else
      AsyReady := TRUE;
    end_if;
  else
    AsyReady := (p_ManagerStructure^.sASY.ucHandshake and 16#10 ) <> 0;
  end_if;

#ifdef _LSL_TARGETARCH_ARM  // IO Image only needed for ARM  CPUs
#ifdef VARAN_iGetInputImage 
  //look if manager is on or we are in post init phase (ManagerOn will be set in first realtime but we want to do something here in postinit) 
  if ( ManagerOn = 1 ) | bPostInitActive = TRUE then
    if AsyReady then
      if b_IOImage then
        VARAN_iGetInputImage(VaranManagerNr, VARAN_DOL_ASY);
      end_if;       
    end_if;
  end_if;
#endif
#endif  

  // if there is a safety manager, we have to call it (but not from post init)
  if SafetyManagerThis & (bPostInitActive = FALSE) then
    SafetyManagerThis^.CyWork(0);
  end_if;

  //------------------------------------------------------------------------------------------------
  //first check Error
  if ( s_VaranManagerSettings.b_LogError = TRUE ) then
    LogError();
  end_if;

  // then check for rt log
  if bd_RtLog then
    if bd_RtLog.WatchdogTriggerFailed & (bd_RtLogged.WatchdogTriggerFailed = FALSE) then
#ifdef HWC_LogError
    HWC_LogError(this, "@0022 (VaranManager::CyWork) [SL] Error triggering the VaranManager Watchdog!");
#endif
      
      bd_RtLogged.WatchdogTriggerFailed := TRUE;
    end_if;
    
    if bd_RtLog.TimeSliceError & (bd_RtLogged.TimeSliceError = FALSE) then
#ifdef HWC_LogError
      HWC_LogError(this,"@019A (VaranManager::CyWork) Timeslice Error! Manager is set off!");
#endif
      
      bd_RtLogged.TimeSliceError := TRUE;
    end_if;
    
    bd_RtLog := 0;
  end_if;

#ifndef VARAN_TIME_MEASUREMENT_DEACTIVATE
  //measure time for cyclic
  ud_time := GetNsTime();
  s_VaranTimes.s_Cyclic.ud_CallTime := ( ud_time - s_VaranTimes.s_Cyclic.ud_Timemark ) / 1000;
  s_VaranTimes.s_Cyclic.ud_Timemark := ud_time;
#endif

  //check if we must disable a device
  if ( b_Disabledevice = TRUE ) then
    DisableDevice();
  end_if;

  //Update retry Counter
  if b_PayloadSupport &
     pMultiVaran^.udVersion >= VM_MULTIVARAN_VERSION_FULL_PAYLOAD_AVAILABLE  then    
    MULTI_VARAN_iGetNodeProperty( hNodeHandle       := vmNodeHandle
                                , udPropertyId      := VM_PROP_GLOBAL_FAILED_ACCESS_COUNTER
                                , pudPropertyValue  := (#us_retry_counter)$^UDINT
                                );    
  else
    us_retry_counter := p_ManagerStructure^.ucGlobalretryCounter;
  end_if;


  //look for change
  if ( us_retry_counter <> s_VaranManagerSettings.us_OldRetryCounter ) then

    //save on global counter
    RetryCounter += TO_USINT( us_retry_counter - s_VaranManagerSettings.us_OldRetryCounter );

    //save new counter
    s_VaranManagerSettings.us_OldRetryCounter := us_retry_counter;

    //update module retry counters cyclic
    if ( s_CyHandles.ud_NrOfHandles > 0 ) then

      //call all connected classes
      pHelp := #s_CyHandles.p_HandleList^[0];
      for i := 0 to s_CyHandles.ud_NrOfHandles - 1 do

        //call class
        pHelp^.p_This^.UpdateRetryCounter();
        
        //get pointer on next handle
        pHelp += sizeof(t_s_OneHandle);
      end_for;
    end_if;

    //update module retry counters cyclic
    if ( s_RtHandles.ud_NrOfHandles > 0 ) then

      //call all connected classes
      pHelp := #s_RtHandles.p_HandleList^[0];
      for i := 0 to s_RtHandles.ud_NrOfHandles - 1 do

        //call class
        pHelp^.p_This^.UpdateRetryCounter();
      
        //get pointer on next handle
        pHelp += sizeof(t_s_OneHandle);
      end_for;
    end_if;
  end_if;


  //look if manager is on or we are in post init phase (ManagerOn will be set in first realtime but we want to do something here in postinit) 
  if ( ManagerOn = 1 ) | bPostInitActive = TRUE then

    //------------------------------------------------------------------------------------------------
    //look if cyclic task is ready (executed)
    if AsyReady = FALSE then
      s_VaranManagerSettings.us_NoCyclicUpdateCnt += 1;
      return;	
    end_if;
    

#ifndef VARAN_TIME_MEASUREMENT_DEACTIVATE
    //------------------------------------------------------------------------------------------------
    //calculate cyclictime of varan task
    if b_PayloadSupport &
       pMultiVaran^.udVersion >= VM_MULTIVARAN_VERSION_FULL_PAYLOAD_AVAILABLE  then
      MULTI_VARAN_iGetNodeProperty( hNodeHandle       := vmNodeHandle
                                  , udPropertyId      := VM_PROP_ASY_TIME_UP_COUNTER
                                  , pudPropertyValue  := #asyTimestamp
                                  );
    else    
      asyTimestamp := p_ManagerStructure^.sASY.uiTTUpCounter;
    end_if;

    
    if ( s_VaranTimes.s_AsyVaranTime.us_NotFirstRun	= 0 ) then

      //get counter of asy task
      s_VaranTimes.s_AsyVaranTime.ud_Timestamp := asyTimestamp;

      //start asy task
      if ( s_CyHandles.b_ExecuteDOL = TRUE ) then
        ExecuteDOL( VARAN_DOL_ASY );
      end_if;

      s_VaranTimes.s_AsyVaranTime.us_NotFirstRun := 1;
      return;
    end_if;
    
    //calculate ASY Time
    s_VaranTimes.s_AsyVaranTime.ud_ActUsageRate := asyTimestamp - s_VaranTimes.s_AsyVaranTime.ud_Timestamp;
    s_VaranTimes.s_AsyVaranTime.ud_Timestamp    := asyTimestamp;

    //look for maximum value
    if ( s_VaranTimes.s_AsyVaranTime.ud_ActUsageRate > s_VaranTimes.s_AsyVaranTime.ud_MaxUsageRate ) then
      s_VaranTimes.s_AsyVaranTime.ud_MaxUsageRate := s_VaranTimes.s_AsyVaranTime.ud_ActUsageRate;
    end_if;

    //save on server
    AsyVaranTime$UDINT := s_VaranTimes.s_AsyVaranTime.ud_ActUsageRate;
#endif

    //----------------------------------------------------------------------------------------------
    //hardware class handling

    // in post init we call only the modules which are logged in for post init
    if bPostInitActive then
      if PostInitModuleCnt then
        pHelpPostInit := #aPostInitList[0];
        for i := 0 to PostInitModuleCnt - 1 do
          
          //call class, if it's still not ready
          if pHelpPostInit^.p_This & pHelpPostInit^.b_CallMe then
            pHelpPostInit^.p_This^.UpdateCy();
          end_if;

          // set pointer on next this pointer
          pHelpPostInit += sizeof(t_s_PostInitList);
        end_for;
      end_if;
    else
      //look if we have classes
      if ( s_CyHandles.ud_NrOfHandles > 0 ) then
    
        //call all connected classes
        pHelp := #s_CyHandles.p_HandleList^[0];
        for i := 0 to s_CyHandles.ud_NrOfHandles - 1 do

#ifdef VARAN_TIME_MEASUREMENT_SINGLE_OBJECTS
          ud_SingleTimeMark1 := OS_READMICROSEC();
#endif

          //call class
          pHelp^.p_This^.UpdateCy();

#ifdef VARAN_TIME_MEASUREMENT_SINGLE_OBJECTS
          ud_SingleTimeMark2 := OS_READMICROSEC();
          pHelp^.TimeMeasuring.ud_ActTime := ud_SingleTimeMark2 - ud_SingleTimeMark1;
          
          if pHelp^.TimeMeasuring.ud_ActTime > pHelp^.TimeMeasuring.ud_MaxTime then
            pHelp^.TimeMeasuring.ud_MaxTime := pHelp^.TimeMeasuring.ud_ActTime;
          end_if;

          if pHelp^.TimeMeasuring.ud_ActTime < pHelp^.TimeMeasuring.ud_MinTime then
            pHelp^.TimeMeasuring.ud_MinTime := pHelp^.TimeMeasuring.ud_ActTime;
          end_if;
#endif

          //get pointer on next handle
          pHelp += sizeof(t_s_OneHandle);
        end_for;
      end_if;
    end_if;

    //start asy task
    if ( s_CyHandles.b_ExecuteDOL = TRUE ) then
      ExecuteDOL( VARAN_DOL_ASY );	
    end_if;
    
  //------------------------------------------------------------ Client Instructions --------------------------------------------------------|
  //                                                                                                                                         V
    //DPRAM data handling        
    if ( IsAlsoClient & p_ManagerClientSpace <> NIL ) then
    
      // copy data to ram 
      // ->WRITE<-
      To_Stdlib.MemCpy( dest := #p_ASYDataWrite^.a_Data[0],     // Mem for p_ASYDataWrite is reserved in VaranManager2
                        source := AsyWriteData.pSDOData,        // Mem for AsyWriteData is reserved in VaranManager2
                        size := SafetyAsyMemWrite$UDINT
                      );
      
      // copy user data from application memory  
      if UserObjectData.pAsyWriteData then
        To_Stdlib.MemCpy( dest := #p_ASYDataWrite^.a_Data[0] + SafetyAsyMemWrite, 
                          source := UserObjectData.pAsyWriteData, 
                          size := UserObjectData.udAsyWriteLength
                        );                  
    end_if;

      if (SafetyAsyMemWrite$UDINT + UserObjectData.udAsyWriteLength) > sizeof(UDINT) then
          To_Stdlib.MemCpy( dest    := p_ManagerClientSpace + VM_CLIENT_ASY_WR_OFFSET + sizeof(UDINT)
                          , source  := p_ASYDataWrite + sizeof(UDINT)
                          , size    := SafetyAsyMemWrite$UDINT + UserObjectData.udAsyWriteLength - sizeof(UDINT)
                          );
      end_if;

      //copy the first 4 bytes to DPRAM (to switch the shift buffer at the right moment)
      ((p_ManagerClientSpace + VM_CLIENT_ASY_WR_OFFSET)$^UDINT)^  := (p_ASYDataWrite$^UDINT)^;   

      
      // copy read data to allocated space 
      // ->READ<-
      if (SafetyAsyMemRead$UDINT + UserObjectData.udAsyReadLength) > sizeof(UDINT) then
        To_Stdlib.MemCpy( dest    := #p_ASYDataRead^.a_Data[0] + sizeof(UDINT)
                        , source  := p_ManagerClientSpace + VM_CLIENT_ASY_RD_OFFSET + sizeof(UDINT)
                        , size    := SafetyAsyMemRead$UDINT + UserObjectData.udAsyReadLength - sizeof(UDINT)
                        );
            end_if;
          
      //copy the first 4 bytes out of DPRAM (to switch the shift buffer at the right moment)
      (p_ASYDataRead$^UDINT)^ := ((p_ManagerClientSpace + VM_CLIENT_ASY_RD_OFFSET)$^UDINT)^; 
        
      // copy data to application memory
      To_Stdlib.MemCpy( dest    := AsyReadData.pSDOData, 
                        source  := #p_ASYDataRead^.a_Data[0], 
                        size    := SafetyAsyMemRead$UDINT 
                      );
                        
      // copy user data to application memory
      if UserObjectData.pAsyReadData then
        To_Stdlib.MemCpy( dest    := UserObjectData.pAsyReadData, 
                          source  := #p_ASYDataRead^.a_Data[0] + SafetyAsyMemRead, 
                          size    := UserObjectData.udAsyReadLength
                        );       
      end_if;
    
    end_if;
//------------------------------------------------------------ Client Instructions --------------------------------------------------------^
//                                                                                                                                         |    
  end_if;

#ifndef VARAN_TIME_MEASUREMENT_DEACTIVATE
  //get cyclic time
  ud_time := GetNsTime();
  s_VaranTimes.s_Cyclic.ud_ActTime := ( ud_time - s_VaranTimes.s_Cyclic.ud_Timemark ) /1000;

  //get maximal time
  if ( s_VaranTimes.s_Cyclic.ud_ActTime > s_VaranTimes.s_Cyclic.ud_MaxTime ) then
    s_VaranTimes.s_Cyclic.ud_MaxTime := s_VaranTimes.s_Cyclic.ud_ActTime;
      end_if;
#endif

  State := READY;


END_FUNCTION //VIRTUAL GLOBAL VaranManager::CyWork
//[#ENGLISH]
//=================================================================================================
//Normal Rt - Funktion for VaranManager_Base
//=================================================================================================
//[servers]	ManagerOn				:R		:marks VaranManager as valid / ok
//			IsoVaranTime			:W		:time of isochronous varan task
//[members]	s_RtHandles				:R		:structure to save Handles and thisp for realtime update methodes
//			s_VaranTimes			:W		:structure for varan time measurement
//			us_UpdateOkRt			:R/W	:if variable = 1 then varan classes are called
//			p_ManagerStructure		:R		:pointer for manager structure (from OS)
//			s_VaranManagerSettings	:R/W	:structure for different varan settings
//			p_SyncOut				:R		:pointer to Varan sync out
//			p_SyncData				:R		:pointer to sync data object
FUNCTION VIRTUAL GLOBAL VaranManager::RtWork
  VAR_INPUT
    EAX		                    : UDINT;
  END_VAR
  VAR_OUTPUT
    state	    	              : UDINT;
  END_VAR
  VAR
    i			                    : UDINT;
    pHelp                     : ^t_s_OneHandle;
  #ifndef VARAN_TIME_MEASUREMENT_DEACTIVATE
    ud_time				            : UDINT;
    ud_IsoDuration            : UDINT;
  #endif
    ud_IsoState               : UDINT;
    systemProperty            : LSL_PROPERTY_VALUE_PAIR;  
    us_newFrameCountThreshold : USINT;
    us_ControlStatus          : USINT;
    
  #ifdef VARAN_TIME_MEASUREMENT_SINGLE_OBJECTS
    ud_SingleTimeMark1        : UDINT;
    ud_SingleTimeMark2        : UDINT;
  #endif
  END_VAR

  //------------------------------------------------------------------------------------------------
  //if manager is not initialized
  if ( ManagerOn = -1 ) then		
    
    // activate sync out for iso buffer
    if IsAlsoClient then  // ----------------------------------------------------------------------------------------------------
    
      // wait until hw-classes are synchrony
      if s_VMFunctions.b_HWClassSynchron = FALSE then

        //first trigger watchdog
        if ( b_RtDebug | ops.tAbsolute - s_VaranManagerSettings.ud_WatchdogTimemark > VM_WATCHDOG_TRIGGER_TIME ) then
          
          s_VaranManagerSettings.ud_WatchdogTimemark := ops.tAbsolute;
          TriggerWatchdog();			//trigger watchdog on varan Manager (local)
        end_if;
        return;
      end_if;

      // after this step, it's not necessary to check framecounter in hw_control anymore
      s_VMFunctions.b_OverrideFrameCheck := TRUE;

      // if superior system is slower, start with the sync after next
      if SuperiorSystemTime > VaranManagerTime then

        if b_PayloadSupport &
          pMultiVaran^.udVersion >= VM_MULTIVARAN_VERSION_FULL_PAYLOAD_AVAILABLE  then
          MULTI_VARAN_iGetNodeProperty( hNodeHandle       := vmNodeHandle
                                      , udPropertyId      := VM_PROP_PLL_SYNC_TIME_FRAME_COUNTER
                                      , pudPropertyValue  := (#us_newFrameCountThreshold)$^UDINT
                                      );
          us_newFrameCountThreshold += 2;
        else
          us_newFrameCountThreshold := p_ManagerPll^.ucSyncTimeFrameCounter + 2;
        end_if;
      
        p_SyncOut^.ucFrameCountThreshold := us_newFrameCountThreshold;
        p_SyncOutISOSwitch^.ucFrameCountThreshold := us_newFrameCountThreshold;
        
      else
      // otherwise don't use syncframecounter
        ucIsoSwitchTemp     := ucIsoSwitchTemp    AND 2#11111101;
        ucVaranManagerTemp  := ucVaranManagerTemp AND 2#11111101;
      end_if;
    
      p_SyncOutISOSwitch^.ucControlStatus := ucIsoSwitchTemp;

      // Write p_SyncOutISOSwitch
      if b_PayloadSupport &
          pMultiVaran^.udVersion >= VM_MULTIVARAN_VERSION_GET_SYSTEM_PROPERTY_AVAILABLE then
        MULTI_VARAN_ICONFIGUREPLLSYNCOUT( hManagerNodeHandle    := vmNodeHandle
                                        , udSyncOutId           := VM_CLIENT_ISO_SWITCH_ID
                                        , udPeriodMultiplier    := p_SyncOutISOSwitch^.ucPeriodMultiplier
                                        , udFrameCountThreshold := p_SyncOutISOSwitch^.ucFrameCountThreshold
                                        , udControlStatus       := p_SyncOutISOSwitch^.ucControlStatus
                                        );  
      end_if;      

      // activate sync out for varan manager (bit0 = 1)
      p_SyncOut^.ucControlStatus := ucVaranManagerTemp;
    else
      // activate sync out for varan manager (bit0 = 1)
      p_SyncOut^.ucControlStatus := 1;    

    end_if; // if IsAlsoClient // ----------------------------------------------------------------------------------------------------   

      // Always write sync out, cannot directly be written with payload support
    if b_PayloadSupport &
       pMultiVaran^.udVersion >= VM_MULTIVARAN_VERSION_GET_SYSTEM_PROPERTY_AVAILABLE  then
      MULTI_VARAN_ICONFIGUREPLLSYNCOUT( hManagerNodeHandle    := vmNodeHandle
                                      , udSyncOutId           := VM_SYNC_OUT_ID
                                      , udPeriodMultiplier    := p_SyncOut^.ucPeriodMultiplier
                                      , udFrameCountThreshold := p_SyncOut^.ucFrameCountThreshold
                                      , udControlStatus       := p_SyncOut^.ucControlStatus
                                      );
    end_if;

    //set manager on
    ManagerOn                             := 1;
    
    //to wait until we must be sync
    s_VaranManagerSettings.us_Wait4Sync   := 3;
    
    //to wait for Rtwork, we must be sync
    s_VaranManagerSettings.us_Wait4RtWork := 7;

    us_RtStep := _Wait4Sync;
    return;							
  end_if;

  //------------------------------------------------------------------------------------------------
  //check if manager on
  if ( ManagerOn <> 1 ) then
    return;
  end_if;

  //first trigger watchdog
  if ( b_RtDebug | ops.tAbsolute - s_VaranManagerSettings.ud_WatchdogTimemark > VM_WATCHDOG_TRIGGER_TIME ) then
    
    s_VaranManagerSettings.ud_WatchdogTimemark := ops.tAbsolute;
    TriggerWatchdog();			//trigger watchdog on varan Manager (local)       
    
    // trigger watchdog on clients (only if vmc is waiting for beeing synchron)
    if TriggerClientWD then
      
      if b_PayloadSupport &
         pMultiVaran^.udVersion >= VM_MULTIVARAN_VERSION_FULL_PAYLOAD_AVAILABLE  then
        MULTI_VARAN_iTriggerWatchdog( hManagerNodeHandle  := vmNodeHandle
                                    , udWatchdogType      := LSL_WD_TYPE_CLIENT
                                    );
      else

#ifdef VARAN_iTriggerClientWd      
        VARAN_iTriggerClientWd(VaranManagerNr);
#endif         
      end_if;
    end_if;   
  end_if;


#ifdef _LSL_TARGETARCH_ARM  // IO Image only needed for ARM  CPUs
#ifdef VARAN_iGetInputImage
  if b_IOImage then
    VARAN_iGetInputImage(VaranManagerNr, VARAN_DOL_ISO);
  end_if;        
#endif
#endif  

  // Payload Support 
  if b_PayloadSupport &
     pMultiVaran^.udVersion >= VM_MULTIVARAN_VERSION_FULL_PAYLOAD_AVAILABLE then
      //set frame counter in Sync data object and trigger client watchdogs
      MULTI_VARAN_iIncrementSyncCounter(hManagerNodeHandle := vmNodeHandle);
  else
    //set frame counter in Sync data object and trigger client watchdogs
    p_SyncData^.us_FrameCounter := p_SyncData^.us_FrameCounter + 1;
  end_if;

  //------------------------------------------------------------------------------------------------
  //look which step we have
  case ( us_RtStep ) of
//**********************************************************************************************************************************************************
    _Wait4Sync:		//wait some ticks (to be synchron)
      //look for either sync counter is zero or pll is locked and device delay time is compensated (if we use VMC)
      if ( s_VaranManagerSettings.us_Wait4Sync = 0 ) then
        us_RtStep := _InitVaranManager;
        return;        
      elsif IsAlsoClient then 

        // Read Pll Status Register
        if b_PayloadSupport &
           pMultiVaran^.udVersion >= VM_MULTIVARAN_VERSION_FULL_PAYLOAD_AVAILABLE  then
          MULTI_VARAN_iGetNodeProperty( hNodeHandle       := vmNodeHandle
                                      , udPropertyId      := VM_PROP_PLL_STATUS_REGISTER
                                      , pudPropertyValue  := (#us_ControlStatus)$^UDINT
                                      );
        else

          us_ControlStatus := p_ManagerPll^.ucControlStatus;
        end_if;       
      
        if (((us_ControlStatus AND 2#0101) <> 2#0101) | (s_VMFunctions.b_HWClassSynchron = FALSE)) then
          // do countdown just after we got pll synchrony
          return;
        end_if;
      end_if;

      s_VaranManagerSettings.us_Wait4Sync -= 1; 
    
//**********************************************************************************************************************************************************
    _InitVaranManager:		//Init Varan Manager (OS)	

      if b_PayloadSupport &
         pMultiVaran^.udVersion >= VM_MULTIVARAN_VERSION_FULL_PAYLOAD_AVAILABLE  then // ---------------------------------------------------------------------------------     
      
        //call init of OS to init varan command list and start varan bus
        // (Replaces VARAN_iInitApp)
     
        //Only set system properties once per system
        if (bSetSystemProperties = TRUE) then
                
          systemProperty.udPropertyId     := SYS_PROP_OPERATIONAL_STATE;
          systemProperty.udPropertyValue  := OP_STATE_POST_INIT;
          MULTI_VARAN_iSetSystemProperties( udPropertyCount       := 1
                                          , psPropertyValuePairs  := #systemProperty
                                          );
        end_if;
                                              
        
#ifndef VARAN_TIME_MEASUREMENT_DEACTIVATE      
        //get iso counter of FPGA to calculate ISO Time
        MULTI_VARAN_iGetIsoDuration ( hManagerNodeHandle  := vmNodeHandle
                                    , pudIsoDurationNs    := #s_VaranTimes.s_IsoVaranTime.ud_Timestamp
                                    );
#endif

        //get old retry counter
        MULTI_VARAN_iGetNodeProperty( hNodeHandle       := vmNodeHandle
                                    , udPropertyId      := VM_PROP_GLOBAL_FAILED_ACCESS_COUNTER
                                    , pudPropertyValue  := (#s_VaranManagerSettings.us_OldRetryCounter)$^UDINT
                                    );   
      else  // if b_PayloadSupport then // ---------------------------------------------------------------------------------

        //call init of OS to init varan command list and start varan bus
        if pVaran then
          VARAN_iInitApp( VaranManagerNr );
        end_if;

#ifndef VARAN_TIME_MEASUREMENT_DEACTIVATE
      //get iso counter of FPGA to calculate ISO Time
      s_VaranTimes.s_IsoVaranTime.ud_Timestamp := p_ManagerStructure^.sISO.uiReserved2;
#endif

        //get old retry counter
        s_VaranManagerSettings.us_OldRetryCounter := p_ManagerStructure^.ucGlobalretryCounter;
      end_if; // if b_PayloadSupport then // ---------------------------------------------------------------------------------

      //start iso task first time
      ExecuteDOL( VARAN_DOL_ISO );

      //next step
      us_RtStep := _Wait4RtWork;

//**********************************************************************************************************************************************************
    _Wait4RtWork://wait for RtWork -> syncs, which are enabled in _InitVaranManager are send now
      
      if b_PayloadSupport &
         pMultiVaran^.udVersion >= VM_MULTIVARAN_DOL_TIMING_AVAILABLE then
      //look if realtime of VaranManager has finished
        MULTI_VARAN_iCheckIsoState( hManagerNodeHandle := vmNodeHandle
                                  , pudIsoState        := #ud_IsoState
                                  );
        
        if ud_IsoState = TK_STATE_EXECUTING then
          TRACE_RtOverlap();
          return;
        end_if;
      else
          //look if realtime of VaranManager has finished
        if ( ( p_ManagerStructure^.sISO.ucHandshake and 16#10 ) = 0 ) then
          TRACE_RtOverlap();
          return;
        end_if;
      end_if;      
      
      if s_VaranManagerSettings.us_Wait4RtWork = 0 then
#ifndef VARAN_TIME_MEASUREMENT_DEACTIVATE
        //take timestamp
        if b_PayloadSupport &
           pMultiVaran^.udVersion >= VM_MULTIVARAN_VERSION_FULL_PAYLOAD_AVAILABLE  then
          MULTI_VARAN_iGetTimeUpCounter( hManagerNodeHandle := vmNodeHandle                                    
                                       , pudTimeUpCounterNs  := #s_VaranTimes.s_Realtime.ud_Timemark
                                       );
        else
        s_VaranTimes.s_Realtime.ud_Timemark := p_ManagerStructure^.uiTUpCounter;
        end_if;
        
        Max_RtCallTime := 0;
        Min_RtCallTime := 16#FFFF_FFFF;
        Max_RtTime := 0;
        Min_RtTime := 16#FFFF_FFFF;
#endif
        us_RtStep := _RtWork;
      else
        ExecuteDOL( VARAN_DOL_ISO );  // Don't Execute when switching to _RtWork, UpDateRtPostscan takes over this call
      end_if;
      
      s_VaranManagerSettings.us_Wait4RtWork -= 1;
      
//**********************************************************************************************************************************************************		
    _RtWork://normal RtWork

#ifndef VARAN_TIME_MEASUREMENT_DEACTIVATE
      //get time in ns
      if b_PayloadSupport &
         pMultiVaran^.udVersion >= VM_MULTIVARAN_VERSION_FULL_PAYLOAD_AVAILABLE  then
        MULTI_VARAN_iGetTimeUpCounter( hManagerNodeHandle := vmNodeHandle                                    
                                     , pudTimeUpCounterNs := #ud_time
                                     );
      else
        ud_time := p_ManagerStructure^.uiTUpCounter;
      end_if;
      

      //get call time
      Act_RtCallTime := ( ud_time - s_VaranTimes.s_Realtime.ud_Timemark ) / 1000;
      s_VaranTimes.s_Realtime.ud_Timemark := ud_time;

      //look for maximum
      if ( Act_RtCallTime > Max_RtCallTime ) then
        Max_RtCallTime := Act_RtCallTime;
      end_if;

      //look for minimum
      if ( Act_RtCallTime < Min_RtCallTime ) then
        Min_RtCallTime := Act_RtCallTime;
      end_if;
      
      //calculate ISO Time
      if b_PayloadSupport &
         pMultiVaran^.udVersion >= VM_MULTIVARAN_DOL_TIMING_AVAILABLE then
        MULTI_VARAN_iGetIsoDuration ( hManagerNodeHandle  := vmNodeHandle
                                    , pudIsoDurationNs    := #s_VaranTimes.s_IsoVaranTime.ud_ActUsageRate
                                    );        
      else
        ud_IsoDuration := p_ManagerStructure^.sISO.uiReserved2;
        
        s_VaranTimes.s_IsoVaranTime.ud_ActUsageRate := ud_IsoDuration - s_VaranTimes.s_IsoVaranTime.ud_Timestamp;
        s_VaranTimes.s_IsoVaranTime.ud_Timestamp := ud_IsoDuration;
      end_if;      

      //look for maximum value
      if ( s_VaranTimes.s_IsoVaranTime.ud_ActUsageRate > IsoVaranTimeMax ) then
        if s_VaranTimes.s_IsoVaranTime.us_NotFirstRun = 0 then
          s_VaranTimes.s_IsoVaranTime.us_NotFirstRun := 1;
        else
          IsoVaranTimeMax := s_VaranTimes.s_IsoVaranTime.ud_ActUsageRate;
        end_if;
      end_if;

      //save on server
      IsoVaranTime$UDINT := s_VaranTimes.s_IsoVaranTime.ud_ActUsageRate;
#endif

      if b_PayloadSupport &
         pMultiVaran^.udVersion >= VM_MULTIVARAN_DOL_TIMING_AVAILABLE then
      //look if realtime of VaranManager has finished
        MULTI_VARAN_iCheckIsoState( hManagerNodeHandle := vmNodeHandle
                                  , pudIsoState        := #ud_IsoState
                                  );
        
        if ud_IsoState = TK_STATE_EXECUTING then
          TRACE_RtOverlap();
          return;
        end_if;
      else
          //look if realtime of VaranManager has finished
        if ( ( p_ManagerStructure^.sISO.ucHandshake and 16#10 ) = 0 ) then
          TRACE_RtOverlap();
          return;
        end_if;
      end_if;
  
      //----------------------------------------------------------------------------------------------
      //hardware class handling

      //look if we have classes
      if ( s_RtHandles.ud_NrOfHandles > 0 ) then
        
        //call all connected classes
        pHelp := #s_RtHandles.p_HandleList^[0];
        
        // faster from 1 to number than from 0 to number-1
        for i := 1 to s_RtHandles.ud_NrOfHandles do
#ifdef VARAN_TIME_MEASUREMENT_SINGLE_OBJECTS
          ud_SingleTimeMark1 := OS_READMICROSEC();
#endif

          //call class
          pHelp^.p_This^.UpdateRt();
          
#ifdef VARAN_TIME_MEASUREMENT_SINGLE_OBJECTS
          ud_SingleTimeMark2 := OS_READMICROSEC();
          pHelp^.TimeMeasuring.ud_ActTime := ud_SingleTimeMark2 - ud_SingleTimeMark1;
          
          if pHelp^.TimeMeasuring.ud_ActTime > pHelp^.TimeMeasuring.ud_MaxTime then
            pHelp^.TimeMeasuring.ud_MaxTime := pHelp^.TimeMeasuring.ud_ActTime;
          end_if;

          if pHelp^.TimeMeasuring.ud_ActTime < pHelp^.TimeMeasuring.ud_MinTime then
            pHelp^.TimeMeasuring.ud_MinTime := pHelp^.TimeMeasuring.ud_ActTime;
          end_if;
#endif
          
          //get pointer on next handle
          pHelp += sizeof(t_s_OneHandle);
        end_for;
      end_if;

  //------------------------------------------------------------ Client Instructions --------------------------------------------------------|
  //                                                                                                                                         V      
      //copy client data out of DPRAM, if we are synchrony
      if ( IsAlsoClient & p_ManagerClientSpace <> NIL ) then

        //--------------------------------------------------------------------------------------------------------------------------------------   
        if bPdoCopyDisable = false then  // PDO data are copied automatic
          // copy data to application memory
          if pIsoReadSafetyData then
            To_Stdlib.MemCpy( dest    := pIsoReadSafetyData, 
                              source 	:= p_ManagerClientSpace + VM_CLIENT_ISO_RD_OFFSET, 
                              size    := SafetyIsoMemRead$UDINT + VM_CLIENT_HEADER_SIZE
                            );
          end_if;
        else
          // copy data to application memory
          if pIsoReadSafetyData then
            To_Stdlib.MemCpy( dest    := pIsoReadSafetyData, 
                              source  := p_ManagerClientSpace + VM_CLIENT_ISO_RD_OFFSET, 
                              size    := sizeof(t_VMC_Header) + sizeof(t_VMC_Safety_Header_TDO)
                              );
          end_if;
        end_if;

        // copy user PDO data from application to manager DPRAM
        if UserObjectData.pIsoReadData then
          To_Stdlib.MemCpy( dest    := UserObjectData.pIsoReadData, 
                            source  := p_ManagerClientSpace + VM_CLIENT_ISO_RD_OFFSET + SafetyIsoMemRead + VM_CLIENT_HEADER_SIZE,
                            size    := UserObjectData.udIsoReadLength 
                          );
        end_if;
      //--------------------------------------------------------------------------------------------------------------------------------------  
 
      end_if;
       
  //------------------------------------------------------------ Client Instructions --------------------------------------------------------^
//**********************************************************************************************************************************************************		
  end_case;

  State := READY;	


END_FUNCTION //VIRTUAL GLOBAL VaranManager::RtWork

//[#ENGLISH]
//=================================================================================================
//Function to add a realtime or cyclic task to VaranManager
//=================================================================================================
//[server]	State					:R		:State of class
//[members]	s_RtHandles				:R/W	:structure to save Handles and thisp for realtime update methodes
//			s_CyHandles				:R/W	:structure to save Handles and thisp for cyclic update methodes
//[locals]	p_one_handle			:W/R	:pointer to next handle in list
//[>ud_dol_type] type of DOL list( Realtime = 3, cyclic = 4 )
//[>p_this] Thispointer of connected varan class
FUNCTION VIRTUAL GLOBAL VaranManager::AddVaranTask
  VAR_INPUT
    ud_dol_type 	: UDINT;
    p_this 	      : ^void;
    callOptions 	: USINT;
  END_VAR
  VAR
    p_one_handle	: ^t_s_OneHandle;
  END_VAR

  //look if we have a thispointer
  if (p_this <> NIL) then
    
    //------------------------------------------------------------------------------------------------
    //realtime 
    if ( ud_dol_type = VARAN_DOL_ISO ) then
      IF callOptions AND CALL_OPTION_RT_PRESCAN THEN
        //is list full
        if ( s_RtHandles.ud_NrOfHandles = s_RtHandles.ud_MaxHandles ) then

          //extend list
          ExtendHandleList( ud_dol_type := VARAN_DOL_ISO );

          //if an error occured return
          if ( State <> _ClassOk ) then
            return;
          end_if;
        end_if;

        //set pointer to next free handle entry
        p_one_handle 			    := s_RtHandles.p_HandleList + ( s_RtHandles.ud_NrOfHandles * sizeof( t_s_OneHandle ) );
        p_one_handle^.p_This 	:= p_this$p_VaranBase;

#ifdef VARAN_TIME_MEASUREMENT_SINGLE_OBJECTS
        p_one_handle^.TimeMeasuring.ud_MinTime := 16#FFFFFFFF;
        _GetObjName( p_this$pVirtualBase, #p_one_handle^.TimeMeasuring.aObjname[0] );
#endif


        //increase number of handles
        s_RtHandles.ud_NrOfHandles += 1;
      END_IF;
      
      IF callOptions AND CALL_OPTION_RT_POSTSCAN THEN
        //is list full
        if ( s_RtPostScanHandles.ud_NrOfHandles = s_RtPostScanHandles.ud_MaxHandles ) then

          //extend list
          ExtendHandleList( ud_dol_type := VARAN_DOL_ISO, callOptions := CALL_OPTION_RT_POSTSCAN );

          //if an error occured return
          if ( State <> _ClassOk ) then
            return;
          end_if;
        end_if;

        //set pointer to next free handle entry
        p_one_handle 			    := s_RtPostScanHandles.p_HandleList + ( s_RtPostScanHandles.ud_NrOfHandles * sizeof( t_s_OneHandle ) );
        p_one_handle^.p_This 	:= p_this$p_VaranBase;

#ifdef VARAN_TIME_MEASUREMENT_SINGLE_OBJECTS
        p_one_handle^.TimeMeasuring.ud_MinTime := 16#FFFFFFFF;
        _GetObjName( p_this$pVirtualBase, #p_one_handle^.TimeMeasuring.aObjname[0] );
#endif

        //increase number of handles
        s_RtPostScanHandles.ud_NrOfHandles += 1;
      END_IF;
    //------------------------------------------------------------------------------------------------
    //cyclic
    elsif ( ud_dol_type = VARAN_DOL_ASY ) then

      //is list full
      if ( s_CyHandles.ud_NrOfHandles = s_CyHandles.ud_MaxHandles ) then

        //extend list
        ExtendHandleList( ud_dol_type := VARAN_DOL_ASY );

        //is an error occured
        if ( State <> _ClassOk ) then
          return;
        end_if;
      end_if;

      //set pointer to next free handle entry
      p_one_handle 			    := s_CyHandles.p_HandleList + ( s_CyHandles.ud_NrOfHandles * sizeof( t_s_OneHandle ) );
      p_one_handle^.p_This 	:= p_this$p_VaranBase;

#ifdef VARAN_TIME_MEASUREMENT_SINGLE_OBJECTS
        p_one_handle^.TimeMeasuring.ud_MinTime := 16#FFFFFFFF;
        _GetObjName( p_this$pVirtualBase, #p_one_handle^.TimeMeasuring.aObjname[0] );
#endif

      //increase number of handles
      s_CyHandles.ud_NrOfHandles += 1;	
    end_if;
  end_if;

END_FUNCTION //VIRTUAL GLOBAL VaranManager::AddVaranTask

//[#ENGLISH]
//=================================================================================================
//Function to add a read data object to varan Manager and install a varan task
//=================================================================================================
//[members] s_CyHandles			:W		:structure to save Handles and thisp for cyclic update methodes
//[locals]	ud_command			:W/R	:to save right command for DO
//[>p_us_position_info]pointer to position info( first byte is length)
//[>ud_dol_type] type of DOL list( 1=direct access, 2=IRQ, 3=realtime, 4=cyclic )
//[>p_ud_handle]pointer to variable to set right handle
//[>ud_address] Address of data object
//[>ud_length] Length of data object
//[>p_ud_data] pointer to variable to get pointer to data
//[>ud_type]0=control area, 1=memory area
//[<sd_retval] 0=OK, negative=error (look lsl_st_varan.h)
FUNCTION VIRTUAL GLOBAL VaranManager::AddRdDO
VAR_INPUT
  p_us_position_info	: ^USINT;
  ud_dol_type		    	:  UDINT;
  p_ud_handle		    	: ^UDINT;
  ud_address		    	:  UDINT;
  ud_length			      :  UDINT;
  p_ud_data		      	: ^UDINT;
  ud_type			       	:  UDINT;
END_VAR
VAR_OUTPUT
  sd_retval			      :  DINT;
END_VAR
VAR
  ud_command		    	:  UDINT;
  TempMem             :  UDINT;
END_VAR

#ifdef VM_DEBUG_PAYLOAD
  // Payload not supported
  if b_PayloadSupport then
   // This method is not supporded with Payload support
    ((0)$^USINT)^ := 0; 
  end_if;  
#endif  
  // if there is no VARAN Interface available, we would crash at the VARAN_iAddDOToDOL call
  if pVaran = NIL then
    sd_retval := VARANMANAGER_DRIVER_NOT_EXISTS;
    return;
  end_if;

  //look which type it is
  if ( ud_type AND 1) = 1 then
    ud_command := VARAN_CMD_MEMORY_READ;		//memory area
  else
    ud_command := VARAN_CMD_CONTROL_READ;		//control area
  end_if;

  //look if we must execute Cyclic DOL list
  if ( ud_dol_type = VARAN_DOL_ASY ) then
    s_CyHandles.b_ExecuteDOL := TRUE;			//set flag to execut Dol list
  end_if;

  //Install Varan data object
  sd_retval := VARAN_iAddDOToDOL	( uiManager			  := VaranManagerNr
                                  , pucNode			    := p_us_position_info
                                  , uiDOLType 		  := ud_dol_type
                                  , puiDOHandle		  := p_ud_handle
                                  , uiCmd				    := ud_command
                                  , uiAddressRead		:= ud_address
                                  , uiLengthRead		:= ud_length
                                  , pucRead			    := p_ud_data
                                  , uiAddressWrite	:= 0
                                  , uiLengthWrite		:= 0
                                  , pucWrite			  := NIL
                                  );

  //look if an error occured
  if ( sd_retval <> VARANMANAGER_OK ) then
    s_ErrorVaranManager.f_AddRdDO := SetVaranDOError( sd_Error 		  := sd_retval 
                                                    , b_manager_off	:= TRUE
                                                    , b_log			    := TRUE
                                                    );
  else
  
    // check if the DO has a special priority
    if ud_type AND VM_PRIORITY_FILTER then
      AddToDOPriorityList(p_ud_handle^$^LSL_VARANFRAME, ud_type AND VM_PRIORITY_FILTER);
    end_if;
  
    // 32 Byte (Header) + 6 Byte (1 Byte Cmd, 4 Byte Addr, 1 Byte Len) + 1 Byte (Response) + n Byte (Load data read) + 0 to 3 Byte (compensate missalignment)
    TempMem := 32 + 6 + 1 + ud_length;
    if (TempMem MOD 4) then
      TempMem := TempMem + (4 - (TempMem MOD 4)); //increase memory, up to a value, which could be divided by 4
    end_if;
    
    case ud_dol_type AND (NOT (VARAN_DOL_NOT_INSERT_DO_INTO_DOL)) of
    // **************************************************
      VARAN_DOL_DA:
        DPRAM_Used.DA_Rd    += TempMem;
        DOCounter.DA_Rd     += 1;        
    // **************************************************                
      VARAN_DOL_ISO:
        DPRAM_Used.ISO_Rd   += TempMem;
        DOCounter.ISO_Rd    += 1;
    // **************************************************
      VARAN_DOL_ASY:
        DPRAM_Used.ASY_Rd   += TempMem;
        DOCounter.ASY_Rd    += 1;
    // **************************************************
      VARAN_DOL_ADMIN:
        DPRAM_Used.Admin_Rd += TempMem;
        DOCounter.Admin_Rd  += 1;
    // **************************************************
      VARAN_DOL_IRQ:
        DPRAM_Used.IRQ_Rd   += TempMem;
        DOCounter.IRQ_Rd    += 1;        
    end_case;     
      
    DPRAM_Used.Total  += TempMem;
    DOCounter.Total   += 1;
      
  end_if;

END_FUNCTION //VIRTUAL GLOBAL VaranManager::AddRdDO

//[#ENGLISH]
//=================================================================================================
//Function to add a write data object to varan Manager and install a varan task
//=================================================================================================
//[members] s_CyHandles			:W		:structure to save Handles and thisp for cyclic update methodes
//[locals]	ud_command			:W/R	:to save right command for DO
//[>p_us_position_info]pointer to position info( first byte is length)
//[>ud_dol_type] type of DOL list( 1=direct access, 2=IRQ, 3=realtime, 4=cyclic )
//[>p_ud_handle]pointer to variable to set right handle
//[>ud_address] Address of data object
//[>ud_length] Length of data object
//[>p_ud_data] pointer to variable to get pointer to data
//[>ud_type]0=control area, 1=memory area
//[<sd_retval] 0=OK, negative=error (look lsl_st_varan.h)
FUNCTION VIRTUAL GLOBAL VaranManager::AddWrDO
VAR_INPUT
  p_us_position_info	  : ^USINT;
  ud_dol_type			      :  UDINT;
  p_ud_handle     			: ^UDINT;
  ud_address		      	:  UDINT;
  ud_length			        :  UDINT;
  p_ud_data			        : ^UDINT;
  ud_type			        	:  UDINT;
END_VAR
VAR_OUTPUT
  sd_retval			        :  DINT;
END_VAR
VAR
  ud_command		      	:  UDINT;
  TempMem               :  UDINT;
END_VAR

#ifdef VM_DEBUG_PAYLOAD
  // Payload not supported
  if b_PayloadSupport then
    // This method is not supporded with Payload support
    ((0)$^USINT)^ := 0; 
  end_if;  
#endif  
  // if there is no VARAN Interface available, we would crash at the VARAN_iAddDOToDOL call
  if pVaran = NIL then
    sd_retval := VARANMANAGER_DRIVER_NOT_EXISTS;
    return;
  end_if;

  //look which type it is
  if ( ud_type AND 1) = 1 then
    ud_command := VARAN_CMD_MEMORY_WRITE;		//memory area
  else
    ud_command := VARAN_CMD_CONTROL_WRITE;		//control area
  end_if;

  //look if we must execute Cyclic DOL list
  if ( ud_dol_type = VARAN_DOL_ASY ) then
    s_CyHandles.b_ExecuteDOL := TRUE;			//set flag to execut Dol list
  end_if;

  //Install Varan data object
  sd_retval := VARAN_iAddDOToDOL	( uiManager			  := VaranManagerNr
                                  , pucNode			    := p_us_position_info
                                  , uiDOLType 		  := ud_dol_type
                                  , puiDOHandle		  := p_ud_handle
                                  , uiCmd				    := ud_command
                                  , uiAddressRead		:= 0
                                  , uiLengthRead		:= 0
                                  , pucRead			    := NIL
                                  , uiAddressWrite	:= ud_address
                                  , uiLengthWrite		:= ud_length
                                  , pucWrite			  := p_ud_data
                                  );

  //look if an error occured
  if ( sd_retval <> VARANMANAGER_OK ) then
    s_ErrorVaranManager.f_AddWrDO := SetVaranDOError	( sd_Error 		  := sd_retval 
                                                      , b_manager_off	:= TRUE
                                                      , b_log			    := TRUE
                                                      );
  else
  
    // check if the DO has a special priority
    if ud_type AND VM_PRIORITY_FILTER then
      AddToDOPriorityList(p_ud_handle^$^LSL_VARANFRAME, ud_type AND VM_PRIORITY_FILTER);
    end_if;

    //32 Byte (Header) + 6 Byte (1 Byte Cmd, 4 Byte Addr, 1 Byte Len) + 1 Byte (Response) + n Byte (load data write) + 0 to 3 Byte (compensate missalignment)
    TempMem := 32 + 6 + 1 + ud_length;
    if (TempMem MOD 4) then
      TempMem := TempMem + (4 - (TempMem MOD 4)); //increase memory, up to a value, which could be divided by 4
    end_if;

    case ud_dol_type AND (NOT (VARAN_DOL_NOT_INSERT_DO_INTO_DOL)) of
    // **************************************************
      VARAN_DOL_DA:
                    DPRAM_Used.DA_Wr    += TempMem;
                    DOCounter.DA_Wr     += 1;        
    // **************************************************                
      VARAN_DOL_ISO:
                    DPRAM_Used.ISO_Wr   += TempMem;
                    DOCounter.ISO_Wr    += 1;
    // **************************************************
      VARAN_DOL_ASY:
                    DPRAM_Used.ASY_Wr   += TempMem;
                    DOCounter.ASY_Wr    += 1;
    // **************************************************
      VARAN_DOL_ADMIN:
                    DPRAM_Used.Admin_Wr += TempMem;
                    DOCounter.Admin_Wr  += 1;
    // **************************************************
      VARAN_DOL_IRQ:
                    DPRAM_Used.IRQ_Wr   += TempMem;
                    DOCounter.IRQ_Wr    += 1;        
      end_case;
      
      DPRAM_Used.Total  += TempMem;
      DOCounter.Total   += 1;
  end_if;

END_FUNCTION //VIRTUAL GLOBAL VaranManager::AddWrDO

//[#ENGLISH]
//=================================================================================================
//Function to add a read/write data object to varan manager and install a varan task
//=================================================================================================
//[members] s_CyHandles			:W		:structure to save Handles and thisp for cyclic update methodes
//[locals]	ud_command			:W/R	:to save right command for DO
//[>p_us_position_info]pointer to position info( first byte is length)
//[>ud_dol_type] type of DOL list( 1=direct access, 2=IRQ, 3=realtime, 4=cyclic )
//[>p_ud_handle] pointer to variable to set right handle
//[>ud_address_read] Address of read data object
//[>ud_length_read] Length of read data object
//[>p_ud_data_read] pointer to variable to get pointer to data
//[>ud_address_write] Address of write data object
//[>ud_length_write] Length of write data object
//[>p_ud_data_write] pointer to variable to get pointer to data
//[>ud_type]0=control area, 1=memory area
//[<sd_retval] 0=OK, negative=error (look lsl_st_varan.h)
FUNCTION VIRTUAL GLOBAL VaranManager::AddRdWrDO
  VAR_INPUT
    p_us_position_info	  : ^USINT;
    ud_dol_type			      :  UDINT;
    p_ud_handle			      : ^UDINT;
    ud_address_read		    :  UDINT;
    ud_length_read		    :  UDINT;
    p_ud_data_read		    : ^UDINT;
    ud_address_write	    :  UDINT;
    ud_length_write		    :  UDINT;
    p_ud_data_write		    : ^UDINT;
    ud_type				        :  UDINT;
  END_VAR
  VAR_OUTPUT
    sd_retval			        :  DINT;
  END_VAR
  VAR
    ud_command			      :  UDINT;
    TempMem               :  UDINT;
  END_VAR

#ifdef VM_DEBUG_PAYLOAD
  // Payload not supported
  if b_PayloadSupport then
    // This method is not supporded with Payload support
    ((0)$^USINT)^ := 0; 
  end_if;  
#endif  
  // if there is no VARAN Interface available, we would crash at the VARAN_iAddDOToDOL call
  if pVaran = NIL then
    sd_retval := VARANMANAGER_DRIVER_NOT_EXISTS;
    return;
  end_if;

  //look which type it is
  if ( ud_type AND 1) = 1 then
    ud_command := VARAN_CMD_MEMORY_READ_WRITE;		//memory area
  else
    ud_command := VARAN_CMD_CONTROL_READ_WRITE;		//control area
  end_if;

  //look if we must execute Cyclic DOL list
  if ( ud_dol_type = VARAN_DOL_ASY ) then
    s_CyHandles.b_ExecuteDOL := TRUE;			//set flag to execut Dol list
  end_if;

  //Install Varan data object
  sd_retval := VARAN_iAddDOToDOL	( uiManager			  := VaranManagerNr
                                  , pucNode			    := p_us_position_info
                                  , uiDOLType 		  := ud_dol_type
                                  , puiDOHandle		  := p_ud_handle
                                  , uiCmd				    := ud_command
                                  , uiAddressRead		:= ud_address_read
                                  , uiLengthRead		:= ud_length_read
                                  , pucRead			    := p_ud_data_read
                                  , uiAddressWrite	:= ud_address_write
                                  , uiLengthWrite		:= ud_length_write
                                  , pucWrite			  := p_ud_data_write
                                  );

  //look if an error occured
  if ( sd_retval <> VARANMANAGER_OK ) then
    s_ErrorVaranManager.f_AddRdWrDO := SetVaranDOError	( sd_Error 		  := sd_retval 
                                                        , b_manager_off	:= TRUE
                                                        , b_log			    := TRUE
                                                        );
  else
  
    // check if the DO has a special priority
    if ud_type AND VM_PRIORITY_FILTER then
      AddToDOPriorityList(p_ud_handle^$^LSL_VARANFRAME, ud_type AND VM_PRIORITY_FILTER);
    end_if;

    //32 Byte (Header) + 11 Byte (1 Byte Cmd, 4 Byte RdAddr, 1 Byte RdLen, 4 Byte WrAddr, 1 Byte WrLen) + 1 Byte (Response) + n Byte (load data read) + n Byte (load data write) + 0 to 3 Byte (compensate missalignment)
    TempMem := 32 + 11 + 1 + ud_length_read + ud_length_write;
    if (TempMem MOD 4) then
      TempMem := TempMem + (4 - (TempMem MOD 4)); //increase memory, up to a value, which could be divided by 4
    end_if;
  
    case ud_dol_type AND (NOT (VARAN_DOL_NOT_INSERT_DO_INTO_DOL)) of
    // **************************************************
      VARAN_DOL_DA:
        DPRAM_Used.DA_RdWr    += TempMem;
        DOCounter.DA_RdWr     += 1;        
    // **************************************************                
      VARAN_DOL_ISO:
        DPRAM_Used.ISO_RdWr   += TempMem;
        DOCounter.ISO_RdWr    += 1;
    // **************************************************
      VARAN_DOL_ASY:
        DPRAM_Used.ASY_RdWr   += TempMem;
        DOCounter.ASY_RdWr    += 1;
    // **************************************************
      VARAN_DOL_ADMIN:
        DPRAM_Used.Admin_RdWr += TempMem;
        DOCounter.Admin_RdWr  += 1;
    // **************************************************
      VARAN_DOL_IRQ:
        DPRAM_Used.IRQ_RdWr   += TempMem;
        DOCounter.IRQ_RdWr    += 1;        
    end_case;     
      
    DPRAM_Used.Total  += TempMem;
    DOCounter.Total   += 1;
  end_if;

END_FUNCTION //VIRTUAL GLOBAL VaranManager::AddRdWrDO

//[#ENGLISH]
//=================================================================================================
//Function executes a data object list of VaranManager
//=================================================================================================
//[>ud_dol_type] type of DOL list( 1=direct access, 2=IRQ, 3=realtime, 4=cyclic )
//[<sd_retval] 0=OK, negative=error (look lsl_st_varan.h)
FUNCTION VIRTUAL GLOBAL VaranManager::ExecuteDOL
  VAR_INPUT
    ud_dol_type	      	: UDINT;
  END_VAR
  VAR_OUTPUT
    sd_retval	        	: DINT;
  END_VAR

  // Payload Support 
  if b_PayloadSupport &
     pMultiVaran^.udVersion >= VM_MULTIVARAN_DOL_TIMING_AVAILABLE then
            
      //if we have a ARM CPU with payload, we have to set output image before we
#ifdef _LSL_TARGETARCH_ARM  // IO Image only needed for ARM  CPUs
#ifdef VARAN_iSetOutputImage
    if b_IOImage then
      VARAN_iSetOutputImage(VaranManagerNr, ud_dol_type);
    end_if;        
#endif
#endif                    
      
    sd_retval := MULTI_VARAN_iExecuteDol( hManagerNodeHandle  := vmNodeHandle
                                        , udDolType           := ud_dol_type
                                        );
  
  else

    // if there is no VARAN Interface available, we would crash at the call
    if pVaran = NIL then
      sd_retval := VARANMANAGER_DRIVER_NOT_EXISTS;
      return;
    end_if;

    case ( ud_dol_type ) of 

      VARAN_DOL_ISO:	      
#ifdef _LSL_TARGETARCH_ARM  // IO Image only needed for ARM  CPUs
#ifdef VARAN_iSetOutputImage
                      if b_IOImage then
                        VARAN_iSetOutputImage(VaranManagerNr, ud_dol_type);
                      end_if;        
#endif
#endif                    
                      
                      sd_retval := VARAN_iExecuteDOLISO( uiManager := VaranManagerNr );

      VARAN_DOL_ASY:	
#ifdef _LSL_TARGETARCH_ARM  // IO Image only needed for ARM  CPUs
#ifdef VARAN_iSetOutputImage
                      if b_IOImage then
                        VARAN_iSetOutputImage(VaranManagerNr, ud_dol_type);
                      end_if;        
#endif
#endif                          
                      sd_retval := VARAN_iExecuteDOLASY( uiManager := VaranManagerNr );

      VARAN_DOL_DA:	  sd_retval := VARAN_iExecuteDOLDA ( uiManager := VaranManagerNr );

      VARAN_DOL_IRQ:  sd_retval := VARAN_iExecuteDOLIRQ( uiManager := VaranManagerNr );
    end_case;
  end_if;

  //look if an error occurs
  if ( sd_retval <> VARANMANAGER_OK ) then
    s_ErrorVaranManager.f_ExecuteDOL := SetVaranDOError	( sd_Error 		  := sd_retval 
                                                        , b_manager_off	:= TRUE
                                                        , b_log			    := TRUE
                                                        );
  end_if;

END_FUNCTION //VIRTUAL GLOBAL VaranManager::ExecuteDOL

//[#ENGLISH]
//=================================================================================================
//Function clears a data object list of VaranManager
//=================================================================================================
//[>ud_dol_type] Type of DOL (see lsl_st_varan.h)
//[<sd_retval] 0=OK, negative=error (look lsl_st_varan.h)
FUNCTION VIRTUAL GLOBAL VaranManager::ClearDOL
  VAR_INPUT
    ud_dol_type	    	: UDINT;
  END_VAR
  VAR_OUTPUT
    sd_retval		      : DINT;
  END_VAR

  // if there is no VARAN Interface available, we would crash at the call
  if pVaran = NIL then
    sd_retval := VARANMANAGER_DRIVER_NOT_EXISTS;
    return;
  end_if;

  sd_retval := VARAN_iClearDOL( uiManager		:= VaranManagerNr
                              , uiDOLType 	:= ud_dol_type
                              );

  //look if an error occurs
  if ( sd_retval <> VARANMANAGER_OK ) then
    s_ErrorVaranManager.f_ClearDOL := SetVaranDOError ( sd_Error 		  := sd_retval 
                                                      , b_manager_off	:= TRUE
                                                      , b_log			    := TRUE
                                                      );
  end_if;

END_FUNCTION //VIRTUAL GLOBAL VaranManager::ClearDOL

//[#ENGLISH]
//=================================================================================================
//Function to read a direct access data object
//=================================================================================================
//[members]	s_DirectAccessDO	:W/R	:structure for direct access
//[>p_us_position_info]pointer to position info( first byte is length )
//[>ud_address]address to read
//[>ud_length]length of data should read
//[>p_ud_data]variable to get pointer to readed data
//[>ud_type] 0=control area, 1=memory area
//[<sd_retval] 0=OK, negative=error (look lsl_st_varan.h)
FUNCTION VIRTUAL GLOBAL VaranManager::RdDO
  VAR_INPUT
    p_us_position_info	: ^USINT;
    ud_address			    :  UDINT;
    ud_length			      :  UDINT;
    p_ud_data			      : ^UDINT;
    ud_type			      	:  UDINT;
  END_VAR
  VAR_OUTPUT
    sd_retval			      :  DINT;
  END_VAR

  //enable semaphore
  To_Multitask.Wait( p_SemaHandle );

  //clear direct access dol list
  sd_retval := ClearDOL( ud_dol_type := VARAN_DOL_DA );

  //look if an error occurs
  if ( sd_retval <> VARANMANAGER_OK ) then
    s_ErrorVaranManager.f_RdDO := SetVaranDOError	( sd_Error 	:= sd_retval 
                                                  , b_manager_off	:= TRUE
                                                  , b_log			:= FALSE
                                                  );
    //disable semaphore
    To_Multitask.Signal( p_SemaHandle );
    return;
  end_if;

  //add data object
  sd_retval := AddRdDO( p_us_position_info  := p_us_position_info
                      , ud_dol_type		      := VARAN_DOL_DA
                      , p_ud_handle		      := ( #s_DirectAccessDO.ud_DOHandle )$^UDINT
                      , ud_address		      := ud_address
                      , ud_length			      := ud_length
                      , p_ud_data			      := p_ud_data
                      , ud_type			        := ud_type
                      );

  //look if an error occurs
  if ( sd_retval <> VARANMANAGER_OK ) then
    s_ErrorVaranManager.f_RdDO := SetVaranDOError( sd_Error 		  := sd_retval 
                                                 , b_manager_off	:= TRUE
                                                 , b_log			    := FALSE
                                                 );
    //disable semaphore
    To_Multitask.Signal( p_SemaHandle );
    return;
  end_if;

  //set run status of data object on
  s_DirectAccessDO.ud_DOHandle^.ucCtrlStat 	  := VARAN_DO_CONT_RUN;

  //set number of allowed retries
  s_DirectAccessDO.ud_DOHandle^.ucRetrys		  := VM_ALLOWED_RETRIES;

  //set time for retry timeout
  s_DirectAccessDO.ud_DOHandle^.uiRetryTimeout:= VM_RETRY_TIMEOUT_DA + ( ( p_us_position_info^ - 1 ) * VM_HUB_DELAY_TIME );

  //Execute dol
  sd_retval := ExecuteDOL( ud_dol_type := VARAN_DOL_DA );//or VARAN_DOL_EXECUTE_WAIT );

  //look if an error occurs
  if ( sd_retval <> VARANMANAGER_OK ) then
    s_ErrorVaranManager.f_RdDO := SetVaranDOError( sd_Error 		  := sd_retval 
                                                 , b_manager_off	:= TRUE
                                                 , b_log			    := FALSE
                                                 );
  end_if;

  //disable semaphore
  To_Multitask.Signal( p_SemaHandle );

END_FUNCTION //VIRTUAL GLOBAL VaranManager::RdDO

//[#ENGLISH]
//=================================================================================================
//Function to write a direct access data object
//=================================================================================================
//[members]	s_DirectAccessDO	:W/R	:structure for direct access
//[>p_us_position_info]pointer to position info( first byte is length)
//[>ud_address]address to write
//[>ud_length]length of data should be written
//[>p_ud_data]pointer to data should be written
//[>ud_type]0=control area, 1=memory area
//[<sd_retval] 0=OK, negative=error (look lsl_st_varan.h)
FUNCTION VIRTUAL GLOBAL VaranManager::WrDO
  VAR_INPUT
    p_us_position_info	: ^USINT;
    ud_address	    		:  UDINT;
    ud_length			      :  UDINT;
    p_ud_data			      : ^UDINT;
    ud_type				      :  UDINT;
  END_VAR
  VAR_OUTPUT
    sd_retval			      :  DINT;
  END_VAR

  //enable semaphore
  To_Multitask.Wait( p_SemaHandle );

  //clear direct access dol list
  sd_retval := ClearDOL( ud_dol_type := VARAN_DOL_DA );

  //look if an error occurs
  if ( sd_retval <> VARANMANAGER_OK ) then
    s_ErrorVaranManager.f_WrDO := SetVaranDOError( sd_Error 		  := sd_retval 
                                                 , b_manager_off	:= TRUE
                                                 , b_log			    := FALSE
                                                 );
    //disable semaphore
    To_Multitask.Signal( p_SemaHandle );
    return;
  end_if;

  //add data object
  sd_retval := AddWrDO	( p_us_position_info  := p_us_position_info
                        , ud_dol_type		      := VARAN_DOL_DA
                        , p_ud_handle		      := ( #s_DirectAccessDO.ud_DOHandle )$^UDINT
                        , ud_address		      := ud_address
                        , ud_length			      := ud_length
                        , p_ud_data			      := ( #s_DirectAccessDO.p_ud_DOWrite )$^UDINT
                        , ud_type			        := ud_type
                        );

  //look if an error occurs
  if ( sd_retval <> VARANMANAGER_OK ) then
    s_ErrorVaranManager.f_WrDO := SetVaranDOError( sd_Error 		  := sd_retval 
                                                 , b_manager_off	:= TRUE
                                                 , b_log			    := FALSE
                                                 );
    //disable semaphore
    To_Multitask.Signal( p_SemaHandle );
    return;
  end_if;

  //set run status of data object on
  s_DirectAccessDO.ud_DOHandle^.ucCtrlStat 	  := VARAN_DO_CONT_RUN;

  //set number of allowed retries
  s_DirectAccessDO.ud_DOHandle^.ucRetrys		  := VM_ALLOWED_RETRIES;

  //set time for retry timeout
  s_DirectAccessDO.ud_DOHandle^.uiRetryTimeout:= VM_RETRY_TIMEOUT_DA + ( ( p_us_position_info^ - 1 ) * VM_HUB_DELAY_TIME );

  //copy write data to dpram space of data object
  To_StdLib.MemCpy( dest 		:= s_DirectAccessDO.p_ud_DOWrite
                  , source 	:= p_ud_data
                  , size 		:= ud_length 
                  );

  //Execute dol
  sd_retval := ExecuteDOL( ud_dol_type := VARAN_DOL_DA );//or VARAN_DOL_EXECUTE_WAIT );

  //look if an error occurs
  if ( sd_retval <> VARANMANAGER_OK ) then
    s_ErrorVaranManager.f_WrDO := SetVaranDOError( sd_Error 		  := sd_retval 
                                                 , b_manager_off	:= TRUE
                                                 , b_log			    := FALSE
                                                 );
  end_if;

  //disable semaphore
  To_Multitask.Signal( p_SemaHandle );

END_FUNCTION //VIRTUAL GLOBAL VaranManager::WrDO

//[#ENGLISH]
//=================================================================================================
//Function to get Pll - Time of VaranManager
//=================================================================================================
//[members]	s_VMFunctions		:R/W	:structure for HwControl class
//[<ud_varan_time]varan time in ns
FUNCTION VIRTUAL GLOBAL VaranManager::GetVaranTime
  VAR_INPUT
    p_ud_IsoStartPoint	: ^UDINT;
  END_VAR
  VAR_OUTPUT
    ud_varan_time		    :  UDINT;
  END_VAR

  //if we have no Pll-Time yet
  if ( s_VMFunctions.ud_VaranTime = 0 ) then 
    
    //we must init VaranManager first
    if ( s_VaranManagerSettings.us_InitCounter = 0 ) then
      bExternalInit := true;
      Init();
    end_if;
  end_if;
  
  ud_varan_time := s_VMFunctions.ud_VaranTime;

  //get iso startpoint to calculate the correct offset
  if ( p_ud_IsoStartPoint <> NIL ) then
    p_ud_IsoStartPoint^ := GetIsoStartPoint();
  end_if;

END_FUNCTION //VIRTUAL GLOBAL VaranManager::GetPllTime

//[#ENGLISH]
//=================================================================================================
//Function to send Sync and trigger Watchdog of Varan Bus
//=================================================================================================
//[<sd_retval] 0=OK, negative=error (look lsl_st_varan.h)
FUNCTION VaranManager::TriggerWatchdog
  VAR_OUTPUT
    sd_retval		    : DINT;
  END_VAR

  if b_PayloadSupport &
     pMultiVaran^.udVersion >= VM_MULTIVARAN_VERSION_FULL_PAYLOAD_AVAILABLE  then
    
    sd_retval := MULTI_VARAN_iTriggerWatchdog(hManagerNodeHandle  := vmNodeHandle
                                            , udWatchdogType      := LSL_WD_TYPE_MANAGER
                                            );
  elsif pVaran then
    sd_retval := VARAN_iTriggerWd( uiManager := VaranManagerNr );
  end_if;

  //if an error occures
  if ( sd_retval <> VARANMANAGER_OK ) then
    s_ErrorVaranManager.f_TriggerWd := SetVaranDOError	( sd_Error 		  := sd_retval 
                                                        , b_manager_off	:= TRUE
                                                        , b_log			    := TRUE
                                                        );
    bd_RtLog.WatchdogTriggerFailed := TRUE;
  end_if;
  
END_FUNCTION //VIRTUAL GLOBAL VaranManager::TriggerWatchdog

//[#ENGLISH]
//=================================================================================================
//Function to extend Handle List
//=================================================================================================
//[servers]	ManagerOn				:W		:marks VaranManager as valid / ok
//[members]	s_RtHandles				:W		:structure to save Handles and thisp for realtime update methodes
//			s_CyHandles				:W		:structure to save Handles and thisp for cyclic update methodes
//			e_ErrorVaranManager		:W		:enum for Error State
//[>ud_dol_type] type of DOL list( Realtime = 3, cyclic = 4 )
FUNCTION VaranManager::ExtendHandleList
  VAR_INPUT
    ud_dol_type 	: UDINT;
    callOptions 	: USINT;
  END_VAR

  //look if an Error occures
  if ( State = _ClassOk ) then
  
    //--------------------------------------------------------------------------------------------------------------------
    //look which list type we have
    if ( ud_dol_type = VARAN_DOL_ISO ) then
      IF callOptions AND CALL_OPTION_RT_PRESCAN THEN
        //set right max handle
        s_RtHandles.ud_MaxHandles += VM_EXTEND_HANDLES;

        //realloc memory for list
        s_RtHandles.p_HandleList$^void := To_StdLib.ReAlloc	( mptr 		:= s_RtHandles.p_HandleList
                                                            , newsize := s_RtHandles.ud_MaxHandles * sizeof( t_s_OneHandle )
                                                            );

        //look if we got memory for our Handle list
        if ( s_RtHandles.p_HandleList ) then

          //set new memory to 0
          To_StdLib.MemSet( dest 	:= s_RtHandles.p_HandleList + ( s_RtHandles.ud_MaxHandles - VM_EXTEND_HANDLES ) * sizeof( t_s_OneHandle )
                          , value := 0
                          , size 	:= VM_EXTEND_HANDLES * sizeof( t_s_OneHandle ) 
                          );
        
        else
          //if not give out a TRACE and set Manager off
          State 		  := _MemoryFault;
          ManagerOn 	:= 0;
          
          // we switch off isochronous task
          TurnOffIsoTask();          

          //Log entry
#ifdef HWC_LogValue1
          HWC_LogValue1(this, "@0690 (VaranManager::ExtendHandleList) No Memory for Varan Manager available! (Extend Rt - Handles: {0})", s_RtHandles.ud_MaxHandles);
#endif
        end_if;
      END_IF;
      
      IF callOptions AND CALL_OPTION_RT_POSTSCAN THEN
        //set right max handle
        s_RtPostScanHandles.ud_MaxHandles += VM_EXTEND_HANDLES;

        //realloc memory for list
        s_RtPostScanHandles.p_HandleList$^void := To_StdLib.ReAlloc	( mptr 		:= s_RtPostScanHandles.p_HandleList
                                                                    , newsize := s_RtPostScanHandles.ud_MaxHandles * sizeof( t_s_OneHandle )
                                                                    );

        //look if we got memory for our Handle list
        if ( s_RtPostScanHandles.p_HandleList ) then

          //set new memory to 0
          To_StdLib.MemSet( dest 	:= s_RtPostScanHandles.p_HandleList + ( s_RtPostScanHandles.ud_MaxHandles - VM_EXTEND_HANDLES ) * sizeof( t_s_OneHandle )
                          , value := 0
                          , size 	:= VM_EXTEND_HANDLES * sizeof( t_s_OneHandle ) 
                          );
        
        else
          //if not give out a TRACE and set Manager off
          State 		  := _MemoryFault;
          ManagerOn 	:= 0;
          
          // we switch off isochronous task
          TurnOffIsoTask();  

          //Log entry
#ifdef HWC_LogValue1
          HWC_LogValue1(this, "@0023 (VaranManager::ExtendHandleList) No Memory for Varan Manager available! (Extend RtPostScan - Handles: {0})", s_RtPostScanHandles.ud_MaxHandles);
#endif
        end_if;
      END_IF;

    //--------------------------------------------------------------------------------------------------------------------
    elsif ( ud_dol_type = VARAN_DOL_ASY ) then

      //set right max handle
      s_CyHandles.ud_MaxHandles += VM_EXTEND_HANDLES;

      //realloc memory for list
      s_CyHandles.p_HandleList$^void := To_StdLib.ReAlloc	( mptr 		:= s_CyHandles.p_HandleList
                                                          , newsize := s_CyHandles.ud_MaxHandles * sizeof( t_s_OneHandle )
                                                          );

      //look if we got memory for our Handle list
      if ( s_CyHandles.p_HandleList ) then

        //set new memory to 0
        To_StdLib.MemSet( dest 	:= s_CyHandles.p_HandleList + ( s_CyHandles.ud_MaxHandles - VM_EXTEND_HANDLES ) * sizeof( t_s_OneHandle )
                        , value := 0
                        , size 	:= VM_EXTEND_HANDLES * sizeof( t_s_OneHandle ) 
                        );

      else
        //if not give out a TRACE and set Manager off
        State 		  := _MemoryFault;
        ManagerOn 	:= 0;

        // we switch off isochronous task
        TurnOffIsoTask();  

        //Log entry
#ifdef HWC_LogValue1
        HWC_LogValue1(this, "@069A (VaranManager::ExtendHandleList) No Memory for Varan Manager available! (Extend Cy - Handles: {0})", s_CyHandles.ud_MaxHandles);
#endif
      end_if;
    end_if;
  end_if;

END_FUNCTION // VaranManager::ExtendHandleList

//[#ENGLISH]
//=================================================================================================
//Function to call Realtime update methode of a varan class
//=================================================================================================
//[>p_this]Thispointer of Varan_Base class
FUNCTION  VaranManager::CallUpdateRt
  VAR_INPUT
    p_this		  	: p_VaranBase;
  END_VAR
  
  p_this^.UpdateRt();

END_FUNCTION // VaranManager::CallUpdateRt

//[#ENGLISH]
//=================================================================================================
//Function to call Cyclic update methode of a varan class
//=================================================================================================
//[>p_this]Thispointer of Varan_Base class
FUNCTION  VaranManager::CallUpdateCy
  VAR_INPUT
    p_this		  	: p_VaranBase;
  END_VAR

  p_this^.UpdateCy();

END_FUNCTION // VaranManager::CallUpdateCy

//[#ENGLISH]
//=================================================================================================
//Function to set Error in VaranManager
//=================================================================================================
//[members]	e_ErrorVaranManager		:W		:Enum for Error State
//[>sd_Error]Error of VaranManager
//[>b_manager_off]0=run, 1=set VaranManagerOff
//[>b_log]0=no logging, 1=log fault
FUNCTION  VaranManager::SetVaranDOError
  VAR_INPUT
    sd_error		    : DINT;
    b_manager_off	  : BOOL;
    b_log			      : BOOL;	
  END_VAR
  VAR_OUTPUT
    sd_enum_error	  : t_e_VaranErrors;
  END_VAR
  
  case ( sd_Error ) of

    VARANMANAGER_DRIVER_NOT_EXISTS:         sd_enum_error := _VaranDriverNotExists;
    VARANMANAGER_DOL_TYPE_WRONG:            sd_enum_error := _WrongDOLType;
    VARANMANAGER_RUN_STATUS_WRONG:          sd_enum_error := _WrongRunStatus;
    VARANMANAGER_DO_HANDLE_INVALID:         sd_enum_error := _DOHandleInvalid;
    VARANMANAGER_DO_RAM_FULL:               sd_enum_error := _DORamFull;
    VARANMANAGER_DO_CMD_INVALID:            sd_enum_error := _DOCmdInvalid;		
    VARANMANAGER_MANAGER_NOT_EXISTS:        sd_enum_error := _ManagerNotExists;		
    VARANMANAGER_DOL_ADDRESS_INVALID:       sd_enum_error := _DOLAddressInvalid;		
    VARANMANAGER_UNKNOWN_COMMAND:           sd_enum_error := _UnknownCommand;
    VARANMANAGER_COMPONENT_NOT_EXISTS:      sd_enum_error := _ComponentNotExists;
    VARANMANAGER_CLIENT_NOT_EXISTS:         sd_enum_error := _ClientNotExists;
    VARANMANAGER_CDIAS_EEPROM_NOT_EXISTS:   sd_enum_error := _CdiasEEPromNotExists;
    VARANMANAGER_CDIAS_EEPROM_NO_GRANT:     sd_enum_error := _CdiasEEPromNoGrant;
    VARANMANAGER_CDIAS_EEPROM_NACK:         sd_enum_error := _CdiasEEPromNack;
    VARANMANAGER_PORT_NOT_EXISTS:           sd_enum_error := _PortNotExists;
    VARANMANAGER_PORT_IS_UPLINK:            sd_enum_error := _PortIsUplink;
    VARANMANAGER_PORT_NO_LINK:              sd_enum_error := _PortNoLink;
    VARANMANAGER_NO_MUTEX:                  sd_enum_error := _NoMutex;
    VARANMANAGER_NO_TASK:                   sd_enum_error := _NoTask;
    VARANMANAGER_ID_NOT_FOUND:              sd_enum_error := _IDNotFound;
    VARANMANAGER_ID_NOT_INITIALIZED:        sd_enum_error := _IDNotInitialized;
    VARANMANAGER_INVALID_DEVICE_ADDRESS:    sd_enum_error := _InvalidDeviceAddress;
    VARANMANAGER_CALLBACK_NOT_HANDLED:      sd_enum_error := _CallbackNotHandled;
    VARANMANAGER_NO_MEM:                    sd_enum_error := _NoMem;
    VARANMANAGER_NO_LEGACY_WD:              sd_enum_error := _NoLegacyWd;
    VARANMANAGER_ADMIN_DOL_EXECUTION_ERROR: sd_enum_error := _AdminDOLExecutionError;
    VARANMANAGER_DA_DOL_EXECUTION_ERROR:    sd_enum_error := _DADOLExecutionError;
    VARANMANAGER_SPI_FLASH_NO_ACCESS:       sd_enum_error := _SPIFlashNoAccess;
    VARANMANAGER_CLIENT_NOT_READY:          sd_enum_error := _ClientNotready;    
    VARANMANAGER_CLIENT_DISABLED:           sd_enum_error := _ClientDisabled;
    VARANMANAGER_CLIENT_CANT_ENABLE:        sd_enum_error := _ClientCantEnable;
    VARANMANAGER_CDIAS_ADDRESS_INVALID:     sd_enum_error := _CdiasAddressInvalid;
    VARANMANAGER_SPI_FLASH_INVALID:         sd_enum_error := _SPIFlashInvalid;
    VARANMANAGER_SPI_DOL_ID_INVALID:        sd_enum_error := _SPIDOLIDInvalid;
    VARANMANAGER_SPI_DOL_INVALID:           sd_enum_error := _SPIDOLInvalid;
    VARANMANAGER_SPI_REQUIRED_LIST_ERROR:   sd_enum_error := _SPIRequiredListError;
    VARANMANAGER_SPI_CHKSUM_ERROR:          sd_enum_error := _SPIChksumError;
    VARANMANAGER_PARAMETER_INVALID:         sd_enum_error := _ParameterInvalid;
    VARANMANAGER_DO_TYPE_NOT_SUPPORTED:     sd_enum_error := _DOTypeNotSupported;
    VARANMANAGER_DMA_ERROR:                 sd_enum_error := _DMAError;
    VARANMANAGER_PROPERTY_ID_INVALID:       sd_enum_error := _PropertyIDInvalid;
    VARANMANAGER_PROPERTY_VALUE_INVALID:    sd_enum_error := _PropertyValueInvalid;
    VARANMANAGER_DO_NUMBER_OVERFLOW:        sd_enum_error := _DONumberOverflow;
    VARANMANAGER_API_USAGE_NOT_ALLOWED:     sd_enum_error := _APIUsageNotAllowed;
    VARANMANAGER_NODE_TYPE_WRONG:           sd_enum_error := _NodeTypeWrong;
    VARANMANAGER_DATA_LENGTH_INVALID:       sd_enum_error := _DataLengthInvalid;
    VARANMANAGER_DO_TYPE_INVALID:           sd_enum_error := _DOTypeInvalid;
    VARANMANAGER_OPERATION_NOT_ALLOWED:     sd_enum_error := _OperationNotAllowed;
    VARANMANAGER_NODE_NUMBER_OVERFLOW:      sd_enum_error := _NodeNumberOverflow;
    VARANMANAGER_NO_HANDLE_FOUND:           sd_enum_error := _NoHandleFound;

    -2147482560:                            sd_enum_error := _TimeoutVaran;  //16#8000_0440

  else
    if sd_Error < 0 then
      sd_enum_error := _UnknownFault;
    end_if;
  end_case;

  s_VaranManagerSettings.sd_LastError 	:= sd_error;
  s_ErrorVaranManager.ud_ErrorCounter   += 1;

  //Log entry
  if b_log then
#ifdef HWC_LogValue1
    HWC_LogValue1(this, "@06A4 (VaranManager::SetVaranDOError) Error happened with ErrorCode {0}", s_VaranManagerSettings.sd_LastError$UDINT);
#endif
  end_if;

  //should we set VaranManager off
  if ( b_manager_off = TRUE ) then

    //Log entry
    if b_log then
#ifdef HWC_LogError
      HWC_LogError(this, "@06AE (VaranManager::SetVaranDOError) Is set off because of last Error!");
#endif
    end_if;

    ManagerOn 		:= 0;

    // End the PostInit Phase as it can't be ended regularly as the VM is set off.
    // Otherwise PostInit Phase would end on timeout.
    bPostInitModulesReady := TRUE;

    //to make log entry in cyclic
    s_VaranManagerSettings.b_LogError := TRUE;

    // we switch off isochronous task
    TurnOffIsoTask();

    //set Hw off
    To_HwControl.SetHardwareOff( e_error := State );
    
    State 			:= sd_enum_error;
  end_if;

END_FUNCTION // VaranManager::SetVaranDOError

//[#ENGLISH]
//=================================================================================================
//Function to get µs time
//=================================================================================================
//[<ud_us_sec(EAX)]µs - Time
FUNCTION  VaranManager::GetMuSec
  VAR_OUTPUT
    ud_us_sec(EAX)		: UDINT;
  END_VAR

#ifdef _LSL_TARGETARCH_X86
  SAVE_REG();
#endif
  ud_us_sec := OS_ReadMicroSec();
#ifdef _LSL_TARGETARCH_X86
  RESTORE_REG();
#endif

END_FUNCTION // VaranManager::GetMuSec

//[#ENGLISH]
//=================================================================================================
//Function to get Varan class position in a string
//=================================================================================================
//[>p_us_info] pointer to save position info (first byte is length)
//[<sd_retval]0=OK, -1=to many hubs( max.15 )
#pragma warning(disable: 73)
FUNCTION VIRTUAL GLOBAL VaranManager::GetVaranPosition
  VAR_INPUT
    p_us_info	  	: ^USINT;
  END_VAR
  VAR_OUTPUT
    sd_retval	  	:  DINT;
  END_VAR

  //I am the Manager -> do nothing
  sd_retval := -1;

END_FUNCTION //VIRTUAL GLOBAL VaranManager::GetVaranPosition
#pragma warning(default: 73)
//[#ENGLISH]
//=================================================================================================
//Function to install callback function for hot plug and play
//=================================================================================================
//[>p_us_position_info]pointer to position info( first byte is length)
//[>ud_action_ptr]pointer to function
//[>ud_thisp]thispointer
//[>sd_required]is class required
FUNCTION VIRTUAL GLOBAL VaranManager::SetObjectCallback
  VAR_INPUT
    p_us_position_info	: ^USINT;
    ud_action_ptr	    	:  UDINT;
    ud_thisp			      :  UDINT;
    sd_required		    	:  DINT;
  END_VAR
  VAR_OUTPUT
    sd_retval		        :  DINT;
  END_VAR
  VAR
    p_one_module        : ^p_VaranBase;
    p_one_posstring     : ^pVoid;
  END_VAR

  sd_retval := AddObjectCallback( p_us_position_info:=p_us_position_info
                                , ud_action_ptr:= ud_action_ptr
                                , ud_thisp:= ud_thisp
                                , sd_required:= sd_required
                                );  
                
  // don't save the this pointer of the varan manager itself
  if p_us_position_info then
    // save pthis to internal list
    if ( s_ModuleList.ud_NrOfModules = s_ModuleList.ud_MaxModules ) then

      //extend list
      sd_retval := ExtendModuleList();

      //if an error occured return
      if ( sd_retval <> VARANMANAGER_OK ) then
        s_ErrorVaranManager.f_SetObjectCallback := SetVaranDOError	( sd_Error 		  := sd_retval 
                                                                    , b_manager_off	:= TRUE
                                                                    , b_log			    := TRUE
                                                                    );
        return;
      end_if;
    end_if;  

    //set pointer to next free handle entry
    p_one_module 	    := (s_ModuleList.p_ModuleList + ( s_ModuleList.ud_NrOfModules * sizeof( p_VaranBase ) ))$^p_VaranBase;
    p_one_module^	    := ud_thisp$p_VaranBase;

    //set pointer to next free handle entry
    p_one_posstring 	:= (s_ModuleList.p_PositionList + ( s_ModuleList.ud_NrOfModules * sizeof(pVoid) ))$^pVoid;
    p_one_posstring^	:= p_us_position_info$^pVoid;

    //increase number of handles
    s_ModuleList.ud_NrOfModules += 1;
  end_if;

END_FUNCTION //VIRTUAL GLOBAL VaranManager::SetObjectCallback

//[#ENGLISH]
//=================================================================================================
//Function sets Manager off
//=================================================================================================
//[server]	ManagerOn			:W		:state of Manager (On/Off)
//[members]	s_DirectAccessDO		:W/R	:structure for direct access
//			s_VaranManagerSettings	:W		:structure for different varan settings
//[>e_error]reason why varan Manager is set off
FUNCTION VIRTUAL GLOBAL VaranManager::SetManagerOff
  VAR_INPUT
    e_error		: t_e_VaranErrors;
  END_VAR
  VAR
    i         : UDINT;
    pHelp     : ^p_VaranBase;
  END_VAR

  ManagerOn 	:= 0;
  
  // we switch off isochronous task
  TurnOffIsoTask();  

  if ( State = _ClassOk ) then
    State		:= e_error;

    //to make log entry in cyclic
    s_VaranManagerSettings.b_LogError := TRUE;

    //update state of modules connected befor error
    if ( s_ModuleList.ud_NrOfModules > 0 ) then

      //check all connected classes
      pHelp := s_ModuleList.p_ModuleList;
      for i := 0 to s_ModuleList.ud_NrOfModules - 1 do

        if pHelp^^.State = _ClassOk then
          //module was connected before Manager was turned off, set new state
          pHelp^^.State   := _ModuleFoundButManagerIsOff;
          pHelp^^.Online  := 0; // also reset the online server
        end_if;
        
        //get pointer on next handle
        pHelp += sizeof(p_VaranBase);
      end_for;
    end_if;
  end_if;
  
  //set HwControl off
  To_HwControl.SetHardwareOff( e_error := e_error );

  // End the PostInit Phase as it can't be ended regularly as the VM is set off.
  // Otherwise PostInit Phase would end on timeout.
  bPostInitModulesReady := TRUE;

END_FUNCTION //VIRTUAL GLOBAL VaranManager::SetManagerOff

//[#ENGLISH]
//=================================================================================================
//Function set a varan error
//=================================================================================================
//[members]	s_VaranManagerSettings	:W		:structure for different varan settings
//[locals]	p_handle	:W/R	:pointer to a varan handle
//			p_data		:W/R	:pointer to data of data object
//			sd_retval	:W/R	:return value of OS - functions
//[>p_Node]pointer to Node string
FUNCTION VIRTUAL GLOBAL VaranManager::SetVaranError
  VAR_INPUT
    p_Node		: ^USINT;
  END_VAR
  VAR
    p_handle	: ^LSL_VARANFRAME;
    p_data		: ^UDINT;
    sd_retval	:  DINT;
    NodeHandle:  UDINT;
  END_VAR

  p_Handle 	:= NIL;
  p_Data 		:= NIL;
  
  //look if init was executed
  if ( s_VaranManagerSettings.us_InitCounter = 0 ) then
    bExternalInit := true;
    Init();
  end_if;

  //log error if we have one
  if ( s_VaranManagerSettings.b_LogError ) then
    LogError();
  end_if;
  
  if b_PayloadSupport then
   
    // see if we can get the handle of the target device
    sd_retval := MULTI_VARAN_iGetNodeHandle(  udManagerNumber := VaranManagerNr
                                           ,  pszHardwarePath := p_Node
                                           ,  phNodeHandle    := #NodeHandle
                                           );
                                                                                          
    if sd_retval = VARANMANAGER_OK then
      // we got the current node handle => use it
      MULTI_VARAN_iReportVaranError( diErrorNumber := VM_ERROR_REQUIRED
                                   , hErrorNode    := NodeHandle
                                   );
    else
      // we don't have the current handle => use the manager handle
      MULTI_VARAN_iReportVaranError( diErrorNumber := VM_ERROR_REQUIRED
                                   , hErrorNode    := vmNodeHandle
                                   );
    end_if;

  elsif pVaran then

    //clear DOL list
    sd_retval := VARAN_iClearDOL( uiManager		:= VaranManagerNr
                                , uiDOLType 	:= VARAN_DOL_DA
                                );

    //look for an Error
    if ( sd_retval <> VARANMANAGER_OK ) then
      s_ErrorVaranManager.f_SetVaranError := SetVaranDOError	( sd_Error 		  := sd_retval 
                                                              , b_manager_off	:= TRUE
                                                              , b_log			    := FALSE
                                                              );
      return;
    end_if;		

    //Install Varan data object
    sd_retval := VARAN_iAddDOToDOL	( uiManager			  := VaranManagerNr
                                    , pucNode			    := p_Node
                                    , uiDOLType 		  := VARAN_DOL_DA
                                    , puiDOHandle		  := ( #p_Handle )$^UDINT
                                    , uiCmd				    := VARAN_CMD_MEMORY_READ
                                    , uiAddressRead		:= 16#1
                                    , uiLengthRead		:= 1
                                    , pucRead			    := ( #p_Data )$^UDINT
                                    , uiAddressWrite	:= 0
                                    , uiLengthWrite		:= 0
                                    , pucWrite			  := NIL
                                    );

    //look for an Error
    if ( sd_retval <> VARANMANAGER_OK ) then
      s_ErrorVaranManager.f_SetVaranError := SetVaranDOError	( sd_Error 		  := sd_retval 
                                                              , b_manager_off	:= TRUE
                                                              , b_log			    := FALSE
                                                              );
      return;
    end_if;		
      
    //set run status of data object on
    p_Handle^.ucCtrlStat 	    := VARAN_DO_SINGLE_RUN or VARAN_DO_REQUIRED;
    p_Handle^.uiRetryTimeout  := 1000;
    p_Handle^.ucRetrys 		    := 1;
    p_Handle^.ucRetryCounter  := 0;

    //Execute DOL list
    sd_retval := VARAN_iExecuteDOLDA( uiManager := VaranManagerNr );
    
    //look for an Error
    if ( sd_retval <> VARANMANAGER_OK ) then
      s_ErrorVaranManager.f_SetVaranError := SetVaranDOError	( sd_Error 		  := sd_retval 
                                                              , b_manager_off	:= TRUE
                                                              , b_log			    := FALSE
                                                              );
      return;
    end_if;		

  end_if;
  
END_FUNCTION //VIRTUAL GLOBAL VaranManager::SetVaranError

//[#ENGLISH]
//=================================================================================================
//Function give back a nono second counter value of VaranManager
//=================================================================================================
//[members]	p_ManagerStructure		:W/R	:pointer for manager structure (from OS)
//			s_VaranManagerSettings	:R		:structure for different varan settings
//[<ud_ns_counter]nano second counter value
FUNCTION VIRTUAL GLOBAL VaranManager::GetNsTime
  VAR_OUTPUT
    ud_ns_counter		: UDINT;
  END_VAR

  //look if init was executed
  if ( s_VaranManagerSettings.us_InitCounter = 0 ) then
    bExternalInit := true;
    Init();
  end_if;	

  if b_PayloadSupport  & 
     pMultiVaran^.udVersion >= VM_MULTIVARAN_VERSION_FULL_PAYLOAD_AVAILABLE then
    MULTI_VARAN_iGetTimeUpCounter( hManagerNodeHandle := vmNodeHandle                                    
                                 , pudTimeUpCounterNs := #ud_ns_counter
                                 );
  elsif ( p_ManagerStructure <> NIL ) then  //if we have the Manager structure

    ud_ns_counter := p_ManagerStructure^.uiTUpCounter;

  end_if;

END_FUNCTION //VIRTUAL GLOBAL VaranManager::GetNsTime

//[#ENGLISH]
//=================================================================================================
//Function trace a Realtime Overlap fault
//=================================================================================================
//[server]	ManagerOn				:W		:state of Manager (On/Off)
//			State					:R		:State of class
//[members]	s_VaranManagerSettings	:W		:structure for different varan settings
FUNCTION  VaranManager::TRACE_RtOverlap

  if ( State = _ClassOk ) then

    State 		:= _TimesliceError;
    ManagerOn	:= 0;

    // we switch off isochronous task
    TurnOffIsoTask();  

    s_VaranManagerSettings.b_LogError := TRUE;

    bd_RtLog.TimeSliceError := TRUE;

    //set Hw off
    To_HwControl.SetHardwareOff( e_error := _TimesliceError );
  end_if;

END_FUNCTION // VaranManager::TRACE_RtOverlap

//[#ENGLISH]
//=================================================================================================
//Function to get watchdog or timeslice error
//=================================================================================================
//[server]	ManagerOn				:W		:state of Manager (On/Off)
//			State					:R		:State of class
//[members]	s_VaranManagerSettings	:W		:structure for different varan settings
//[>ud_reason]reason of callback
FUNCTION  VaranManager::Varan_CallBack
  VAR_INPUT
    ud_reason   	: UDINT;
  END_VAR
  VAR
    pHelp         : ^t_s_FlexHub;
    HandleError   : BOOL;
#ifdef VARANMANAGER_CB_VMC_BUF_DA
    Time1, Time2  : UDINT;
#endif
  END_VAR

  if ( State = _ClassOk ) 
#ifdef VARANMANAGER_CB_VMC_BUF_DA
   | ( ud_reason = VARANMANAGER_CB_VMC_BUF_DA )
#else
  #pragma message("Need newer lsl_st_varan.h file for direct access buffer of vmc");
#endif
    then

    // if we're not told other ways, raise "exception" (time slice error or whatever)
    HandleError := TRUE;

    case ( ud_reason ) of
// **********************************************************************************************************************************************
      VARANMANAGER_CB_TIME_SLICE_ERROR:	
        
#ifdef VARAN_iSetManagerCallbackOnVmcBufDaInt
        if (_RTOSVersion >= VM_DA_BUFFER_AVAILABLE) & pVaran then
          VARAN_iSetManagerCallbackOnVmcBufDaInt(0);
        end_if;
#endif
        State := _TimesliceErrorIRQ;
  
// **********************************************************************************************************************************************
      VARANMANAGER_CB_WATCHDOG_ERROR:		
#ifdef VARAN_iSetManagerCallbackOnVmcBufDaInt
        if (_RTOSVersion >= VM_DA_BUFFER_AVAILABLE) & pVaran then
          VARAN_iSetManagerCallbackOnVmcBufDaInt(0);
        end_if;
#endif
        State := _WatchdogError;

// **********************************************************************************************************************************************
#ifdef VARANMANAGER_CB_VMC_BUF_DA
      VARANMANAGER_CB_VMC_BUF_DA:       

Time1 := OS_READMICROSEC();

        // don't raise exception
        HandleError := FALSE;

        // read data from buffer (first byte is irq quit address) and store it in application memory
        
        // first copy data
        if DA_IRQ_Length > VM_CLIENT_HEADER_SIZE then
          To_Stdlib.MemCpy(dest   := DA_IRQ_pData + VM_CLIENT_HEADER_SIZE
                         , source := p_ManagerClientSpace + VM_CLIENT_DA_RD_OFFSET + VM_CLIENT_HEADER_SIZE
                         , size   := DA_IRQ_Length - VM_CLIENT_HEADER_SIZE
                         );        
        end_if;      
        
        // switch buffer and read last(first) 4 Byte (to quit irq after read-out all data)
        DA_IRQ_pData^$UDINT :=  (p_ManagerClientSpace + VM_CLIENT_DA_RD_OFFSET)^$UDINT;

        // call user irq method
        DA_IRQ_pFunc$IRQMethodDummy(DA_IRQ_pthis);

// do not delete time measurement, could be useful when someone waits for a response in the same cycle
Time2 := OS_READMICROSEC();
DAIRQTime := Time2 - Time1;
#endif
// **********************************************************************************************************************************************
      VARANMANAGER_CB_DISCONNECT,       
      VARANMANAGER_CB_CONNECT:
        
        // don't raise exception
        HandleError := FALSE;
        
      // refresh flex hub classes

        // call all flexhubs
        if pFlexHubs then
        
          // TODO: check which component has been dis-/connected and store info in t_s_FlexHub_Parameters, which will be passed to the flexhubs
        
          pHelp := pFlexHubs;
          while pHelp <> NIL do
            WR(pHelp^.pServer, ud_reason$DINT);
            pHelp := pHelp^.pNext;
          end_while;
        end_if;
    end_case;
    
    if HandleError then
      // only for errors
      
      //to make log entry in cyclic
      s_VaranManagerSettings.b_LogError := TRUE;

      // we switch off isochronous task
      TurnOffIsoTask();  

      //set Hw off
      To_HwControl.SetHardwareOff( e_error := State );

      //set Manager off
      ManagerOn := 0;
    end_if;
  end_if;

END_FUNCTION // VaranManager::Varan_CallBack

//[#ENGLISH]
//=================================================================================================
//Function to get pointer to node information
//=================================================================================================
//[>p_us_position_info]pointer to position info( first byte is length)
//[>p_node_info]pointer to node info
FUNCTION VIRTUAL GLOBAL VaranManager::GetNodeInfo
  VAR_INPUT
    p_us_position_info	: ^USINT;
    p_node_info		    	: ^PLSL_VARANNODEINFO;
  END_VAR
  VAR_OUTPUT
    sd_retval			      :  DINT;
  END_VAR
  VAR
    ud_NodeHandle       : UDINT;
    nodeProperty        : LSL_PROPERTY_VALUE_PAIR;
  END_VAR

  //look if init was executed
  if ( s_VaranManagerSettings.us_InitCounter = 0 ) then
    bExternalInit := true;
    Init();
  end_if;

  if p_us_position_info & p_node_info then
    if b_PayloadSupport then //----------------------------------------------------------------------------------------------------------
    
      // Check the pointer, the data is now stored to the pointer 
      if p_node_info then        
        sd_retval := MULTI_VARAN_iGetNodeHandle ( udManagerNumber := VaranManagerNr
                                                , pszHardwarePath := p_us_position_info
                                                , phNodeHandle    := #ud_NodeHandle
                                                );
    
        // Return the ErrorCode
        if sd_retval <> VARANMANAGER_OK then
          return;
        end_if;
        
        sd_retval := MULTI_VARAN_iGetNodeInformation( hNodeHandle := ud_NodeHandle
                                                    , psNodeInfo  := p_node_info^
                                                    );
    
        //look for an Error
        if ( sd_retval <> VARANMANAGER_OK ) then
          p_node_info^ := NIL;
          s_ErrorVaranManager.f_GetNodeInfo := SetVaranDOError( sd_Error 		  := sd_retval 
                                                              , b_manager_off	:= FALSE
                                                              , b_log			    := FALSE
                                                              );
          return;
        end_if;
        
#ifndef VARAN_TIME_MEASUREMENT_DEACTIVATE
        if pMultiVaran^.udVersion >= VM_MULTIVARAN_VERSION_FULL_PAYLOAD_AVAILABLE then 
          //save max response time
          if ( p_node_info^^.uiResponseTimeMax > s_VaranTimes.ud_MaxResponseTime ) then

            s_VaranTimes.ud_MaxResponseTime := p_node_info^^.uiResponseTimeMax;

            //set T3 (no command executed before isochronous task)
            s_ManagerControlData.ud_MaxTimeCmdExecution := s_ManagerControlData.ud_IsoStartPoint -
                                  (2*( ( ( 276 * VM_TIMEOUT_ONE_BYTE )			//max 128 read/write befehl
                                    + s_VaranTimes.ud_MaxResponseTime       //The Manager need 2 Commands before he is free ( Prefetch + actual Command), reason for the whole term multiple 2
                                    )                                       //minimize the Jitter from the VARAN-BUS
                                    * ( VM_ALLOWED_RETRIES + 1 ))
                                  );

            //if time is neg set to 0
            if ( s_ManagerControlData.ud_MaxTimeCmdExecution$DINT < 0 ) then
              s_ManagerControlData.ud_MaxTimeCmdExecution := 0;
            end_if;
            
            // Write the data
            nodeProperty.udPropertyId    := VM_PROP_MAX_COMMAND_EXECUTION_TIME;
            nodeProperty.udPropertyValue := s_ManagerControlData.ud_MaxTimeCmdExecution;
            MULTI_VARAN_iSetNodeProperties( hNodeHandle           := vmNodeHandle
                                          , udPropertyCount       := 1
                                          , psPropertyValuePairs  := #nodeProperty
                                          ); 
            
          end_if;
        
        else
          //save max response time
          if ( p_node_info^^.uiResponseTimeMax > s_VaranTimes.ud_MaxResponseTime ) & p_ManagerStructure then

            s_VaranTimes.ud_MaxResponseTime := p_node_info^^.uiResponseTimeMax;

            //set T3 (no command executed before isochronous task)
            p_ManagerStructure^.uiMaxTimeCmdExecution := 	p_ManagerStructure^.uiIsoStartPoint -
                                  (2*( ( ( 276 * VM_TIMEOUT_ONE_BYTE )			//max 128 read/write befehl
                                    + s_VaranTimes.ud_MaxResponseTime       //The Manager need 2 Commands before he is free ( Prefetch + actual Command), reason for the whole term multiple 2
                                    )                                       //minimize the Jitter from the VARAN-BUS
                                    * ( VM_ALLOWED_RETRIES + 1 ))
                                  );

            //if time is neg set to 0
            if ( p_ManagerStructure^.uiMaxTimeCmdExecution$DINT < 0 ) then
              p_ManagerStructure^.uiMaxTimeCmdExecution := 0;
            end_if;
          end_if;
        end_if;
#endif

      else        
        sd_retval := VM_CMD_ERROR_EMPTY_POINTER;
      end_if;

    
    elsif pVaran then  // if b_PayloadSupport then //----------------------------------------------------------------------------------------------------------
      
      //call OS - function to right device address	
      sd_retval := VARAN_iGetNodeInfo	( uiManager	:= VaranManagerNr
                                      , pucNode	  := p_us_position_info
                                      , pNodeInfo	:= p_node_info
                                      );

      //look for an Error
      if ( sd_retval <> VARANMANAGER_OK ) then
        s_ErrorVaranManager.f_GetNodeInfo := SetVaranDOError( sd_Error 		  := sd_retval 
                                                            , b_manager_off	:= FALSE
                                                            , b_log			    := FALSE
                                                            );
        return;
      end_if;		

#ifndef VARAN_TIME_MEASUREMENT_DEACTIVATE
      //save max response time
      if ( p_node_info^^.uiResponseTimeMax > s_VaranTimes.ud_MaxResponseTime ) & p_ManagerStructure then

        s_VaranTimes.ud_MaxResponseTime := p_node_info^^.uiResponseTimeMax;
        
        //set T3 (no command executed before isochronous task)
        p_ManagerStructure^.uiMaxTimeCmdExecution := 	p_ManagerStructure^.uiIsoStartPoint -
                              (2*( ( ( 276 * VM_TIMEOUT_ONE_BYTE )			//max 128 read/write befehl
                                + s_VaranTimes.ud_MaxResponseTime       //The Manager need 2 Commands before he is free ( Prefetch + actual Command), reason for the whole term multiple 2
                                )                                       //minimize the Jitter from the VARAN-BUS
                                * ( VM_ALLOWED_RETRIES + 1 ))
                              );

        //if time is neg set to 0
        if ( p_ManagerStructure^.uiMaxTimeCmdExecution$DINT < 0 ) then
          p_ManagerStructure^.uiMaxTimeCmdExecution := 0;
        end_if;
      end_if;
#endif
    end_if;	  // if b_PayloadSupport then //----------------------------------------------------------------------------------------------------------

  else
    sd_retval := -101;
  end_if;

END_FUNCTION //VIRTUAL GLOBAL VaranManager::GetNodeInfo

//[#ENGLISH]
//=================================================================================================
//Function to get Varan Manager number
//=================================================================================================
//[clients]	VaranManagerNr		:R		:number of varan manager
//[members]	pVaran					:R		:pointer to varan os functions
//			s_VaranManagerSettings	:R		:structure for different varan settings
//[<sd_Manager_number]number of varan Manager
//[>p_varan]address of pointer to varan
FUNCTION VIRTUAL GLOBAL VaranManager::GetManagerNumber
  VAR_INPUT
    p_varan				    : ^pVoid;
  END_VAR
  VAR_OUTPUT
    ud_manager_number	:  UDINT;
  END_VAR

  //look if init was executed
  if ( s_VaranManagerSettings.us_InitCounter = 0 ) then
    bExternalInit := true;
    Init();
  end_if;

  //set pointer to varan functions
  p_varan^:= pVaran;
  
  //give back varan manager number
  ud_manager_number := VaranManagerNr.read();

END_FUNCTION //VIRTUAL GLOBAL VaranManager::GetManagerNumber

//[#ENGLISH]
//=================================================================================================
//Function to log faults in cyclic (to prevent an error 67)
//=================================================================================================
//[server]	State					:W		:State of class
//[members]	s_VaranManagerSettings	:W		:structure for different varan settings
FUNCTION  VaranManager::LogError
  VAR
    ud_reason	      : UDINT;
    b_SetError    	: BOOL;
  END_VAR

  ud_reason := 0;

  b_SetError := FALSE;

  //look which entry
  case ( State ) of 	    
//**********************************************************************************************************************************************************
    _TimeSliceError:	//Log entry
#ifdef HWC_LogError
      HWC_LogError(this, "@06B8 (VaranManager::LogError) Timeslice Error! Manager is set off!");
#endif
      ud_reason := VM_ERROR_TIMESLICE;
      b_SetError := TRUE;

//**********************************************************************************************************************************************************
    _TimesliceErrorIRQ:	//Log entry
#ifdef HWC_LogError
      HWC_LogError(this, "@06C2 (VaranManager::LogError) Timeslice Error Interrupt, Manager is set off!");
#endif
      ud_reason := VM_ERROR_TIMESLICE_IRQ;
      b_SetError := TRUE;

//**********************************************************************************************************************************************************
    _WatchdogError:		//Log entry
#ifdef HWC_LogError
      HWC_LogError(this, "@06CC (VaranManager::LogError) Watchdog Error Interrupt, Manager is set off!");
#endif
      ud_reason := VM_ERROR_WATCHDOG;
      b_SetError := TRUE;

//**********************************************************************************************************************************************************
    _RequiredError:		//Log entry
#ifdef HWC_LogError
      HWC_LogError(this, "@06D6 (VaranManager::LogError) Required Module not ready, Manager is set off!");
#endif
      //b_SetError := FALSE;

//**********************************************************************************************************************************************************
    _DeviceError:		//Log entry
#ifdef HWC_LogError
      HWC_LogError(this, "@06E0 (VaranManager::LogError) Error on Device, Manager is set off!");
#endif
      ud_reason := VM_ERROR_DEVICE;
      b_SetError := TRUE;
              
//**********************************************************************************************************************************************************
    _CDIASRequiredError, _DIASRequiredError, _DiasError: //Log Entry
#ifdef HWC_LogError
      HWC_LogError(this, "@0024 (VaranManager::LogError) Required DIAS/CDIAS Module not ready, Manager is set off!");
#endif
      ud_reason   := VM_ERROR_DEVICE;
      b_SetError  := TRUE;
      State       := _RequiredError;

//**********************************************************************************************************************************************************
  else     //Unknown fault, log that an error occured
#ifdef HWC_LogValue1
    HWC_LogValue1(this, "@0025 (VaranManager::LogError) Unknown Fault (State = {0}), Manager is set off!", State);
#endif
  end_case;

  //reset log flag
  s_VaranManagerSettings.b_LogError := FALSE;

  //set Hw off
  To_HwControl.SetHardwareOff( e_error := State );

  //produce Varan Manager Error
  if ( b_SetError & PreventManagerError = 0) then
    
    if b_PayloadSupport & pMultiVaran^.udVersion >= VM_MULTIVARAN_VERSION_FULL_PAYLOAD_AVAILABLE  then
      MULTI_VARAN_iReportVaranError(diErrorNumber := ud_reason$DINT
                                  , hErrorNode    := vmNodeHandle);

    elsif pVaran & (pVaran^.udVersion >= 16#00001104 ) then
      VARAN_iSetManagerError( VaranManagerNr, ud_reason );
    end_if;
  end_if;

END_FUNCTION // VaranManager::LogError

//[#ENGLISH]
//=================================================================================================
//Function returns state of Varan manger class
//=================================================================================================
//[<e_state]error of varan manager
FUNCTION VIRTUAL GLOBAL VaranManager::GetManagerState
  VAR_OUTPUT
    e_state		  : t_e_VaranErrors;
  END_VAR

  e_state := State;

END_FUNCTION //VIRTUAL GLOBAL VaranManager::GetManagerState

//[#ENGLISH]
//=================================================================================================
//Function to add a multiple read/write register
//=================================================================================================
//[>p_us_position_info]pointer to position info( first byte is length)
//[>ud_dol_type] type of DOL list( 1=direct access, 2=IRQ, 3=realtime, 4=cyclic )
//[>p_ud_handle] pointer to variable to set right handle
//[>ud_address_read] Address of read data object
//[>ud_length_read] Length of read data object
//[>p_ud_data_read] pointer to variable to get pointer to data
//[>ud_address_write] Address of write data object
//[>ud_length_write] Length of write data object
//[>p_ud_data_write] pointer to variable to get pointer to data
//[>us_filter]filter number
//[>ui_number_of_slices]maximal number of slices
//[<sd_retval] 0=OK, negative=error (look lsl_st_varan.h)
FUNCTION GLOBAL VaranManager::AddMultipleRdWr
  VAR_INPUT
    p_us_position_info		: ^USINT;
    ud_dol_type				    :  UDINT;
    p_ud_handle				    : ^UDINT;
    ud_address_read			  :  UDINT;
    ud_length_read			  :  UDINT;
    p_ud_data_read			  : ^UDINT;
    ud_address_write		  :  UDINT;
    ud_length_write			  :  UDINT;
    p_ud_data_write			  : ^UDINT;
    us_filter				      :  USINT;
    ui_number_of_slices		:  UINT;
  END_VAR
  VAR_OUTPUT
    sd_retval				      :  DINT;
  END_VAR
  VAR
    ud_command			      :  UDINT;
    TempMem               :  UDINT;
  END_VAR

  //look if right OS - Version
  if ( _RTOSVersion >= 16#1194 ) & pVaran then

    //set command
    ud_command := VARAN_CMD_MULTIPLE_MEMORY_RW or ( us_filter shl 8 ) or ( ui_number_of_slices shl 16 );

    //look if we must execute Cyclic DOL list
    if ( ud_dol_type = VARAN_DOL_ASY ) then
      s_CyHandles.b_ExecuteDOL := TRUE;			//set flag to execut Dol list
    end_if;

    //Install Varan data object
    sd_retval := VARAN_iAddDOToDOL( uiManager     := VaranManagerNr
                                  , pucNode       := p_us_position_info
                                  , uiDOLType     := ud_dol_type
                                  , puiDOHandle   := p_ud_handle
                                  , uiCmd				  := ud_command
                                  , uiAddressRead := ud_address_read
                                  , uiLengthRead  := ud_length_read
                                  , pucRead       := p_ud_data_read
                                  , uiAddressWrite:= ud_address_write
                                  , uiLengthWrite := ud_length_write
                                  , pucWrite      := p_ud_data_write
                                  );

    //look if an error occured
    if ( sd_retval <> VARANMANAGER_OK ) then
      s_ErrorVaranManager.f_AddRdWrDO := SetVaranDOError( sd_Error      := sd_retval 
                                                        , b_manager_off := TRUE
                                                        , b_log         := TRUE
                                                        );
    else
    //   32Byte (Header) + 
    // + 13 Byte (Addr + Len +... --> See design spec appendix) + 
    // + (1 Byte (Response) + n Byte) * slices (load data read) + 
    // + n * slices Byte (load data write) + 
    // + 0 to 3 Byte (compensate missalignment)
      TempMem := 32 + 13 + (1 + ud_length_read) * ui_number_of_slices + ud_length_write * ui_number_of_slices;
      if (TempMem MOD 4) then
        TempMem := TempMem + (4 - (TempMem MOD 4)); //increase memory, up to a value, which could be divided by 4
      end_if;
    
      if ud_dol_type = VARAN_DOL_ISO then
        DPRAM_Used.ISO_RdWr += TempMem;
        DOCounter.ISO_RdWr  += 1;
      else
        DPRAM_Used.ASY_RdWr += TempMem;
        DOCounter.ASY_RdWr  += 1;
      end_if;
      
      DPRAM_Used.Total      += TempMem;
      DOCounter.Total       += 1;      
    end_if;
  else
    sd_retval := -100;	//Manager is off
  end_if;

END_FUNCTION //VIRTUAL GLOBAL VaranManager::AddMultipleRdWr

//[#ENGLISH]
//=================================================================================================
//Function to get an actual filter number
//=================================================================================================
//[<us_filter]number of filter
FUNCTION GLOBAL VaranManager::GetFilterNumber
  VAR_OUTPUT
    us_filter : USINT;
  END_VAR

  if ( s_VaranManagerSettings.us_FilterNumber <> 255 ) then
    //increment filter number
    s_VaranManagerSettings.us_FilterNumber += 1;
    us_filter := s_VaranManagerSettings.us_FilterNumber;
  else
    us_filter := 0;
  end_if;

END_FUNCTION //VIRTUAL GLOBAL VaranManager::GetFilterNumber

//[#ENGLISH]
//=================================================================================================
//Function to write a direct access data object
//=================================================================================================
//[members]	s_DirectAccessDO	:W/R	:structure for direct access
//[>p_us_position_info]pointer to position info( first byte is length)
//[>ud_address_read] Address of read data object
//[>ud_length_read] Length of read data object
//[>p_ud_data_read] pointer to variable to get pointer to data
//[>ud_address_write] Address of write data object
//[>ud_length_write] Length of write data object
//[>p_ud_data_write] pointer to variable to get pointer to data
//[>us_filter] number of filter
//[>us_slices] max number of slices
//[>p_handle]pointer to varan header
//[<sd_retval] 0=OK, negative=error (look lsl_st_varan.h)
FUNCTION GLOBAL VaranManager::MultipleRdWrDO
  VAR_INPUT
    p_us_position_info	: ^USINT;
    ud_address_read		  :  UDINT;
    ud_length_read		  :  UDINT;
    p_ud_data_read		  : ^UDINT;
    ud_address_write  	:  UDINT;
    ud_length_write		  :  UDINT;
    p_ud_data_write	  	: ^UDINT;
    us_filter			      :  USINT;
    us_slices			      :  USINT;
    p_handle			      : ^PLSL_VARANFRAME;
  END_VAR
  VAR_OUTPUT
    sd_retval		      	:  DINT;
  END_VAR

  //look if right OS - Version
  if ( _RTOSVersion >= 16#1194 ) then

    //clear direct access dol list
    sd_retval := ClearDOL( ud_dol_type := VARAN_DOL_DA );

    //look if an error occurs
    if ( sd_retval <> VARANMANAGER_OK ) then
      s_ErrorVaranManager.f_WrDO := SetVaranDOError	( sd_Error 	    := sd_retval 
                                                    , b_manager_off	:= TRUE
                                                    , b_log			    := FALSE
                                                    );
      return;
    end_if;

    //add data object
    sd_retval := AddMultipleRdWr( p_us_position_info	:= p_us_position_info
                                , ud_dol_type			    := VARAN_DOL_DA
                                , p_ud_handle			    := p_handle$^UDINT
                                , ud_address_read		  := ud_address_read
                                , ud_length_read		  := ud_length_read
                                , p_ud_data_read		  := ( #p_ud_data_read )$^UDINT
                                , ud_address_write		:= ud_address_write
                                , ud_length_write		  := ud_length_write
                                , p_ud_data_write		  := ( #p_ud_data_write )$^UDINT
                                , us_filter				    := us_filter
                                , ui_number_of_slices	:= us_slices
                                );
    
    
    //look if an error occurs
    if ( sd_retval <> VARANMANAGER_OK ) then
      s_ErrorVaranManager.f_WrDO := SetVaranDOError	( sd_Error 		  := sd_retval 
                                                    , b_manager_off	:= TRUE
                                                    , b_log			    := FALSE
                                                    );
      return;
    end_if;

    //set run status of data object on
    p_handle^^.ucCtrlStat 	        := VARAN_DO_SINGLE_RUN;

    //set number of allowed retries
    p_handle^^.ucRetrys	          	:= VM_ALLOWED_RETRIES;

    //set time for retry timeout
    p_handle^^.uiRetryTimeout       := VM_MAX_RETRY_TIMEOUT_MULTIPLE;

    //Execute dol
    sd_retval := ExecuteDOL( ud_dol_type := VARAN_DOL_DA );//or VARAN_DOL_EXECUTE_WAIT );

    //look if an error occurs
    if ( sd_retval <> VARANMANAGER_OK ) then
      s_ErrorVaranManager.f_WrDO := SetVaranDOError	( sd_Error 		  := sd_retval 
                                                    , b_manager_off	:= TRUE
                                                    , b_log			    := FALSE
                                                    );
      return;
    end_if;

  else
    sd_retval := -100;	//Manager is off
  end_if;

END_FUNCTION //VIRTUAL GLOBAL VaranManager::MultipleRdWrDO

//[#ENGLISH]
//=================================================================================================
//Function to read SPI data
//=================================================================================================
//[>p_us_position_info]pointer to position info( first byte is length)
//[>ud_offset]offset in SPI flash
//[>ud_length]length of data (max. 128Byte)
//[>p_data]pointer to allocated memory for read data
//[<sd_retval] 0=OK, negative=error (look lsl_st_varan.h)
FUNCTION VIRTUAL GLOBAL VaranManager::ReadSPIData
  VAR_INPUT
    p_us_position_info	  : ^USINT;
    ud_offset		        	:  UDINT;
    ud_length		        	:  UDINT;
    p_data			        	: ^USINT;
  END_VAR
  VAR_OUTPUT
    sd_retval		          :  DINT;
  END_VAR
  VAR
    ud_sent_page	        :  UDINT;
    ud_NodeHandle         : UDINT;
    sPropertyValuePair    : LSL_PROPERTY_VALUE_PAIR;
  END_VAR

  //look if right OS - Version
  if ( _RTOSVersion >= 16#119F ) then

    if ( ud_length and VM_SPI_IDENT_LIST ) then
      ud_length     := ud_length and 16#7FFF_FFFF;
      ud_sent_page  := 16#FFFF_FFFF;   // = Read from the last page 
    else
      ud_sent_page  := ud_offset / VM_SPI_PAGE_SIZE;
    end_if;			
    
    //look for length
    if ( ud_length <= 0 | ud_length > 128 | p_data = NIL ) then
      sd_retval := -101;
      return;
    end_if;

    if b_PayloadSupport then
      // Get Node Handle
      sd_retval := MULTI_VARAN_iGetNodeHandle ( udManagerNumber := VaranManagerNr
                                              , pszHardwarePath := p_us_position_info
                                              , phNodeHandle    := #ud_NodeHandle
                                              );
                                              
      if sd_retval <> VARANMANAGER_OK then
        return;
      end_if;
      
      // set request
      sPropertyValuePair.udPropertyId     := ND_PROP_SPI_MASTER_REQUEST;
      sPropertyValuePair.udPropertyValue  := SPI_MASTER_REQ_SET;
      sd_retval := MULTI_VARAN_iSetNodeProperties ( hNodeHandle           := ud_NodeHandle
                                                  , udPropertyCount       := 1
                                                  , psPropertyValuePairs  := #sPropertyValuePair
                                                  );
      // look for an error
      if ( sd_retval <> VARANMANAGER_OK ) then
        return;
      end_if;	      
      
      // set right page
      sd_retval := MULTI_VARAN_iSpiMasterReadFlashPage( hNodeHandle           := ud_NodeHandle
                                                      , udPageNumber          := ud_sent_page
                                                      , udOffsetInPage        := ud_offset mod VM_SPI_PAGE_SIZE
                                                      , udReadLength          := ud_length
                                                      , bBlockUntilCompleted  := true
                                                      , pusData               := p_data
                                                      );
      //look for an error
      if ( sd_retval <> VARANMANAGER_OK ) then
        return;
      end_if;
      
      //clear request
      sPropertyValuePair.udPropertyId     := ND_PROP_SPI_MASTER_REQUEST;
      sPropertyValuePair.udPropertyValue  := SPI_MASTER_REQ_CLEARED;
      sd_retval := MULTI_VARAN_iSetNodeProperties ( hNodeHandle           := ud_NodeHandle
                                                  , udPropertyCount       := 1
                                                  , psPropertyValuePairs  := #sPropertyValuePair
                                                  ); 
    elsif pVaran then
    
      //set request
    sd_retval := VARAN_iSPIMasterSetRequest	( uiManager	:= VaranManagerNr
                                            , pucNode	  := p_us_position_info
                                            );
    
    //look for an error
    if ( sd_retval <> VARANMANAGER_OK ) then
      return;
    end_if;	

    //set right page
    sd_retval := VARAN_iSPIMasterPageRead	( uiManager	:= VaranManagerNr
                                          , pucNode	  := p_us_position_info
                                          , uiPage	  := ud_sent_page
                                          );

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

    ud_sent_page := ud_offset mod VM_SPI_PAGE_SIZE;

    //read data of page
    sd_retval := VARAN_iSPIMasterPageReadBuffer	( uiManager	:= VaranManagerNr
                                                , pucNode	  := p_us_position_info
                                                , uiOffset	:= ud_sent_page
                                                , uiLen		  := ud_length
                                                , puiPage	  := p_data
                                                );

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

    //clear request
    sd_retval := VARAN_iSPIMasterClearRequest	( uiManager	:= VaranManagerNr
                                              , pucNode	  := p_us_position_info
                                              ); 
    end_if;
    
  else
    sd_retval := -100;
  end_if;

END_FUNCTION //VIRTUAL GLOBAL VaranManager::ReadSPIData

//[#ENGLISH]
//=================================================================================================
//Function add a foreign package request
//=================================================================================================
//[>p_us_position_info]pointer to position info( first byte is length)
//[>ud_dol_type] type of DOL list( 1=direct access, 2=IRQ, 3=realtime, 4=cyclic )
//[>p_ud_handle]pointer to variable to set right handle
//[>ud_address] Address of data object
//[<sd_retval] 0=OK, negative=error (look lsl_st_varan.h)
FUNCTION VIRTUAL GLOBAL VaranManager::AddForeignPackRequest
  VAR_INPUT
    p_us_position_info	: ^USINT;
    ud_dol_type		    	: UDINT;
    p_ud_handle			    : ^UDINT;
    ud_address			    : UDINT;
  END_VAR
  VAR_OUTPUT
    sd_retval		      	: DINT;
  END_VAR
  VAR
    ud_NodeHandle       : UDINT;
  END_VAR

  //look if we must execute Cyclic DOL list
  if ( ud_dol_type = VARAN_DOL_ASY ) then
    s_CyHandles.b_ExecuteDOL := TRUE;			//set flag to execut Dol list
  end_if;

  if b_PayloadSupport &
       pMultiVaran^.udVersion >= VM_MULTIVARAN_VERSION_FULL_PAYLOAD_AVAILABLE  then
    sd_retval := MULTI_VARAN_iGetNodeHandle ( udManagerNumber := VaranManagerNr
                                            , pszHardwarePath := p_DisablePath
                                            , phNodeHandle    := #ud_NodeHandle
                                            );
  
    // Return the ErrorCode
    if sd_retval then
      return;
    end_if;
    
    sd_retval := MULTI_VARAN_iAddDo(  phDoHandle                    := p_ud_handle
                                    , hNodeHandle                   := ud_NodeHandle
                                    , bDoRequired                   := 0
                                    , udDolType                     := ud_dol_type
                                    , udCommand                     := VARAN_CMD_FOREIGN_PACKET_REQ
                                    , udPriority                    := VM_PRIORITY_READ_DO
                                    , udPrescalerCounterThreshold   := 0
                                    , udPrescalerCounterStartValue  := 0
                                    , udReadOffset                  := VARAN_CLIENT_FP_SAFETY
                                    , udReadLength                  := VARAN_FPR_SAFETY_ID
                                    , udWriteOffset                 := 0
                                    , udWriteLength                 := 0
                                    , udFilter                      := 0
                                    , udSlices                      := 0
                                    , udWritePayloadType            := WR_PLD_TYPE_STANDARD
                                    ); 

    
  else
    // if there is no VARAN Interface available, we would crash at the call
    if pVaran = NIL then
      sd_retval := VARANMANAGER_DRIVER_NOT_EXISTS;
      return;
    end_if;

    //Install Varan data object
    sd_retval := VARAN_iAddDOToDOL	( uiManager			  := VaranManagerNr
                                    , pucNode			    := p_us_position_info
                                    , uiDOLType 		  := ud_dol_type + ( VARAN_DO_EXECUTE_FIFO_EMPTY shl 24 ) // in the highest byte we have the init value for the uc_CtrlStat Register
                                    , puiDOHandle		  := p_ud_handle
                                    , uiCmd				    := VARAN_CMD_FOREIGN_PACKET_REQ
                                    , uiAddressRead		:= ud_address + VARAN_CLIENT_FP_SAFETY
                                    , uiLengthRead		:= VARAN_FPR_SAFETY_ID
                                    , pucRead			    := NIL
                                    , uiAddressWrite	:= 0
                                    , uiLengthWrite		:= 0
                                    , pucWrite			  := NIL
                                    );
  end_if;
    
  
  //look if an error occured
  if ( sd_retval <> VARANMANAGER_OK ) then
    s_ErrorVaranManager.f_AddFoPaReq := SetVaranDOError ( sd_Error 		  := sd_retval 
                                                        , b_manager_off	:= TRUE
                                                        , b_log			    := TRUE
                                                        );
  end_if;

  //look if an error occured
  if ( sd_retval <> VARANMANAGER_OK ) then
    s_ErrorVaranManager.f_AddFoPaReq := SetVaranDOError ( sd_Error 		  := sd_retval 
                                                        , b_manager_off	:= TRUE
                                                        , b_log			    := TRUE
                                                        );
  end_if;

END_FUNCTION //VIRTUAL GLOBAL VaranManager::AddForeignPackRequest

//[#ENGLISH]
//=================================================================================================
//Function to get sync frame counter
//=================================================================================================
//[<us_frame_counter] sync frame counter
FUNCTION VIRTUAL GLOBAL VaranManager::GetSyncFrameCounter
  VAR_OUTPUT
    us_frame_counter		: USINT;
  END_VAR

  if b_PayloadSupport &
     pMultiVaran^.udVersion >= VM_MULTIVARAN_VERSION_FULL_PAYLOAD_AVAILABLE  then
    MULTI_VARAN_iGetNodeProperty( hNodeHandle       := vmNodeHandle
                                , udPropertyId      := VM_PROP_SYNC_COUNTER
                                , pudPropertyValue  := (#us_frame_counter)$^UDINT
                                );
  else
    us_frame_counter := p_SyncData^.us_FrameCounter;
  end_if;
  

END_FUNCTION //VIRTUAL GLOBAL VaranManager::GetSyncFrameCounter

//[<retval]ISO start point [ns]
FUNCTION VIRTUAL GLOBAL VaranManager::GetIsoStartPoint
  VAR_OUTPUT
    retval	  	: UDINT;
  END_VAR

  //if init is not executed yet
  if ( s_VaranManagerSettings.us_InitCounter = 0 ) then
    GetISOStartTime();
  end_if;	 

  retval := VaranManagerTime * IsoStartPoint / 100;

END_FUNCTION //VIRTUAL GLOBAL VaranManager::GetIsoStartPoint


FUNCTION  VaranManager::GetISOStartTime

  //set realtime start point of varan list
  //VaranManagerTime must be below 47ms! 
  IsoStartPoint := IsoStartPoint.Read();
  if( IsoStartPoint < 1 )then
    IsoStartPoint := 50;
  end_if;
  if( IsoStartPoint > 99 )then
    IsoStartPoint := 50;
  end_if;

END_FUNCTION // VaranManager::GetISOStartTime

//=================================================================================================
//Function to set disable device in cyclic
//=================================================================================================
//[>p_us_position_info]path of varan
FUNCTION VIRTUAL GLOBAL VaranManager::SetDisableDevice
  VAR_INPUT
    p_us_position_info		: ^USINT;
  END_VAR
  VAR_OUTPUT
    sd_retval		          :  DINT;
  END_VAR

  sd_retval := -100;
  
  if ( b_DisableDevice = FALSE ) then
    b_DisableDevice := TRUE;
    p_DisablePath   := p_us_position_info;
    sd_retval       := 0;
  end_if;

END_FUNCTION //VIRTUAL GLOBAL VaranManager::SetDisableDevice

//=================================================================================================
//Function to disable device in cyclic
//=================================================================================================
FUNCTION  VaranManager::DisableDevice
  VAR_OUTPUT
    sd_retval		    : DINT;
  END_VAR
  VAR
    ud_NodeHandle   : UDINT;
    nodeProperty    : LSL_PROPERTY_VALUE_PAIR;
  END_VAR

  if b_PayloadSupport & 
     pMultiVaran^.udVersion > VM_MULTIVARAN_VERSION_FULL_PAYLOAD_AVAILABLE then 
  
    sd_retval := MULTI_VARAN_iGetNodeHandle ( udManagerNumber := VaranManagerNr
                                            , pszHardwarePath := p_DisablePath
                                            , phNodeHandle    := #ud_NodeHandle
                                            );
    
    // Return the ErrorCode
    if sd_retval then
      return;
    end_if;
    
    nodeProperty.udPropertyId    := ND_PROP_CONNECTION_STATE;
    nodeProperty.udPropertyValue := CN_STATE_DISCONNECTED;
    sd_retval := MULTI_VARAN_iSetNodeProperties ( hNodeHandle           := ud_NodeHandle
                                                , udPropertyCount       := 1
                                                , psPropertyValuePairs  := #nodeProperty
                                                ); 

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

    //disable device
    sd_retval := VARAN_iSetNodeEnableStatus	( uiManager		  := VaranManagerNr
                                            , pucNode		    := p_DisablePath
                                            , uiNodeStatus	:= 0
                                            );
                        
    b_DisableDevice := FALSE;
                        
  else
    sd_retval := -100;
  end_if;

END_FUNCTION // VaranManager::DisableDevice


FUNCTION GLOBAL VaranManager::ReadWaitingTimeBeforeSync
  VAR_OUTPUT
    ud_waitingtime 	  : UDINT;
  END_VAR

  ud_waitingtime := 0;

  if b_PayloadSupport  & 
    pMultiVaran^.udVersion >= VM_MULTIVARAN_VERSION_FULL_PAYLOAD_AVAILABLE then
                                
    ud_waitingtime := s_ManagerControlData.ud_IsoStartPoint - s_ManagerControlData.ud_MaxTimeCmdExecution;
    
  // check manager structure
  elsif ( p_ManagerStructure ) then  
     ud_waitingtime := p_ManagerStructure^.uiIsoStartPoint - p_ManagerStructure^.uiMaxTimeCmdExecution;
  end_if;

END_FUNCTION


FUNCTION GLOBAL VaranManager::SetWaitingTimeBeforeSync
  VAR_INPUT
    ud_waitingtime 	: UDINT;
  END_VAR  
  VAR
    nodeProperty    : LSL_PROPERTY_VALUE_PAIR;
  END_VAR

  if b_PayloadSupport  & 
     pMultiVaran^.udVersion >= VM_MULTIVARAN_VERSION_FULL_PAYLOAD_AVAILABLE then
    //set T3 (no command executed before isochronous task)
    s_ManagerControlData.ud_MaxTimeCmdExecution := s_ManagerControlData.ud_IsoStartPoint - ud_waitingtime;
    
    //if time is neg set to 0
    if ( s_ManagerControlData.ud_MaxTimeCmdExecution$DINT < 0 ) then
      s_ManagerControlData.ud_MaxTimeCmdExecution := 0;
    end_if;
    
    // Write the data
    nodeProperty.udPropertyId    := VM_PROP_MAX_COMMAND_EXECUTION_TIME;
    nodeProperty.udPropertyValue := s_ManagerControlData.ud_MaxTimeCmdExecution;
    MULTI_VARAN_iSetNodeProperties( hNodeHandle           := vmNodeHandle
                                  , udPropertyCount       := 1
                                  , psPropertyValuePairs  := #nodeProperty
                                  ); 
    

  elsif ( p_ManagerStructure ) then
  
    //set T3 (no command executed before isochronous task)
    p_ManagerStructure^.uiMaxTimeCmdExecution := 	p_ManagerStructure^.uiIsoStartPoint - ud_waitingtime;

    //if time is neg set to 0
    if ( p_ManagerStructure^.uiMaxTimeCmdExecution$DINT < 0 ) then
      p_ManagerStructure^.uiMaxTimeCmdExecution := 0;
    end_if;
  end_if;

END_FUNCTION


FUNCTION VIRTUAL GLOBAL VaranManager::AddIsoClientRdData
  VAR_INPUT
    ud_length 	: UDINT;
    p_pdata 	  : ^void;
  END_VAR
  VAR_OUTPUT
    sd_retval 	: DINT;
  END_VAR

  if (IsAlsoClient <> 0) & (SuperiorSystemTime <> 0) then
    if us_InitCounter < 6 then 
      if (SafetyIsoMemRead$UDINT + ud_length) <= (VM_CLIENT_MAX_BUFFER_USE - VM_CLIENT_HEADER_SIZE) then
        if p_pdata <> NIL then
          if UserObjectData.pIsoReadData = NIL then
            UserObjectData.udIsoReadLength := ud_length;
            UserObjectData.pIsoReadData    := p_pdata;
            sd_retval := 0;       // OK
          else
            sd_retval := -4;      // adding was allready done
          end_if;
        else
          sd_retval := -3;        // invalid pointer
        end_if;
      else
        sd_retval := -2;          // invalid length
      end_if;
    else
      sd_retval := -1;            // method was called to late
    end_if;
  else
    sd_retval := -5;              // wrong client settings
  end_if;

END_FUNCTION //GLOBAL VaranManager::AddIsoClientRdData


FUNCTION VIRTUAL GLOBAL VaranManager::AddIsoClientWrData
  VAR_INPUT
    ud_length 	: UDINT;
    p_pdata 	  : ^void;
  END_VAR
  VAR_OUTPUT
    sd_retval 	: DINT;
  END_VAR

  if (IsAlsoClient <> 0) & (SuperiorSystemTime <> 0) then
    if us_InitCounter < 6 then 
      if (SafetyIsoMemWrite$UDINT + ud_length) <= (VM_CLIENT_MAX_BUFFER_USE - VM_CLIENT_HEADER_SIZE) then
        if p_pdata <> NIL then
          if UserObjectData.pIsoWriteData = NIL then
            UserObjectData.udIsoWriteLength := ud_length;
            UserObjectData.pIsoWriteData    := p_pdata;
            sd_retval := 0;       // OK
          else
            sd_retval := -4;      // adding was allready done
          end_if;
        else
          sd_retval := -3;        // invalid pointer
        end_if;
      else
        sd_retval := -2;          // invalid length
      end_if;
    else
      sd_retval := -1;            // method was called to late
    end_if;
  else
    sd_retval := -5;              // wrong client settings
  end_if;

END_FUNCTION //GLOBAL VaranManager::AddIsoClientWrData


FUNCTION VIRTUAL GLOBAL VaranManager::AddAsyClientRdData
  VAR_INPUT
    ud_length 	: UDINT;
    p_pdata 	  : ^void;
  END_VAR
  VAR_OUTPUT
    sd_retval 	: DINT;
  END_VAR

  if (IsAlsoClient <> 0) & (SuperiorSystemTime <> 0) then
    if us_InitCounter < 6 then 
      if (SafetyAsyMemRead$UDINT + ud_length) <= (VM_CLIENT_MAX_BUFFER_USE - VM_CLIENT_HEADER_SIZE) then
        if p_pdata <> NIL then
          if UserObjectData.pAsyReadData = NIL then
            UserObjectData.udAsyReadLength  := ud_length;
            UserObjectData.pAsyReadData     := p_pdata;
            sd_retval := 0;       // OK
          else
            sd_retval := -4;      // adding was allready done
          end_if;
        else
          sd_retval := -3;        // invalid pointer
        end_if;
      else
        sd_retval := -2;          // invalid length
      end_if;
    else
      sd_retval := -1;            // method was called to late
    end_if;
  else
    sd_retval := -5;              // wrong client settings
  end_if;

END_FUNCTION //GLOBAL VaranManager::AddASYClientRdData


FUNCTION VIRTUAL GLOBAL VaranManager::AddAsyClientWrData
  VAR_INPUT
    ud_length 	: UDINT;
    p_pdata 	  : ^void;
  END_VAR
  VAR_OUTPUT
    sd_retval 	: DINT;
  END_VAR

  if (IsAlsoClient <> 0) & (SuperiorSystemTime <> 0) then
    if us_InitCounter < 6 then 
      if (SafetyAsyMemWrite$UDINT + ud_length) <= (VM_CLIENT_MAX_BUFFER_USE - VM_CLIENT_HEADER_SIZE) then
        if p_pdata <> NIL  then
          if UserObjectData.pAsyWriteData = NIL then
            UserObjectData.udAsyWriteLength := ud_length;
            UserObjectData.pAsyWriteData    := p_pdata;
            sd_retval := 0;       // OK
          else
            sd_retval := -4;      // adding was allready done
          end_if;
        else
          sd_retval := -3;        // invalid pointer
        end_if;
      else
        sd_retval := -2;          // invalid length
      end_if;
    else
      sd_retval := -1;            // method was called to late
    end_if;
  else
    sd_retval := -5;              // wrong client settings
  end_if;

END_FUNCTION //GLOBAL VaranManager::AddASYClientWrData


FUNCTION VaranManager::ActISOReadLength
  VAR_INPUT
    loop 	  : USINT;
  END_VAR
  VAR_OUTPUT
    length 	: UDINT;
  END_VAR

  if (loop + 1) < ISORdVaranPackages then
    length := 128;
    return;
  end_if;

  if (loop + 1) = ISORdVaranPackages then
    length := ISOLastPackageRdSize;
  else
    length := 0;
  end_if;
  
END_FUNCTION	


FUNCTION VaranManager::ActISOWriteLength
  VAR_INPUT
    loop 	  : USINT;
  END_VAR
  VAR_OUTPUT
    length 	: UDINT;
  END_VAR
  
  if (loop + 1) < ISOWrVaranPackages then
    length := 128;
    return;
  end_if;

  if (loop + 1) = ISOWrVaranPackages then
    length := ISOLastPackageWrSize;
  else
    length := 0;
  end_if;

END_FUNCTION


FUNCTION VaranManager::ActASYReadLength
  VAR_INPUT
    loop 	  : USINT;
  END_VAR
  VAR_OUTPUT
    length 	: UDINT;
  END_VAR

  if (loop + 1) < ASYRdVaranPackages then
    length := 128;
    return;
  end_if;

  if (loop + 1) = ASYRdVaranPackages then
    length := ASYLastPackageRdSize;
  else
    length := 0;
  end_if;

END_FUNCTION


FUNCTION VaranManager::ActASYWriteLength
  VAR_INPUT
    loop 	  : USINT;
  END_VAR
  VAR_OUTPUT
    length 	: UDINT;
  END_VAR

  if (loop + 1) < ASYWrVaranPackages then
    length := 128;
    return;
  end_if;

  if (loop + 1) = ASYWrVaranPackages then
    length := ASYLastPackageWrSize;
  else
    length := 0;
  end_if;

END_FUNCTION


FUNCTION VaranManager::InitMulDivVMC
  VAR_OUTPUT
    sd_retval 	: DINT;
  END_VAR
  VAR
    i           : DINT;
    Divi        : USINT;
    VaranMulti  : USINT;
    CPUMulti    : USINT;
    nodeProperty: ARRAY [0..2] OF LSL_PROPERTY_VALUE_PAIR;
  END_VAR

  // initialize return value
  sd_retval := 0;

  //set right pointer
  p_ManagerClientSpace$UDINT += VM_CLIENT_OFFSET;
  
  //superior time must not zero
  if ( SuperiorSystemTime = 0 ) then
    State := _VaranTimeError;
    IF ( _firstscan = TRUE ) THEN
      //Log entry
#ifdef HWC_LogError
      HWC_LogError(this, "@06EA (VaranManager::InitMulDivVMC) SuperiorSystemTime is 0!");
#endif
    END_IF;
    sd_retval := -1;
    return;
  end_if;  

  if b_PayloadSupport &
     pMultiVaran^.udVersion >= VM_MULTIVARAN_VERSION_FULL_PAYLOAD_AVAILABLE  then  // -------------------------------------------------------------------
    
    // Sync outs are no longer written with DA, changes are stored locally and writte once
    p_SyncOutISOSwitch := #s_SyncOutISOSwitch;
  
  else  // if b_PayloadSupport then  // -------------------------------------------------------------------
    
    //look for right sync out pointer
    p_SyncOutISOSwitch := #p_ManagerPll^.sSynOutPeripheral1;

    //look in all peripheral sync outs
    for i := 1 to VM_MAX_SYNC_OUTS - 1 do
      
      //look if sync out id is correct
      if ( p_SyncOutISOSwitch^.ucSyncOutID = VM_CLIENT_ISO_SWITCH_ID ) then
        exit;					//we found right sync out --> exit
      end_if;

      //get pointer to next sync out
      p_SyncOutISOSwitch += sizeof ( LSL_VARANPLLSYNCOUT );

      //if we searched all sync outs without success, leave method
      if ( i = VM_MAX_SYNC_OUTS - 1 ) then
        //Log entry
#ifdef HWC_LogError
        HWC_LogError(this, "@06F4 (VaranManager::InitMulDivVMC) Couldn't find sync out for switching alternating buffer");
#endif

        State     := _PllError;
        sd_retval := -2;
        return;
      end_if;
    end_for;
  end_if; // if b_PayloadSupport then  // -------------------------------------------------------------------

  // check if the varan times are multiple of each other
  if ((VaranManagerTime MOD SuperiorSystemTime) <> 0) &
     ((SuperiorSystemTime MOD VaranManagerTime) <> 0) then

    //Log entry
#ifdef HWC_LogError
    HWC_LogError(this, "@06FE (VaranManager::InitMulDivVMC) VaranTime of superior system and inferior system have to be multiples of each other");
#endif

    State     := _PllError;
    sd_retval := -3;
    return;
  end_if;
  
  // check if the superior varan time is multiple of inferior system time
  if ((MainTimer MOD SuperiorSystemTime) <> 0) &
     ((SuperiorSystemTime MOD MainTimer) <> 0) then

    //Log entry
#ifdef HWC_LogError
    HWC_LogError(this, "@0708 (VaranManager::InitMulDivVMC) VaranTime of superior system and maintimer of inferior system have to be multiples of each other");
#endif

    State     := _PllError;
    sd_retval := -4;
    return;
  end_if;

  // check factor of superior varan time to inferior system time (maintimer)
  if (MainTimer <= SuperiorSystemTime) then
    // if system cycle times are different (master is slower), calculate difference (rounded)
    CPUMulti  := 1;
    Divi      := to_usint(SuperiorSystemTime / MainTimer);
    if (Divi < 1) then
      Divi := 1;
    end_if;
  else
    // if system cycle times are different (slave is slower), calculate difference (rounded)
    Divi := 1;
    CPUMulti := to_usint(MainTimer / SuperiorSystemTime);
    if (CPUMulti < 1) then
      CPUMulti := 1;
    end_if;
  end_if;

  if b_PayloadSupport &
     pMultiVaran^.udVersion >= VM_MULTIVARAN_VERSION_GET_SYSTEM_PROPERTY_AVAILABLE  then
    // Bit settig is done be the OS
    // set System Period Time
    nodeProperty[0].udPropertyId    := VM_PROP_PLL_SYSTEM_PERIOD_TIME;
    nodeProperty[0].udPropertyValue := SuperiorSystemTime / 10;
    
    // set System Period Divider (Pll)
    nodeProperty[1].udPropertyId    := VM_PROP_PLL_SYSTEM_PERIOD_DIVIDER;
    nodeProperty[1].udPropertyValue := Divi;
    
    MULTI_VARAN_iSetNodeProperties( hNodeHandle           := vmNodeHandle
                                  , udPropertyCount       := 2
                                  , psPropertyValuePairs  := #nodeProperty[0]);
    
    
    // if slave is slower and OS would be slower than 1ms because sync input, we use multiplier for CPU also
    if (SuperiorSystemTime < 1000000) & (CPUMulti > 1) then
      MULTI_VARAN_ICONFIGUREPLLSYNCOUT( hManagerNodeHandle    := vmNodeHandle
                                      , udSyncOutId           := VM_SYNC_CPU_ID
                                      , udPeriodMultiplier    := CPUMulti
                                      , udFrameCountThreshold := 0
                                      , udControlStatus       := 1
                                      );  // enable cpu sync out in any case and enable frame count
    else
      MULTI_VARAN_ICONFIGUREPLLSYNCOUT( hManagerNodeHandle    := vmNodeHandle
                                      , udSyncOutId           := VM_SYNC_CPU_ID
                                      , udPeriodMultiplier    := 1
                                      , udFrameCountThreshold := 0
                                      , udControlStatus       := 1
                                      );  // enable cpu sync out in any case and enable frame count
    end_if;
    
  else
  
  // disable divider (bit 4) and pll (bit 6)
  p_ManagerPll^.ucControlStatus := p_ManagerPll^.ucControlStatus and 2#10101111;

  // set System Period Time
  p_ManagerPll^.aucPeriod$UDINT := SuperiorSystemTime / 10;

  // set System Period Divider (Pll)
  p_ManagerPll^.ucSystemPeriodDivider := Divi; // if you get an error on this line, you need the new lsl_st_varan.h where the name of the structure element is corrected

  // enable divider (bit 4) and pll (bit 6)
  p_ManagerPll^.ucControlStatus := p_ManagerPll^.ucControlStatus or 2#01010000;
  
  // if slave is slower and OS would be slower than 1ms because sync input, we use multiplier for CPU also
  if (SuperiorSystemTime < 1000000) & (CPUMulti > 1) then
    p_ManagerPll^.sSynOutCPU.ucPeriodMultiplier   := CPUMulti;
  else
    p_ManagerPll^.sSynOutCPU.ucPeriodMultiplier   := 1;
  end_if;
  p_ManagerPll^.sSynOutCPU.ucFrameCountThreshold  := 0;
  p_ManagerPll^.sSynOutCPU.ucControlStatus        := 1; // enable cpu sync out in any case and enable frame count
  end_if;  

  VaranMulti := to_usint(VaranManagerTime / MainTimer) * CPUMulti;

  // get modulo value for synchronity check
  if SuperiorSystemTime > VaranManagerTime then
    VMC_ModValue := SuperiorSystemTime / VaranManagerTime;
    if VMC_ModValue < 1 then
      VMC_ModValue := 1;
    end_if;
  else
    VMC_ModValue := 1;
  end_if;

  // set Period Multiplier of Varan Manager
  p_SyncOut^.ucPeriodMultiplier := VaranMulti;

  ucVaranManagerTemp := 2#011; // framecounter

  // enable iso switch sync (bit0 = 1) in RtWork together with varan sync
  if (VaranMulti > 1) then
    // set Period Multiplier of ISO Switch
    p_SyncOutISOSwitch^.ucPeriodMultiplier := VaranMulti;
   
    // if (divisor > 1) and (superior time is not greater) then use system sync of superior system
    if (Divi > 1) & (SuperiorSystemTime <= VaranManagerTime) then
      ucVaranManagerTemp  := 
      ucIsoSwitchTemp     := 2#101;
      
      // correct multipliers
      p_SyncOutISOSwitch^.ucPeriodMultiplier  /= Divi;
      p_SyncOut^.ucPeriodMultiplier           /= Divi;
    else
      // if superior time is greater use superior sync for iso switch
      if (SuperiorSystemTime > VaranManagerTime) then
        p_SyncOutISOSwitch^.ucPeriodMultiplier := 1;
        ucIsoSwitchTemp := 2#101;
      else
        // otherwise divided sync
        ucIsoSwitchTemp := 2#011; // framecounter
      end_if;
    end_if;
  else
    // set Period Multiplier of ISO Switch
    p_SyncOutISOSwitch^.ucPeriodMultiplier := 1;

    // use system sync of superior system (bit2 = 1)
    ucIsoSwitchTemp := 2#101;
  end_if;

  // Write p_SyncOutISOSwitch, (p_SyncOut is written at the end of FirstInit)
  if b_PayloadSupport  & 
     pMultiVaran^.udVersion >= VM_MULTIVARAN_VERSION_FULL_PAYLOAD_AVAILABLE then
    MULTI_VARAN_ICONFIGUREPLLSYNCOUT( hManagerNodeHandle    := vmNodeHandle
                                    , udSyncOutId           := VM_CLIENT_ISO_SWITCH_ID
                                    , udPeriodMultiplier    := p_SyncOutISOSwitch^.ucPeriodMultiplier
                                    , udFrameCountThreshold := p_SyncOutISOSwitch^.ucFrameCountThreshold
                                    , udControlStatus       := p_SyncOutISOSwitch^.ucControlStatus
                                    );  
  end_if;
   
END_FUNCTION


FUNCTION GLOBAL VaranManager::FrameCounterChanged
  VAR_INPUT
    pOld 	  : ^USINT;
    pAct 	  : ^USINT;
  END_VAR
  VAR_OUTPUT
    retcode : BOOL;
  END_VAR
  VAR
    Temp    : USINT;
  END_VAR

  if b_PayloadSupport &
     pMultiVaran^.udVersion >= VM_MULTIVARAN_VERSION_FULL_PAYLOAD_AVAILABLE  then
    MULTI_VARAN_iGetNodeProperty( hNodeHandle       := vmNodeHandle
                                , udPropertyId      := VM_PROP_PLL_SYNC_TIME_FRAME_COUNTER
                                , pudPropertyValue  := (#Temp)$^UDINT
                                );
  else
    Temp := p_ManagerPll^.ucSyncTimeFrameCounter;
  end_if;

  if pOld & pAct then
    pOld^ := OldFrameCounter;
    pAct^ := Temp;
  end_if;

  if Temp <> OldFrameCounter then
    retcode         := TRUE;
    OldFrameCounter := Temp;
  else
    retcode := FALSE;
  end_if;

END_FUNCTION


FUNCTION VIRTUAL GLOBAL VaranManager::GetDocumentation
  VAR_INPUT
    p_us_position_info 	: ^USINT;
    p_dpne 	            : ^CHAR;
  END_VAR
  VAR_OUTPUT
    sd_retval 	        : DINT;
  END_VAR
  VAR
    FileHandle          : DINT;
    FileData            : ^USINT;
    BaseListAddress     : UDINT;
  END_VAR

  sd_retval := 0;

  if p_us_position_info & p_dpne then

    // try to open file
    FileHandle := To_FileSys.FileOpen( filename   := p_dpne, 
                                       attributes := ATT_CREATE_ALWAYS
                                     );

    // check success of opening file
    if FileHandle >= 0 then
      
      //check OS version
      if ( _RTOSVersion < VM_SPI_OS_VERSION ) then
        // access of SPI flash not possible
        sd_retval := -3;
        return;
      end_if;
      
      // check if documentation is available and get file size and offset in SPI flash
      if ( SearchSPIList(p_us_position_info, VM_SPI_DOCU_ID, #BaseListAddress) <> VARANMANAGER_OK ) then
        sd_retval := -4;
        return;
      end_if;

      sd_retval := GetDocuFileInfo(p_us_position_info := p_us_position_info, 
                                   ud_listOffset      := BaseListAddress
                                  );


      //allocate memory for the file data
      FileData := ( To_StdLib.Malloc( size := ud_SPI_Docu_Length ) )$^USINT;

      if ( FileData = NIL ) then
        State := _MemoryFault;
        sd_retval := -5;
        return;
      end_if;

      //read the whole file
      sd_retval := ReadSPIDataComfort( p_us_position_info := p_us_position_info,
                                       ud_offset	        := ud_SPI_Offset,
                                       ud_length	        := ud_SPI_Docu_Length,
                                       p_data		          := FileData
                                     );
      //look for an error
      if ( sd_retval <> VARANMANAGER_OK ) then
        sd_retval := -6;
        return;
      end_if;
     
      // write bytes into file
      if To_FileSys.FileWrite( handle := FileHandle, 
                               buffer := FileData, 
                               length := ud_SPI_Docu_Length
                             ) <> ud_SPI_Docu_Length$DINT then
        sd_retval := -7;
      end_if;
      
      To_StdLib.Free(FileData);                     
      To_FileSys.FileClose(handle := FileHandle);
    else
      // failed to open file
      sd_retval := -2;
    end_if;
  else
    // invalid parameters
    sd_retval := -1;
  end_if;

END_FUNCTION


FUNCTION VaranManager::SearchSPIList
  VAR_INPUT
    p_us_position_info 	: ^USINT;
    SearchID 	          : UDINT;
    p_BaseListAddress   : ^UDINT;
  END_VAR
  VAR_OUTPUT
    sd_retval 	        : DINT;
  END_VAR
  VAR
    i				            : UDINT;
    a_data              : ARRAY[0..31] OF UDINT;
  END_VAR

  if p_BaseListAddress = NIL then
    // invalid parameters
    sd_retval := -101;
    return;
  end_if;

  //read SPI data
  sd_retval := ReadSPIData( p_us_position_info	:= p_us_position_info
                          , 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
    sd_retval := -102;
    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
    sd_retval := -103;
    return;
  end_if;

  //search for SPI Flash Configuration
  for i := 0 to a_data[ 3 ] / sizeof( UDINT ) do

    //look for configuration id in 3rd byte
    if ( ( a_data[ i + 4 ] and 16#FF00_0000 ) = SearchID ) then
      p_BaseListAddress^ := a_data[ i + 4 ] and 16#00FF_FFFF;
      sd_retval := 0;
      return;
    end_if;
    
  end_for;

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

END_FUNCTION


FUNCTION VaranManager::GetDocuFileInfo
  VAR_INPUT
    p_us_position_info 	: ^USINT;
    ud_listOffset 	    : UDINT;
  END_VAR
  VAR_OUTPUT
    sd_retval 	        : DINT;
  END_VAR
  VAR
    a_data			        : ARRAY[0..2] OF UDINT;
  END_VAR

  //read header of documentation list
  sd_retval := ReadSPIDataComfort(p_us_position_info  := p_us_position_info,            
                                  ud_offset           := ud_listOffset,
                                  ud_length	          := sizeof(a_data),
                                  p_data	            := ( #a_data )$^USINT
                                 );

  //look for an error
  if ( sd_retval <> VARANMANAGER_OK ) then
    return;
  end_if;
  
  // check if length is > 0
  if ( a_data[ 2 ] = 0 ) then
    sd_retval := -100;
    return;
  end_if;
  
  // save length of file
  ud_SPI_Docu_Length := a_data[ 2 ];
  
  //offset = listoffset + 4 byte for checksum + 4 byte for list version + 4 byte length
  ud_SPI_Offset := ud_listOffset + 12;

END_FUNCTION


FUNCTION VaranManager::ReadSPIDataComfort
  VAR_INPUT
    p_us_position_info 	: ^USINT;
    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 :=      ReadSPIData( p_us_position_info	:= p_us_position_info,
                                   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


FUNCTION VIRTUAL GLOBAL VaranManager::GetSerialNo
  VAR_INPUT
    p_us_position_info 	: ^USINT;
    p_SerialNo 	        : ^CHAR;
  END_VAR
  VAR_OUTPUT
    sd_retval 	        : DINT;
  END_VAR
  VAR
    BaseListAddress     : UDINT;
    a_data              : ARRAY[0..31] OF UDINT;
  END_VAR

  if p_us_position_info & p_SerialNo then

    //check OS version
    if ( _RTOSVersion < VM_SPI_OS_VERSION ) then
      // access of SPI flash not possible
      sd_retval := -2;
      return;
    end_if;
    
    // check if documentation is available and get file size and offset in SPI flash
    if ( SearchSPIList(p_us_position_info, VM_SPI_SERIALNO_ID, #BaseListAddress) <> VARANMANAGER_OK ) then
      sd_retval := -3;
      return;
    end_if;

    //read header of serial number list
    sd_retval := ReadSPIDataComfort(p_us_position_info  := p_us_position_info,            
                                    ud_offset           := BaseListAddress,
                                    ud_length	          := 12,
                                    p_data	            := ( #a_data )$^USINT
                                   );

    //look for an error and check if length is > 0 and smaller than max length
    if ( sd_retval <> VARANMANAGER_OK ) | ( a_data[ 2 ] = 0 ) | ( a_data[ 2 ] > SERNO_STRING_SIZE ) then
      sd_retval := -4;
      return;
    end_if;

    //read the whole serial number string
    sd_retval := ReadSPIDataComfort( p_us_position_info := p_us_position_info,
                                     ud_offset	        := BaseListAddress + 12,
                                     ud_length	        := a_data[ 2 ],
                                     p_data		          := p_SerialNo
                                   );
     
    //add string termination
    (p_SerialNo + a_data[ 2 ])^ := 0;

    //look for an error
    if ( sd_retval <> VARANMANAGER_OK ) then
      sd_retval := -5;
      return;
    end_if;
  else
    // invalid parameters
    sd_retval := -1;
  end_if;
  
END_FUNCTION


FUNCTION VIRTUAL GLOBAL VaranManager::AllowRequiredError
  VAR_OUTPUT
    sd_retval 	: DINT;
  END_VAR

  SetRequiredError  := TRUE;
  sd_retval         := 0;

END_FUNCTION


FUNCTION VIRTUAL GLOBAL VaranManager::SetObjectThisp
  VAR_INPUT
    p_us_ObjectPath 	: ^USINT;
    ud_thisp 	        : UDINT;
  END_VAR
  VAR_OUTPUT
    sd_retval 	      : DINT;
  END_VAR
  
  if ( pHardwareTree <> NIL ) then
    sd_retval := HWT_iSetObjectThisp(VaranManagerNr,p_us_ObjectPath,ud_thisp);
  else
    sd_retval := 0;
  end_if;

END_FUNCTION


FUNCTION VIRTUAL GLOBAL VaranManager::GetObjectThisp
  VAR_INPUT
    p_us_ObjectPath : ^USINT;
  END_VAR
  VAR_OUTPUT
    ud_thisp 	      : UDINT;    
  END_VAR
  
  if ( pHardwareTree <> NIL ) then
    ud_thisp := HWT_iGetObjectThisp(VaranManagerNr,p_us_ObjectPath);
  else
    ud_thisp := 0;
  end_if;

END_FUNCTION

//BLEERN001 start
FUNCTION VIRTUAL GLOBAL VaranManager::UpdateRtPostScan
VAR
  i                   : UDINT;
  pHelp               : ^t_s_OneHandle;
  AliveCheck          : DINT;
#ifndef VARAN_TIME_MEASUREMENT_DEACTIVATE
  ud_time	      	    : UDINT;
#endif  
  ud_TempPllStatus    : UDINT;
#ifdef VARAN_TIME_MEASUREMENT_SINGLE_OBJECTS
  ud_SingleTimeMark1  : UDINT;
  ud_SingleTimeMark2  : UDINT;
#endif
END_VAR


  IF (us_RtStep <> _RtWork) THEN
    return;
  END_IF; 
 
  if ManagerOn then

    //look if we have classes
    if ( s_RtPostScanHandles.ud_NrOfHandles > 0 ) then
      
      //call all connected classes
      pHelp := #s_RtPostScanHandles.p_HandleList^[0];
      for i := 0 to s_RtPostScanHandles.ud_NrOfHandles - 1 do

#ifdef VARAN_TIME_MEASUREMENT_SINGLE_OBJECTS
        ud_SingleTimeMark1 := OS_READMICROSEC();
#endif

        //call class
        pHelp^.p_This^.UpdateRtPostScan();
        
#ifdef VARAN_TIME_MEASUREMENT_SINGLE_OBJECTS
        ud_SingleTimeMark2 := OS_READMICROSEC();
        pHelp^.TimeMeasuring.ud_ActTime := ud_SingleTimeMark2 - ud_SingleTimeMark1;
        
        if pHelp^.TimeMeasuring.ud_ActTime > pHelp^.TimeMeasuring.ud_MaxTime then
          pHelp^.TimeMeasuring.ud_MaxTime := pHelp^.TimeMeasuring.ud_ActTime;
        end_if;

        if pHelp^.TimeMeasuring.ud_ActTime < pHelp^.TimeMeasuring.ud_MinTime then
          pHelp^.TimeMeasuring.ud_MinTime := pHelp^.TimeMeasuring.ud_ActTime;
        end_if;
#endif        

        //get pointer on next handle
        pHelp += sizeof(t_s_OneHandle);
      end_for;
    end_if;

    if ( IsAlsoClient & p_ManagerClientSpace <> NIL ) then

      //increment alive counter
      pIsoWriteSafetyData^.VMC_Header.ui_AliveCounter += 1;

      if b_PayloadSupport &
         pMultiVaran^.udVersion >= VM_MULTIVARAN_VERSION_FULL_PAYLOAD_AVAILABLE  then
        MULTI_VARAN_iGetNodeProperty( hNodeHandle       := vmNodeHandle
                                    , udPropertyId      := VM_PROP_PLL_STATUS_REGISTER
                                    , pudPropertyValue  := #ud_TempPllStatus
                                    );   
        pIsoWriteSafetyData^.VMC_Header.us_Status.PLL_Locked := (ud_TempPllStatus AND 2#0101) = 2#0101; // check pll locked and device delay time compensated bit                           
      else
      
        pIsoWriteSafetyData^.VMC_Header.us_Status.PLL_Locked := (p_ManagerPll^.ucControlStatus AND 2#0101) = 2#0101; // check pll locked and device delay time compensated bit
      end_if;
      
      if bPdoCopyDisable = false then
      
        // copy safety data from application memory to manager DPRAM    
        if pIsoWriteSafetyData then
          To_Stdlib.MemCpy( dest    := p_ManagerClientSpace + VM_CLIENT_ISO_WR_OFFSET, 
                            source  := pIsoWriteSafetyData,
                            size    := (SafetyIsoMemWrite + VM_CLIENT_HEADER_SIZE)$UDINT 
                          );
        end_if;
      else
        // copy data from application memory
        if pIsoWriteSafetyData then
          // copy header and TDO data from application memory    
          To_Stdlib.MemCpy( dest    := p_ManagerClientSpace + VM_CLIENT_ISO_WR_OFFSET 
                          , source  := pIsoWriteSafetyData 
                          , size    := sizeof(t_VMC_Header) + sizeof(t_VMC_Safety_Header_TDO)
                          );
        end_if;
      end_if;
      // copy user PDO data from application to manager DPRAM
      if UserObjectData.pIsoWriteData then
        To_Stdlib.MemCpy( dest    := p_ManagerClientSpace + VM_CLIENT_ISO_WR_OFFSET + SafetyIsoMemWrite + VM_CLIENT_HEADER_SIZE, 
                          source  := UserObjectData.pIsoWriteData,
                          size    := UserObjectData.udIsoWriteLength 
                        );
      end_if;                  

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

      // check AliveCounter every Xth cycle (because the other system may have a different speed)
      if pIsoWriteSafetyData^.VMC_Header.ui_AliveCounter MOD VMC_ModValue = 0 then
        //check alive counter
        AliveCheck := pIsoReadSafetyData^.VMC_Header.ui_AliveCounter - ui_AliveCounterOld;
        if ( AliveCheck$INT <= 0 ) then
          SyncCheck := 0;
        else
          SyncCheck := (SyncCheck SHL 1) OR pIsoWriteSafetyData^.VMC_Header.us_Status.PLL_Locked;
        end_if;
        ui_AliveCounterOld := pIsoReadSafetyData^.VMC_Header.ui_AliveCounter;

        if SyncCheck = 16#FF then
          SuperiorSystemOK  := 1;
          TriggerClientWD   := FALSE;
        else
          SuperiorSystemOK  := 0;
          UnSyncCounter     += 1;
        end_if;
      end_if;
    else
      SuperiorSystemOK := -1;
    end_if;

    ExecuteDOL( VARAN_DOL_ISO );

  
#ifndef VARAN_TIME_MEASUREMENT_DEACTIVATE
    //get rt time 

    if b_PayloadSupport &
       pMultiVaran^.udVersion >= VM_MULTIVARAN_VERSION_FULL_PAYLOAD_AVAILABLE  then
      MULTI_VARAN_iGetTimeUpCounter( hManagerNodeHandle := vmNodeHandle                                    
                                   , pudTimeUpCounterNs := #ud_time
                                   );
    else
      ud_time := p_ManagerStructure^.uiTUpCounter;
    end_if;

    //get call time
    s_VaranTimes.s_Realtime.ud_ActTime := Act_RtTime := ( ud_time - s_VaranTimes.s_Realtime.ud_Timemark ) / 1000;

    //look for maximum
    if ( Act_RtTime > Max_RtTime ) then
      Max_RtTime := Act_RtTime;
    end_if;

    //look for minimum
    if ( Act_RtTime < Min_RtTime ) then
      Min_RtTime := Act_RtTime;
    end_if;
#endif  

  end_if;

END_FUNCTION


#pragma warning(disable:73)
FUNCTION GLOBAL VaranManager::TopologyChangeLogin
  VAR_INPUT
    pServer 	: ^DINT;
  END_VAR
#pragma warning(default:73)
// the whole method makes no sense, if we don't get a callback
#ifdef VARAN_iSetManagerCallbackOnConnect
  VAR
    pHelp     : ^t_s_FlexHub;
  END_VAR
  
  // general callback works only on os versions >= 01.02.085
  if _RTOSVersion >= 16#1255 then
      
    // Flexhub makes no sense when we don't have a varan interface (e.g LARS), we don't need to allocate memory here
      if pVaran = NIL then
        return;
      end_if;

    if pFlexHubs = NIL then
      pFlexHubs$pVoid := To_StdLib.Malloc(size:=sizeof(t_s_FlexHub));      
      pHelp := pFlexHubs;
      
      // only on the first login we call the OS interface
      VARAN_iSetManagerCallbackOnConnect(1);
    else
      pHelp := pFlexHubs;
      while pHelp^.pNext <> NIL do
        pHelp := pHelp^.pNext;
      end_while;
      pHelp^.pNext$pVoid := To_StdLib.Malloc(size:=sizeof(t_s_FlexHub));
      pHelp := pHelp^.pNext;
    end_if;
    
    if pHelp <> NIL then
      pHelp^.pServer := pServer - sizeof(SvrCh.pMeth);
      pHelp^.pNext   := NIL;
    else
#ifdef HWC_LogError
      HWC_LogError(this,"@08AC (VaranManager::TopologyChangeLogin) Failed to allocate memory for flexhub");
#endif      
    end_if;
  else

#ifdef HWC_LogError
    HWC_LogError(this,"@019B (VaranManager::TopologyChangeLogin) General callback for FlexHub works only on os versions >= 01.02.085");
#endif
  
  end_if;
#else
#ifdef HWC_LogError
 HWC_LogError(this,"@019C (VaranManager::TopologyChangeLogin) Need newer lsl_st_varan.h file for general callback functionality");
#endif
  #pragma message("Need newer lsl_st_varan.h file for general callback functionality (used for FlexHub class)")
#endif

END_FUNCTION


FUNCTION GLOBAL VaranManager::AddDAClientRdData
  VAR_INPUT
    ud_length 	: UDINT;
    p_pdata 	  : ^void;
    pThis 	    : ^void;
    pFunction 	: ^void;
  END_VAR
  VAR_OUTPUT
    sd_retval 	: DINT;
  END_VAR
  
  //check if manager is also client
  if (IsAlsoClient = 0) | (SuperiorSystemTime = 0) then
    sd_retval := -6;
    return;    
  end_if;

  //check length (we reserve 4 bytes for header)
  if ( ud_length > (VM_CLIENT_MAX_BUFFER_USE - VM_CLIENT_HEADER_SIZE) ) then
    sd_retval := -2;
    return;
  end_if;

  //check pointer
  if ( p_pdata = NIL ) | (pThis = NIL) | (pFunction = NIL) then
    sd_retval := -3;
    return;
  end_if;

  // check fpga version (must be >= 1.4) and os version (must be >= 01.02.103)
  if Release < 16#14 then
  
    // fpga doesn't support the new buffer
    sd_retval := -7;
#ifdef HWC_LogError    
    HWC_LogError(this, "@019D (VaranManager::AddDAClientRdData) FPGA version of VMC needs to be at least 1.4 to support the direct access buffer");
#endif
    return;

  elsif _RTOSVersion < VM_DA_BUFFER_AVAILABLE then
  
    // os doesn't support the irq callback
    sd_retval := -8;
#ifdef HWC_LogError    
    HWC_LogError(this, "@019E (VaranManager::AddDAClientRdData) For IRQ Callback on VMC buffer os version >= 01.02.103 is required");
#endif
    return;
  else
  
#ifdef VARAN_iSetManagerCallbackOnVmcBufDaInt
    // if there is no VARAN Interface available, we would crash at the call
    if pVaran = NIL then
      sd_retval := VARANMANAGER_DRIVER_NOT_EXISTS;
      return;
    end_if;

    // install irq callback
    VARAN_iSetManagerCallbackOnVmcBufDaInt(1);
    DA_IRQ_pFunc  := pFunction;
    DA_IRQ_pthis  := pThis;
    
    //save length and data pointer
    DA_IRQ_Length := ud_length ;
    DA_IRQ_pData  := p_pdata;

#else
    // newer lsl_st_varan.h neccessary to use this functionality
    sd_retval := -9;
#ifdef HWC_LogError    
    HWC_LogError(this, "@019F (VaranManager::AddDAClientRdData) Need newer lsl_st_varan.h file to install IRQ Callback on VMC direct access buffer");
#endif    
    #pragma message("Need newer lsl_st_varan.h file to install IRQ Callback on VMC direct access buffer");
    return;
#endif
  end_if;
      
  sd_retval := 0;
  
END_FUNCTION


FUNCTION GLOBAL VaranManager::SendDAClientWrData
  VAR_INPUT
    ud_length 	: UDINT;
    p_pdata 	  : ^void;
  END_VAR
  VAR_OUTPUT
    sd_retval 	: DINT;
  END_VAR

  //check if manager is also client
  if (IsAlsoClient = 0) | (SuperiorSystemTime = 0) then
    sd_retval := -6;
    return;    
  end_if;
  
  //check support of da buffer
  if Release < 16#14 then
    sd_retval := -1;
    return;
  end_if;
    
  //check length (we reserve 4 bytes for header)
  if ( ud_length > (VM_CLIENT_MAX_BUFFER_USE - VM_CLIENT_HEADER_SIZE) ) then
    sd_retval := -2;
    return;
  end_if;

  //check pointer
  if ( p_pdata = NIL ) then
    sd_retval := -3;
    return;
  end_if;

  // save data to output data memory
  if ud_length > VM_CLIENT_HEADER_SIZE then  
    To_Stdlib.MemCpy(dest   := p_ManagerClientSpace + VM_CLIENT_DA_WR_OFFSET + VM_CLIENT_HEADER_SIZE
                   , source := p_pdata + VM_CLIENT_HEADER_SIZE
                   , size   := ud_length - VM_CLIENT_HEADER_SIZE
                   );
  end_if;
  
  // the first 4 byte are written in the end (switch buffer)
  (p_ManagerClientSpace + VM_CLIENT_DA_WR_OFFSET)^ := p_pdata^$DINT;

  sd_retval := 0;
  
END_FUNCTION


FUNCTION VIRTUAL GLOBAL VaranManager::GetNsTimeBPLLTicks
  VAR_OUTPUT
    ud_ns_counter 	: UDINT;
  END_VAR
  
  //look if init has been executed
  if ( s_VaranManagerSettings.us_InitCounter = 0 ) then
    bExternalInit := true;
    Init();
  end_if;

  if b_PayloadSupport &
    pMultiVaran^.udVersion >= VM_MULTIVARAN_VERSION_FULL_PAYLOAD_AVAILABLE  then
    MULTI_VARAN_iGetNodeProperty( hNodeHandle       := vmNodeHandle
                                , udPropertyId      := VM_PROP_TIME_UP_COUNTER_BETWEEN_PLL_TICKS
                                , pudPropertyValue  := #ud_ns_counter
                                ); 
  else
  
    //if we have the Manager structure
    if ( p_ManagerStructure <> NIL ) then
      ud_ns_counter := p_ManagerStructure^.uiTUpCounterBPLLTicks;
    end_if;
  end_if;

END_FUNCTION


FUNCTION VIRTUAL GLOBAL VaranManager::AddMovDO
  VAR_INPUT
    ud_dol_type 	      : UDINT;
    p_ud_handle 	      : ^UDINT;
    p_ud_MovSettings 	  : ^UDINT;
    ud_type 	          : UDINT;
  END_VAR
  VAR_OUTPUT
    sd_retval 	        : DINT;
  END_VAR
  VAR
    p_dummy             : UDINT;
    pVaranHandle        : ^LSL_VARANFRAME;
//    TempMem             :  UDINT;
  END_VAR
  
#ifdef VM_DEBUG_PAYLOAD
  // Payload not supported
  if b_PayloadSupport then
    // This method is not supporded with Payload support
    ((0)$^USINT)^ := 0; 
  end_if;  
#endif  

  if p_ud_MovSettings then

    // add data object Move Command (add write and change the command type)
    sd_retval := AddWrDO( p_us_position_info:=NIL
                        , ud_dol_type:=ud_dol_type
                        , p_ud_handle:=p_ud_handle
                        , ud_address:=0
                        , ud_length:=0
                        , p_ud_data:= #p_dummy
                        , ud_type:= VM_MEMORY_ACCESS
                        );
                    
    // if no error, we initialize the return structure
    if ( sd_retval = VARANMANAGER_OK ) then
      // check if the DO has a special priority
      if ud_type AND VM_PRIORITY_FILTER then
        AddToDOPriorityList(p_ud_handle^$^LSL_VARANFRAME, ud_type AND VM_PRIORITY_FILTER);
      end_if;

      pVaranHandle              := (p_ud_handle^)$^LSL_VARANFRAME;
      
      // replace the write command with the move command
      pVaranHandle^.ucDOType    := 16#10;
      
      // start with not moving anything
      pVaranHandle^.ucCtrlStat  := VARAN_DO_NO_RUN;
      
      // start of the mover settings is, where normally the ucRetrys is (no retries necessary in local memory)
      p_ud_MovSettings^         := (#pVaranHandle^.ucRetrys)$UDINT;

(*    // is already counted with the AddWrDO-Call
      //26 Byte (Header) + 2 Byte (compensate missalignment)
      TempMem := 28;
    
      case ud_dol_type of
      // **************************************************
        VARAN_DOL_DA:
          DPRAM_Used.DA_RdWr += TempMem;
          DOCounter.DA_RdWr  += 1;        
      // **************************************************                
        VARAN_DOL_ISO:
          DPRAM_Used.ISO_RdWr += TempMem;
          DOCounter.ISO_RdWr  += 1;
      // **************************************************
        VARAN_DOL_ASY:
          DPRAM_Used.ASY_RdWr += TempMem;
          DOCounter.ASY_RdWr  += 1;
      // **************************************************
        VARAN_DOL_ADMIN:
          DPRAM_Used.Admin_RdWr += TempMem;
          DOCounter.Admin_RdWr  += 1;
      // **************************************************
        VARAN_DOL_IRQ:
          DPRAM_Used.IRQ_RdWr += TempMem;
          DOCounter.IRQ_RdWr  += 1;        
      end_case;
*)
    else
      p_ud_MovSettings^ := NIL;
    end_if;
    
  end_if;

END_FUNCTION

// Method not used with Payload DO's, OS Handles priority's in this case.
FUNCTION VaranManager::AddToDOPriorityList
  VAR_INPUT
    pHandle 	    : ^LSL_VARANFRAME;
    ud_Priority 	: HDINT;
  END_VAR
  VAR
    pListHelp     : ^t_PrioListList;
    pHelp         : ^t_PrioHandleList;
  END_VAR

  // if there is no VARAN Interface available, we would crash at adding dummy DOs
  if pVaran = NIL then
    return;
  end_if;

  // check if there is already a list with a priority
  if pPriorityList = NIL then
    // if not, create it
    pPriorityList$pVoid := To_StdLib.Malloc(size:=sizeof(t_PrioListList));
    pListHelp := pPriorityList;
    if pListHelp <> NIL then
      pListHelp^.Prio  := ud_Priority;
      pListHelp^.pList := NIL;
      pListHelp^.pNext := NIL;
    else
      // failed to allocate memory
      State := _NoMem;
      return;
    end_if;
  else
    pListHelp := pPriorityList;
    while (pListHelp^.Prio <> ud_Priority) & (pListHelp^.pNext <> NIL) do
      pListHelp := pListHelp^.pNext;
    end_while;
    if (pListHelp^.Prio <> ud_Priority) then
      pListHelp^.pNext$pVoid := To_StdLib.Malloc(size:=sizeof(t_PrioListList));
      pListHelp := pListHelp^.pNext;
      if pListHelp <> NIL then
        pListHelp^.Prio  := ud_Priority;
        pListHelp^.pList := NIL;
        pListHelp^.pNext := NIL;
      else
        // failed to allocate memory
        State := _NoMem;
        return;
      end_if;
    end_if;
  end_if;
  
  // now we have the pointer to the list of the right priority (pListHelp^.pList)

  // check if there is already an entry with this handle
  if pListHelp^.pList = NIL then
    // if not, create it
    pListHelp^.pList$pVoid := To_StdLib.Malloc(size:=sizeof(t_PrioHandleList));
    pHelp := pListHelp^.pList;
  else
    pHelp := pListHelp^.pList;
    while (pHelp^.pHandle <> pHandle) & (pHelp^.pNext <> NIL) do
      pHelp := pHelp^.pNext;
    end_while;
    if (pHelp^.pHandle <> pHandle) then
      pHelp^.pNext$pVoid := To_StdLib.Malloc(size:=sizeof(t_PrioHandleList));
      pHelp := pHelp^.pNext;
    else
      // already in list
      return;
    end_if;
  end_if;

  if pHelp <> NIL then
    pHelp^.pHandle := pHandle;
    pHelp^.pNext := NIL;
  else
    // failed to allocate memory
    State := _NoMem;
    return;
  end_if;

END_FUNCTION

// Method not used with Payload DO's, OS Handles priority's in this case.
FUNCTION VaranManager::SortCmdsByPriority
  VAR
    pHelpFrame        : ^LSL_VARANFRAME;
    pHelp             : ^t_PrioHandleList;
    pNonPrioList      : ^t_PrioHandleList;
    pActList          : ^t_PrioListList;
    pNextList         : ^t_PrioListList;
    pPreviousList     : ^t_PrioListList;
    bMadeSort         : BOOL;
    sd_retval         : DINT;
    pDummyReadData    : UDINT;
    pDummyHandle      : UDINT;
    pTerminationFrame : ^LSL_VARANFRAME;
  END_VAR

  // search for first command which is not in priority list
  pHelpFrame := p_SyncAndWdDO;

  // if first command is not sync, we don't sort anything (check command = 0 and subcommand = 1) => some error may have occured
  if ((((#pHelpFrame^.uiResponseTime)$^USINT + 4)^ AND 16#F0) = 0) & (((#pHelpFrame^.uiResponseTime)$^USINT + 5)^ = 1) then
  
    // add a dummy DO just to be the last one after sorting (otherwise the OS can't add DOs during runtime like for DIAS DRIVE)
#pragma warning(disable: 75)
    sd_retval := VARAN_iAddDOToDOL	( uiManager			  := VaranManagerNr
                                    , pucNode			    := NIL
                                    , uiDOLType 		  := VARAN_DOL_ISO
                                    , puiDOHandle		  := #pDummyHandle
                                    , uiCmd				    := VARAN_CMD_MEMORY_READ
                                    , uiAddressRead		:= 0
                                    , uiLengthRead		:= 1
                                    , pucRead			    := #pDummyReadData
                                    , uiAddressWrite	:= 0
                                    , uiLengthWrite		:= 0
                                    , pucWrite			  := NIL
                                    );
#pragma warning(default: 75)
  
    //if an error occured => we don't sort anything
    if ( sd_retval <> VARANMANAGER_OK ) then
      // tell the RT that we're finished with sorting
      us_RtStep := _Wait4Sync;
      return;
    end_if;    

    pNonPrioList  := NIL;
    pHelpFrame    := pHelpFrame^.pNext$^LSL_VARANFRAME;
    while pHelpFrame <> 16#FFFFFFFF do
      
      if IsInPriorityList(pHelpFrame) = FALSE then
        // put the non-priored commands in an own list (without sync)

        if pNonPrioList = NIL then
          // if not, create it
          pNonPrioList$pVoid := To_StdLib.Malloc(size:=sizeof(t_PrioHandleList));
          pHelp := pNonPrioList;
        else
          pHelp := pNonPrioList;
          while (pHelp^.pNext <> NIL) do
            pHelp := pHelp^.pNext;
          end_while;
          pHelp^.pNext$pVoid := To_StdLib.Malloc(size:=sizeof(t_PrioHandleList));
          pHelp := pHelp^.pNext;
        end_if;

        if pHelp <> NIL then
          pHelp^.pHandle := pHelpFrame;
          pHelp^.pNext := NIL;
        else
          // failed to allocate memory
          State := _NoMem;
          return;
        end_if;
      end_if;
      
      if pHelpFrame^.pNext = 16#FFFFFFFF then 
        pTerminationFrame := pHelpFrame;
      end_if;
      
      pHelpFrame := pHelpFrame^.pNext$^LSL_VARANFRAME;
    end_while;

    // now we got the priorized and the non-priorized commands
    
    // sort the lists by priority number
    bMadeSort := TRUE;
    while bMadeSort do
      bMadeSort := FALSE;
   
      // go through all priority lists
      pPreviousList := pActList := pPriorityList;
      while pActList^.pNext do
        // if the next list has a higher priority number => resort it
        if pActList^.Prio > pActList^.pNext^.Prio then
          pNextList         := pActList^.pNext;
          
          pActList^.pNext   := pNextList^.pNext;
          pNextList^.pNext  := pActList;
          
          // if it's the first module, we have to change also the pointer to the list
          if pPriorityList = pActList then
            pPreviousList         := pPriorityList := pNextList;
          else
            // if the beginning of the list has changed it doesn't count, because then we start again automatically
            bMadeSort             := TRUE;
            pPreviousList^.pNext  := pNextList;
          end_if;
          pActList := pNextList;
        else
          pActList := pActList^.pNext;
        end_if;
        
        if (pActList <> pPriorityList) & (pActList <> pPriorityList^.pNext) then
          pPreviousList := pPreviousList^.pNext;
        end_if;
      end_while;
    end_while;

    // the lists in pPriorityList are now sorted by priority => hang the non-priorized list as last priority after this
    pActList := pPriorityList;
    while (pActList^.pNext <> NIL) do
      pActList := pActList^.pNext;
    end_while;
    pActList^.pNext$pVoid := To_StdLib.Malloc(size:=sizeof(t_PrioListList));
    pActList := pActList^.pNext;
    if pActList <> NIL then
      pActList^.Prio  := 16#FFFFFFFF;
      pActList^.pList := pNonPrioList;
      pActList^.pNext := NIL;
      pNonPrioList    := NIL;  // no more need to remember this
    else
      // failed to allocate memory
      State := _NoMem;
      return;
    end_if;

    // change pNext of Sync-Command to the first command of our list
    p_SyncAndWdDO^.pNext$^LSL_VARANFRAME := pPriorityList^.pList^.pHandle;
    
    // and now we go through the list and change all next pointers (priority is automatically given)
    pActList := pPriorityList;
    while pActList do
      // go through all elements of this list
      pHelp := pActList^.pList;
      while pHelp^.pNext do
        pHelp^.pHandle^.pNext$^LSL_VARANFRAME := pHelp^.pNext^.pHandle;
      
        pHelp := pHelp^.pNext;
      end_while;
      
      if pActList^.pNext then
        pHelp^.pHandle^.pNext$^LSL_VARANFRAME := pActList^.pNext^.pList^.pHandle;
      end_if;
      
      pActList := pActList^.pNext;
    end_while;
  end_if;

END_FUNCTION

// Method not used with Payload DO's, OS Handles priority's in this case.
FUNCTION VaranManager::IsInPriorityList
  VAR_INPUT
    pHandle 	: ^LSL_VARANFRAME;
  END_VAR
  VAR_OUTPUT
    retcode 	: BOOL;
  END_VAR
  VAR
    pListHelp : ^t_PrioListList;
    pHelp     : ^t_PrioHandleList;
  END_VAR

  retcode := FALSE;
  
  // go through all priority lists
  pListHelp := pPriorityList;
  while pListHelp do
    // go through all elements of this list
    pHelp := pListHelp^.pList;
    while pHelp do
      // check if it's the handle we search for
      if pHelp^.pHandle = pHandle then
        retcode := TRUE;
        return;
      end_if;
    
      pHelp := pHelp^.pNext;
    end_while;
    
    pListHelp := pListHelp^.pNext;
  end_while;

END_FUNCTION


FUNCTION VaranManager::FirstInit
VAR
  sd_retval     	    : DINT;
  ud_counter	        : UDINT;
  i		          	    : UDINT;
  ManagerNodeString   : USINT;
  nodeProperty        : ARRAY [0..2] of LSL_PROPERTY_VALUE_PAIR; 
  aStrSemaphore       : ARRAY [0..99] of CHAR;
  aStrVaranManagerNr  : ARRAY [0..5] of CHAR;
  udTempCyTime        : UDINT;
END_VAR

  bFirstInitDone      := true;
  
  //read Clients
  VaranManagerNr	    := VaranManagerNr.read();
  VaranManagerTime    := VaranManagerTime.read();
//  IRQTaskTime         := IRQTaskTime.read();
  IsAlsoClient        := IsAlsoClient.read();
  SuperiorSystemTime  := SuperiorSystemTime.Read();
  
  //Check if varanmanager number is available on HW
  if VaranManagerNr > udSystemVaranManagerCnt then
#ifdef HWC_LogError
    HWC_LogValue2(this, "@01A0 (VaranManager::FirstInit) Invalid varanmanagernumber 0x{0}! Max. number on this CPU is 0x{1}", VaranManagerNr ,udSystemVaranManagerCnt);
#endif
    state := _ManagerError;
    ManagerOn := 0;
    return;
  end_if;
  
  //set limit for VaranManagerTime
  if VaranManagerTime > 32000000 then
#ifdef HWC_LogError
    HWC_LogError(this, "@0026 (VaranManager::FirstInit) Maximum limit for VaranManagerTime (32 000 000 ns = 32 ms) exceeded");
#endif
    state := _VaranTimeError;
    ManagerOn := 0;
    return;
  end_if;
  
  //get rt-debug state
  b_RtDebug := To_HwControl.GetRtDebugState() <> 0;
    
  //****************************************************************************                                  
  if b_PayloadSupport
     & pMultiVaran^.udVersion >= VM_MULTIVARAN_DOL_SET_REQUIRED_ERROR_ISO_START_TIME then
    
    //-----------------------------------------------------------------------------------------------   
    //get manager node info from os    
    p_NodeInfo := #s_NodeInfo;
    
    sd_retval := MULTI_VARAN_iGetNodeInformation( hNodeHandle := vmNodeHandle
                                                , psNodeInfo  := p_NodeInfo
                                                );
    
    if	( sd_retval <> VARANMANAGER_OK 
      | p_NodeInfo = NIL
      )
    then
      State := _NoHardware;
      return;
    end_if;
    
    // get release of FPGA
    Release := p_NodeInfo^.ucFPGAVersion;
    
  //-----------------------------------------------------------------------------------------------
    
    p_SyncOut := #s_SyncOut;
    
    // disable varan manager sync out
    // Searching for the correct sync is no longer nessersary because we pass the sync ID when it is configured
    // The value will be writted o the VM later in this method with MULTI_VARAN_ICONFIGUREPLLSYNCOUT
    p_SyncOut^.ucControlStatus      := 0;    
    
    // set required bit on (for varan error in init (os set bit in function InitApp) later)    
    nodeProperty[0].udPropertyId    := VM_PROP_REQUIRED_ERROR_ENABLED;
    nodeProperty[0].udPropertyValue := 1;
    MULTI_VARAN_iSetNodeProperties( hNodeHandle           := vmNodeHandle
                                  , udPropertyCount       := 1
                                  , psPropertyValuePairs  := #nodeProperty[0]
                                  );

    //Get ISO start Time
    GetISOStartTime();
    
    s_ManagerControlData.ud_IsoStartPoint := VaranManagerTime * IsoStartPoint / 100;
    
    nodeProperty[0].udPropertyId          := VM_PROP_ISO_START_TIME;
    nodeProperty[0].udPropertyValue       := s_ManagerControlData.ud_IsoStartPoint;
    MULTI_VARAN_iSetNodeProperties( hNodeHandle           := vmNodeHandle
                                  , udPropertyCount       := 1
                                  , psPropertyValuePairs  := #nodeProperty[0]
                                  );   
    
    //Check if OS supports full payload
    if b_PayloadSupport &
       pMultiVaran^.udVersion < VM_MULTIVARAN_VERSION_FULL_PAYLOAD_AVAILABLE then  
        
      //OS do not support full payload with the multivaran interface
      //so we need to use some functions from the old interface.
        
      //-----------------------------------------------------------------------------------------------
      //get Manager structure
      sd_retval := VARAN_iGetManagerControl	( uiManager := VaranManagerNr
                                            , pvCB 		  := ( #p_ManagerStructure )$^PLSL_CONTROLBLOCK
                                            , pvPLL		  := ( #p_ManagerPll )$^PLSL_VARANPLL
                                            );

      //look for an error
      if	( sd_retval 			<> 	VARANMANAGER_OK
        | p_ManagerStructure	=	NIL
        | p_ManagerPll			  =	NIL
        )
      then
        State 		:= _NotInitialized;
        ManagerOn	:= 0;
        return;
      end_if;
      
      //look for right sync out pointer
      p_SyncOut := #p_ManagerPll^.sSynOutPeripheral1;
      ud_Counter := VaranManagerNr;

      //look in all peripheral sync outs
      for i := 1 to VM_MAX_SYNC_OUTS - 1 do
        
        //look if sync out id is correct
        if ( p_SyncOut^.ucSyncOutID = VM_SYNC_OUT_ID ) then
          
          //if it is right pll for right manager number (first is vor VaranManager number 0, second for VaranManager number 1, ....)
          if ( ud_counter = 0 ) then
            exit;					//we found right sync out --> exit
          end_if;
          ud_counter -= 1;			//we find one for lower VaranManager number
        end_if;

        //get pointer to next sync out
        p_SyncOut += sizeof ( LSL_VARANPLLSYNCOUT );

        //if we searched all sync outs set VaranManager off
        if ( i = VM_MAX_SYNC_OUTS - 1 ) then
          p_SyncOut := NIL;
          State 		:= _NotInitialized;
          ManagerOn	:= 0;
          return;
        end_if;
      end_for;

      //disable varan manager sync out
      p_SyncOut^.ucControlStatus := 0;      
    end_if;       
    
  else // if b_PayloadSupport **************************************************************************** 

    // if there is no VARAN Interface available, we would crash at the call
    if pVaran = NIL then
      sd_retval := VARANMANAGER_DRIVER_NOT_EXISTS;
      return;
    end_if;

      //-----------------------------------------------------------------------------------------------
    //get manager node info from os
    ManagerNodeString := 0;
    
    //call OS - function (must be OS-funciton because of error handling)	
    sd_retval := VARAN_iGetNodeInfo	( uiManager	:= VaranManagerNr
                                    , pucNode	  := #ManagerNodeString
                                    , pNodeInfo	:= #p_NodeInfo
                                    );

    if	( sd_retval <> VARANMANAGER_OK 
      | p_NodeInfo = NIL
      )
    then
      State := _NoHardware;
      return;
    end_if;

      // get release of FPGA
    Release := p_NodeInfo^.ucFPGAVersion;

    //-----------------------------------------------------------------------------------------------
    //get Manager structure
    sd_retval := VARAN_iGetManagerControl	( uiManager := VaranManagerNr
                                          , pvCB 		  := ( #p_ManagerStructure )$^PLSL_CONTROLBLOCK
                                          , pvPLL		  := ( #p_ManagerPll )$^PLSL_VARANPLL
                                          );

    //look for an error
    if	( sd_retval 			<> 	VARANMANAGER_OK
      | p_ManagerStructure	=	NIL
      | p_ManagerPll			= 	NIL
      )
    then
      State 		:= _NotInitialized;
      ManagerOn	:= 0;
      return;
    end_if;

    //look for right sync out pointer
    p_SyncOut := #p_ManagerPll^.sSynOutPeripheral1;
    ud_Counter := VaranManagerNr;

    //look in all peripheral sync outs
    for i := 1 to VM_MAX_SYNC_OUTS - 1 do
      
      //look if sync out id is correct
      if ( p_SyncOut^.ucSyncOutID = VM_SYNC_OUT_ID ) then
        
        //if it is right pll for right manager number (first is for VaranManager number 0, second for VaranManager number 1, ....)
        if ( ud_counter = 0 ) then
          exit;					//we found right sync out --> exit
        end_if;
        ud_counter -= 1;			//we find one for lower VaranManager number
      end_if;

      //get pointer to next sync out
      p_SyncOut += sizeof ( LSL_VARANPLLSYNCOUT );

      //if we searched all sync outs set VaranManager off
      if ( i = VM_MAX_SYNC_OUTS - 1 ) then
        p_SyncOut := NIL;
        State 		:= _NotInitialized;
        ManagerOn	:= 0;
        return;
      end_if;
    end_for;

    //disable varan manager sync out
    p_SyncOut^.ucControlStatus := 0;

    //set required bit on (for varan error in init (os set bit in function InitApp) later)
    p_ManagerStructure^.ucTCEnable := p_ManagerStructure^.ucTCEnable or 16#80;

    //Get ISO start Time
    GetISOStartTime();

    p_ManagerStructure^.uiIsoStartPoint := VaranManagerTime * IsoStartPoint / 100;
    
  end_if; // if b_PayloadSupport ****************************************************************************

  // get maintimer in ns to compare with varan times
  MainTimer := _ClockTicks * 1000;  

  //look if VaranManagerTime is a multiple of maintimer (maintimer has to be always less or equal the varan time)
  if ( VaranManagerTime mod MainTimer <> 0 ) then
    //Log entry
#ifdef HWC_LogValue2
    HWC_LogValue2(this, "@064A (VaranManager::FirstInit) VaranManagerTime ({0}) is not a multiple of MainTimer ({1})!", VaranManagerTime, MainTimer);
#endif

    State 		:= _NotInitialized;
    ManagerOn	:= 0;
    return;
  end_if;

//------------------------------------------------------------ Client Instructions --------------------------------------------------------|
//                                                                                                                                         V
  if ( IsAlsoClient ) then

    if b_PayloadSupport &
       pMultiVaran^.udVersion >= VM_MULTIVARAN_VERSION_FULL_PAYLOAD_AVAILABLE  then
      sd_retval := MULTI_VARAN_iGetNodeProperty(  hNodeHandle       := vmNodeHandle
                                                , udPropertyId      := VC_OPT_PROP_BUFFER_ADDRESS_ISO // = Offset 0 in p_ManagerClientSpace
                                                , pudPropertyValue  := (#p_ManagerClientSpace)$^UDINT );
    
    elsif ( _RTOSVersion >= 16#11DA ) & pVaran then
  
      //Schnittstelle vom OS holen!!!!!!			
      sd_retval := VARAN_iGetManagerClientAddress	( uiManager		:= VaranManagerNr
                                                  , uiType		  := 0
                                                  , puiAddress	:= ( #p_ManagerClientSpace )$^UDINT
                                                  );
    end_if;

    //check if function is available
    if ( sd_retval <> VARANMANAGER_OK | p_ManagerClientSpace = NIL ) then

      IsAlsoClient := 0;

#ifdef HWC_LogError
      HWC_LogError(this, "@0654 (VaranManager::FirstInit) Client - Function not available but activated! (at least OS - Version 1.1.217 required)");
#endif
    else
      TriggerClientWD             := TRUE;
      bEnableManagerWithNoModules := TRUE; // activate, to ensure varan-client functionality if no varan clients are connected to the manager.
      sd_retval                   := InitMulDivVMC();

      //look for an error
      if ( sd_retval <> 0 ) then
        ManagerOn	:= 0;
        return;	
      end_if;
    end_if;
    
  end_if;
    
//------------------------------------------------------------ Client Instructions --------------------------------------------------------^
//                                                                                                                                         |   

  //get system periode time
  if b_PayloadSupport &
     pMultiVaran^.udVersion >= VM_MULTIVARAN_VERSION_FULL_PAYLOAD_AVAILABLE  then
    
    if MULTI_VARAN_iGetNodeProperty( hNodeHandle       := vmNodeHandle
                                , udPropertyId      := VM_PROP_PLL_SYSTEM_PERIOD_TIME
                                , pudPropertyValue  := #ud_SystemPeriod
                                ) <> VARANMANAGER_OK then
           
#ifdef HWC_LogError
      HWC_LogError(this,"@01A1 (VaranManager::FirstInit) Failed to get PLL System period time");
#endif
           
      State 		:= _NotInitialized;
      ManagerOn	:= 0;
      return;
    else
    ud_SystemPeriod *= 10;
    end_if;                                
                                
  else
    ud_SystemPeriod := ( ( p_ManagerPll^.aucPeriod )$UDINT and 16#FF_FFFF ) * 10;
  end_if;  

  //look if VaranManager is a multiple of system periode
  if ( VaranManagerTime mod ud_SystemPeriod <> 0 ) & 
     ( ud_SystemPeriod mod VaranManagerTime <> 0 ) then
    IF ( _firstscan = TRUE ) THEN
      //Log entry
#ifdef HWC_LogValue2
      HWC_LogValue2(this, "@065E (VaranManager::FirstInit) VaranManagerTime ({0}) is not a multiple of System Period Time ({1})!", VaranManagerTime, ud_SystemPeriod);
#endif

    END_IF;
    State 		:= _NotInitialized;
    ManagerOn	:= 0;
    return;
  end_if;
  
  if ( IsAlsoClient = 0 ) then

    //-----------------------------------------------------------------------------------------------
    //set sync out signal for peripherie sync out
    p_SyncOut^.ucPeriodMultiplier 	:= TO_USINT( VaranManagerTime / ud_SystemPeriod );
  end_if;
  
  //-----------------------------------------------------------------------------------------------
  //Write sync out, cannot directly be written with payload support
  if b_PayloadSupport &
     pMultiVaran^.udVersion >= VM_MULTIVARAN_VERSION_GET_SYSTEM_PROPERTY_AVAILABLE  then
    
    sd_retval := MULTI_VARAN_ICONFIGUREPLLSYNCOUT( hManagerNodeHandle    := vmNodeHandle
                                    , udSyncOutId           := VM_SYNC_OUT_ID
                                    , udPeriodMultiplier    := p_SyncOut^.ucPeriodMultiplier
                                    , udFrameCountThreshold := p_SyncOut^.ucFrameCountThreshold
                                    , udControlStatus       := p_SyncOut^.ucControlStatus
                                    );
  end_if;

  //-----------------------------------------------------------------------------------------------
  //set function list for controlling class
  s_VMFunctions.p_This		                := this;
  s_VMFunctions.ud_VaranTime	            := VaranManagerTime;
  s_VMFunctions.b_IsAlsoClient            := to_bool(IsAlsoClient);
  s_VMFunctions.ud_SuperiorTime           := SuperiorSystemTime;
  s_VMFunctions.SafetyManagerThisPointer  := #SafetyManagerThis;

  CoreSelect := CoreSelect.Read();
    
  //Check for correct setting
  if CoreSelect < TASK_SELECT_CORE0 | CoreSelect > TASK_SELECT_COREMAX then   
    
#ifdef HWC_LogValue2
      HWC_LogValue2(this, "@01A2 (VaranManager::FirstInit) Client CoreSelect is invalid. Max Value: 0x{0}, Set value: 0x{1}",TASK_SELECT_COREMAX,CoreSelect$UDINT);
#endif

    state := _InvalidConfguration;
    ManagerOn := 0;
    return;
  end_if;  
  
  //send info to HwControl class
#ifdef CMD_LOGIN_VARANMANAGER
  
    MyPara.uiCmd := CMD_LOGIN_VARANMANAGER;
    MyPara.aPara[0] := VaranManagerNr$DINT;               //Number of the VaranManager
    MyPara.aPara[1] := (#s_VMFunctions)$DINT;             //Pointer to function list
    MyPara.aPara[2] := CoreSelect$DINT;                   //Selection on which core the manager should be called (0 ... Core 0, 1 ... Core 1)
    MyPara.aPara[3] := ( VaranManagerTime / 1000 )$DINT;  //ud_RtTime_us
    
    //Always set cyclic to 1ms, except we have a maintimer which is greater than 1ms, then set it to maintimer (to have the same behaviour like the old system)
    if _ClockTicks > 1000 then
      udTempCyTime := _ClockTicks;  
    else
      udTempCyTime := 1000;
    end_if;

    MyPara.aPara[4] := udTempCyTime$DINT;  //ud_CyTime_us
    
    To_HwControl.NewInst(pPara:=#MyPara, pResult:=#MyResult);
    
    sd_retval := MyResult.aData[0]$DINT;

#else
  
    if CoreSelect > TASK_SELECT_CORE0 then
#ifdef HWC_LogError
      HWC_LogError(this, "@01A3 (VaranManager::FirstInit) Need newer version of HwControl.h Headerfile. CoreSelect is not supported. Varanmanager will be called from the first CPU-core.");
#endif
      state := _InvalidConfguration;
      ManagerOn := 0;
      return;
    end_if;
  
    sd_retval := To_HwControl.AddVaranManager	( ud_manager_number	:= VaranManagerNr
                                              , p_function_list	  := #s_VMFunctions
                                              );
#endif

  //look for an error
  if ( sd_retval <> 0 ) then
  
#ifdef HWC_LogValue1
      HWC_LogValue1(this, "@01A4 (VaranManager::FirstInit) Failed to add VaranManager to HWControl. ErrorCode: 0x{0}!",sd_retval$UDINT);
#endif

    State 		:= _NotInitialized;
    ManagerOn	:= 0;
    return;	
  end_if;

  //Check if we have the ability to give the OS the information which VaranManager runs on which processor core
  //The processing of the interrupts affecting this varanmanager also takes place on the same processor core as the realtime/cyclic of the hardware classes
  //*******************************************************************************************************
  if b_PayloadSupport & pMultiVaran^.udVersion >= VM_MULTIVARAN_VERSION_SET_CORESELECT_INFO_AVAILABLE then
    
    //Property ID of CoreSelect
    nodeProperty[0].udPropertyId    := VM_PROP_CORE_NUMBER;
    
    //Set Coreselect (0 ... first core, 1 ... second core, ...)
    nodeProperty[0].udPropertyValue := CoreSelect$UDINT;

    sd_retval := MULTI_VARAN_iSetNodeProperties( hNodeHandle           := vmNodeHandle
                                               , udPropertyCount       := 1
                                               , psPropertyValuePairs  := #nodeProperty[0]
                                               ); 
                                               
    if sd_retval <> VARANMANAGER_OK then
    #ifdef HWC_LogError
      HWC_LogError(this, "@04A9 (VaranManager::FirstInit) Failed to set core select information for OS! (VM_PROP_CORE_NUMBER)");
    #endif
    
      State 		:= _NotInitialized;
      ManagerOn	:= 0;
      return;
    end_if;
  end_if;
  //*******************************************************************************************************
  
  //-----------------------------------------------------------------------------------------------
  //install callback function for Timslice and watchdog error
  sd_retval := SetObjectCallback	( p_us_position_info	:= NIL
                                  , ud_action_ptr			  := ( #Varan_CallBack() )$UDINT
                                  , ud_thisp				    := this$UDINT
                                  , sd_required			    := 0
                                  );

  //look if an error occurs
  if ( sd_retval <> VARANMANAGER_OK ) then

#ifdef HWC_LogValue1
      HWC_LogValue1(this, "@065E (VaranManager::FirstInit) Failed to install callback function for Timeslice and watchdog error. Errorcode: 0x{0}",sd_retval$UDINT);
#endif

    State 		  := _CallBackError;
    ManagerOn 	:= 0;
    return;
  end_if;

  //-----------------------------------------------------------------------------------------------
  //Semaphore for direct accesses
  
  _strcpy(dest:=#aStrSemaphore[0], src:="VM_DA_SEMA_");
  
  ASCII_BIN1.Bin2Ascii(pt:=#astrVaranManagerNr[0], value:=to_dint(VaranManagerNr), format:=16#800);
  _strcat(dest:=#aStrSemaphore[0], src:=#aStrVaranManagerNr[0]);
  

  p_SemaHandle := To_Multitask.CreateSemaphore( MTSEMATYPE_RESOURCE, 1, 0, #aStrSemaphore[0] );
  if( p_SemaHandle = NIL )then
    State 		:= _NotInitialized;
    ManagerOn	:= 0;
#ifdef HWC_LogError
    HWC_LogError(this, "@0668 (VaranManager::FirstInit) Unable to create semaphore for async access!");
#endif
  end_if;
  
  //-----------------------------------------------------------------------------------------------
  if b_PayloadSupport &
     pMultiVaran^.udVersion >= VM_MULTIVARAN_VERSION_FULL_PAYLOAD_AVAILABLE  then
    // p_SyncAndWdDO p_SyncData are handled by OS when there is Payload Support
    
    //set periode of varan system
    nodeProperty[0].udPropertyId     := VM_PROP_PLL_SYSTEM_PERIOD_TIME;  // Also sets p_SyncData^.ui_Periode
    nodeProperty[0].udPropertyValue  := VaranManagerTime / 10 ;
    
    MULTI_VARAN_iSetNodeProperties( hNodeHandle           := vmNodeHandle
                                  , udPropertyCount       := 1
                                  , psPropertyValuePairs  := #nodeProperty[0]);
    
  else  
    //get data of Sync and Watchdog DO 
    sd_retval := VARAN_iGetSyncAndWdDO	( uiManager	:= VaranManagerNr
                                        , pvDO		  := #p_SyncAndWdDO
                                        , pvData	  := #p_SyncData$pvoid
                                        );

    //look for an error
    if	(( sd_retval <> VARANMANAGER_OK ) & 
         ( s_VaranManagerSettings.us_InitCounter >= 10 )) then
      State 		:= _NotInitialized;
      ManagerOn	:= 0;
      return;
    end_if;

    //set periode of varan system
    p_SyncData^.ui_Periode := TO_UINT(  VaranManagerTime / 10 );				  //in 10ns steps
    p_SyncData^.us_Periode := TO_USINT( VaranManagerTime / 10 SHR 16 );		//in 10ns steps
  end_if;

  //set timemark for triggering watchdog
  s_VaranManagerSettings.ud_WatchdogTimemark := ops.tAbsolute - VM_WATCHDOG_TRIGGER_TIME;
    
END_FUNCTION


FUNCTION VaranManager::ExtendModuleList
  VAR_OUTPUT
    sd_retval   : DINT;
  END_VAR
  
  sd_retval := VARANMANAGER_OK;
    //--------------------------------------------------------------------------------------------------------------------
  //set right max handle
  s_ModuleList.ud_MaxModules += VM_EXTEND_HANDLES;

  //realloc memory for list
  s_ModuleList.p_ModuleList$^void := To_StdLib.ReAlloc	( mptr 		  := s_ModuleList.p_ModuleList
                                                        , newsize 	:= s_ModuleList.ud_MaxModules * sizeof( p_VaranBase )
                                                        );

  //look if we got memory for our Handle list
  if ( s_ModuleList.p_ModuleList ) then

    //set new memory to 0
    To_StdLib.MemSet( dest 	:= s_ModuleList.p_ModuleList + ( s_ModuleList.ud_MaxModules - VM_EXTEND_HANDLES ) * sizeof( p_VaranBase )
                    , value := 0
                    , size 	:= VM_EXTEND_HANDLES * sizeof( p_VaranBase ) 
                    );
  
  else
    //if not give out a TRACE
    sd_retval := VARANMANAGER_NO_MEM;

    //Log entry
#ifdef HWC_LogValue1
    HWC_LogValue1(this, "@0027 (VaranManager::ExtendModuleList) No Memory for Varan Manager available! (Extend Module List: {0})", s_ModuleList.ud_MaxModules);
#endif
  end_if;                  
    
    
  s_ModuleList.p_PositionList$^void := To_StdLib.ReAlloc( mptr     := s_ModuleList.p_PositionList
                                                        , newsize  := s_ModuleList.ud_MaxModules * sizeof (pVoid)
                                                        );                          
  
  //look if we got memory for our Handle list
  if ( s_ModuleList.p_PositionList ) then

    //set new memory to 0
    To_StdLib.MemSet( dest 	:= s_ModuleList.p_PositionList + ( s_ModuleList.ud_MaxModules - VM_EXTEND_HANDLES ) * sizeof( pVoid )
                    , value := 0
                    , size 	:= VM_EXTEND_HANDLES * sizeof(pVoid ) 
                    );
  
  else
    //if not give out a TRACE
    sd_retval := VARANMANAGER_NO_MEM;

    //Log entry
#ifdef HWC_LogValue1
    HWC_LogValue1(this, "@0028 (VaranManager::ExtendModuleList) No Memory for Varan Manager available! (Extend Position List: {0})", s_ModuleList.ud_MaxModules);
#endif
  end_if;

END_FUNCTION

FUNCTION GLOBAL VaranManager::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(OS_CILGet("LSL_MULTITASK", #mt_api$void)) THEN
      mt_api := NIL;
    end_if;
  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] := '%';
      str_this[1] := 'm';
      _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 GLOBAL VaranManager::MutexStart
  VAR_INPUT
    pMutex 	: pVoid;
  END_VAR

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

END_FUNCTION


FUNCTION GLOBAL VaranManager::MutexStop
  VAR_INPUT
    pMutex 	: pVoid;
  END_VAR

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

END_FUNCTION


FUNCTION VIRTUAL GLOBAL VaranManager::Control::NewInst
  VAR_INPUT
    pPara 	                  : ^CmdStruct;
    pResult 	                : ^Results;
  END_VAR
  VAR_OUTPUT
    ret_code 	                : IprStates;
  END_VAR
  VAR
    p_paraAddDO               : ^t_VM_CMD_AddDO;
    p_paraMovDO               : ^t_VM_CMD_AddMovDo; 
    p_paraGetPointers         : ^t_VM_CMD_GetDataPointers;
    p_paraGetModuleHandel     : ^t_VM_CMD_GetModuleHandle; 
    PostInitRetcode           : iprStates;
    pHelpPostInit             : ^t_s_PostInitList;
    i                         : UINT;
    pHelp                     : ^void;  // This pointer to call newinst
    // local variables for the Requested HWTString
    pStr_HWTRequested         : ^CHAR;
    ui_HWTRequestedLength     : UINT;
    us_HWTRequestedCurrIndex  : USINT;    
    i_Req                     : UINT; 
    // local variables for HWTStrings in the VM
    pStr_HWTVM                : ^CHAR;
    us_HWTVMLength            : USINT;
    i_VM                      : USINT;
    ud_ModuleIndex            : UDINT;    
    b_ModuleFound             : BOOL;
    // local variables to safe currently found module
    pStr_HWTVMCurrent         : ^CHAR;
    ud_ModuleIndexCurrent     : UDINT;
    TempArray                 : ARRAY [0..SERNO_STRING_SIZE-1] OF USINT;
    a_HelpArray               : ARRAY[0..99] OF CHAR;
	  ud_StrSize                : UDINT;
    ud_MaxStrSize             : UDINT;
    sSPIIDHeader              : t_s_SPIListHeader;
    b_GetExtendedInfoDirectly : BOOL;
    ud_NodeHandle             : UDINT;

    MyPara                    : CmdStruct;
    MyResult                  : results;

    //local variables for dummy mux callback
    sd_retval                 : DINT;
  END_VAR

  ret_code := READY;  // Overwritten on error

  CASE pPara^.uiCmd OF
//**********************************************************************************************************************************************************
    CMD_POST_INIT_CALL: // call from hwcontrol
      // Check Loader Version if function is supported
      if ops.uiLoaderVersion$UINT >= VM_POST_INIT_AVAILABLE then
        bPostInitActive := TRUE;

#ifdef _LSL_TARGETARCH_ARM  // IO Image only needed for ARM  CPUs
#ifdef VARAN_iSetOutputImage
        // the image is not copied from the shadow ram to the VM DPRAM so far => copy it
        if (b_IOImageWritten = FALSE) & b_IOImage then
          VARAN_iSetOutputImage(VaranManagerNr, VARAN_DOL_ASY);
          b_IOImageWritten := TRUE;
        end_if;        
#endif
#endif  

        // we wait here until the initialisation of the Varan Rt and the SDIAS Clients has been finished
        CyWork(0);
      
        if bPostInitModulesReady then
          
          MyPara.uiCmd := CMD_GET_SUPPORTED_FEATURES;
          
          //Check if post init done cmd will be called from hwcontrol
          To_HwControl.NewInst(pPara:=#MyPara, pResult:=#MyResult);
          if MyResult.aData$t_HWC_SupportedFeatureBits1.PostInitDoneCmdCalled = FALSE then
            bPostInitActive := FALSE;
          end_if;
          
          ret_code := READY;
        else
          if PostInitOSWaitObjectsCnt then
            // on salamander we can wait shorter
            if HWC_ops_is_salamander() then            
              // wait 1µs (this gives enough time to other tasks on the same task priority to perform their actions)
              To_Multitask.TASKDELAYUS(timeout0:=1);
            else
              // on RTK we have to wait 1ms, because the 1µs daily is not available here
              To_Multitask.TASKDELAY(timeout0:=1);
            end_if;
          end_if;

          ret_code := BUSY;
        end_if;
      else
        // Should be impossible as we never request a Postinit if the Loader version is incorrect.
#ifdef HWC_LogError
        HWC_LogError(this, "@01A5 (VaranManager::Control::NewInst) CMD_POST_INIT_CALL not supported with current Loader. Loader Version >= 02.02.137 is required");
#endif
        ret_code := ERROR;
      end_if;

//**********************************************************************************************************************************************************
    CMD_POST_INIT_RT_SYNC:
      // check if all modules are ready
      if WaitForSyncSendObjectsCnt then
        CyWork(0);

        ret_code := BUSY;
      end_if;

//**********************************************************************************************************************************************************
    CMD_POST_INIT_RT_READY:
      // check post init modules
      if PostInitModuleCnt then
        pHelpPostInit := #aPostInitList[0];
        for i := 0 to PostInitModuleCnt - 1 do
          
          //call class, if it's still not ready
          if pHelpPostInit^.p_This then
            PostInitRetcode := pHelpPostInit^.p_This^.NewInst(pPara, pResult);
            
            // only overwrite the ready returncode if the returncode from the post init objects is different to it
            if PostInitRetcode <> READY then
              ret_code := PostInitRetcode;
            end_if;
          end_if;

          // set pointer on next this pointer
          pHelpPostInit += sizeof(t_s_PostInitList);
        end_for;
      end_if;

      // if manager is disabled => return error
      if ManagerOn = 0 then
        ret_code := ERROR;

      // if we're not ready, return busy
      elsif us_RtStep <> _RtWork then
        ret_code := BUSY;
        
      elsif ret_code = READY then
        // everything ready
        b_PostInitRtSyncReady := TRUE;
      end_if;

    
//**********************************************************************************************************************************************************      
    CMD_SET_POSTINIT_DONE:  //call from hwcontrol
      
      //HwControl Postinit phase now finished.
      bPostInitActive := FALSE; 
    
//**********************************************************************************************************************************************************      
    CMD_FORCE_POST_INIT_END:  // call from hwcontrol
      // HWControl has run into timeout and has ended the Post Init Phase
      // This call informs the VM thats the Phase has ended.
      bPostInitActive := FALSE;
      
      //Check if this manager is the reason for the timeout, show it on server
      if ManagerOn <> 1 then
        State := _TimeoutInInit; 
      end_if;

//**********************************************************************************************************************************************************
    CMD_POST_INIT_DO_SORT:    // call from hwcontrol
      // sort safety DOs if there is more than 1
      if pPriorityList & pPriorityList^.pNext & 
        b_PayloadSupport = false then     // OS Handles Priorities of DO if b_PayloadSupport = true

        SortCmdsByPriority();
        
#ifdef _LSL_TARGETARCH_ARM  // IO Image only needed for ARM  CPUs
#ifdef VARAN_iSetOutputImage
        // Varandata has to be written once after sorting the DOs
        if b_IOImage then
          VARAN_iSetOutputImage(VaranManagerNr, VARAN_DOL_ISO);
        end_if;        
      else
        // Varandata has to be written once after adding the DOs even without sorting anything because we need the shadow RAM image in the VM DPRAM)
        if b_IOImage then
          VARAN_iSetOutputImage(VaranManagerNr, VARAN_DOL_ISO);
        end_if;             
#endif
#endif  
      end_if;
      
//**********************************************************************************************************************************************************
    CMD_GET_HARDWARE_TREE_ENTRY:

      pHelp                     := nil;  // This pointer to call newinst
      // local variables for the Requested HWTString
      ui_HWTRequestedLength     := 0;
      us_HWTRequestedCurrIndex  := 0;    
      i_Req                     := 0; 
      // local variables for HWTStrings in the VM
      pStr_HWTVM                := NIL;
      us_HWTVMLength            := 0;
      i_VM                      := 0;
      ud_ModuleIndex            := 0;    
      b_ModuleFound             := FALSE;

      // local variables to safe currently found module
      pStr_HWTVMCurrent         := NIL;
      ud_ModuleIndexCurrent     := 0;


      ret_code := ERROR;
      pResult^.aData[0]$t_HWCGetHardwareTreeEntryOut.retcode := _HWC_RETVAL_ERROR_VARAN_MODULE_NOT_FOUND;      

     
      pStr_HWTRequested     := pPara^.aPara[0]$t_HWCGetHardwareDiagnosisIn.pStr_HardewareTreeEntry;
      
      //First HWT Path
      if pStr_HWTRequested = nil then
      
        ud_VaranPosition := VM_OBJECT_PATH;
      
        // Return String of the Varanmanger
        ret_code := READY;
        pResult^.aData$t_HWCGetHardwareTreeEntryOut.retcode := _HWC_RETVAL_OK_HWTSTR_RETURNED;
        pResult^.aData[0]$t_HWCGetHardwareTreeEntryOut.pStr_NextHardewareTreeEntry := (#ud_VaranPosition)$^CHAR;
      
      // Only possible for VM own HWT Path
      elsif (pStr_HWTRequested^$USINT = 2) then
        
        if pStr_HWTRequested^$UDINT = VM_OBJECT_PATH then
          
          if s_ModuleList.p_ModuleList^ then
            // Return first Module in list
            ret_code := s_ModuleList.p_ModuleList^$p_VaranBase^.NewInst(pPara,pResult);
          else
            // VM was found but there are no modules connected
            ret_code := READY;
            pResult^.aData[0]$t_HWCGetHardwareTreeEntryOut.retcode := _HWC_RETVAL_OK_MODULE_FOUND;        
          end_if;
        end_if;
      
      else
      
        //Search for module
        ui_HWTRequestedLength     := (pStr_HWTRequested)$^UINT^ + 1;  //+1 because we compare the strings, 2 byte length
        us_HWTRequestedCurrIndex  := pPara^.aPara[0]$t_HWCGetHardwareDiagnosisIn.us_current_index;
        
        ud_ModuleIndex := 0;
        b_ModuleFound := FALSE;
        
        //loop over all modules
        while (ud_ModuleIndex < s_ModuleList.ud_NrOfModules) &
              (b_ModuleFound = FALSE) do
              
          pStr_HWTVM := (s_ModuleList.p_PositionList+ (ud_ModuleIndex * 4))^$^CHAR;  // 4 = SizeOf(^CHAR)
          
          if pStr_HWTVM  then
            us_HWTVMLength := pStr_HWTVM^;  //First byte is length
            
            i_Req := us_HWTRequestedCurrIndex;
            i_Vm  := 1;

            //Loop over strings
            while i_Req <= ui_HWTRequestedLength & 
                  i_Vm  <= us_HWTVMLength do
              
              if (pStr_HWTRequested + i_Req)^ <> (pStr_HWTVM + i_Vm)^ then // Compare byte
                // Strings are not equal
                exit;
              end_if;
              
              i_Req += 1;
              i_VM  += 1;
            end_while;

            if (i_Req <= ui_HWTRequestedLength ) &                        // End of requested string was not reached
               (i_Vm = us_HWTVMLength + 1) &                              // And end of compared string reached
               ( (pStr_HWTRequested + i_Req)^ and HWT_ESCAPE_SEQU ) then  // Escape sequece found in Requested string 
               
              b_ModuleFound := TRUE;
              
//              pPara^.aPara[0]$t_HWCGetHardwareDiagnosisIn.us_current_index   := i_Req$USINT;
//              pPara^.aPara[0]$t_HWCGetHardwareDiagnosisIn.us_current_length  := (ui_HWTRequestedLength - i_Req)$USINT;
              exit;
            end_if;

            
            if (i_Vm = us_HWTVMLength + 1) & (i_Req = ui_HWTRequestedLength + 1) then   // All Bytes and Length are equal
              b_ModuleFound := TRUE;
              
//              pPara^.aPara[0]$t_HWCGetHardwareDiagnosisIn.us_current_index  := i_Req$USINT - 1;  // -1 because we increased over max length at the end of the while loop
//              pPara^.aPara[0]$t_HWCGetHardwareDiagnosisIn.us_current_length := 1; // Last entry of string was reached, index points to last entry   
              exit;
            end_if;

          end_if;
          
          ud_ModuleIndex += 1;  // Select next Module
          
        end_while;
        
        if b_ModuleFound then
        
          // Call module again incase it is an extension module          
          pHelp     := s_ModuleList.p_ModuleList + sizeof(p_VaranBase) * ud_ModuleIndex;
          ret_code  := pHelp^$p_VaranBase^.NewInst(pPara,pResult);
          
          // Return if new HWT String was found
          if ret_code = READY & 
             pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.retcode = _HWC_RETVAL_OK_HWTSTR_RETURNED then
            return;
          end_if;
        
          ud_ModuleIndex        += 1;  // Select next Module
          ud_ModuleIndexCurrent := ud_ModuleIndex;          
          
          b_ModuleFound := TRUE;  // Only set to enter loop
          
          while (ud_ModuleIndexCurrent < s_ModuleList.ud_NrOfModules) & 
                (b_ModuleFound = TRUE) do
            
            pStr_HWTVMCurrent := (s_ModuleList.p_PositionList+ (ud_ModuleIndexCurrent * 4))^$^CHAR ;  // 4 = SizeOf(^CHAR)
            
            if pStr_HWTVMCurrent then
            
              // Check if module has already been called (multiple entries in list)
              ud_ModuleIndex  := 0;            
              b_ModuleFound   := FALSE;
          
              //loop over all modules to search for duplicates
              while (ud_ModuleIndex < ud_ModuleIndexCurrent & 
                     b_ModuleFound = FALSE) do
                
                pStr_HWTVM := (s_ModuleList.p_PositionList+ (ud_ModuleIndex * 4))^$^CHAR ;  // 4 = SizeOf(^CHAR)
                
                if pStr_HWTVM then
                
                  // Compare string length
                  if pStr_HWTVMCurrent^ = pStr_HWTVM^ then
                  
                    // Compare string content
                    if _memcmp( ptr1 := pStr_HWTVMCurrent + 1, 
                                ptr2 := pStr_HWTVM +1, 
                                cntr := pStr_HWTVMCurrent^) = 0 then
                      
                      // Multiple entry, Check next Module
                      b_ModuleFound         := TRUE;
                      ud_ModuleIndexCurrent += 1;
                      exit;
                      
                    end_if;
                  end_if;                
                end_if;
                
                ud_ModuleIndex += 1;
              
              end_while; 
              
              if b_ModuleFound = FALSE then
                exit; // Non duplicate entry
              end_if;
            
            else  // if pStr_HWTVMCurrent then
              ud_ModuleIndexCurrent += 1;
            end_if;

          end_while;
  
          if b_ModuleFound = FALSE then
            // Call Class
            pHelp     := s_ModuleList.p_ModuleList + sizeof(p_VaranBase) * ud_ModuleIndexCurrent;
            ret_code  := pHelp^$p_VaranBase^.NewInst(pPara,pResult);
          end_if;          

        else
          pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.retcode := _HWC_RETVAL_ERROR_VARAN_MODULE_NOT_FOUND;
          ret_code := ERROR;
        end_if;

      end_if;
     
//**********************************************************************************************************************************************************
    CMD_GET_HARDWARE_DIAGNOSIS:
      
      pHelp                     := nil;  // This pointer to call newinst
      // local variables for the Requested HWTString
      ui_HWTRequestedLength     := 0;
      us_HWTRequestedCurrIndex  := 0;    
      i_Req                     := 0; 
      // local variables for HWTStrings in the VM
      pStr_HWTVM                := NIL;
      us_HWTVMLength            := 0;
      i_VM                      := 0;
      ud_ModuleIndex            := 0;    
      b_ModuleFound             := FALSE;
      
      
      ret_code := ERROR;
      pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.retcode := _HWC_RETVAL_ERROR;
      
      pStr_HWTRequested     := pPara^.aPara[0]$t_HWCGetHardwareDiagnosisIn.pStr_HardewareTreeEntry;
      
      if pStr_HWTRequested then
      
        // Check for VM String
        if (pStr_HWTRequested)$^UINT^ = 2 then
          
          if (pStr_HWTRequested)$^UDINT^ = VM_OBJECT_PATH then
          
            TempArray[0] := 0;
            
            if this <> p_this then
              //Reset statemachine
              eSPISSW := _GetVendorName;
              //Save This pointer
              p_this := this;
              
              // Reset Flags
              bDiagnosisDataAvailableFlags.HWVersion   := FALSE;
              bDiagnosisDataAvailableFlags.VendorName  := FALSE;
              bDiagnosisDataAvailableFlags.DeviceName  := FALSE;
              bDiagnosisDataAvailableFlags.OrderingNo  := FALSE;
              bDiagnosisDataAvailableFlags.LicenseNo   := FALSE;
              bDiagnosisDataAvailableFlags.SerialNo    := FALSE;
            end_if;
            
            case eSPISSW of
            	_GetVendorName:
                ret_code$DINT := GetSPIDataFromID(  p_us_position_info  := #TempArray[0]
                                                  , udListID            := VM_SPI_VENDOR_NAME_ID
                                                  , pData               := #a_VendorName[0]
                                                  , udRequDataLength    := sizeof(a_VendorName)
                                                  , pIDHeader           := #sSPIIDHeader
                                                  );
                
                if ret_code = READY then
                
                  // Null Termination ----------------------------------------
                  ud_StrSize    := sSPIIDHeader.ListLength;
                  ud_MaxStrSize := sizeof(a_VendorName);  
                  
                  pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.pStr_VendorName                    := (#a_VendorName)$^CHAR; // Will be overwritten if this pointer is not equal
                  
                  (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;
                  
                  bDiagnosisDataAvailableFlags.VendorName := TRUE;
                                
                  eSPISSW := _GetSerialNo;
                  ret_code := BUSY;
                else
                  pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.retcode := _HWC_RETVAL_ERROR_VARAN_SPI_ACCESS_FAILED;
                  //set SSW to SPI Data Ready, because we return the values which are already in the HWK
                  eSPISSW := _SPIDataReady;
                  ret_code := BUSY;
                end_if;
                
              _GetSerialNo:
                ret_code$DINT := GetSPIDataFromID(  p_us_position_info  := #TempArray[0]
                                                  , udListID            := VM_SPI_SERIALNO_ID
                                                  , pData               := #a_SerialNo[0]
                                                  , udRequDataLength    := sizeof(a_SerialNo)
                                                  , pIDHeader           := #sSPIIDHeader
                                                  );
                
                if ret_code = READY then
                
                  // Null Termination ----------------------------------------
                  ud_StrSize    := sSPIIDHeader.ListLength;
                  ud_MaxStrSize := sizeof(a_SerialNo);  
                  
                  pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.pStr_SerialNo                    := (#a_SerialNo)$^CHAR; // Will be overwritten if this pointer is not equal
                  
                  (pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.pStr_SerialNo + ud_MaxStrSize)^ := 0;
                  if ud_StrSize < ud_MaxStrSize then
                    (pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.pStr_SerialNo + ud_StrSize)^  := 0;  
                  end_if;
                  
                  bDiagnosisDataAvailableFlags.SerialNo := TRUE;
                                
                  eSPISSW   := _GetDeviceName;
                  ret_code  := BUSY;
                else
                  pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.retcode := _HWC_RETVAL_ERROR_VARAN_SPI_ACCESS_FAILED;
                  //set SSW to SPI Data Ready, because we return the values which are already in the HWK
                  eSPISSW   := _SPIDataReady;
                  ret_code  := BUSY;
                end_if;              
              
            	_GetDeviceName:
                ret_code$DINT := GetSPIDataFromID(  p_us_position_info  := #TempArray[0]
                                                  , udListID            := VM_SPI_DEVICE_NAME_ID
                                                  , pData               := #a_DeviceName[0]
                                                  , udRequDataLength    := sizeof(a_DeviceName)
                                                  , pIDHeader           := #sSPIIDHeader
                                                  );
                
                if ret_code = READY then
                
                  // Null Termination ----------------------------------------
                  ud_StrSize    := sSPIIDHeader.ListLength;
                  ud_MaxStrSize := sizeof(a_DeviceName);  
                  
                  pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.pStr_DeviceName                    := (#a_DeviceName)$^CHAR; // Will be overwritten if this pointer is not equal
                  
                  (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;
                  
                  bDiagnosisDataAvailableFlags.DeviceName := TRUE;
                                
                  eSPISSW   := _GetOrderingNo;
                  ret_code  := BUSY;
                else
                  pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.retcode := _HWC_RETVAL_ERROR_VARAN_SPI_ACCESS_FAILED;
                  //set SSW to SPI Data Ready, because we return the values which are already in the HWK
                  eSPISSW   := _SPIDataReady;
                  ret_code  := BUSY;
                end_if;
              
            	_GetOrderingNo:
                ret_code$DINT := GetSPIDataFromID(  p_us_position_info  := #TempArray[0]
                                                  , udListID            := VM_SPI_ORDERING_NO_ID
                                                  , pData               := #a_OrderingNo[0]
                                                  , udRequDataLength    := sizeof(a_OrderingNo)
                                                  , pIDHeader           := #sSPIIDHeader
                                                  );
                
                if ret_code = READY then
                
                  // Null Termination ----------------------------------------
                  ud_StrSize    := sSPIIDHeader.ListLength;
                  ud_MaxStrSize := sizeof(a_OrderingNo);  
                  
                  pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.pStr_OrderingNo                    := (#a_OrderingNo)$^CHAR; // Will be overwritten if this pointer is not equal
                  
                  (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;
                  
                  bDiagnosisDataAvailableFlags.OrderingNo := TRUE;
                                
                  eSPISSW   := _GetLicenseNoHWVersion;
                  ret_code  := BUSY;
                else
                  pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.retcode := _HWC_RETVAL_ERROR_VARAN_SPI_ACCESS_FAILED;
                  //set SSW to SPI Data Ready, because we return the values which are already in the HWK
                  eSPISSW   := _SPIDataReady;
                  ret_code  := BUSY;
                end_if;
              
            	_GetLicenseNoHWVersion:
              
                ret_code$DINT := GetSPIDataFromID(  p_us_position_info  := #TempArray[0]
                                                  , udListID            := VM_SPI_IDENTIFICATION_LIST
                                                  , pData               := #a_HelpArray[0]
                                                  , udRequDataLength    := sizeof(udHWVersion) + sizeof(udLicenseNo)
                                                  , pIDHeader           := #sSPIIDHeader
                                                  , udOffset            := 8                                                  
                                                  );
                
                udLicenseNo := a_HelpArray[0]$UDINT;
                udHWVersion := a_HelpArray[4]$UDINT;
              
                if ret_code = READY then
                  bDiagnosisDataAvailableFlags.LicenseNo := TRUE;
                  bDiagnosisDataAvailableFlags.HWVersion := TRUE;             
                  eSPISSW   := _SPIDataReady;
                  ret_code  := BUSY;
                else
                  pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.retcode := _HWC_RETVAL_ERROR_VARAN_SPI_ACCESS_FAILED;
                  //set SSW to SPI Data Ready, because we return the values which are already in the HWK
                  eSPISSW   := _SPIDataReady;
                  ret_code  := BUSY;
                end_if;
              
            	_SPIDataReady:
                //Don't reset statemachine because if we have the same this pointer we don't have to make spi Accesses again
                //eSPISSW := _GetVendorName;
                
                //Data which is already in HWK available
                if p_NodeInfo then
                
                  pResult^.aData$t_HWCGetHardwareDiagnosisOut.hd_FPGAVersion      := to_udint(p_NodeInfo^.ucFPGAVersion);
                  pResult^.aData$t_HWCGetHardwareDiagnosisOut.ud_DeviceID         := to_udint(p_NodeInfo^.uiDeviceID);
                  pResult^.aData$t_HWCGetHardwareDiagnosisOut.ud_VendorID         := to_udint(p_NodeInfo^.uiVendorID);
                end_if;

                if bDiagnosisDataAvailableFlags.VendorName then
                  pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.pStr_VendorName  := (#a_VendorName)$^CHAR;            
                end_if;
                
                if bDiagnosisDataAvailableFlags.HWVersion & bDiagnosisDataAvailableFlags.LicenseNo then
                  pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.hd_HWVersion     := udHWVersion;
                  pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.ud_LicenseNo     := udLicenseNo; 
                end_if;
                
                if bDiagnosisDataAvailableFlags.DeviceName then
                  pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.pStr_DeviceName  := (#a_DeviceName)$^CHAR;
                end_if;          
                
                if bDiagnosisDataAvailableFlags.OrderingNo then
                  pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.pStr_OrderingNo  := (#a_OrderingNo)$^CHAR;
                end_if;
                
                if bDiagnosisDataAvailableFlags.SerialNo then
                  pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.pStr_SerialNo    := (#a_SerialNo)$^CHAR;
                end_if;
                
                ret_code                                                          := READY;
                pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.retcode            := _HWC_RETVAL_OK;
              
            end_case;
          end_if;
          
          return;
        end_if;
      
        ui_HWTRequestedLength     := (pStr_HWTRequested)$^UINT^ + 1;  //+1 because we compare the strings, 2 byte length
        us_HWTRequestedCurrIndex  := pPara^.aPara[0]$t_HWCGetHardwareDiagnosisIn.us_current_index;
        
        ud_ModuleIndex := 0;
        b_ModuleFound := FALSE;
        
        //loop over all modules
        while (ud_ModuleIndex < s_ModuleList.ud_NrOfModules) &
              (b_ModuleFound = FALSE) do
              
          pStr_HWTVM := (s_ModuleList.p_PositionList+ (ud_ModuleIndex * 4))^$^CHAR ;  // 4 = SizeOf(^CHAR)
          
          if pStr_HWTVM  then
            us_HWTVMLength := pStr_HWTVM^;  //First byte is length
            
            i_Req := us_HWTRequestedCurrIndex;
            i_Vm  := 1;
            
            //Loop over strings
            while i_Req <= ui_HWTRequestedLength & 
                  i_Vm  <= us_HWTVMLength do
            
              if (pStr_HWTRequested + i_Req)^ <> (pStr_HWTVM + i_Vm)^ then // Compare byte
                // Strings are not equal
                exit;
              end_if;
              
              i_Req += 1;
              i_VM  += 1;
            end_while;
            

            if (i_Req <= ui_HWTRequestedLength ) &                        // End of requested string was not reached
            (i_Vm = us_HWTVMLength + 1) &                                 // And end of compared string reached
               ( (pStr_HWTRequested + i_Req)^ and HWT_ESCAPE_SEQU ) then  // Escape sequece found in Requested string 
               
              b_ModuleFound := TRUE;
              pPara^.aPara[0]$t_HWCGetHardwareDiagnosisIn.us_current_index   := i_Req$USINT;
              pPara^.aPara[0]$t_HWCGetHardwareDiagnosisIn.us_current_length  := (ui_HWTRequestedLength - i_Req)$USINT;
              exit;
            end_if;

            
            if (i_Vm = us_HWTVMLength + 1) & (i_Req = ui_HWTRequestedLength + 1) then   // All Bytes and Length are equal
              b_ModuleFound := TRUE;
              pPara^.aPara[0]$t_HWCGetHardwareDiagnosisIn.us_current_index  := i_Req$USINT - 1;  // -1 because we increased over max length at the end of the while loop
              pPara^.aPara[0]$t_HWCGetHardwareDiagnosisIn.us_current_length := 1; // Last entry of string was reached, index points to last entry   
              exit;
            end_if;

          end_if;
          
          ud_ModuleIndex += 1;  // Select next Module
          
        end_while;
        
        if b_ModuleFound then
          // Call Class
          pHelp     := s_ModuleList.p_ModuleList + sizeof(p_VaranBase) * ud_ModuleIndex;
          ret_code  := pHelp^$p_VaranBase^.NewInst(pPara,pResult);
        else
          pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.retcode := _HWC_RETVAL_ERROR_VARAN_MODULE_NOT_FOUND;
          ret_code  := ERROR;
        end_if;

      end_if;

//**********************************************************************************************************************************************************
    VM_CMD_NEED_POST_INIT_CALL: // call from varan client
      // Check Loader Version if function is supported
      if ops.uiLoaderVersion$UINT >= VM_POST_INIT_AVAILABLE then
      
        // store this pointer of the module
        aPostInitList[PostInitModuleCnt].p_This := pPara^.aPara[0]$p_VaranBase;
        
        // remember if we have to wait for DOs to be created
        aPostInitList[PostInitModuleCnt].Settings := pPara^.aPara[1]$BSINT;
        if aPostInitList[PostInitModuleCnt].Settings.Wait4DOCreation then
          WaitForPostInitObjectsCnt += 1;
          if aPostInitList[PostInitModuleCnt].Settings.Wait4MoveDOCreation then
            WaitForPostInitMoveObjectsCnt += 1;
          end_if;
        end_if;
        
        // remember if we have to wait for the sync of this module
        if aPostInitList[PostInitModuleCnt].Settings.Wait4SyncSend then
          WaitForSyncSendObjectsCnt += 1;
        end_if;

        aPostInitList[PostInitModuleCnt].b_CallMe := TRUE;
        
        // return index for this module
        pResult^.uiLng          := 2;
        pResult^.aData[0]$UINT  := PostInitModuleCnt;
        
        // increase number of post init modules
        PostInitModuleCnt       += 1;
        
        // we're no longer ready with post init. we have to wait until all modules from the list are finished
        bPostInitModulesReady   := FALSE;
      else
#ifdef HWC_LogError
        HWC_LogError(this, "@01A6 (VaranManager::Control::NewInst) VM_CMD_NEED_POST_INIT_CALL not supported with current Loader. Loader Version >= 02.02.137 is required");
#endif
        ret_code := ERROR;
      end_if;
      
//**********************************************************************************************************************************************************
    VM_CMD_POST_INIT_FINISHED: // call from varan client
      // Check Loader Version if function is supported
      if ops.uiLoaderVersion$UINT >= VM_POST_INIT_AVAILABLE then
      
        // only relevant during last Init
        if PostInitModuleCnt then
          // check if it's a valid index
          if pPara^.aPara[1]$UINT < VM_MAX_POST_INIT_MODULES then
            // check if our local this pointer matches this object
            if pPara^.aPara[0]$p_VaranBase = aPostInitList[pPara^.aPara[1]$UINT].p_This then
              // increase number of ready objects
              PostInitModuleReadyCnt += 1;
//              aPostInitList[pPara^.aPara[1]$UINT].b_CallMe := FALSE;

              // check if it's an object we were waiting for
              if aPostInitList[pPara^.aPara[1]$UINT].Settings.Wait4DOCreation then
                aPostInitList[pPara^.aPara[1]$UINT].Settings.Wait4DOCreation := FALSE;
                
                if WaitForPostInitObjectsCnt then
                  WaitForPostInitObjectsCnt -= 1;
                else
#ifdef HWC_LogError
                  HWC_LogError(this, "@01A7 (VaranManager::Control::NewInst) There is already no more post init object to wait for! (VM_CMD_POST_INIT_FINISHED)");
#endif
                  ret_code := ERROR;
                end_if;
              end_if;    

              // check if it's an object we were waiting for
              if aPostInitList[pPara^.aPara[1]$UINT].Settings.Wait4MoveDOCreation then
                aPostInitList[pPara^.aPara[1]$UINT].Settings.Wait4MoveDOCreation := FALSE;
                
                if WaitForPostInitMoveObjectsCnt then
                  WaitForPostInitMoveObjectsCnt -= 1;
                else
#ifdef HWC_LogError
                  HWC_LogError(this, "@01A8 (VaranManager::Control::NewInst) There is already no more post init object to wait for (create move DOs)! (VM_CMD_POST_INIT_FINISHED)");
#endif
                  ret_code := ERROR;
                end_if;
              end_if;    

              // on last init we check if all modules which need to have finished their init
              if PostInitModuleReadyCnt = PostInitModuleCnt then
                bPostInitModulesReady := TRUE;
              end_if;          
            else
#ifdef HWC_LogError
              HWC_LogError(this, "@01A9 (VaranManager::Control::NewInst) This pointer of post init module given doesn't match locally stored this pointer for this index!");
#endif
              ret_code := ERROR;
            end_if;
          else
#ifdef HWC_LogError
            HWC_LogError(this, "@01AA (VaranManager::Control::NewInst) Invalid index of post init module given!");
#endif
            ret_code := ERROR;
          end_if;
        else
#ifdef HWC_LogError
          HWC_LogError(this, "@01AB (VaranManager::Control::NewInst) More modules ready with last init than expected");
#endif
          ret_code := ERROR;
        end_if;
      else
#ifdef HWC_LogError
        HWC_LogError(this, "@01AC (VaranManager::Control::NewInst) VM_CMD_POST_INIT_FINISHED not supported with current Loader. Loader Version >= 02.02.137 is required");        
#endif
        ret_code := ERROR;
      end_if;

//**********************************************************************************************************************************************************
    VM_CMD_IS_PAYLOAD_SUPPORTED:  // to get the status of PayloadSupport
      pResult^.aData[0]$BOOL := b_PayloadSupport;
    
//**********************************************************************************************************************************************************
    VM_CMD_DO_CREATION_FINISHED: // a post-init module is finished with creating DOs
      // Check Loader Version if function is supported
      if ops.uiLoaderVersion$UINT >= VM_POST_INIT_AVAILABLE then
      
        // only relevant during last Init
        if PostInitModuleCnt then
          // check if it's a valid index
          if pPara^.aPara[1]$UINT < VM_MAX_POST_INIT_MODULES then
            // check if our local this pointer matches this object
            if pPara^.aPara[0]$p_VaranBase = aPostInitList[pPara^.aPara[1]$UINT].p_This then
              // check if it's an object we were waiting for
              if aPostInitList[pPara^.aPara[1]$UINT].Settings.Wait4DOCreation then
                aPostInitList[pPara^.aPara[1]$UINT].Settings.Wait4DOCreation := FALSE;
                
                if WaitForPostInitObjectsCnt then
                  WaitForPostInitObjectsCnt -= 1;
                else
#ifdef HWC_LogError
                  HWC_LogError(this, "@01AD (VaranManager::Control::NewInst) There is already no more post init object to wait for!");
#endif
                  ret_code := ERROR;
                end_if;
              else
#ifdef HWC_LogError
                HWC_LogError(this, "@01AE (VaranManager::Control::NewInst) Module finished with DO creation, where  There is already no more post init object to wait for!");
#endif
                ret_code := ERROR;                
              end_if;    
            else
#ifdef HWC_LogError
              HWC_LogError(this, "@01A9 (VaranManager::Control::NewInst) This pointer of post init module given doesn't match locally stored this pointer for this index!");
#endif
              ret_code := ERROR;
            end_if;
          else
#ifdef HWC_LogError
            HWC_LogError(this, "@01AA (VaranManager::Control::NewInst) Invalid index of post init module given!");
#endif
            ret_code := ERROR;
          end_if;
        else
#ifdef HWC_LogError
          HWC_LogError(this, "@01AB (VaranManager::Control::NewInst) More modules ready with last init than expected");
#endif
          ret_code := ERROR;
        end_if;
      else
#ifdef HWC_LogError
        HWC_LogError(this, "@01AF (VaranManager::Control::NewInst) VM_CMD_DO_CREATION_FINISHED not supported with current Loader. Loader Version >= 02.02.137 is required");
#endif
        ret_code := ERROR;
      end_if;

//**********************************************************************************************************************************************************
    VM_CMD_MOVE_DO_CREATION_FINISHED:
      // Check Loader Version if function is supported
      if ops.uiLoaderVersion$UINT >= VM_POST_INIT_AVAILABLE then
      
        // only relevant during last Init
        if PostInitModuleCnt then
          // check if it's a valid index
          if pPara^.aPara[1]$UINT < VM_MAX_POST_INIT_MODULES then
            // check if our local this pointer matches this object
            if pPara^.aPara[0]$p_VaranBase = aPostInitList[pPara^.aPara[1]$UINT].p_This then
              // check if it's an object we were waiting for
              if aPostInitList[pPara^.aPara[1]$UINT].Settings.Wait4MoveDOCreation then
                aPostInitList[pPara^.aPara[1]$UINT].Settings.Wait4MoveDOCreation := FALSE;
                
                if WaitForPostInitMoveObjectsCnt then
                  WaitForPostInitMoveObjectsCnt -= 1;
                else
#ifdef HWC_LogError
                  HWC_LogError(this, "@01B0 (VaranManager::Control::NewInst) There is already no more post init object to wait for (create move DOs)!");
#endif
                  ret_code := ERROR;
                end_if;
              else
#ifdef HWC_LogError
                HWC_LogError(this, "@01B1 (VaranManager::Control::NewInst) Module finished with move DO creation, where  There is already no more post init object to wait for!");
#endif
                ret_code := ERROR;                
              end_if;    
            else
#ifdef HWC_LogError
              HWC_LogError(this, "@01B2 (VaranManager::Control::NewInst) This pointer of post init module given doesn't match locally stored this pointer for this index! (Move DOs)");
#endif
              ret_code := ERROR;
            end_if;
          else
#ifdef HWC_LogError
            HWC_LogError(this, "@01B3 (VaranManager::Control::NewInst) Invalid index of post init module given! (Move DOs)");
#endif
            ret_code := ERROR;
          end_if;
        else
#ifdef HWC_LogError
          HWC_LogError(this, "@01B4 (VaranManager::Control::NewInst) More modules ready with last init than expected (Move DOs)");
#endif
          ret_code := ERROR;
        end_if;
      else
#ifdef HWC_LogError
        HWC_LogError(this, "@01B5 (VaranManager::Control::NewInst) VM_CMD_MOVE_DO_CREATION_FINISHED not supported with current Loader. Loader Version >= 02.02.137 is required (Move DOs)");
#endif
        ret_code := ERROR;
      end_if;
      
//**********************************************************************************************************************************************************
    VM_CMD_DO_MEM_READY: // check if all post init objects are finished with creating DOs
      // if we're not in post init or the varan manager has finished waiting for post init objects => the DO memory is ready
      if WaitForPostInitObjectsCnt = 0 then
        pResult^.aData[4] := TRUE;
      else
        pResult^.aData[4] := FALSE;
      end_if;
      
//**********************************************************************************************************************************************************
    VM_CMD_MOVE_DO_MEM_READY: // check if all post init objects are finished with creating move DOs
      // if we're not in post init or the varan manager has finished waiting for post init objects => the move DO memory is ready
      if WaitForPostInitMoveObjectsCnt = 0 then
        pResult^.aData[4] := TRUE;
      else
        pResult^.aData[4] := FALSE;
      end_if;

//**********************************************************************************************************************************************************
    VM_CMD_SYNC_SEND_READY:
      // only work on it if the post init rt hasn't been finished, otherwise we would have the log messages if modules are plugged at runtime
      if b_PostInitRtSyncReady = FALSE then
        // Check Loader Version if function is supported
        if ops.uiLoaderVersion$UINT >= VM_POST_INIT_AVAILABLE then
          // only relevant during last Init
          if PostInitModuleCnt then
            // check if it's a valid index
            if pPara^.aPara[1]$UINT < VM_MAX_POST_INIT_MODULES then
              // check if our local this pointer matches this object
              if pPara^.aPara[0]$p_VaranBase = aPostInitList[pPara^.aPara[1]$UINT].p_This then
                // check if it's an object we were waiting for
                if aPostInitList[pPara^.aPara[1]$UINT].Settings.Wait4SyncSend then
                  aPostInitList[pPara^.aPara[1]$UINT].Settings.Wait4SyncSend := FALSE;
                  
                  if WaitForSyncSendObjectsCnt then
                    WaitForSyncSendObjectsCnt -= 1;
                  else
#ifdef HWC_LogError
                    HWC_LogError(this, "@01B6 (VaranManager::Control::NewInst) There is already no more post init object to wait for (sync send ready)!");
#endif
                    ret_code := ERROR;
                  end_if;
                else
#ifdef HWC_LogError
                  HWC_LogError(this, "@01B7 (VaranManager::Control::NewInst) Module finished with sync send ready, where  There is already no more post init object to wait for!");
#endif
                  ret_code := ERROR;                
                end_if;    
              else
#ifdef HWC_LogError
                HWC_LogError(this, "@01B8 (VaranManager::Control::NewInst) This pointer of post init module given doesn't match locally stored this pointer for this index! (Move DOs)");
#endif
                ret_code := ERROR;
              end_if;
            else
#ifdef HWC_LogError
              HWC_LogError(this, "@01B9 (VaranManager::Control::NewInst) Invalid index of post init module given! (sync send ready)");
#endif
              ret_code := ERROR;
            end_if;
          else
#ifdef HWC_LogError
            HWC_LogError(this, "@01BA (VaranManager::Control::NewInst) More modules ready with last init than expected (sync send ready)");
#endif
            ret_code := ERROR;
          end_if;
        else
#ifdef HWC_LogError
          HWC_LogError(this, "@01B5 (VaranManager::Control::NewInst) VM_CMD_MOVE_DO_CREATION_FINISHED not supported with current Loader. Loader Version >= 02.02.137 is required (Move DOs)");
#endif
          ret_code := ERROR;
        end_if;
      end_if;
      
//**********************************************************************************************************************************************************
    VM_CMD_SET_MUX_THIS: // ignore this command, it's only for the VaranMux classes
      ret_code := ERROR; // return error => command not handled

//**********************************************************************************************************************************************************
    VM_CMD_INSTALL_DUMMY_CALLBACK:
      
      if pPara^.aPara[0] >= 4 * sizeof(DINT) then
      
        sd_retval := AddObjectCallback( p_us_position_info  := pPara^.aPara[1]$^USINT
                                      , ud_action_ptr       := pPara^.aPara[2]$UDINT
                                      , ud_thisp            := pPara^.aPara[3]$UDINT
                                      , sd_required         := pPara^.aPara[4]
                                      );        
      else

#ifdef HWC_LogError
        HWC_LogError(this, "@01BB (VaranManager::Control::NewInst) VM_CMD_INSTALL_DUMMY_CALLBACK. Length of NewInst Commando is invalid");
#endif
        
      end_if;

//**********************************************************************************************************************************************************
    CMD_EXTEND_POST_INIT_TIME:
      // forward to HwControl
      To_HwControl.NewInst(pPara, pResult);
 
//**********************************************************************************************************************************************************
    CMD_GET_HW_TIMESTAMP:
    
      // forward to HwControl
      if pPara^.aPara[0]$t_GetHwTimestampCmd.udVersion = 1 then
        // Insert Coreselect if CmdVersion = 1 and increase CmdVersion to 2
        pPara^.aPara[0]$t_GetHwTimestampCmd.udVersion     := 2;
        pPara^.aPara[0]$t_GetHwTimestampCmd.udCoreSelect  := CoreSelect;
      end_if;      
      ret_code := To_HwControl.NewInst(pPara, pResult);

//*****************************************************************************
    VM_CMD_GET_SYSTEM_MANAGER_CNT:
    
      pResult^.aData[0]$UDINT := udSystemVaranManagerCnt;
      
//**********************************************************************************************************************************************************
    CMD_HWC_REQ_PLLNS_REGULATION:
      // forward it to HwControl
      ret_code := To_HwControl.NewInst(pPara, pResult);

//**********************************************************************************************************************************************************
    VM_CMD_GET_EXTENDED_NODE_INFO:

      // set the length of the result to the size of the return value
      pResult^.uiLng := sizeof(DINT);
      
      // and initialize the returncode with error
      pResult^.aData$DINT := -100;

      // check the command version
      case pPara^.aPara$t_VM_CMD_GetExtNodeInfo.ud_CmdVersion of
        VM_CMD_GET_EXTENDED_NODE_INFO_VER_1: 

        // check for valid parameters (pointers)
        if pPara^.aPara$t_VM_CMD_GetExtNodeInfo.p_PositionInfo & pPara^.aPara$t_VM_CMD_GetExtNodeInfo.p_SerNoStr then
          
          b_GetExtendedInfoDirectly := FALSE;
          if b_PayloadSupport then
            // Get the Node handle
            sd_retval := MULTI_VARAN_IGETNODEHANDLE(  udManagerNumber := VaranManagerNr
                                                    , pszHardwarePath := pPara^.aPara$t_VM_CMD_GetExtNodeInfo.p_PositionInfo
                                                    , phNodeHandle    := #ud_NodeHandle
                                                    );
            
            // if we got a node handle
            if sd_retval = VARANMANAGER_OK then
              // get the serial number (the OS writes up to 256 Bytes to the pointer and returns an error if the serial number string in the device is longer than that)
              sd_retval := MULTI_VARAN_IGETNODEPROPERTY(hNodeHandle       := ud_NodeHandle
                                                      , udPropertyId      := ND_PROP_VARAN_SERIAL_NO
                                                      , pudPropertyValue  := pPara^.aPara$t_VM_CMD_GetExtNodeInfo.p_SerNoStr$^UDINT
                                                       );
              
              if ( sd_retval = VARANMANAGER_OK ) then
              
                // now check if there are some optional infos needed
                
                if pPara^.aPara$t_VM_CMD_GetExtNodeInfo.p_HwVersion then
                  // get the hardware version
                  sd_retval := MULTI_VARAN_IGETNODEPROPERTY(hNodeHandle       := ud_NodeHandle
                                                          , udPropertyId      := ND_PROP_VARAN_HW_VERSION
                                                          , pudPropertyValue  := pPara^.aPara$t_VM_CMD_GetExtNodeInfo.p_HwVersion
                                                           );
                  if ( sd_retval <> VARANMANAGER_OK ) then
                    // failed to get the property => do it directly
                    b_GetExtendedInfoDirectly := TRUE;              
                  end_if;
                end_if;

                if pPara^.aPara$t_VM_CMD_GetExtNodeInfo.p_LicenseNo then
                  // get the license number
                  sd_retval := MULTI_VARAN_IGETNODEPROPERTY(hNodeHandle       := ud_NodeHandle
                                                          , udPropertyId      := ND_PROP_VARAN_LICENSE_NO
                                                          , pudPropertyValue  := pPara^.aPara$t_VM_CMD_GetExtNodeInfo.p_LicenseNo
                                                           );
                  if ( sd_retval <> VARANMANAGER_OK ) then
                    // failed to get the property => do it directly
                    b_GetExtendedInfoDirectly := TRUE;              
                  end_if;
                end_if;
              else
                // failed to get the property => do it directly
                b_GetExtendedInfoDirectly := TRUE;              
              end_if;
            else
              // failed to get node handle => do it directly
              b_GetExtendedInfoDirectly := TRUE;
            end_if;
          else
            // if the multi varan interface is not available => do it directly
            b_GetExtendedInfoDirectly := TRUE;
          end_if;
          
          // if we didn't get the info from the OS
          if b_GetExtendedInfoDirectly then
            // read directly from the SPI flash of the module
            sd_retval := GetExtNodeInfoDirectly(pPara:=(#pPara^.aPara)$^t_VM_CMD_GetExtNodeInfo);
            
            pResult^.aData$DINT := sd_retval;
          else
            // we already got the info we need => initialize returnvalue with OK
            pResult^.aData$DINT := sd_retval;
          end_if;      
        else
          // invalid parameters/pointers
          pResult^.aData$DINT := -102;
          ret_code := ERROR;
        end_if;          
      else
        // unsupported command version
        pResult^.aData$DINT := -101;
        ret_code := ERROR;
      end_case;

//**********************************************************************************************************************************************************
    VM_CMD_NEED_POST_INIT_TASK_DELAY: // call from varan client
      // increase the number of modules who need this
      PostInitOSWaitObjectsCnt += 1;
      
//**********************************************************************************************************************************************************            
    CMD_HWC_GET_REQUIREDWAITTIME:  //Returns the maximum time, that a required Module should wait in the Init() until the HW is found
      // forward it to HwControl
      ret_code := To_HwControl.NewInst(pPara, pResult);
      
//**********************************************************************************************************************************************************
    else    // Commands for Payload
      if b_PayloadSupport then
        
        pResult^.uiLng          := sizeof(DINT);
        pResult^.aData[0]$DINT  := VM_CMD_NOT_IMPLEMENTED; // Default Return code, must be overwritten by induvidual methods
        
        CASE pPara^.uiCmd OF      
        
        //*****************************************************************************
          VM_CMD_GET_MODULE_HANDLE :
            p_paraGetModuleHandel := (pPara^.aPara[0])$^t_VM_CMD_GetModuleHandle;
          
            pResult^.aData[0]$DINT := GetModuleHandle(  p_us_PositionInfo := p_paraGetModuleHandel^.p_us_position_info
                                                      , p_ud_ModuleHandle := p_paraGetModuleHandel^.p_ud_module_handle);
        
        //*****************************************************************************
          VM_CMD_ADD_DO :
            p_paraAddDO := (pPara^.aPara[0])$^t_VM_CMD_AddDO;
            pResult^.aData[0]$DINT := AddPayloadDO( p_ud_DoHandle                 := p_paraAddDO^.p_ud_DoHandle
                                                  , ud_NodeHandle                 := p_paraAddDO^.ud_ModuleHandle
                                                  , ud_DoRequired                 := p_paraAddDO^.ud_b_DoRequired
                                                  , ud_DolType                    := p_paraAddDO^.ud_DolType
                                                  , ud_Command                    := p_paraAddDO^.ud_Command
                                                  , ud_Priority                   := p_paraAddDO^.ud_Priority
                                                  , ud_PrescalerCounterThreshold  := p_paraAddDO^.ud_PreScalerCounterThreshold
                                                  , ud_PrescalerCounterStartValue := p_paraAddDO^.ud_PreScalerCounterStartValue
                                                  , ud_ReadOffset                 := p_paraAddDO^.ud_OffsetRead
                                                  , ud_ReadLength                 := p_paraAddDO^.ud_LengthRead
                                                  , ud_WriteOffset                := p_paraAddDO^.ud_OffsetWrite
                                                  , ud_WriteLength                := p_paraAddDO^.ud_LengthWrite
                                                  , ud_Filter                     := p_paraAddDO^.ud_Filter
                                                  , ud_Slices                     := p_paraAddDO^.ud_Slices
                                                  , ud_WritePayloadType           := p_paraAddDO^.ud_WritePayloadType);
          
        //*****************************************************************************
          VM_CMD_ADD_MOV_DO :
            p_paraMovDO := (pPara^.aPara[0])$^t_VM_CMD_AddMovDo;
            pResult^.aData[0]$DINT := AddPayloadMoveDO( p_ud_DoHandle                 := p_paraMovDO^.p_ud_DoHandle
                                                      , ud_bDoRequired                := p_paraMovDO^.ud_b_DoRequired
                                                      , ud_DolType                    := p_paraMovDO^.ud_DolType
                                                      , ud_Priority                   := p_paraMovDO^.ud_Priority
                                                      , ud_PrescalerCounterThreshold  := p_paraMovDO^.ud_PreScalerCounterThreshold
                                                      , ud_PrescalerCounterStartValue := p_paraMovDO^.ud_PreScalerCounterStartValue
                                                      , ud_hSourceReadDoHandle        := p_paraMovDO^.ud_SourceReadDoHandle
                                                      , ud_ReadOffset                 := p_paraMovDO^.ud_SourceReadOffset
                                                      , ud_hDestinationWriteDoHandle  := p_paraMovDO^.ud_DestinationWriteDoHandle
                                                      , ud_WriteOffset                := p_paraMovDO^.ud_DestinationWriteOffset
                                                      , ud_MoveDataLength             := p_paraMovDO^.ud_LengthMove);
            
        //*****************************************************************************
          VM_CMD_GET_DATA_POINTERS  :      
            p_paraGetPointers := (pPara^.aPara[0])$^t_VM_CMD_GetDataPointers;
            pResult^.aData[0]$DINT := GetDataPointers(  ud_hDoHandle  := p_paraGetPointers^.ud_DoHandle
                                                      , pp_ReadData   := p_paraGetPointers^.p_ud_ReadData$^pVoid
                                                      , pp_WriteData  := p_paraGetPointers^.p_ud_WriteData$^pVoid);

        //*****************************************************************************
          VM_CMD_IS_DMA_ACTIVE :
            if PayloadFrame = 1 then
              pResult^.aData[0]$BOOL := TRUE;
            else
              pResult^.aData[0]$BOOL := FALSE;
            end_if;
            
        //*****************************************************************************
          else
            ret_code := ERROR;
        END_CASE;
              
      else
        pResult^.uiLng := sizeof(DINT);
        pResult^.aData[0]$DINT := VM_CMD_NOT_IMPLEMENTED;
#ifdef HWC_LogError
        HWC_LogError(this, "@01BC (VaranManager::Control::NewInst) Unknown command!");
#endif
        ret_code := ERROR;
      end_if;

  END_CASE;

END_FUNCTION


FUNCTION VaranManager::TurnOffIsoTask
  VAR
    s_PropertyValuePair : LSL_PROPERTY_VALUE_PAIR;
  END_VAR

  if b_PayloadSupport &
     pMultiVaran^.udVersion >= VM_MULTIVARAN_VERSION_FULL_PAYLOAD_AVAILABLE  then
    s_PropertyValuePair.udPropertyId    := VM_PROP_TASK_STATE_ISO;
    s_PropertyValuePair.udPropertyValue := TK_STATE_STOPPED;
    MULTI_VARAN_iSetNodeProperties( hNodeHandle           := vmNodeHandle
                                  , udPropertyCount       := 1
                                  , psPropertyValuePairs  := #s_PropertyValuePair
                                  );
  elsif p_ManagerStructure then
    p_ManagerStructure^.ucTCEnable := p_ManagerStructure^.ucTCEnable AND VM_DISABLE_ISO_TASK;
  end_if;

END_FUNCTION


FUNCTION VaranManager::AddPayloadDO
  VAR_INPUT
    p_ud_DoHandle 	                : ^UDINT;
    ud_NodeHandle 	                : UDINT;
    ud_DoRequired 	                : UDINT;
    ud_DolType 	                    : UDINT;
    ud_Command 	                    : UDINT;
    ud_Priority 	                  : UDINT;
    ud_PrescalerCounterThreshold 	  : UDINT;
    ud_PrescalerCounterStartValue 	: UDINT;
    ud_ReadOffset 	                : UDINT;
    ud_ReadLength 	                : UDINT;
    ud_WriteOffset 	                : UDINT;
    ud_WriteLength 	                : UDINT;
    ud_Filter 	  	                : UDINT;
    ud_Slices 	  	                : UDINT;
    ud_WritePayloadType             : UDINT;
  END_VAR
  VAR_OUTPUT
    sd_retval 	  	                : DINT;
  END_VAR
  VAR
    TempMem                         : UDINT;
    TempMemWr                       : UDINT;
  END_VAR
  
#ifdef VM_DEBUG_PAYLOAD
  if b_PayloadSupport = false then
    // This method is not suppored without payload 
    ((0)$^USINT)^ := 0; 
  end_if;  
#endif
  
  //look if we Manager is on
  if ( ManagerOn ) then
    //look if we must execute Cyclic DOL list
    if ( ud_DolType = VARAN_DOL_ASY ) then
      s_CyHandles.b_ExecuteDOL := TRUE;			//set flag to execut Dol list
    end_if;
    
    sd_retval := MULTI_VARAN_iAddDo(  phDoHandle                    := p_ud_DoHandle
                                    , hNodeHandle                   := ud_NodeHandle
                                    , bDoRequired                   := ud_DoRequired
                                    , udDolType                     := ud_DolType
                                    , udCommand                     := ud_Command
                                    , udPriority                    := ud_Priority
                                    , udPrescalerCounterThreshold   := ud_PrescalerCounterThreshold
                                    , udPrescalerCounterStartValue  := ud_PrescalerCounterStartValue
                                    , udReadOffset                  := ud_ReadOffset
                                    , udReadLength                  := ud_ReadLength
                                    , udWriteOffset                 := ud_WriteOffset
                                    , udWriteLength                 := ud_WriteLength
                                    , udFilter                      := ud_Filter
                                    , udSlices                      := ud_Slices
                                    , udWritePayloadType            := ud_WritePayloadType$LSL_WRITE_PAYLOAD_TYPE);   
    
    //look if an error occured
    if ( sd_retval <> VARANMANAGER_OK ) then
      s_ErrorVaranManager.f_AddRdDO := SetVaranDOError( sd_Error 		  := sd_retval 
                                                      , b_manager_off	:= TRUE
                                                      , b_log			    := TRUE
                                                      );                              
    else      
      
      if PayloadFrame = 1 then  // Use PayloadFrame because, b_PayloadSupport only shows the interface used.
                            // Payload DO Mem Calculaition +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
        case ud_Command of
        
            VARAN_CMD_CONTROL_READ,
            VARAN_CMD_MEMORY_READ:      // Read DO -------------------------------------------------------------------------------------------------------------------------------
                // 1 Byte Status + n Byte (Load data read) + 0 to 3 Byte (compensate missalignment)
                TempMem := 1 + ud_ReadLength;
                
                // 1 Byte Control
                TempMemWr := 1;
                
                // Increase for variable DO
                if ud_WritePayloadType > WR_PLD_TYPE_STANDARD$UDINT then
                  TempMemWr += 16#0E;
                end_if;
                
                case ud_DolType AND (NOT (VARAN_DOL_NOT_INSERT_DO_INTO_DOL)) of
                // **************************************************
                  VARAN_DOL_DA:
                    DPRAM_Used.DA_Rd            += TempMem + TempMemWr + SIZE_PAYLOAD_FRAME_HEADER_DO;
                    DPRAM_Used_Payload.DA_Rd    += TempMem;
                    DPRAM_Used_Payload.DA_Wr    += TempMemWr;
                    DOCounter.DA_Rd             += 1;
                                
                // **************************************************                
                  VARAN_DOL_ISO:
                    DPRAM_Used.ISO_Rd           += TempMem + TempMemWr + SIZE_PAYLOAD_FRAME_HEADER_DO;
                    DPRAM_Used_Payload.ISO_Rd   += TempMem;
                    DPRAM_Used_Payload.ISO_Wr   += TempMemWr;
                    DOCounter.ISO_Rd            += 1;
                                                                
                // **************************************************
                  VARAN_DOL_ASY:
                    DPRAM_Used.ASY_Rd           += TempMem + TempMemWr + SIZE_PAYLOAD_FRAME_HEADER_DO;
                    DPRAM_Used_Payload.ASY_Rd   += TempMem;
                    DPRAM_Used_Payload.ASY_Wr   += TempMemWr;
                    DOCounter.ASY_Rd            += 1;

                // **************************************************
                  VARAN_DOL_ADMIN:
                    DPRAM_Used.Admin_Rd         += TempMem + TempMemWr + SIZE_PAYLOAD_FRAME_HEADER_DO;
                    DPRAM_Used_Payload.Admin_Rd += TempMem;
                    DPRAM_Used_Payload.ASY_Wr   += TempMemWr;
                    DOCounter.Admin_Rd          += 1;

                // **************************************************
                  VARAN_DOL_IRQ:
                    DPRAM_Used.IRQ_Rd         += TempMem + TempMemWr + SIZE_PAYLOAD_IRQ_FRAME_HEADER_DO;
                    DPRAM_Used_Payload.IRQ_Rd += TempMem;
                    DPRAM_Used_Payload.IRQ_Wr += TempMemWr;
                    DOCounter.IRQ_Rd          += 1;   
                end_case;
                
                DPRAM_Used_Payload.Payload_Read     += TempMem;
                DPRAM_Used_Payload.Payload_Write    += TempMemWr;
                
                if ud_DolType <> VARAN_DOL_IRQ then
                  DPRAM_Used.Total                  += TempMem + TempMemWr + SIZE_PAYLOAD_FRAME_HEADER_DO;
                  DPRAM_Used_Payload.Payload_Header += SIZE_PAYLOAD_FRAME_HEADER_DO;                
                else
                  DPRAM_Used.Total                  += TempMem + TempMemWr + SIZE_PAYLOAD_IRQ_FRAME_HEADER_DO;
                  DPRAM_Used_Payload.Payload_Header += SIZE_PAYLOAD_IRQ_FRAME_HEADER_DO;                
                end_if;

                DPRAM_Used_Payload.Total            += TempMem + TempMemWr;   

                DOCounter.Total                     += 1;
                
            VARAN_CMD_CONTROL_WRITE,
            VARAN_CMD_MEMORY_WRITE:     // Write DO -------------------------------------------------------------------------------------------------------------------------------
                // 1 Byte Control + n Byte (Load data read) + 0 to 3 Byte (compensate missalignment)
                TempMemWr := 1 + ud_WriteLength;
                
                // Increase for variable DO
                if ud_WritePayloadType > WR_PLD_TYPE_STANDARD$UDINT then
                  TempMemWr += 16#0E;
                end_if;
                                
                // 1 Byte Status in Read DPRAM
                TempMem := 1;
                
                case ud_DolType AND (NOT (VARAN_DOL_NOT_INSERT_DO_INTO_DOL)) of
                // **************************************************
                  VARAN_DOL_DA:
                    DPRAM_Used.DA_Wr            += TempMem + TempMemWr + SIZE_PAYLOAD_FRAME_HEADER_DO;
                    DPRAM_Used_Payload.DA_Rd    += TempMem;
                    DPRAM_Used_Payload.DA_Wr    += TempMemWr; 
                    DOCounter.DA_Wr             += 1;     
                    
                // **************************************************                
                  VARAN_DOL_ISO:
                    DPRAM_Used.ISO_Wr           += TempMem + TempMemWr + SIZE_PAYLOAD_FRAME_HEADER_DO;
                    DPRAM_Used_Payload.ISO_Rd   += TempMem;
                    DPRAM_Used_Payload.ISO_Wr   += TempMemWr;
                    DOCounter.ISO_Wr            += 1;
                    
                // **************************************************
                  VARAN_DOL_ASY:
                    DPRAM_Used.ASY_Wr           += TempMem + TempMemWr + SIZE_PAYLOAD_FRAME_HEADER_DO;
                    DPRAM_Used_Payload.ASY_Rd   += TempMem;
                    DPRAM_Used_Payload.ASY_Wr   += TempMemWr;
                    DOCounter.ASY_Wr            += 1;

                // **************************************************
                  VARAN_DOL_ADMIN:
                    DPRAM_Used.Admin_Wr         += TempMem + TempMemWr + SIZE_PAYLOAD_FRAME_HEADER_DO;
                    DPRAM_Used_Payload.Admin_Rd += TempMem;
                    DPRAM_Used_Payload.Admin_Wr += TempMemWr;
                    DOCounter.Admin_Wr          += 1;
                                
                // **************************************************
                  VARAN_DOL_IRQ:
                    DPRAM_Used.IRQ_Wr           += TempMem + TempMemWr + SIZE_PAYLOAD_IRQ_FRAME_HEADER_DO;
                    DPRAM_Used_Payload.ISO_Rd   += TempMem;
                    DPRAM_Used_Payload.IRQ_Wr   += TempMemWr;
                    DOCounter.IRQ_Wr            += 1;        

                end_case;                   

                DPRAM_Used_Payload.Payload_Read     += TempMem;
                DPRAM_Used_Payload.Payload_Write    += TempMemWr;
                
                if ud_DolType <> VARAN_DOL_IRQ then
                  DPRAM_Used.Total                  += TempMem + TempMemWr + SIZE_PAYLOAD_FRAME_HEADER_DO;
                  DPRAM_Used_Payload.Payload_Header += SIZE_PAYLOAD_FRAME_HEADER_DO;                
                else
                  DPRAM_Used.Total                  += TempMem + TempMemWr + SIZE_PAYLOAD_IRQ_FRAME_HEADER_DO;
                  DPRAM_Used_Payload.Payload_Header += SIZE_PAYLOAD_IRQ_FRAME_HEADER_DO;                
                end_if;

                DPRAM_Used_Payload.Total            += TempMem + TempMemWr;
                DOCounter.Total                     += 1;
            
            VARAN_CMD_CONTROL_READ_WRITE,
            VARAN_CMD_MEMORY_READ_WRITE:// Read/Write DO -------------------------------------------------------------------------------------------------------------------------------
                // 1 Byte Control + n Byte (Load data read) + 0 to 3 Byte (compensate missalignment) x2                
                TempMem   := 1 + ud_ReadLength;                
                
                TempMemWr := 1 + ud_WriteLength;      
                                
                // Increase for variable DO
                if ud_WritePayloadType = WR_PLD_TYPE_RW_ACCESS_CONFIGURABLE$UDINT then
                  TempMemWr += 16#14;
                elsif ud_WritePayloadType > WR_PLD_TYPE_STANDARD$UDINT then
                  TempMemWr += 16#0E;
                end_if;
              
                case ud_DolType AND (NOT (VARAN_DOL_NOT_INSERT_DO_INTO_DOL)) of
                // **************************************************
                  VARAN_DOL_DA:
                    DPRAM_Used.DA_RdWr          += TempMem + TempMemWr + SIZE_PAYLOAD_FRAME_HEADER_DO;
                    DPRAM_Used_Payload.DA_Rd    += TempMem;
                    DPRAM_Used_Payload.DA_Wr    += TempMemWr;
                    DOCounter.DA_RdWr           += 1;        
                                                                
                // **************************************************                
                  VARAN_DOL_ISO:
                    DPRAM_Used.ISO_RdWr         += TempMem + TempMemWr + SIZE_PAYLOAD_FRAME_HEADER_DO;
                    DPRAM_Used_Payload.ISO_Rd   += TempMem;
                    DPRAM_Used_Payload.ISO_Wr   += TempMemWr;
                    DOCounter.ISO_RdWr          += 1;

                // **************************************************
                  VARAN_DOL_ASY:
                    DPRAM_Used.ASY_RdWr         += TempMem + TempMemWr + SIZE_PAYLOAD_FRAME_HEADER_DO;
                    DPRAM_Used_Payload.ASY_Rd   += TempMem;
                    DPRAM_Used_Payload.ASY_Wr   += TempMemWr;
                    DOCounter.ASY_RdWr          += 1;

                // **************************************************
                  VARAN_DOL_ADMIN:
                    DPRAM_Used.Admin_RdWr       += TempMem + TempMemWr + SIZE_PAYLOAD_FRAME_HEADER_DO;
                    DPRAM_Used_Payload.Admin_Rd += TempMem;
                    DPRAM_Used_Payload.Admin_Wr += TempMemWr;
                    DOCounter.Admin_RdWr        += 1;

                // **************************************************
                  VARAN_DOL_IRQ:
                    DPRAM_Used.IRQ_RdWr         += TempMem + TempMemWr + SIZE_PAYLOAD_IRQ_FRAME_HEADER_DO;
                    DPRAM_Used_Payload.IRQ_Rd   += TempMem;
                    DPRAM_Used_Payload.IRQ_Wr   += TempMemWr;
                    DOCounter.IRQ_RdWr          += 1;    
                                

                end_case;
                
                DPRAM_Used_Payload.Payload_Read     += TempMem;
                DPRAM_Used_Payload.Payload_Write    += TempMemWr;
                
                if ud_DolType <> VARAN_DOL_IRQ then
                  DPRAM_Used.Total                  += TempMem + TempMemWr + SIZE_PAYLOAD_FRAME_HEADER_DO;
                  DPRAM_Used_Payload.Payload_Header += SIZE_PAYLOAD_FRAME_HEADER_DO;                
                else
                  DPRAM_Used.Total                  += TempMem + TempMemWr + SIZE_PAYLOAD_IRQ_FRAME_HEADER_DO;
                  DPRAM_Used_Payload.Payload_Header += SIZE_PAYLOAD_IRQ_FRAME_HEADER_DO;                
                end_if;

                DPRAM_Used_Payload.Total            += TempMem + TempMemWr;
                DOCounter.Total                     += 1;
            
            
        end_case;      
      else    // Standard DO Mem Calculation +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
        
        case ud_Command of
        
            VARAN_CMD_CONTROL_READ,
            VARAN_CMD_MEMORY_READ:      // Read DO -------------------------------------------------------------------------------------------------------------------------------
                // 32 Byte (Header) + 6 Byte (1 Byte Cmd, 4 Byte Addr, 1 Byte Len) + 1 Byte (Response) + n Byte (Load data read) + 0 to 3 Byte (compensate missalignment)
                TempMem := 32 + 6 + 1 + ud_ReadLength;
                if (TempMem MOD 4) then
                  TempMem := TempMem + (4 - (TempMem MOD 4)); //increase memory, up to a value, which could be divided by 4
                end_if;
                
                case ud_DolType AND (NOT (VARAN_DOL_NOT_INSERT_DO_INTO_DOL)) of
                // **************************************************
                  VARAN_DOL_DA:
                                DPRAM_Used.DA_Rd    += TempMem;
                                DOCounter.DA_Rd     += 1;        
                // **************************************************                
                  VARAN_DOL_ISO:
                                DPRAM_Used.ISO_Rd   += TempMem;
                                DOCounter.ISO_Rd    += 1;
                // **************************************************
                  VARAN_DOL_ASY:
                                DPRAM_Used.ASY_Rd   += TempMem;
                                DOCounter.ASY_Rd    += 1;
                // **************************************************
                  VARAN_DOL_ADMIN:
                                DPRAM_Used.Admin_Rd += TempMem;
                                DOCounter.Admin_Rd  += 1;
                // **************************************************
                  VARAN_DOL_IRQ:
                                DPRAM_Used.IRQ_Rd   += TempMem;
                                DOCounter.IRQ_Rd    += 1;        
                end_case;
                
                DPRAM_Used.Total  += TempMem;
                DOCounter.Total   += 1;
                
            VARAN_CMD_CONTROL_WRITE,
            VARAN_CMD_MEMORY_WRITE:     // Write DO -------------------------------------------------------------------------------------------------------------------------------
                //32 Byte (Header) + 6 Byte (1 Byte Cmd, 4 Byte Addr, 1 Byte Len) + 1 Byte (Response) + n Byte (load data write) + 0 to 3 Byte (compensate missalignment)
                  TempMem := 32 + 6 + 1 + ud_WriteLength;
                  if (TempMem MOD 4) then
                    TempMem := TempMem + (4 - (TempMem MOD 4)); //increase memory, up to a value, which could be divided by 4
                  end_if;

                  case ud_DolType AND (NOT (VARAN_DOL_NOT_INSERT_DO_INTO_DOL)) of
                  // **************************************************
                    VARAN_DOL_DA:
                                  DPRAM_Used.DA_Wr    += TempMem;
                                  DOCounter.DA_Wr     += 1;        
                  // **************************************************                
                    VARAN_DOL_ISO:
                                  DPRAM_Used.ISO_Wr   += TempMem;
                                  DOCounter.ISO_Wr    += 1;
                  // **************************************************
                    VARAN_DOL_ASY:
                                  DPRAM_Used.ASY_Wr   += TempMem;
                                  DOCounter.ASY_Wr    += 1;
                  // **************************************************
                    VARAN_DOL_ADMIN:
                                  DPRAM_Used.Admin_Wr += TempMem;
                                  DOCounter.Admin_Wr  += 1;
                  // **************************************************
                    VARAN_DOL_IRQ:
                                  DPRAM_Used.IRQ_Wr   += TempMem;
                                  DOCounter.IRQ_Wr    += 1;        
                  end_case; 
                  
                  DPRAM_Used.Total  += TempMem;
                  DOCounter.Total   += 1;
            
            VARAN_CMD_CONTROL_READ_WRITE,
            VARAN_CMD_MEMORY_READ_WRITE:// Read/Write DO -------------------------------------------------------------------------------------------------------------------------------
                  //32 Byte (Header) + 11 Byte (1 Byte Cmd, 4 Byte RdAddr, 1 Byte RdLen, 4 Byte WrAddr, 1 Byte WrLen) + 1 Byte (Response) + n Byte (load data read) + n Byte (load data write) + 0 to 3 Byte (compensate missalignment)
                  TempMem := 32 + 11 + 1 + ud_ReadLength + ud_WriteLength;
                  if (TempMem MOD 4) then
                    TempMem := TempMem + (4 - (TempMem MOD 4)); //increase memory, up to a value, which could be divided by 4
                  end_if;
                
                  case ud_DolType AND (NOT (VARAN_DOL_NOT_INSERT_DO_INTO_DOL)) of
                  // **************************************************
                    VARAN_DOL_DA:
                                  DPRAM_Used.DA_RdWr    += TempMem;
                                  DOCounter.DA_RdWr     += 1;        
                  // **************************************************                
                    VARAN_DOL_ISO:
                                  DPRAM_Used.ISO_RdWr   += TempMem;
                                  DOCounter.ISO_RdWr    += 1;
                  // **************************************************
                    VARAN_DOL_ASY:
                                  DPRAM_Used.ASY_RdWr   += TempMem;
                                  DOCounter.ASY_RdWr    += 1;
                  // **************************************************
                    VARAN_DOL_ADMIN:
                                  DPRAM_Used.Admin_RdWr += TempMem;
                                  DOCounter.Admin_RdWr  += 1;
                  // **************************************************
                    VARAN_DOL_IRQ:
                                  DPRAM_Used.IRQ_RdWr   += TempMem;
                                  DOCounter.IRQ_RdWr    += 1;        
                  end_case;
                  
                  DPRAM_Used.Total  += TempMem;
                  DOCounter.Total   += 1;
            
        end_case;

      end_if; // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    
    end_if;
  else
    sd_retval := -100;	//Manager is off
  end_if;
END_FUNCTION


FUNCTION VaranManager::AddPayloadMoveDO
  VAR_INPUT
    p_ud_DoHandle 	                : ^UDINT;
    ud_bDoRequired 	                : UDINT;
    ud_DolType 	                    : UDINT;
    ud_Priority 	                  : UDINT;
    ud_PrescalerCounterThreshold 	  : UDINT;
    ud_PrescalerCounterStartValue 	: UDINT;
    ud_hSourceReadDoHandle 	        : UDINT;
    ud_ReadOffset 	                : UDINT;
    ud_hDestinationWriteDoHandle 	  : UDINT;
    ud_WriteOffset 	                : UDINT;
    ud_MoveDataLength 	            : UDINT;
  END_VAR
  VAR_OUTPUT
    sd_retval 	                    : DINT;
  END_VAR

#ifdef VM_DEBUG_PAYLOAD
  if b_PayloadSupport = false then
    // This method is not suppored without payload 
    ((0)$^USINT)^ := 0; 
  end_if;  
#endif

  //look if we must execute Cyclic DOL list
  if ( ud_DolType = VARAN_DOL_ASY ) then
    s_CyHandles.b_ExecuteDOL := TRUE;			//set flag to execut Dol list
  end_if;
  
  sd_retval := MULTI_VARAN_iAddMoveDo(  phDoHandle                    := p_ud_DoHandle
                                      , bDoRequired                   := ud_bDoRequired
                                      , udDolType                     := ud_DolType
                                      , udPriority                    := ud_Priority
                                      , udPrescalerCounterThreshold   := ud_PrescalerCounterThreshold
                                      , udPrescalerCounterStartValue  := ud_PrescalerCounterStartValue
                                      , hSourceReadDoHandle           := ud_hSourceReadDoHandle
                                      , udReadOffset                  := ud_ReadOffset
                                      , hDestinationWriteDoHandle     := ud_hDestinationWriteDoHandle
                                      , udWriteOffset                 := ud_WriteOffset
                                      , udMoveDataLength              := ud_MoveDataLength
                                      );
  //look if an error occured
  if ( sd_retval <> VARANMANAGER_OK ) then
    s_ErrorVaranManager.f_AddRdDO := SetVaranDOError( sd_Error      := sd_retval 
                                                    , b_manager_off := TRUE
                                                    , b_log         := TRUE
                                                    );                              
  else   
    // Payload Move DO Mem Calculation
    if ( ud_DolType = VARAN_DOL_ASY ) then
      DPRAM_Used.ASY_Mov          += sizeof(LSL_VARANFRAMEPAYLOADMOVEHEADER);      
      DPRAM_Used_Payload.ASY_Rd   += 1; // 1 Byte status
      DPRAM_Used_Payload.ASY_Wr   += sizeof(LSL_VARANFRAMEMOVEWRITEPAYLOAD);      
      DOCounter.ASY_Mov           += 1;
    else
      DPRAM_Used.ISO_Mov          += sizeof(LSL_VARANFRAMEPAYLOADMOVEHEADER);    
      DPRAM_Used_Payload.ISO_Rd   += 1; // 1 Byte status
      DPRAM_Used_Payload.ISO_Wr   += sizeof(LSL_VARANFRAMEMOVEWRITEPAYLOAD);      
      DOCounter.ISO_Mov           += 1;
    end_if;    
    
    DPRAM_Used.Total              += sizeof(LSL_VARANFRAMEPAYLOADMOVEHEADER) + 1 + sizeof(LSL_VARANFRAMEMOVEWRITEPAYLOAD);  // Header + Read Statusbyte + Write Payload
    DPRAM_Used_Payload.Total      += 1 + sizeof(LSL_VARANFRAMEMOVEWRITEPAYLOAD);  // Read Statusbyte + Write Payload
    DOCounter.Total               += 1;
  end_if;
  
END_FUNCTION


FUNCTION VaranManager::GetDataPointers
  VAR_INPUT
    ud_hDoHandle 	: UDINT;
    pp_ReadData 	: ^pVoid;
    pp_WriteData 	: ^pVoid;
  END_VAR
  VAR_OUTPUT
    sd_retval 	  : DINT;
  END_VAR

#ifdef VM_DEBUG_PAYLOAD
  if b_PayloadSupport = false then
    // This method is not suppored without payload 
    ((0)$^USINT)^ := 0; 
  end_if;  
#endif

  // if there is no VARAN Interface available, we would crash at the call
  if pMultiVaran = NIL then
    sd_retval := VARANMANAGER_DRIVER_NOT_EXISTS;
    return;
  end_if;

  sd_retval :=  MULTI_VARAN_iGetDataPointers( hDoHandle   := ud_hDoHandle
                                            , ppvReadData := pp_ReadData
                                            , ppvWriteData:= pp_WriteData
                                            );

END_FUNCTION


FUNCTION VaranManager::GetModuleHandle
  VAR_INPUT
    p_us_PositionInfo 	: ^USINT;
    p_ud_ModuleHandle 	: ^UDINT;
  END_VAR
  VAR_OUTPUT
    sd_retval 	        : DINT;
  END_VAR  
  
  // if there is no VARAN Interface available, we would crash at the call
  if pMultiVaran = NIL then
    sd_retval := VARANMANAGER_DRIVER_NOT_EXISTS;
    return;
  end_if;

  sd_retval := MULTI_VARAN_iGetNodeHandle(  udManagerNumber := VaranManagerNr
                                          , pszHardwarePath := p_us_PositionInfo
                                          , phNodeHandle    := p_ud_ModuleHandle
                                          );
  
END_FUNCTION


FUNCTION VaranManager::AddObjectCallback
	VAR_INPUT
		p_us_position_info 	: ^USINT;
		ud_action_ptr 	    : UDINT;
		ud_thisp 	          : UDINT;
		sd_required 	      : DINT;
	END_VAR
	VAR_OUTPUT
		sd_retval 	        : DINT;
	END_VAR
  VAR
    ud_NodeHandle       : UDINT;
  END_VAR

  if State = _NoVaranInterface then
    sd_retval := -100;
    return;
  end_if;
  //get right required flag
  if ( sd_required ) then
    sd_required := VARAN_DEVICE_REQUIRED;
  else
    sd_required := VARAN_DEVICE_DEFAULT;
  end_if;

  if b_PayloadSupport &
       pMultiVaran^.udVersion >= VM_MULTIVARAN_VERSION_FULL_PAYLOAD_AVAILABLE  then
    sd_retval := MULTI_VARAN_iGetNodeHandle ( udManagerNumber := VaranManagerNr
                                            , pszHardwarePath := p_us_position_info
                                            , phNodeHandle    := #ud_NodeHandle
                                            );

    if sd_retval <> VARANMANAGER_OK then
      return;
    end_if;

                                              
    //call OS - function to set callback
    sd_retval := MULTI_VARAN_iSetApplicationCallback( hNodeHandle           := ud_NodeHandle
                                                    , pfApplicationCallback := ud_action_ptr$pvoid
                                                    , pvUserData            := ud_thisp$pvoid
                                                    , udRequired            := sd_required$UDINT
                                                    );
    
  elsif pVaran then

    //call OS - function to set callback   
    sd_retval := VARAN_iSetObjectCallback	( uiManager   := VaranManagerNr
                                          , pucNode     := p_us_position_info
                                          , uiCallback  := ud_action_ptr
                                          , uiThis      := ud_thisp
                                          , uiRequired  := sd_required$UDINT
                                          );    
  end_if;

  //look for an error
  if ( sd_retval <> VARANMANAGER_OK ) then
    s_ErrorVaranManager.f_SetObjectCallback := SetVaranDOError	( sd_Error 		  := sd_retval 
                                                                , b_manager_off	:= TRUE
                                                                , b_log			    := TRUE
                                                                );
  end_if;

END_FUNCTION


FUNCTION VaranManager::GetSPIDataFromID
	VAR_INPUT
		p_us_position_info 	: ^USINT;
		udListID 	          : UDINT;
		pData 	            : ^CHAR;
		udRequDataLength 	  : UDINT;
		pIDHeader 	        : ^t_s_SPIListHeader;
		udOffset 	          : UDINT;(* := 16#00 *)
	END_VAR
	VAR_OUTPUT
		sd_retval 	        : DINT;
	END_VAR
  VAR
    BaseListAddress     : UDINT;
    a_data              : ARRAY[0..31] OF UDINT;
  END_VAR

  if p_us_position_info & pData & udRequDataLength > 0 then

    //check OS version
    if ( _RTOSVersion < VM_SPI_OS_VERSION ) then
      // access of SPI flash not possible
      sd_retval := -2;
      return;
    end_if;
    
    // check if list is available and get size and offset in SPI flash
    if ( SearchSPIList(p_us_position_info, udListID, #BaseListAddress) <> VARANMANAGER_OK ) then
      sd_retval := -3;
      return;
    end_if;

    //read header of list
    sd_retval := ReadSPIDataComfort(p_us_position_info  := p_us_position_info,            
                                    ud_offset           := BaseListAddress,
                                    ud_length	          := sizeof(t_s_SPIListHeader),
                                    p_data	            := ( #a_data )$^USINT
                                    );
                                    
    _memcpy(ptr1:=pIDHeader, ptr2:=#a_data[0], cntr:=sizeof(t_s_SPIListHeader));
    
    //look for an error and check if length is > 0
    if ( sd_retval <> VARANMANAGER_OK ) | ( a_data[ 2 ] = 0 ) then
      sd_retval := -4;
      return;
    end_if;

    //read the whole serial number string
    sd_retval := ReadSPIDataComfort( p_us_position_info := p_us_position_info,
                                     ud_offset	        := BaseListAddress + sizeof(t_s_SPIListHeader) + udOffset,  //+12 ist List Header
                                     ud_length	        := udRequDataLength,
                                     p_data		          := pData
                                    );
     

    //look for an error
    if ( sd_retval <> VARANMANAGER_OK ) then
      sd_retval := -5;
      return;
    end_if;
  else
    // invalid parameters
    sd_retval := -1;
  end_if;

END_FUNCTION


FUNCTION GLOBAL VaranManager::RaiseManagerError
	VAR_INPUT
		udReason 	: UDINT;
	END_VAR
  
  State := udReason$t_e_VaranErrors;

  if b_PayloadSupport & pMultiVaran^.udVersion >= VM_MULTIVARAN_VERSION_FULL_PAYLOAD_AVAILABLE  then
    MULTI_VARAN_iReportVaranError( diErrorNumber := udReason$DINT
                                 , hErrorNode    := vmNodeHandle
                                 );

  elsif pVaran & (pVaran^.udVersion >= 16#00001104 ) then
    VARAN_iSetManagerError( VaranManagerNr, udReason );
  end_if; 

END_FUNCTION


FUNCTION VaranManager::GetExtNodeInfoDirectly
	VAR_INPUT
		pPara 	: ^t_VM_CMD_GetExtNodeInfo;
	END_VAR
	VAR_OUTPUT
		sd_retval 	: DINT;
	END_VAR
  VAR
    BaseListAddress     : UDINT;
    FoundIt             : BOOL;
    DataObjList         : ARRAY[0..31] OF UDINT;
    i                   : UDINT;
    sSPIListHeader      : t_s_SPIListHeader;
    sSPIIDList          : t_s_SPIIDListContent;
  END_VAR
  
  // initialize the retcode with error
  sd_retval := -1000;

  // the position info and pointer to the serial number are obligatory (always get the serial number)
  if pPara^.p_PositionInfo & pPara^.p_SerNoStr then

    //check OS version
    if ( _RTOSVersion < VM_SPI_OS_VERSION ) then
      // access of SPI flash not possible
      sd_retval := -1011;
      return;
    end_if;

    //************** GET THE ID LIST **********************************************


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

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

    //look for right Identifier
    if ( DataObjList[ 0 ] <> 16#12345678 ) then
      sd_retval := -1009;
      return;
    end_if;

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



    //************** GET THE SERIAL NUMBER ****************************************

    FoundIt := FALSE;

    //search for SPI Flash Configuration
    for i := 0 to DataObjList[ 3 ] / sizeof( UDINT ) do

      //look for configuration id in 3rd byte
      if ( ( DataObjList[ i + 4 ] and 16#FF00_0000 ) = VM_SPI_SERIALNO_ID ) then
        BaseListAddress := DataObjList[ i + 4 ] and 16#00FF_FFFF;
        FoundIt := TRUE;
      end_if;
      
    end_for;

    //if no entry is found
    if FoundIt = FALSE then
      sd_retval := -1007;
      return;
    end_if;

    //read header of serial number list
    sd_retval := ReadSPIDataComfort(p_us_position_info  := pPara^.p_PositionInfo,            
                                    ud_offset           := BaseListAddress,
                                    ud_length	          := sizeof(t_s_SPIListHeader),
                                    p_data	            := ( #sSPIListHeader )$^USINT
                                   );

    //look for an error and check if length is > 0 and smaller than max length
    if ( sd_retval <> VARANMANAGER_OK ) | ( sSPIListHeader.ListLength = 0 ) | ( sSPIListHeader.ListLength > SERNO_STRING_SIZE ) then
      sd_retval := -1006;
      return;
    end_if;

    //read the whole serial number string
    sd_retval := ReadSPIDataComfort( p_us_position_info := pPara^.p_PositionInfo,
                                     ud_offset	        := BaseListAddress + sizeof(t_s_SPIListHeader),
                                     ud_length	        := sSPIListHeader.ListLength,
                                     p_data		          := pPara^.p_SerNoStr
                                   );
     
    //add string termination
    (pPara^.p_SerNoStr + sSPIListHeader.ListLength)^ := 0;

    //look for an error
    if ( sd_retval <> VARANMANAGER_OK ) then
      sd_retval := -1005;
      return;
    end_if;
    
      //************** GET THE HARDWARE VERSION AND LICENSE NUMBER ******************
    
    // check if any additional data is needed
    if pPara^.p_HwVersion | pPara^.p_LicenseNo then
          
      FoundIt := FALSE;

      //search for SPI Flash Configuration
      for i := 0 to DataObjList[ 3 ] / sizeof( UDINT ) do

        //look for configuration id in 3rd byte
        if ( ( DataObjList[ i + 4 ] and 16#FF00_0000 ) = VM_SPI_IDENTIFICATION_LIST ) then
          BaseListAddress := DataObjList[ i + 4 ] and 16#00FF_FFFF;
          FoundIt := TRUE;
        end_if;
        
      end_for;

      //if no entry found
      if FoundIt = FALSE then
        sd_retval := -1004;
        return;
      end_if;

      //read header of identification list
      sd_retval := ReadSPIDataComfort(p_us_position_info  := pPara^.p_PositionInfo,            
                                      ud_offset           := BaseListAddress,
                                      ud_length	          := sizeof(t_s_SPIListHeader),
                                      p_data	            := ( #sSPIListHeader )$^USINT
                                     );

      //look for an error and check if length is >= 16 (hw version is at offset 12 with 4 bytes)
      if ( sd_retval <> VARANMANAGER_OK ) | ( sSPIListHeader.ListLength < 16 ) then
        sd_retval := -1003;
        return;
      end_if;

      //read the hardware version
      sd_retval := ReadSPIDataComfort( p_us_position_info := pPara^.p_PositionInfo,
                                       ud_offset	        := BaseListAddress + sizeof(t_s_SPIListHeader),
                                       ud_length	        := sizeof(t_s_SPIIDListContent),
                                       p_data		          := (#sSPIIDList)$^USINT
                                     );

      //look for an error
      if ( sd_retval <> VARANMANAGER_OK ) then
        sd_retval := -1002;
        return;
      end_if;  
      
      // if the HwVersion pointer is valid => store the HwVersion there
      if pPara^.p_HwVersion then
        pPara^.p_HwVersion^ := sSPIIDList.HwVersion;
      end_if;

      // if the LicenseNo pointer is valid => store the HwVersion there
      if pPara^.p_LicenseNo then
        pPara^.p_LicenseNo^ := sSPIIDList.LicenseNo;
      end_if;
    end_if;
    
    // success
    sd_retval := 0;
  else
    // invalid parameters
    sd_retval := -1001;
  end_if;
  
END_FUNCTION
