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

//{{LSL_DEFINES
#ifndef _T_VARANDRIVEBASE_H
#define _T_VARANDRIVEBASE_H

#define VAC011_DEVICE_ID		              1005					// device id of VAC011
#define VAC012_DEVICE_ID		              1061					// device id of VAC012
#define VAC013_DEVICE_ID		              1075					// device id of VAC012

#define DIASDRIVE_MAXI_DEVICE_ID          1070          // device id of Dias Drive Maxi
#define DIASDRIVE_MINI_DEVICE_ID          1071          // device id of Dias Drive Mini


//#define DIASDRIVE_WaitTime_ns		            1ms * 1000 * 1000	//time in ns to send next DO in async mode

#define DIASDRIVE_OFFSET_Axis		            16#40							// memory for every axis (offset for axis 1 is 0, for axis 2 is 16#40..)
#define DIASDRIVE_OFFSET_AxisRead	          16#20							//Offset to read data of one axis
#define DIASDRIVE_OFFSET_FAST_AXIS_WRITE    16#C0
#define DIASDRIVE_OFFSET_FAST_AXIS_READ     DIASDRIVE_OFFSET_FAST_AXIS_WRITE + 16#22

#define DIASDRIVE_QUIT_ERROR_WAIT_TIME    50  // in ms

// drive address mapping
#define DIASDRIVE_ADR_ALT_BUF             16#0000  // memory offset for alternating buffer of drive
#define DIASDRIVE_ADR_SERVICE             16#1000  // memory offset for service data of drive
#define DIASDRIVE_ADR_PLL                 16#2000  // memory offset for PLL of drive
#define DIASDRIVE_ADR_LVDS_BUS            16#3000  // memory offset for lvds bus interface of drive
#define DIASDRIVE_ADR_LVDS_DIAG           16#4000  // memory offset for lvds diagnostic of drive

#define DIASDRIVE_ADR_INPUTS              16#4900  // memory offset of digital inputs


#define DIASDRIVE_ADR_OFFSET_CHANNEL      16#0800  // memory for every channel
#define DIASDRIVE_ADR_OFFSET_AXIS         16#0200  // memory for every axis

#define DIASDRIVE_ADR_AXIS_WR_OFFSET      16#0000  // offset to access write data
#define DIASDRIVE_ADR_AXIS_RD_OFFSET      16#0100  // offset to access read data

#define DIASDRIVE_ADR_ALT_BUF_RD_OFFSET   16#0400
#define DIASDRIVE_ADR_ALT_BUF_WR_OFFSET   16#0000

#define DIASDRIVE_ADR_SERVICE_READ        16#0030
#define DIASDRIVE_ADR_SERVICE_WRITE       16#0000

#define DIASDRIVE_MAX_AXIS                8
#define DIASDRIVE_MAX_AXIS_PER_MODULE     3
#define DIASDRIVE_MAX_AXIS_300            3 // with dias drive 300 only up to 3 axis possible

#define WRITETIME_TO_DPRAM                1000 // time in ns to write data to manager dpram

#endif // _T_VARANDRIVEBASE_H
//}}LSL_DEFINES

//{{LSL_DECLARATION

(*!
<Class
	Name               = "_VaranDriveBase"
	Revision           = "1.69"
	GUID               = "{CF382F5A-2099-43AD-826A-CBD4B58600BB}"
	RealtimeTask       = "false"
	CyclicTask         = "false"
	BackgroundTask     = "false"
	Sigmatek           = "true"
	OSInterface        = "false"
	HighPriority       = "false"
	Automatic          = "false"
	UpdateMode         = "Prescan"
	IconPath           = ".\Class\Varan_16x16.ico"
	SharedCommandTable = "true"
	Objectsize         = "(584,120)"
	Comment            = "class for VAC011, VAC012 and DiasDrive Mini/Maxi varan interface card">
	<Channels>
		<Server Name="CRC_ErrorCounter" GUID="{9B1EC11E-C16B-4B00-BC45-0C37934BF4AB}" Visualized="true" Initialize="false" WriteProtected="true" Retentive="false" Comment="counts CRC error of all 3 axis"/>
		<Server Name="Input1" GUID="{DF561791-84BB-4612-AC47-0E91FBEA294D}" Visualized="false" Initialize="false" WriteProtected="true" Retentive="false" Comment="State of digital input 1 of drive&#13;&#10;&#13;&#10;-1..input information not available&#13;&#10; 0..input is low&#13;&#10; 1..input is high"/>
		<Server Name="Input2" GUID="{241BBF40-CCF7-411C-9DB3-3A1BB427C2DC}" Visualized="false" Initialize="false" WriteProtected="true" Retentive="false" Comment="State of digital input 2 of drive&#13;&#10;&#13;&#10;-1..input information not available&#13;&#10; 0..input is low&#13;&#10; 1..input is high"/>
		<Server Name="Input3" GUID="{A1F6FB70-6902-4689-A0CF-2920C7DA4070}" Visualized="false" Initialize="false" WriteProtected="true" Retentive="false" Comment="State of digital input 3 of drive&#13;&#10;&#13;&#10;-1..input information not available&#13;&#10; 0..input is low&#13;&#10; 1..input is high"/>
		<Server Name="Input4" GUID="{CF96BEE1-DB24-4F60-974C-70B37437FCCF}" Visualized="false" Initialize="false" WriteProtected="true" Retentive="false" Comment="State of digital input 4 of drive&#13;&#10;&#13;&#10;-1..input information not available&#13;&#10; 0..input is low&#13;&#10; 1..input is high"/>
		<Server Name="Input5" GUID="{454B374A-244B-4914-9883-68ABD96E6A7D}" Visualized="false" Initialize="false" WriteProtected="true" Retentive="false" Comment="State of digital input 5 of drive&#13;&#10;&#13;&#10;-1..input information not available&#13;&#10; 0..input is low&#13;&#10; 1..input is high"/>
		<Server Name="Input6" GUID="{3627AFEA-98BE-418E-AE24-6634874FE4E8}" Visualized="false" Initialize="false" WriteProtected="true" Retentive="false" Comment="State of digital input 6 of drive&#13;&#10;&#13;&#10;-1..input information not available&#13;&#10; 0..input is low&#13;&#10; 1..input is high"/>
		<Server Name="Input7" GUID="{2E496502-EB36-4CDA-A06C-7F082DF5EAF0}" Visualized="false" Initialize="false" WriteProtected="true" Retentive="false" Comment="State of digital input 7 of drive&#13;&#10;&#13;&#10;-1..input information not available&#13;&#10; 0..input is low&#13;&#10; 1..input is high"/>
		<Server Name="Input8" GUID="{02552925-7297-4F91-8593-7E29A7366A6C}" Visualized="false" Initialize="false" WriteProtected="true" Retentive="false" Comment="State of digital input 8 of drive&#13;&#10;&#13;&#10;-1..input information not available&#13;&#10; 0..input is low&#13;&#10; 1..input is high"/>
		<Server
			Name           = "RetryCounter"
			Initialize     = "false"
			Visualized     = "true"
			WriteProtected = "true"
			Comment        = "retry counter of varan module">
		</Server>
		<Server
			Name           = "State"
			Initialize     = "false"
			Visualized     = "true"
			WriteProtected = "true">
		</Server>
		<Server Name="Synchron" GUID="{2D75C4B3-F3C5-4A62-80BA-6DFC7D1C23C8}" Visualized="true" Initialize="false" WriteProtected="true" Retentive="false"/>
		<Server Name="VaranOut_1" GUID="{52F54445-ABBF-46DD-9EF4-4245A8158007}" Class="Hub_Base" Visualized="true" Initialize="false" WriteProtected="true" Retentive="false"/>
		<Client Name="FetchDigitalInputs" Required="false" Internal="false" DefValue="0" Comment="Client is set as init value.&#13;&#10;a value &lt;&gt; 0 means the digital inputs of the drive are fetched synchronously and displayed on the Servers Input1 to Input8"/>
		<Client Name="Hub_Base0" Required="true" Internal="true"/>
		<Client Name="VaranTimeMultiplier" Required="false" Internal="false" Comment="multiplier of varan time as init value."/>
	</Channels>
	<RevDoku>
		<Owner Company="Sigmatek" Author="RamAnd"/>
		<Dokumentation Revision="1.69" Date="16.10.2023" Author="LanSte" Company="Sigmatek" Description="Added GetRequiredWaitTime. If this method is overwritten, the class will wait for for an required module in the init()"/>
		<Dokumentation Revision="1.68" Date="15.06.2022" Author="RamAnd" Company="Sigmatek" Description="Added new Server HardwareVersion to show the hardware version of the VARAN type label."/>
		<Dokumentation Revision="1.67" Date="07.04.2020" Author="EisMic" Company="Sigmatek" Description="Changed comment of client &quot;UserAction&quot; in Varan_Base class."/>
		<Dokumentation Revision="1.66" Date="09.12.2019" Author="LanSte" Company="Sigmatek" Description="Added Server ProtocolVersion. InterframeGap is included in the resource calculation."/>
		<Dokumentation Revision="1.65" Date="30.01.2018" Author="RamAnd" Company="Sigmatek" Description="Class is using constant VM_MULTIVARAN_ADD_DO_INTO_DOL now from VaranManager_Base.h file instead of own define section."/>
		<Dokumentation Revision="1.64" Date="06.02.2017" Author="PieSte" Company="Sigmatek" Description="Changed &quot;Online&quot; server behavior to set online first if cyclic data is valid due to SA35740.&#13;&#10;Corrected an error that MDD100 drives are not initialized if Payload is active."/>
		<Dokumentation Revision="1.63" Date="02.09.2016" Author="ZoePat" Company="Sigmatek" Description="Corrected error with asyncron communication, that could overwrite realtime data for 1 cycle if a SDD3xx was used with VarantimeMultiplier &gt; 1."/>
		<Dokumentation Revision="1.62" Date="10.05.2016" Author="RamAnd" Company="Sigmatek" Description="Suppressed warning that would occur with target ARM on compiler version 30 or higher."/>
		<Dokumentation Revision="1.61" Date="02.05.2016" Author="EisMic" Company="Sigmatek" Description="Corrected an error that SDD115 and SDD120 were not initialized."/>
		<Dokumentation Revision="1.60" Date="04.04.2016" Author="EisMic" Company="Sigmatek" Description="Corrected error in initialisation which leads to an error that the drive is not initialized."/>
		<Dokumentation Revision="1.59" Date="17.02.2016" Author="EisMic" Company="Sigmatek" Description="Prescalersettings were not set correctly when Payload is active."/>
		<Dokumentation Revision="1.58" Date="24.08.2015" Author="EisMic" Company="Sigmatek" Description="DataObjects are now installed in UpdateCy and are added to DOList in UpdateRt if the OS supports the new interface method. Version 16#1003 or higher of the pMultiVaran-Interface is needed to use this feature."/>
		<Dokumentation Revision="1.57" Date="17.06.2015" Author="PieSte" Company="Sigmatek" Description="Corrected function Varan_HwDisconnect() to set dataobjects off."/>
		<Dokumentation Revision="1.56" Date="24.03.2015" Author="EisMic" Company="Sigmatek" Description="Check pointer p_NodeInfo for validity in method GetRetryTimeout due to access exception error if method Varan_HWDisconnect is called and no hardware was available."/>
		<Dokumentation Revision="1.55" Date="30.07.2014" Author="RamAnd" Company="Sigmatek" Description="Loop to check for retries could have caused a crash, if the drive wasn&apos;t initialized so far."/>
		<Dokumentation Revision="1.54" Date="07.07.2014" Author="LanSte" Company="Sigmatek" Description="Added support for reading hardware diagnosis via newinst cmd: CMD_GET_HARDWARE_DIAGNOSE "/>
		<Dokumentation Revision="1.53" Date="04.07.2014" Author="PieSte" Company="Sigmatek" Description="Saved client FetchDigitalInputs to TempFetchDigitalInputs to avoid an access exception if it was changed during run."/>
		<Dokumentation Revision="1.52" Date="07.05.2014" Author="LanSte" Company="Sigmatek" Description="Minimized the interface request via CILGET by useing private pointers to reduce time in init."/>
		<Dokumentation Revision="1.51" Date="06.03.2014" Author="RamAnd" Company="Sigmatek" Description="Changed offset of SyncOut 1 (62,5µs) to be synchron with the SyncOut 0 to prevent inconsistent data in the drive firmware."/>
		<Dokumentation Revision="1.50" Date="12.02.2014" Author="ZoePat" Company="Sigmatek" Description="ExtendedAxis for Axis2 of SDD210 and SDD215 din&apos;t work."/>
		<Dokumentation Revision="1.40" Date="20.01.2014" Author="RamAnd&#13;&#10;PieSte" Company="Sigmatek" Description="Success of GetSyncParameter and SetSyncParameter couldn&apos;t be ensured because the return value wasn&apos;t initialized if the method succeeds.&#13;&#10;Add TaskDelay 15ms in Varan_HwConnect to initialize the Hardware."/>
		<Dokumentation Revision="1.30" Date="05.12.2013" Author="Peeale" Company="Sigmatek" Description="Added payload support; ISO-DOs now start in RT-task to work also on ARM-CPUs;"/>
		<Dokumentation Revision="1.23" Date="18.07.2012" Author="ObeChr" Company="Sigmatek" Description="Implemented time measurement for internal tests in methods UpdateRt, UpdateRtPostScan and UpdateCy"/>
		<Dokumentation Revision="1.22" Date="25.01.2012" Author="ZoePat" Company="Sigmatek" Description="Corrected usage of ENUM types."/>
		<Dokumentation Revision="1.21" Date="09.11.2011" Author="RamAnd" Company="Sigmatek" Description="The memory initialisation of last change has been done too late (after new data was already set)."/>
		<Dokumentation Revision="1.20" Date="16.08.2011" Author="PibPet" Company="Sigmatek" Description="Fixed Problem with the Initialisation from the Drive. Reinit the Memory before sending."/>
		<Dokumentation Revision="1.19" Date="05.07.2011" Author="RamAnd" Company="Sigmatek" Description="Fixed problems in intialisation of SDD drives with less than 3 axis."/>
		<Dokumentation Revision="1.18" Date="14.06.2011" Author="RamAnd" Company="Sigmatek" Description="Fixed crash, when a MDD100 is exchanged with a SDD300 or the other way round."/>
		<Dokumentation Revision="1.17" Date="31.05.2011" Author="RamAnd" Company="Sigmatek" Description="Added possibility to read out the digital inputs of the drive synchronously."/>
		<Dokumentation Revision="1.16" Date="31.05.2011" Author="RamAnd" Company="Sigmatek" Description="DataObjects for VARAN communication are now created and started in the corresponding tasks (ISO-DOs in RT and ASY-DOs in CY) instead of creating and starting all DOs in the connect-callback."/>
		<Dokumentation Revision="1.15" Date="18.05.2011" Author="RamAnd" Company="Sigmatek" Description="After the Online-Server changed to 1, it was possible that the synchron values (like actual position) took 1 more realtime cycle to be shown by the class."/>
		<Dokumentation Revision="1.14" Date="04.01.2011" Author="BleErn" Company="Sigmatek" Description="Added Client Transparent that allows to disable a VARAN-HW-Class"/>
		<Dokumentation Revision="1.13" Date="14.02.2011" Author="BleErn" Company="Sigmatek" Description="Fixed problems with asynchronous communication"/>
		<Dokumentation Revision="1.12" Date="07.12.2010" Author="RamAnd" Company="Sigmatek" Description="Fixed problems in initialisation, when device is plugged in and out within a short time."/>
		<Dokumentation Revision="1.11" Date="25.10.2010" Author="BleErn" Company="Sigmatek" Description="Safety input of VAC013 did not trigger correct errors because of a incorrect comparison of HW-ID"/>
		<Dokumentation Revision="1.10" Date="13.08.2010" Author="BleErn" Company="Sigmatek" Description="Removed an irritating comment from implementation"/>
		<Dokumentation Revision="1.9" Date="10.08.2010" Author="Ramand" Company="Sigmatek" Description="Added support for SDD115"/>
		<Dokumentation Revision="1.8" Date="02.06.2010" Author="BleErn / RamAnd" Company="Sigmatek" Description="Optimization of UpdateRtPostScan method.&#13;&#10;Added support for SDD210"/>
		<Dokumentation Revision="1.7" Date="10.03.2010" Author="RamAnd" Company="Sigmatek" Description="Added serial number validation"/>
		<Dokumentation Revision="1.6" Date="17.05.2010" Author="RamAnd" Company="Sigmatek" Description="Changed defines to avoid compiler warning &quot;Identical Redefinition&quot;"/>
		<Dokumentation Revision="1.5" Date="26.02.2010" Author="RamAnd" Company="Sigmatek" Description="Added support for VAC013"/>
		<Dokumentation Revision="1.4" Date="15.02.2010" Author="RamAnd" Company="Sigmatek" Description="Class works now also with SDD215"/>
		<Dokumentation Revision="1.3" Date="15.01.2010" Author="RamAnd" Company="Sigmatek" Description="Removed Client AxisAvailable. The available axis are now automatically detected."/>
		<Dokumentation Revision="1.2" Date="03.12.2009" Author="RamAnd" Company="Sigmatek" Description="Improved comment on client &quot;AxisAvailable&quot;."/>
		<Dokumentation Revision="1.1" Date="09.11.2009" Author="RamAnd" Company="Sigmatek" Description="Login of VaranRtPostScan did not work properly if the init of the _VaranDriveBase has been called before the VaranManager-Init."/>
		<Dokumentation Revision="1.0" Date="06.10.2009" Author="RamAnd" Company="Sigmatek" Description="Error in Init has been solved (could have led to a VARAN FATAL ERROR)"/>
	</RevDoku>
	<Network Name="_VaranDriveBase">
		<!-- List of Components in this network -->
		<Components>
			<Object
				Name       = "_base"
				GUID       = "{4F8ADAEB-11BC-424D-A610-2A3263C72A44}"
				Class      = "Varan_Base"
				Position   = "(240,120)"
				Visualized = "true">
				<Channels>
					<Server Name="ConnectCounter"/>
					<Server Name="DeviceAddress"/>
					<Server Name="DeviceID"/>
					<Server Name="DiagControl"/>
					<Server Name="FaultCounter"/>
					<Server Name="HardwareVersion"/>
					<Server Name="Online"/>
					<Server Name="ProtocolVersion"/>
					<Server Name="Release"/>
					<Server Name="RetryCounter"/>
					<Server Name="RXLost"/>
					<Server Name="SerialNo"/>
					<Server Name="State"/>
					<Server Name="TXLost"/>
					<Server Name="ValidateSerNo"/>
					<Server Name="VendorID"/>
					<Client Name="Required" Value="1"/>
					<Client Name="SerNoValidation"/>
					<Client Name="TimeBase" Value="0"/>
					<Client Name="TimeBaseOffset" Value="0"/>
					<Client Name="To_MultiTask"/>
					<Client Name="To_StdLib"/>
					<Client Name="Transparent"/>
					<Client Name="UserAction"/>
					<Client Name="VaranIn"/>
				</Channels>
			</Object>
			<Object
				Name       = "Hub_Base0"
				GUID       = "{DCCA7F12-6BB0-4896-879A-9E7762EC5DDB}"
				Class      = "Hub_Base"
				Position   = "(870,780)"
				Visualized = "true">
				<Channels>
					<Server Name="Control"/>
					<Client Name="Splitter_Place" Value="0"/>
					<Client Name="VaranIn"/>
				</Channels>
			</Object>
		</Components>
		<Comments>
		</Comments>
		<!-- List of Connections in this network -->
		<Connections>
			<Connection Source="this.State" Destination="_base.State" Vertices="(1468,210),(724,210),"/>
			<Connection Source="this.Online" Destination="_base.Online" Vertices="(1468,270),(724,270),"/>
			<Connection Source="this.Release" Destination="_base.Release" Vertices="(1468,330),(724,330),"/>
			<Connection Source="this.DeviceAddress" Destination="_base.DeviceAddress" Vertices="(1468,450),(724,450),"/>
			<Connection Source="_base.VaranIn" Destination="this.VaranIn" Vertices="(240,210),(38,210),"/>
			<Connection Source="_base.Required" Destination="this.Required" Vertices="(240,270),(38,270),"/>
			<Connection Source="this.VendorID" Destination="_base.VendorID" Vertices="(1468,510),(724,510),"/>
			<Connection Source="this.DeviceID" Destination="_base.DeviceID" Vertices="(1468,570),(724,570),"/>
			<Connection Source="_base.UserAction" Destination="this.UserAction" Vertices="(240,330),(38,330),"/>
			<Connection Source="Hub_Base0.VaranIn" Destination="_base.State" Vertices="(870,870),(810,870),(810,210),(724,210),"/>
			<Connection Source="this.VaranOut_1" Destination="Hub_Base0.Control" Vertices="(1468,1470),(1296,870),"/>
			<Connection Source="this.RetryCounter" Destination="_base.RetryCounter" Vertices="(1468,690),(724,690),"/>
			<Connection Source="this.Hub_Base0" Destination="Hub_Base0.Control"/>
			<Connection Source="this.SerialNo" Destination="_base.SerialNo" Vertices="(1468,630),(724,630),"/>
			<Connection Source="_base.SerNoValidation" Destination="this.SerNoValidation" Vertices="(240,390),(38,390),"/>
			<Connection Source="this.ValidateSerNo" Destination="_base.ValidateSerNo" Vertices="(1468,750),(724,750),"/>
			<Connection Source="_base.Transparent" Destination="this.Transparent" Vertices="(240,450),(38,450),"/>
			<Connection Source="this.ProtocolVersion" Destination="_base.ProtocolVersion" Vertices="(1468,810),(724,1110),"/>
			<Connection Source="this.HardwareVersion" Destination="_base.HardwareVersion" Vertices="(1468,390),(724,390),"/>
		</Connections>
		<!-- Headerfiles -->
		<Options>
		</Options>
	</Network>
</Class>
*)
#pragma using Varan_Base

_VaranDriveBase : CLASS
: Varan_Base
	TYPE
	  t_AxisState :
	  (
	    _NotUsed,
	    _NoInit,
	    _InitOk,
	    _NoParaList,
	    _NotSynchron,
	    _AxisOk
	  )$USINT;
	  t_ParaState :
	  (
	    _SendExecution,
	    _ResetExecution,
	    _Wait4Response,
	    _IdleState,
	    _GotValueForExecution
	  )$UDINT;
#pragma pack(push, 1)
	  t_ParaList : STRUCT
	    us_number : USINT;
	    sd_value : DINT;
	  END_STRUCT;
#pragma pack(pop)
#pragma pack(push, 1)
	  t_ReadValuePtr : STRUCT  //! <Type Public="true" Name="t_ReadValuePtr"/>
	    a_SyncValues : ARRAY [0..4] OF DINT;
	    bs_InputStates : BSINT
	    [
	      1 OptionBoardInputState,
	    ];
	  END_STRUCT;
#pragma pack(pop)
#pragma pack(push, 1)
	  t_WriteValuePtr : STRUCT  //! <Type Public="true" Name="t_WriteValuePtr"/>
	    a_SyncValues : ARRAY [0..4] OF DINT;
	  END_STRUCT;
#pragma pack(pop)
	  t_AxisData : STRUCT
	    e_AxisState : t_AxisState;
	    us_ParaReady : t_ParaState;
	    sd_Asyncdata : DINT;
	    sd_ObjectError : DINT;
	    b_ListActive : BOOL;
	    p_ParaList : ^t_ParaList;
	    ui_ParaListCnt : UINT;
	    ud_CRCError : UDINT;
	    ud_DOLength : UDINT;
	    b_ExtendedAxis : DINT;
	    b_FastAxis : DINT;
	    b_OldToggleState : DINT;
	    s_ReadValues : t_ReadValuePtr;
	    s_WriteValues : t_WriteValuePtr;
	  END_STRUCT;
#pragma pack(push, 1)
	  t_DataReadOneAxis : STRUCT
	    us_ReceiveState : BSINT
	    [
	      1 ExecutedObjectTransfer,
	      2 CRC_Error,
	      4 OnlineToolWriteOk,
	    ];
	    us_Reserved1 : USINT;
	    us_DigitalIO : USINT;
	    us_TransmitControl : BSINT
	    [
	      1 ToggleBit,
	      2 ErrorInObjectHandling,
	      3 Warning,
	      4 ErrorBit,
	      5 SyncLocked,
	      6 MainsApplied,
	      7 ExternalLock,
	      8 notused,
	    ];
	    sd_ObjectValue : DINT;
	    sd_Value6 : DINT;
	    sd_Value7 : DINT;
	    sd_Value8 : DINT;
	    sd_Value9 : DINT;
	    sd_Value10 : DINT;
	  END_STRUCT;
#pragma pack(pop)
#pragma pack(push, 1)
	  t_DataWriteAsync : STRUCT
	    us_TransmitExecution : BSINT
	    [
	      1 StartObjectTransfer,
	      2 RepeatObjectTransfer,
	      3 EnableValue3_5,
	      4 ClearOnlineToolWriteOk,
	    ];
	    us_Reserved1 : USINT;
	    us_DriveControl : BSINT
	    [
	      1 ToggleBit,
	      2 ReadWriteObject,
	      3 InitCommunicatian,
	      4 EnableInput1,
	      5 UnlockInput1,
	      6 UnlockBrake,
	      7 InterfaceComError,
	      8 NoSetPoint,
	    ];
	    us_ObjectAddress : USINT;
	    sd_ObjectValue : DINT;
	  END_STRUCT;
#pragma pack(pop)
#pragma pack(push, 1)
	  t_DataWriteOneAxis : STRUCT
	    us_TransmitExecution : BSINT
	    [
	      1 StartObjectTransfer,
	      2 RepeatObjectTransfer,
	      3 EnableValue3_5,
	      4 ClearOnlineToolWriteOk,
	    ];
	    us_Reserved1 : USINT;
	    us_DriveControl : BSINT
	    [
	      1 ToggleBit,
	      2 ReadWriteObject,
	      3 InitCommunication,
	      4 EnableInput1,
	      5 UnlockInput1,
	      6 UnlockBrake,
	      7 InterfaceComError,
	      8 NoSetPoint,
	    ];
	    us_ObjectAddress : USINT;
	    sd_ObjectValue : DINT;
	    sd_Value1 : DINT;
	    sd_Value2 : DINT;
	    sd_Value3 : DINT;
	    sd_Value4 : DINT;
	    sd_Value5 : DINT;
	  END_STRUCT;
#pragma pack(pop)
#pragma pack(push, 1)
	  t_FastAxisRead : STRUCT
	    us_DigInOut : USINT;
	    us_TrasmittControl : USINT;
	    sd_Value8 : DINT;
	    sd_Value9 : DINT;
	    sd_Value10 : DINT;
	  END_STRUCT;
#pragma pack(pop)
#pragma pack(push, 1)
	  t_FastAxisWrite : STRUCT
	    us_TransmittExecution : BSINT
	    [
	      5 EnableType2,
	      6 DirectAccess,
	    ];
	    us_Reserved1 : USINT;
	    us_DriveControl : USINT;
	    us_Reserved2 : USINT;
	    sd_Value3 : DINT;
	    sd_Value4 : DINT;
	    sd_Value5 : DINT;
	  END_STRUCT;
#pragma pack(pop)
#pragma pack(push, 1)
	  t_DOFastAxis : STRUCT
	    p_Handle : ^LSL_VARANFRAME;
	    p_DOSettings : ^t_VaranDOSettingsRdWr;
	    p_DataRead : ^t_FastAxisRead;
	    p_DataWrite : ^t_FastAxisWrite;
	    us_OldRetryCounter : USINT;
	  END_STRUCT;
#pragma pack(pop)
	  t_DOOneAxis : STRUCT
	    p_Handle : ^LSL_VARANFRAME;
	    p_DOSettings : ^t_VaranDOSettingsRdWr;
	    p_DataRead : ^t_DataReadOneAxis;
	    p_DataWrite : ^t_DataWriteOneAxis;
	    AsyDataTemp : t_DataWriteOneAxis;
	    b_NewAsyDataTemp : BOOL;
	    us_OldRetryCounter : USINT;
	  END_STRUCT;
#pragma pack(push, 1)
	  t_DrivePLLRd : STRUCT
	    SystemPeriodTime : UINT;
	    Reserved1 : UINT;
	    MaxCountValue : UINT;
	    Reserved2 : UINT;
	    DriveCycleCounter : UINT;
	    StatusRegister : BSINT
	    [
	      1 PLL_Locked,
	    ];
	    Reserved3 : SINT;
	    SyncOut1Offset : UINT;
	    Reserved4 : UINT;
	  END_STRUCT;
#pragma pack(pop)
#pragma pack(push, 1)
	  t_DrivePLLWr : STRUCT
	    SystemPeriodTime : UINT;
	    Reserved1 : UINT;
	  END_STRUCT;
#pragma pack(pop)
	  t_InitSSW :
	  (
	    _SetDataObjectOn,
	    _SetInitAxis,
	    _WaitInit,
	    _SetFinishInit,
	    _SetExecuteBack,
	    _GetFinishInit,
	    _CyIdle
	  )$UDINT;
#pragma pack(push, 1)
	  t_newASYRead : STRUCT
	    sd_ObjectValue : DINT;
	    us_TransmitControl : BSINT
	    [
	      1 ToggleBit,
	      2 ErrorInObjectHandling,
	      3 Warning,
	      4 ErrorBit,
	      5 SyncLocked,
	      6 MainsApplied,
	      7 ExternalLock,
	      8 notused,
	    ];
	    us_DigitalIO : USINT;
	  END_STRUCT;
#pragma pack(pop)
	  t_newASYReadArray : ARRAY [0..DIASDRIVE_MAX_AXIS-1] OF t_newASYRead;
#pragma pack(push, 1)
	  t_newASYWrite : STRUCT
	    sd_ObjectValue : DINT;
	    us_DriveControl : BSINT
	    [
	      1 ToggleBit,
	      2 ReadWriteObject,
	      3 InitCommunication,
	      4 EnableInput1,
	      5 UnlockInput1,
	      6 UnlockBrake,
	      7 InterfaceComError,
	      8 NoSetPoint,
	    ];
	    us_ObjectAddress : USINT;
	  END_STRUCT;
#pragma pack(pop)
	  t_newASYWriteArray : ARRAY [0..DIASDRIVE_MAX_AXIS-1] OF t_newASYWrite;
#pragma pack(push, 1)
	  t_newASYDO : STRUCT
	    p_Handle : ^LSL_VARANFRAME;
	    p_DOSettings : ^t_VaranDOSettingsRdWr;
	    p_DataRead : ^t_newASYReadArray;
	    p_DataWrite : ^t_newASYWriteArray;
	    us_OldRetryCounter : USINT;
	    AsyDataTemp : t_newASYWriteArray;
	    b_NewAsyDataTemp : ARRAY [0..DIASDRIVE_MAX_AXIS-1] OF BOOL;
	  END_STRUCT;
#pragma pack(pop)
#pragma pack(push, 1)
	  t_newDigInDO : STRUCT
	    p_Handle : ^LSL_VARANFRAME;
	    p_DOSettings : ^t_VaranDOSettingsRd;
	    p_DataRead : ^USINT;
	    us_OldRetryCounter : USINT;
	  END_STRUCT;
#pragma pack(pop)
#pragma pack(push, 1)
	  t_newReadDataOneAxis : STRUCT
	    Value6 : DINT;
	    Value7 : DINT;
	    Value8 : DINT;
	    Value9 : DINT;
	    Value10 : DINT;
	  END_STRUCT;
#pragma pack(pop)
#pragma pack(push, 1)
	  t_newWriteDataOneAxis : STRUCT
	    Value1 : DINT;
	    Value2 : DINT;
	    Value3 : DINT;
	    Value4 : DINT;
	    Value5 : DINT;
	  END_STRUCT;
#pragma pack(pop)
#pragma pack(push, 1)
	  t_newISODO : STRUCT
	    p_Handle : ^LSL_VARANFRAME;
	    p_DOSettings : ^t_VaranDOSettingsRdWr;
	    p_DataRead : ^t_newReadDataOneAxis;
	    p_DataWrite : ^t_newWriteDataOneAxis;
	    us_OldRetryCounter : USINT;
	  END_STRUCT;
#pragma pack(pop)
#pragma pack(push, 1)
	  t_ParaSkipOneAxis : STRUCT
	    us_No : USINT;
	    p_Values : ^USINT;
	  END_STRUCT;
#pragma pack(pop)
	  t_ParaSkipList : ARRAY [0..DIASDRIVE_MAX_AXIS-1] OF t_ParaSkipOneAxis;
	  t_RtSSW :
	  (
	    CompInitAxis,
	    CompGetSendParaList,
	    CompWaitForSynchrony,
	    CompOperational,
	    InitAxis,
	    GetSendParaList,
	    WaitForSynchrony,
	    Operational
	  )$UDINT;
	END_TYPE
  //Servers:
	CRC_ErrorCounter 	: SvrCh_DINT;
	Synchron 	: SvrCh_DINT;
	Input1 	: SvrCh_DINT;
	Input2 	: SvrCh_DINT;
	Input3 	: SvrCh_DINT;
	Input4 	: SvrCh_DINT;
	Input5 	: SvrCh_DINT;
	Input6 	: SvrCh_DINT;
	Input7 	: SvrCh_DINT;
	Input8 	: SvrCh_DINT;
	VaranOut_1 	: SvrChCmd_DINT;
  //Clients:
	Hub_Base0 	: CltChCmd_Hub_Base;
	VaranTimeMultiplier 	: CltCh_UDINT;
	FetchDigitalInputs 	: CltCh_DINT;
  //Variables:
		aAxisData : ARRAY [0..DIASDRIVE_MAX_AXIS-1] OF t_AxisData;

		aDataObjects : ARRAY [0..DIASDRIVE_MAX_AXIS-1] OF t_DOOneAxis;

		newIsoDOs : ARRAY [0..DIASDRIVE_MAX_AXIS-1] OF t_newISODO;

		newAsyDO 	: t_newASYDO;
		newDigInDO 	: t_newDigInDO;
		us_Firstscan 	: USINT;
		us_AxisNumber 	: USINT;
		e_InitSSW 	: t_InitSSW;
		b_InitOk 	: BOOL;
		ud_TimemarkInit 	: UDINT;
		ud_TimeCounter 	: UDINT;
		b_SyncEnabled 	: BOOL;
		sd_SyncOffset 	: DINT;
		ud_VaranTime 	: UDINT;
		ud_IsoStartPoint 	: UDINT;
		b_FastDODeactivate 	: BOOL;
		s_DataFastAxis 	: t_DOFastAxis;
		RwFastSpeed 	: t_FastAxisWrite;
		s_SkipParameter 	: t_ParaSkipList;
		AxisAvailableHW : BDINT
		[
		];

		ExtendedAxisSettings : BDINT
		[
		];

		FastAxisSettings : BDINT
		[
		];

		b_CompatibilityMode 	: BOOL;			//! <Variable Comment="TRUE....SDD300 series model&#13;&#10;FALSE...SDD100/5000 series model" Name="b_CompatibilityMode"/>
		pCallBackServer 	: ^UDINT;
		AxisAvailableNo 	: USINT;
		CompAxisAvailableNo 	: SINT;
		AxisAvailable100 	: USINT;
		GetCompAxisSSW 	: UDINT;
		e_RtSSW 	: t_RtSSW;
		CreatedCompDOs 	: BOOL;
		CreatedNewIsoDOs 	: BOOL;
		CreatedNewAsyDOs 	: BOOL;
		b_UpdateThisTime 	: BOOL;
		b_IsSDD21x 	: BOOL;
		b_AlreadyConnected 	: BOOL;
		DataInitFinished 	: BOOL;
		TempFetchDigitalInputs 	: BOOL;
		p_DriveMngBase 	: ^void;
		bAddDOsToListSupport 	: BOOL;			//! <Variable Comment="Flag is True if the os version supports to add DOs to DOL with multivaraninterface (MULTI_VARAN_IINSERTDOINTODOL)" Name="bAddDOsToListSupport"/>
  //Functions:
				//! <Function Comment="=================================================================================================&#13;&#10;Init for Varan Client&#13;&#10;=================================================================================================&#13;&#10;" Name="Init"/>
	FUNCTION VIRTUAL GLOBAL Init;
				//! <Function Comment="Cy - Funktion of Varan class ( called bei VaranMaster )" Name="UpdateCy"/>
	FUNCTION VIRTUAL GLOBAL UpdateCy;
				//! <Function Comment="=================================================================================================&#13;&#10;Rt - Funktion of Varan class ( called bei VaranMaster )&#13;&#10;=================================================================================================&#13;&#10;" Name="UpdateRt"/>
	FUNCTION VIRTUAL GLOBAL UpdateRt;
	
	FUNCTION VIRTUAL GLOBAL UpdateRtPostScan;
				//! <Function Comment="=================================================================================================&#13;&#10;Function is called if a varan module is connected&#13;&#10;=================================================================================================&#13;&#10;" Name="Varan_HwConnect"/>
	FUNCTION VIRTUAL GLOBAL Varan_HwConnect
		VAR_INPUT
			ud_data 	: UDINT;			//! <Variable Comment="data of call back" Name="Varan_HwConnect.ud_data"/>
		END_VAR
		VAR_OUTPUT
			sd_retval 	: DINT;			//! <Variable Comment="0=Ok, -1=class not okay, -2=wrong axle, -3=axle not in use, -4=varan error in data object" Name="Varan_HwConnect.sd_retval"/>
		END_VAR;
				//! <Function Comment="=================================================================================================&#13;&#10;Function is called if a varan interrupt occures&#13;&#10;=================================================================================================&#13;&#10;" Name="Varan_HwInterrupt"/>
	FUNCTION VIRTUAL GLOBAL Varan_HwInterrupt
		VAR_INPUT
			ud_reason 	: UDINT;			//! <Variable Comment="reason of interrupt" Name="Varan_HwInterrupt.ud_reason"/>
			ud_data 	: ^t_CallBackInterrupt;
		END_VAR
		VAR_OUTPUT
			sd_retval 	: DINT;
		END_VAR;
				//! <Function Comment="=================================================================================================&#13;&#10;Function is called if a varan module is disconnected&#13;&#10;=================================================================================================&#13;&#10;" Name="Varan_HwDisconnect"/>
	FUNCTION VIRTUAL GLOBAL Varan_HwDisconnect
		VAR_INPUT
			ud_data 	: UDINT;
		END_VAR
		VAR_OUTPUT
			sd_retval 	: DINT;
		END_VAR;
				//! <Function Comment="=================================================================================================&#13;&#10;Function to set all Data Objects off&#13;&#10;=================================================================================================&#13;&#10;" Name="SetDOsOff"/>
	FUNCTION VIRTUAL GLOBAL SetDOsOff;
				//! <Function Comment="=================================================================================================&#13;&#10;Function to update module retry counter&#13;&#10;=================================================================================================&#13;&#10;" Name="UpdateRetryCounter"/>
	FUNCTION VIRTUAL GLOBAL UpdateRetryCounter;
				//! <Function Comment="Check if DeviceID is supported by class" Name="CheckDeviceID"/>
	FUNCTION VIRTUAL GLOBAL CheckDeviceID
		VAR_INPUT
			ID2Check 	: UDINT;			//! <Variable Comment="VARAN DeviceID, which should be checked" Name="CheckDeviceID.ID2Check"/>
		END_VAR
		VAR_OUTPUT
			IsOK 	: BOOL;			//! <Variable Comment="TRUE...DeviceID is ok with this class&#13;&#10;FALSE..DeviceID is not ok with this class" Name="CheckDeviceID.IsOK"/>
		END_VAR;
				//! <Function Comment="[#ENGLISH]&#13;&#10;=================================================================================================&#13;&#10;Function to initailize each axle&#13;&#10;=================================================================================================&#13;&#10;[members] s_Axle[x]Data  :R/W :structure for data of one axle&#13;&#10;   s_DataObjectA[x] :R/W :structure for data object of one axle&#13;&#10;   e_InitSSW   :R/W :init ssw&#13;&#10;   ud_TimemarkInit  :W/R :timeout for init&#13;&#10;[locals] p_axle    :W/R :pointer to right axle data&#13;&#10;   p_data_object  :W/R :pointer to right axle data object information&#13;&#10;" Name="InitAxis"/>
	FUNCTION InitAxis
		VAR_INPUT
			us_AxisNo 	: USINT;			//! <Variable Comment="number of axle" Name="InitAxis.us_AxisNo"/>
		END_VAR
		VAR_OUTPUT
			sd_retval 	: DINT;
		END_VAR;
				//! <Function Comment="=================================================================================================&#13;&#10;Function to get object value state&#13;&#10;=================================================================================================&#13;&#10;" Name="GetParameterState"/>
	FUNCTION GLOBAL GetParameterState
		VAR_INPUT
			us_Axis 	: USINT;
		END_VAR
		VAR_OUTPUT
			sd_para_state 	: DINT;			//! <Variable Comment="&gt;0=Object Error, 0=ok, -1=function not ready, -2=wrong axle, -3=Axle not in use, -4=varan error in data object" Name="GetParameterState.sd_para_state"/>
		END_VAR;
				//! <Function Comment="=================================================================================================&#13;&#10;Function to set a object value&#13;&#10;=================================================================================================&#13;&#10;" Name="SetParameter"/>
	FUNCTION GLOBAL SetParameter
		VAR_INPUT
			us_Axis 	: USINT;
			us_para_nr 	: USINT;			//! <Variable Comment="number of parameter" Name="SetParameter.us_para_nr"/>
			us_rdwr 	: USINT;			//! <Variable Comment="0=read, 1=write" Name="SetParameter.us_rdwr"/>
			sd_para_value 	: DINT;			//! <Variable Comment="value of parameter (only for write)" Name="SetParameter.sd_para_value"/>
		END_VAR
		VAR_OUTPUT
			sd_retval 	: DINT;
		END_VAR;
				//! <Function Comment="=================================================================================================&#13;&#10;Function to get object value of parameter&#13;&#10;=================================================================================================&#13;&#10;" Name="GetParameter"/>
	FUNCTION GLOBAL GetParameter
		VAR_INPUT
			us_Axis 	: USINT;
		END_VAR
		VAR_OUTPUT
			sd_para_data 	: DINT;			//! <Variable Comment="value of readed parameter" Name="GetParameter.sd_para_data"/>
		END_VAR;
				//! <Function Comment="=================================================================================================&#13;&#10;Function to set parameter parameter list&#13;&#10;=================================================================================================&#13;&#10;" Name="SetParaList"/>
	FUNCTION GLOBAL SetParaList
		VAR_INPUT
			us_Axis 	: USINT;
			p_list 	: ^void;			//! <Variable Comment="pointer to parameter list" Name="SetParaList.p_list"/>
			ui_counter 	: UINT;			//! <Variable Comment="number of parameters" Name="SetParaList.ui_counter"/>
		END_VAR
		VAR_OUTPUT
			sd_retval 	: DINT;
		END_VAR;
				//! <Function Comment="=================================================================================================&#13;&#10;Function to get a synchron parameter&#13;&#10;=================================================================================================&#13;&#10;" Name="GetSyncParameter"/>
	FUNCTION GLOBAL GetSyncParameter
		VAR_INPUT
			us_Axis 	: USINT;
			us_value 	: USINT;			//! <Variable Comment="0=Value1, 1=Value2, 2=Value3, 3=Value4, 4=Value5" Name="GetSyncParameter.us_value"/>
			p_data 	: ^DINT;			//! <Variable Comment="to this pointer value is written" Name="GetSyncParameter.p_data"/>
		END_VAR
		VAR_OUTPUT
			sd_retval 	: DINT;
		END_VAR;
				//! <Function Comment="=================================================================================================&#13;&#10;Function to set a synchron Parameter&#13;&#10;=================================================================================================&#13;&#10;" Name="SetSyncParameter"/>
	FUNCTION GLOBAL SetSyncParameter
		VAR_INPUT
			us_Axis 	: USINT;
			us_value 	: USINT;
			sd_data 	: DINT;			//! <Variable Comment="data of value" Name="SetSyncParameter.sd_data"/>
		END_VAR
		VAR_OUTPUT
			sd_retval 	: DINT;
		END_VAR;
	
	FUNCTION InitAxisNew
		VAR_INPUT
			us_AxisNo 	: USINT;
		END_VAR
		VAR_OUTPUT
			sd_retval 	: DINT;
		END_VAR;
				//! <Function Comment="[#ENGLISH]&#13;&#10;=================================================================================================&#13;&#10;Function for parameter handling in synchron mode&#13;&#10;=================================================================================================&#13;&#10;[members] s_Axle[x]Data  :R/W :structure for data of one axle&#13;&#10;   s_DataObjectA[x] :R/W :structure for data object of one axle&#13;&#10;[locals] p_axle   :W/R :pointer to right axle data&#13;&#10;   p_DataObject :W/R :pointer to right data object for axle&#13;&#10;" Name="GetObjectValue"/>
	FUNCTION GetObjectValue
		VAR_INPUT
			us_Axis 	: USINT;
		END_VAR;
	
	FUNCTION GetObjectValueNew
		VAR_INPUT
			us_Axis 	: USINT;
		END_VAR;
				//! <Function Comment="=================================================================================================&#13;&#10;Function inits drive for all axes used&#13;&#10;=================================================================================================&#13;&#10;" Name="InitDrive"/>
	FUNCTION GLOBAL InitDrive;
	
	FUNCTION GLOBAL SetAxisOn
		VAR_INPUT
			ud_Axis 	: BDINT;
		END_VAR;
				//! <Function Comment="Function to skip parameters in the parameter list.&#13;&#10;Parameters to be skipped have to be defined via Newinst command 1" Name="SkipEntries"/>
	FUNCTION SkipEntries
		VAR_INPUT
			us_Axis 	: USINT;
			p_Axis 	: ^t_AxisData;
		END_VAR;
				//! <Function Comment="tell the drive class, the software setting and install callback (calls write-method of given server) to get available configuration" Name="StartCommunication"/>
	FUNCTION GLOBAL StartCommunication
		VAR_INPUT
			AxisExtend 	: BDINT;
			AxisFast 	: BDINT;
			pServer4CallBack 	: ^BDINT;			//! <Variable Comment="pass address of server (e.g. #MyServer) to get a callback (write-method) of this server, if the hardware is available on varan (available axis are passed as input parameter)" Name="StartCommunication.pServer4CallBack"/>
		END_VAR;
	
	FUNCTION GLOBAL GetAxisRdPtr
		VAR_INPUT
			AxisNr 	: DINT;			//! <Variable Comment="number of axis for which you want the pointer (1..8)" Name="GetAxisRdPtr.AxisNr"/>
		END_VAR
		VAR_OUTPUT
			pReadPara 	: ^t_ReadValuePtr;
		END_VAR;
	
	FUNCTION GLOBAL GetAxisWrPtr
		VAR_INPUT
			AxisNr 	: DINT;
		END_VAR
		VAR_OUTPUT
			pWritePara 	: ^t_WriteValuePtr;
		END_VAR;
	
	FUNCTION GLOBAL GetDriveIntState
		VAR_OUTPUT
			retcode 	: DINT;			//! <Variable Comment="0..Initialisation of Axles&#13;&#10;1..Download of Drive Parameters&#13;&#10;2..Wait until Drive is synchron with Varan&#13;&#10;3..Operational mode" Name="GetDriveIntState.retcode"/>
		END_VAR;
	
	FUNCTION GLOBAL ExternInitFinished;
	
	FUNCTION GetDriveType
		VAR_INPUT
			HWCode 	: DINT;
		END_VAR
		VAR_OUTPUT
			AxisNo 	: SINT;
		END_VAR;
	
	FUNCTION InstallDefaultDO;
	
	FUNCTION AddIsoDOsCompMode;
	
	FUNCTION AddIsoDOsNew;
	
	FUNCTION GLOBAL GetSeries
		VAR_OUTPUT
			retcode 	: USINT;
		END_VAR;
	
	FUNCTION GLOBAL IsSDD21x
		VAR_OUTPUT
			retcode 	: BOOL;
		END_VAR;
				//! <Function Comment="Save the passed DriveMngBase this pointer. Needed for Hardwarediagnosis." Name="SetObjectCallBack"/>
	FUNCTION GLOBAL SetObjectCallBack
		VAR_INPUT
			p_DriveMngBaseNew 	: ^void;
		END_VAR;
	
	FUNCTION VIRTUAL GLOBAL State::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 Hub_Base


//}}LSL_DECLARATION


FUNCTION GLOBAL TAB _VaranDriveBase::@CT_
0$UINT,
2#0100000000000000$UINT, //TY__VARANDRIVEBASE
1$UINT, 69$UINT, (SIZEOF(::_VaranDriveBase))$UINT, 
11$UINT, 3$UINT, 0$UINT, 
TO_UDINT(766164962), "_VaranDriveBase", //Class
TO_UDINT(862125188), "Varan_Base", 2$UINT, 21$UINT, //Baseclass
//Servers:
(::_VaranDriveBase.CRC_ErrorCounter.pMeth)$UINT, _CH_SVR$UINT, 2#0000000000000000$UINT, TO_UDINT(2665485201), "CRC_ErrorCounter", 
(::_VaranDriveBase.Synchron.pMeth)$UINT, _CH_SVR$UINT, 2#0000000000000000$UINT, TO_UDINT(4124736508), "Synchron", 
(::_VaranDriveBase.Input1.pMeth)$UINT, _CH_SVR$UINT, 2#0000000000000000$UINT, TO_UDINT(1344628668), "Input1", 
(::_VaranDriveBase.Input2.pMeth)$UINT, _CH_SVR$UINT, 2#0000000000000000$UINT, TO_UDINT(3375117830), "Input2", 
(::_VaranDriveBase.Input3.pMeth)$UINT, _CH_SVR$UINT, 2#0000000000000000$UINT, TO_UDINT(3190490768), "Input3", 
(::_VaranDriveBase.Input4.pMeth)$UINT, _CH_SVR$UINT, 2#0000000000000000$UINT, TO_UDINT(542085939), "Input4", 
(::_VaranDriveBase.Input5.pMeth)$UINT, _CH_SVR$UINT, 2#0000000000000000$UINT, TO_UDINT(1464378277), "Input5", 
(::_VaranDriveBase.Input6.pMeth)$UINT, _CH_SVR$UINT, 2#0000000000000000$UINT, TO_UDINT(3460428319), "Input6", 
(::_VaranDriveBase.Input7.pMeth)$UINT, _CH_SVR$UINT, 2#0000000000000000$UINT, TO_UDINT(3108422281), "Input7", 
(::_VaranDriveBase.Input8.pMeth)$UINT, _CH_SVR$UINT, 2#0000000000000000$UINT, TO_UDINT(704241432), "Input8", 
(::_VaranDriveBase.VaranOut_1.pMeth)$UINT, _CH_SVR_OBJ$UINT, 2#0000000000000000$UINT, TO_UDINT(2138873746), "VaranOut_1", 
//Clients:
(::_VaranDriveBase.Hub_Base0.pCh)$UINT, _CH_CLT_OBJ$UINT, 2#0000000000000010$UINT, TO_UDINT(1954527509), "Hub_Base0", TO_UDINT(3238133653), "Hub_Base", 1$UINT, 21$UINT, 
(::_VaranDriveBase.VaranTimeMultiplier.pCh)$UINT, _CH_CLT_DATA$UINT, 2#0000000000000000$UINT, TO_UDINT(873970582), "VaranTimeMultiplier", 
(::_VaranDriveBase.FetchDigitalInputs.pCh)$UINT, _CH_CLT_DATA$UINT, 2#0000000000000000$UINT, TO_UDINT(2304224197), "FetchDigitalInputs", 
END_FUNCTION


#define USER_CNT__VaranDriveBase 49

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	IF VaranOut_1.pMeth THEN
		ret_code	:= C_OK;
	ELSE
		ret_code	:= C_OUTOF_NEAR;
		RETURN;
	END_IF;

END_FUNCTION

//{{LSL_IMPLEMENTATION
FUNCTION VIRTUAL GLOBAL _VaranDriveBase::Init
  VAR
    sd_retval   : DINT;
  END_VAR

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

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

		//-----------------------------------------------------------------------------------------------
		//init the base class
		Varan_Base::Init();
    
		//if an error in base class occurs return
		if ( State <> _NotInitialized ) then
			return;
		end_if;
    
    //Reset Flag
    bAddDOsToListSupport := FALSE;    
    
    //bAddDosToListSupport Flag:
    //Install the isochrone dataobjects in cywork and not in the realtime task, due to the high realtime load in the first rt cycles.
    //The dataobjects are only installed an not added to the DOL in the os with the mask VARAN_DOL_NOT_INSERT_DO_INTO_DOL.
    //With the new os-function MULTI_VARAN_IINSERTDOINTODOL the Dataobjects are now added to the DOL List in the Os.
    //pMultiVaran-Interfaceversion must be equal or higher than 16#1003
    
    //Check interface version
    if b_PayloadSupport then
      if pMultiVaran then
        if pMultiVaran^.udVersion >= VM_MULTIVARAN_ADD_DO_INTO_DOL then
        // We have the new interface, set flag to remember it later
          bAddDOsToListSupport := TRUE;
        end_if;
      end_if;
    end_if;
    
    //read cycle time
    VaranTimeMultiplier := VaranTimeMultiplier.read();
    
    if b_PayloadSupport then
      // Payload DOs automatically use the client Timebase to set the Prescaler of the DOs
      TimeBase := VaranTimeMultiplier;
    end_if;

    if ( VaranTimeMultiplier = 0 ) then
      VaranTimeMultiplier := 1;
    end_if;

    //because on startup we need no waittime for bootloader
    us_AxisNumber := 1;
    
    //get varan time and calculate offset for sync
    ud_VaranTime := VaranIn.GetVaranTime( #ud_IsoStartPoint );
    sd_SyncOffset := ( ud_VaranTime - ud_IsoStartPoint )$DINT / 10;
    
    // check if there is a need to get the digital drive inputs
    TempFetchDigitalInputs := (FetchDigitalInputs.Read())$BOOL;
    if TempFetchDigitalInputs = 0 then
      // if not => show that the input information is not available
      Input1 :=
      Input2 := 
      Input3 :=
      Input4 := 
      Input5 := 
      Input6 := 
      Input7 :=
      Input8 := -1;
    end_if;
    
  elsif us_Firstscan = 2 then // 3rd init, because we need to wait with callback until our pCallBackServer is a valid pointer (done in 2nd init)
  
    //-----------------------------------------------------------------------------------------------
    //install Varantask
    VaranIn.AddVaranTask( ud_dol_type	:= VARAN_DOL_ISO
              , p_this		:= this
              , callOptions := CALL_OPTION_RT_PRESCAN OR CALL_OPTION_RT_POSTSCAN
              );
    VaranIn.AddVaranTask( ud_dol_type := VARAN_DOL_ASY
                        , p_this      := this 
                        );
              
		//-----------------------------------------------------------------------------------------------
		//call connect hardware function
		sd_retval := Varan_CallBack	( ud_reason	:= VARANMANAGER_CB_CONNECT
                                , ud_data	:= 0
                                );

		//produce Varan Error if module not ok
		if ( sd_retval <> VARANMANAGER_OK ) then

			VaranIn.SetVaranError( p_Node := p_VaranPosition );
		end_if;
  end_if;

	us_Firstscan += 1;
  
END_FUNCTION


FUNCTION VIRTUAL GLOBAL _VaranDriveBase::Varan_HwConnect
	VAR_INPUT
		ud_data 	: UDINT;
	END_VAR
	VAR_OUTPUT
		sd_retval 	: DINT;
	END_VAR
  VAR
  	i : UDINT;
  END_VAR

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

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

(*
	//look if it is right hardware
	if ((DeviceID <> VAC011_DEVICE_ID )
	&   (DeviceID <> VAC012_DEVICE_ID )
	&   (DeviceID <> VAC013_DEVICE_ID )
  &   (DeviceID <> DIASDRIVE_MINI_DEVICE_ID )
  &   (DeviceID <> DIASDRIVE_MAXI_DEVICE_ID )) then
		State := _WrongHardware;
		return;
  end_if;
*)
 
  //------------------------------------------------------------------------------------------------
	//we must wait because peripherie reset needs 15ms
	To_MultiTask.TASKDELAY( timeout0 := 15ms );	

  // initialize axis data
  for i := 0 to (DIASDRIVE_MAX_AXIS-1) do
    aAxisData[i].e_AxisState := _NotUsed;
  end_for;
  
  if (DeviceID = VAC011_DEVICE_ID ) |
     (DeviceID = VAC012_DEVICE_ID ) |
     (DeviceID = VAC013_DEVICE_ID ) then
    b_CompatibilityMode := TRUE;
  else
    b_CompatibilityMode := FALSE;
	end_if;
  
  // reset the write memory of all existing DOs
  // SDD300
  for i := 0 to (sizeof(aDataObjects)/sizeof(t_DOOneAxis))-1 do
    if aDataObjects[i].p_DataWrite then  
      _memset(dest:=aDataObjects[i].p_DataWrite, usByte:=0, cntr:=aDataObjects[i].p_DOSettings^.us_ByteCntWr);
    end_if;
  end_for;

  // MDD100
  for i := 0 to (sizeof(newIsoDOs)/sizeof(t_newISODO))-1 do
    if newIsoDOs[i].p_DataWrite then  
      _memset(dest:=newIsoDOs[i].p_DataWrite, usByte:=0, cntr:=newIsoDOs[i].p_DOSettings^.us_ByteCntWr);
    end_if;
  end_for;
  

  // if it's a new drive, check configuration => which axis are available
  if (b_CompatibilityMode = FALSE) then
  
    //set Pll data (set divider to get 62,5µs)
    //sd_retval := 
    SetNewPllData(ud_delay_time:=0, us_divider:= to_usint(ud_VaranTime / 62500) );
    if b_PayloadSupport then
      sd_retval := MULTI_VARAN_iExecuteDirectAccess(  hNodeHandle := ud_HandleModule
                                                    , udCommand   := VARAN_CMD_MEMORY_READ
                                                    , udOffset    := DIASDRIVE_ADR_SERVICE + 16#60
                                                    , udLength    := sizeof(AxisAvailableHW)
                                                    , pusData     := ( #AxisAvailableHW )$^USINT
                                                    , pudErrorInfo:= NIL); 
                                                    
            //look for an error
      if ( sd_retval <> VARANMANAGER_OK ) then
        State := _DirectAccessFailed;
        return;
      end_if;
                                                    
    else
      sd_retval := VARAN_iReadMemoryDA(   uiManager		  := ud_VaranManagerNr
                                        , uiAddress		  := DeviceAddress + DIASDRIVE_ADR_SERVICE + 16#60
                                        , uiLen			    := sizeof(AxisAvailableHW)
                                        , uiRetryTimeout:= GetRetryTimeout( ud_bytes := sizeof(AxisAvailableHW) )
                                        , pvData		    := ( #AxisAvailableHW )$^UDINT
                                        , puiError		  := NIL
                                        );
                                        
      //look for an error
      if ( sd_retval <> VARANMANAGER_OK ) then
        State := _DirectAccessFailed;
        return;
      end_if;
    end_if;
    
    // check hw-settings (highest bit is 1 in new version, where hw-configuration is detected)
    if AxisAvailableHW.32 then
      // we delete it, not needed for further use
      AxisAvailableHW.32 := 0;
    else
      AxisAvailableHW := 2#001001011011;  // for older firmware versions, where hw-configuration couldn't be detected
      //           PLACE:  (3)(2)(1)(0)
    end_if;
   
    e_RtSSW := InitAxis;

    // tell the drive handling class, which of the needed axis are really available
    if pCallBackServer then
      WR(pCallBackServer, AxisAvailableHW$DINT);
    end_if;    

  else

    //set Pll data
    sd_retval := SetPllData();

    // in old version there are maximal 3 axis possible, but we don't know how much we got yet
    AxisAvailableHW := 2#111;
    
    // we don't know how many axis are really available, we have to check parameter with drive info later
    CompAxisAvailableNo := 0;
    GetCompAxisSSW := 0;
    
    e_RtSSW := CompInitAxis;
  end_if;  

  // now we got a connection to the hardware and know which axis are available
  Online := 1;

	//if we are not in init 
	if ( us_Firstscan = 12 ) then
		us_AxisNumber := 0;
	end_if;

	//---------------------------------------------------------------------------------------------------------
	//class is not initialized
	ud_TimeCounter 	:= VaranTimeMultiplier;
	b_SyncEnabled 	:= FALSE;
	State			:= _NotInitialized;
	e_InitSSW 		:= _SetDataObjectOn;
	ud_TimemarkInit := ops.tAbsolute;
	sd_retval 		:= VARANMANAGER_OK;
  
  b_AlreadyConnected := FALSE;

END_FUNCTION


FUNCTION VIRTUAL GLOBAL _VaranDriveBase::Varan_HwInterrupt
	VAR_INPUT
		ud_reason 	: UDINT;
		ud_data 	: ^t_CallBackInterrupt;
	END_VAR
	VAR_OUTPUT
		sd_retval 	: DINT;
	END_VAR
  VAR
  	i : DINT;
  END_VAR

	b_InitOk			:= FALSE;
  b_SyncEnabled := FALSE;
  Online := 0;

	//look if Axis are in use
  for i := 0 to (DIASDRIVE_MAX_AXIS-1) do
    if ( aAxisData[i].e_AxisState <> _NotUsed ) then
      aAxisData[i].e_AxisState := _NoInit;
      aAxisData[i].b_ListActive := FALSE;
      aAxisData[i].us_ParaReady := _IdleState;
    end_if;
  end_for;

  SetDOsOff();

	//call function of base class
	sd_retval := Varan_Base::Varan_HwInterrupt	( ud_reason := ud_reason
                                              , ud_data 	:= ud_data
                                              );

END_FUNCTION


FUNCTION VIRTUAL GLOBAL _VaranDriveBase::Varan_HwDisconnect
	VAR_INPUT
		ud_data 	: UDINT;
	END_VAR
	VAR_OUTPUT
		sd_retval 	: DINT;
	END_VAR
  VAR
  	i : DINT;
  END_VAR

	b_InitOk			:= FALSE;
  b_SyncEnabled := FALSE;
  b_IsSDD21x      := FALSE;
  Online := 0;

	//look if Axis are in use
  for i := 0 to (DIASDRIVE_MAX_AXIS-1) do
    if ( aAxisData[i].e_AxisState <> _NotUsed ) then
      aAxisData[i].e_AxisState := _NoInit;
      aAxisData[i].b_ListActive := FALSE;
      aAxisData[i].us_ParaReady := _IdleState;
    end_if;
  end_for;
  
  SetDOsOff();
  
	//call function of base class
	sd_retval := Varan_Base::Varan_HwDisconnect( ud_data := ud_data );

END_FUNCTION


FUNCTION _VaranDriveBase::InitAxis
	VAR_INPUT
		us_AxisNo 	: USINT;
	END_VAR
	VAR_OUTPUT
		sd_retval 	: DINT;
	END_VAR
  VAR
    p_Axis			: ^t_AxisData;
    p_data_object	: ^t_DOOneAxis;
  END_VAR

	//we do this only if class is not initialized
	if ( State <> _NotInitialized ) then
		return;
	end_if;

	//------------------------------------------------------------------------------------------------
	//look which Axis we have and set pointers
//  if (us_AxisNo >= 0) & (us_AxisNo <= (AxisAvailableNo-1)) then
  if (us_AxisNo < DIASDRIVE_MAX_AXIS) & (aAxisData[us_AxisNo].e_AxisState <> _NotUsed) then
    p_Axis			:= #aAxisData[us_AxisNo];
    p_data_object	:= #aDataObjects[us_AxisNo];
  else
    //go to idle state
    sd_retval := _CyIdle;
    return;
  end_if;

	//------------------------------------------------------------------------------------------------
	//look which case we have
	case ( e_InitSSW ) of 

		//-----------------------------------------------------------------------------------------------
		_SetDataObjectOn:
					//is Axis in use
					if ( p_Axis^.e_AxisState <> _NotUsed ) then
            
            if b_PayloadSupport then
            
              if bAddDOsToListSupport then
                sd_retval := MULTI_VARAN_IINSERTDOINTODOL(p_data_object^.p_Handle$UDINT);             
              end_if;

              EnableDO(ud_DOHandle:= p_data_object^.p_Handle$UDINT);
            else
              // Payload DOs automatically use the client Timebase to set the Prescaler of the DOs
            //set right multiplier
              p_data_object^.p_Handle^.ucExePrescaler := VaranTimeMultiplier$USINT - 1;  
						//reset data object of Axis
						ResetDataObject	( p_handleDO	:= p_data_object^.p_Handle
                            , us_state		:= VARAN_DO_CONT_RUN
                            , ud_bytes		:= p_Axis^.ud_DOLength * 2
                            );
            end_if;                
(*
            if ( us_AxisNo = 3 & UseFastAxis ) then
              
              ResetDataObject	( p_handleDO	:= s_DataFastAxis.p_Handle
                              , us_state		:= VARAN_DO_CONT_RUN
                              , ud_bytes		:= sizeof( t_FastAxisRead ) + sizeof( t_FastAxisWrite )
                              );
              
              s_DataFastAxis.p_DataWrite^.us_TransmittExecution.EnableType2 := TRUE;
            end_if;
*)            
						//next step
						e_InitSSW := _SetInitAxis;
					
					else
						//go to idle state
						e_InitSSW := _CyIdle;
					end_if;

		//-----------------------------------------------------------------------------------------------
		_SetInitAxis:
					//InitAxis
					if ( p_Axis^.e_AxisState = _NoInit ) then

						p_data_object^.p_DataWrite^.us_TransmitExecution.StartObjectTransfer 	:= TRUE;
						p_data_object^.p_DataWrite^.us_DriveControl.InitCommunication 			:= TRUE;
					end_if;

					//next step and timestamp
					e_InitSSW 		:= _WaitInit;
					ud_TimemarkInit := ops.tAbsolute;

		//-----------------------------------------------------------------------------------------------
		_WaitInit:	//reset startobjecttransfer bit
					p_data_object^.p_DataWrite^.us_TransmitExecution.StartObjectTransfer 	:= FALSE;
					
					//look if Axis 1 must be init
					if ( p_Axis^.e_AxisState = _NoInit ) then
						
						//object must be executed, error in object handling must be set and error code must be 9
						if	( p_data_object^.p_DataRead^.us_ReceiveState.ExecutedObjectTransfer		= TRUE
							& p_data_object^.p_DataRead^.us_TransmitControl.ErrorInObjectHandling	= TRUE
							& p_data_object^.p_DataRead^.sd_ObjectValue 							= 9
							)
						then
							//set Axis to next state	
							p_Axis^.e_AxisState := _NoParaList;
							e_InitSSW := _SetFinishInit;
            //after timeout check again
            elsif ( ops.tAbsolute - ud_TimemarkInit > 1sec ) then
              e_InitSSW := _SetInitAxis;
            end_if;						
          //after timeout check again
					elsif ( ops.tAbsolute - ud_TimemarkInit > 1sec ) then
						e_InitSSW := _SetInitAxis;
					end_if;	


		//-----------------------------------------------------------------------------------------------
		_SetFinishInit:

					//If Axis is in right state
					if ( p_Axis^.e_AxisState = _NoParaList ) then

						p_data_object^.p_DataWrite^.us_TransmitExecution.StartObjectTransfer 	:= TRUE;
						p_data_object^.p_DataWrite^.us_DriveControl.InitCommunication 			:= FALSE;
					end_if;

					//next step and timestamp
					e_InitSSW 		:= _GetFinishInit;
					ud_TimemarkInit := ops.tAbsolute;

		//-----------------------------------------------------------------------------------------------
		_GetFinishInit:

					//look if Axis is in use and error bit is reset
					if	( p_data_object^.p_DataRead^.us_TransmitControl.ErrorInObjectHandling = FALSE) &
						  ( p_data_object^.p_DataRead^.us_ReceiveState.ExecutedObjectTransfer 	= TRUE )
					then
					//reset startobjecttransfer bit
            p_data_object^.p_DataWrite^.us_TransmitExecution.StartObjectTransfer 	:= FALSE;
											
						//final step, init ok and class ok
						e_InitSSW := _CyIdle;

					else
												
						//try again if return value is 10 or 8 (see DiasDrive Doku)
						if	( ( p_data_object^.p_DataRead^.sd_ObjectValue = 10 | p_data_object^.p_DataRead^.sd_ObjectValue = 8 )
							& p_data_object^.p_DataRead^.us_TransmitControl.ErrorInObjectHandling = TRUE
							) 
						then
							e_InitSSW 			:= _SetInitAxis;
							p_Axis^.e_AxisState := _NoInit;
						end_if;

						//if timeout check again
						if ( ops.tAbsolute - ud_TimemarkInit > 2sec ) then
							e_InitSSW := _SetFinishInit;
						end_if;	
					end_if;
					
		
		//-----------------------------------------------------------------------------------------------
		_CyIdle:	

	end_case;
  
	//return ssw
	sd_retval := e_InitSSW$DINT;

END_FUNCTION


FUNCTION VIRTUAL GLOBAL _VaranDriveBase::UpdateRt
  VAR
    sd_retval		: DINT;
    i           : UDINT;
    TempInputs  : BSINT;
  END_VAR
 
//=================================================================================================
#ifdef VM_CLASS_TIME_MEASUREMENT
	StartTimeMeasurement(VARANTIME_RT);
#endif
//=================================================================================================

	//update in right intervall
	ud_TimeCounter -= 1;
	if ( ud_TimeCounter <> 0 ) THEN
    b_UpdateThisTime := FALSE;
		return;
  else
    b_UpdateThisTime := TRUE;
	end_if;

	ud_TimeCounter := VaranTimeMultiplier;

	//call rt of base
	Varan_Base::UpdateRt();

  if Online then
    case e_RtSSW of
    
      //*****************************************************************************
      //**      Comp = compatibility mode to dias drive 300 series                 **
      //*****************************************************************************
      CompInitAxis:      
      
        //first enable sync of varan and drive
        if ( b_SyncEnabled = FALSE ) then
          sd_retval := EnableSyncOut	( us_sync_nr				:= 0
                                      , sd_offset					:= sd_SyncOffset
                                      , us_period_multiplier		:= VaranTimeMultiplier$USINT
                                      , us_frame_count_treshold	:= 0
                                      , us_enable_frame_count		:= 0
                                      , b_use_divider_sync := FALSE
                                      );

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

          sd_retval := EnableSyncOut	( us_sync_nr				:= 1
                                      , sd_offset					:= sd_SyncOffset MOD 6250
                                      , us_period_multiplier		:= 0
                                      , us_frame_count_treshold	:= 0
                                      , us_enable_frame_count		:= 0
                                      , b_use_divider_sync := TRUE
                                      );

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

          b_SyncEnabled := TRUE;
          return;
        end_if;
          
        if bAddDOsToListSupport = false then
          InstallDefaultDO();
        end_if;
      
        if b_AlreadyConnected = TRUE then        
          //*****************************************************************************
          //**  switch Axis                                                            **
          //*****************************************************************************
          case ( us_AxisNumber ) of
          
            // ***********************************************************************************************************************************
            0:	//we must wait 3 secs because in sdrive bootloader is active
                  if ( ops.tAbsolute - ud_TimemarkInit > 3secs ) then
                    us_AxisNumber += 1;
                  end_if;                
                
            // ***********************************************************************************************************************************
            1: 	//wait until first axis is initialized
                if InitAxis( us_AxisNo := 0 ) = _CyIdle$DINT then
                  us_AxisNumber 	+=1;
                  e_InitSSW 	:= _SetDataObjectOn;
                end_if;
              
            // ***********************************************************************************************************************************
            2: // we check how many axis are really available (parameter communication)
              //Check for DataInitFinished false too, because CompAxisAvailableNo is changed in step 1 so step 2 of the ssw would not be executed
              if CompAxisAvailableNo = 0 | DataInitFinished = FALSE  then
                case GetCompAxisSSW of
                
                  // ***********************************************************************************************************************************
                  0:
                    //set data for object handling
                    aAxisData[0].us_ParaReady := _SendExecution;
                    
                    aDataObjects[0].p_DataWrite^.us_ObjectAddress	:= 189;
                    aDataObjects[0].p_DataWrite^.sd_ObjectValue		:= 0;
                    aDataObjects[0].p_DataWrite^.us_DriveControl.ReadWriteObject := 0;

                    GetCompAxisSSW += 1;

                  // ***********************************************************************************************************************************
                  1:
                    //Axis "0" object value
                    GetObjectValue( us_Axis := 0 );
                    
                    //look if parameter handling is ready
                    if	( aAxisData[0].us_ParaReady	= _IdleState ) & 
                        ( aAxisData[0].b_ListActive	= FALSE)  &
                        ( aDataObjects[0].p_DataWrite^.us_ObjectAddress = 189) then
                      //look for an object handling error
                      if (aAxisData[0].sd_ObjectError = 0) then
                        sd_retval := GetParameter(us_axis:=0);
                        if sd_retval <> 120 then
                          CompAxisAvailableNo := GetDriveType(sd_retval);
                          if CompAxisAvailableNo > 0 then
                            AxisAvailableNo := CompAxisAvailableNo$USINT;                          
                          end_if;

                          // at SDD215 the middle axis is not available
                          if b_IsSDD21x then
                            aAxisData[1].e_AxisState := _NotUsed;
                          end_if;
                            
                          // tell the drive handling class, which of the needed axis are really available
                          if pCallBackServer then
                            WR(pCallBackServer, AxisAvailableHW$DINT);
                          end_if;    

                          DataInitFinished := FALSE;
                          GetCompAxisSSW += 1;

                        else
                          GetCompAxisSSW := 0;
                        end_if;
                      end_if;
                    end_if;
                  
                  // ***********************************************************************************************************************************
                  2:	//is done at cy task if bAddDOsToListSupport is true
                  
                    //Check if we can use the new interface and add DOs in UpdateCy
                    if bAddDOsToListSupport = false then
                      //We have the old interface, install DOs here
                      AddIsoDOsCompMode();
                    end_if;
                  
                end_case;
                
              else     

                if us_AxisNumber <= AxisAvailableNo then
                  if AxisAvailableHW AND (1 SHL (us_AxisNumber-1)$UDINT) then
                    if InitAxis( us_AxisNo := us_AxisNumber-1 ) = _CyIdle$DINT then
                      us_AxisNumber += 1;
                      e_InitSSW 	:= _SetDataObjectOn;
                    end_if;
                  else
                    us_AxisNumber += 1;
                  end_if;
                else
                  us_AxisNumber := DIASDRIVE_MAX_AXIS_300+1;
                end_if;
              end_if;          
                
            // ***********************************************************************************************************************************
            3..DIASDRIVE_MAX_AXIS_300:
              if us_AxisNumber <= AxisAvailableNo then
                if AxisAvailableHW AND (1 SHL (us_AxisNumber-1)$UDINT) then
                  if InitAxis( us_AxisNo := us_AxisNumber-1 ) = _CyIdle$DINT then
                    us_AxisNumber += 1;
                    e_InitSSW 	:= _SetDataObjectOn;
                  end_if;
                else
                  us_AxisNumber += 1;
                end_if;
              else
                us_AxisNumber := DIASDRIVE_MAX_AXIS_300+1;
              end_if;
      
            else
              //class is ready
              b_InitOk 	:= TRUE;
              us_AxisNumber 	:= 0;
              e_RtSSW := CompGetSendParaList;
        
          end_case;
          
        end_if;      
        

      // ******************************************************************************************************************************************
      CompGetSendParaList:
        
        // update asynchron parameters
        sd_retval := 0;
        if AxisAvailableNo then
          for i := 0 to (AxisAvailableNo-1) do
            // at SDD215 the middle axis is not available
            if aAxisData[i].e_AxisState <> _NotUsed then
              //Axis "i" object value
              GetObjectValue( us_Axis := to_usint(i) );
            end_if;          
          end_for;
        end_if;
        
      // we get into the next step via ExternInitFinished-Method
      // ******************************************************************************************************************************************

      CompWaitForSynchrony:
        if AxisAvailableNo & aDataObjects[0].p_DataRead^.us_TransmitControl.SyncLocked then
          // before we set state to operational we get the values 1 time otherwise online would be 1 but no actual values are available
          for i := 0 to (AxisAvailableNo-1) do
            if ( aAxisData[i].e_AxisState <> _NotUsed ) then
              aAxisData[i].e_AxisState := _AxisOk;

              //-----------------------------------------------------------------------------------------------
              // update asynchron parameters
              //Axis "i" object value
              GetObjectValue( us_Axis := to_usint(i) );
              //------------------------------------------------------------------------------------------------

              if aAxisData[i].b_ExtendedAxis then
                _memcpy(#aAxisData[i].s_ReadValues.a_SyncValues[ 0 ], #aDataObjects[i].p_DataRead^.sd_Value6, 5 * sizeof(DINT));
              else
                aAxisData[i].s_ReadValues.a_SyncValues[ 0 ] := aDataObjects[i].p_DataRead^.sd_Value6;
                aAxisData[i].s_ReadValues.a_SyncValues[ 1 ] := aDataObjects[i].p_DataRead^.sd_Value7;
                
              end_if;

              //look for CRC error
              if ( aDataObjects[i].p_DataRead^.us_ReceiveState.CRC_Error = TRUE ) then
                aAxisData[i].ud_CRCError += 1;
                CRC_ErrorCounter += 1;
              end_if;
            end_if;
          end_for;

          e_RtSSW := CompOperational;
          State 		:= _ClassOk;
        end_if;

      // ******************************************************************************************************************************************
      CompOperational:
        if AxisAvailableNo then
          Synchron := aDataObjects[0].p_DataRead^.us_TransmitControl.SyncLocked;
          if Synchron then
            for i := 0 to (AxisAvailableNo-1) do
              if ( aAxisData[i].e_AxisState <> _NotUsed ) then
                aAxisData[i].e_AxisState := _AxisOk;

                //-----------------------------------------------------------------------------------------------
                // update asynchron parameters
                //Axis "i" object value
                GetObjectValue( us_Axis := to_usint(i) );
                //------------------------------------------------------------------------------------------------

                if aAxisData[i].b_ExtendedAxis then
                  _memcpy(#aAxisData[i].s_ReadValues.a_SyncValues[ 0 ], #aDataObjects[i].p_DataRead^.sd_Value6, 5 * sizeof(DINT));
                else
                  aAxisData[i].s_ReadValues.a_SyncValues[ 0 ] := aDataObjects[i].p_DataRead^.sd_Value6;
                  aAxisData[i].s_ReadValues.a_SyncValues[ 1 ] := aDataObjects[i].p_DataRead^.sd_Value7;
                  
                end_if;

                //look for CRC error
                if ( aDataObjects[i].p_DataRead^.us_ReceiveState.CRC_Error = TRUE ) then
                  aAxisData[i].ud_CRCError += 1;
                  CRC_ErrorCounter += 1;
                end_if;
              end_if;
            end_for;
          else
            for i := 0 to (AxisAvailableNo-1) do
              if ( aAxisData[i].e_AxisState <> _NotUsed ) then
                aAxisData[i].e_AxisState := _NotSynchron;

                //-----------------------------------------------------------------------------------------------
                // update asynchron parameters
                //Axis "i" object value
                GetObjectValue( us_Axis := to_usint(i) );
                //------------------------------------------------------------------------------------------------

                if aAxisData[i].b_ExtendedAxis then
                  _memcpy(#aAxisData[i].s_ReadValues.a_SyncValues[ 0 ], #aDataObjects[i].p_DataRead^.sd_Value6, 5 * sizeof(DINT));
                else
                  aAxisData[i].s_ReadValues.a_SyncValues[ 0 ] := aDataObjects[i].p_DataRead^.sd_Value6;
                  aAxisData[i].s_ReadValues.a_SyncValues[ 1 ] := aDataObjects[i].p_DataRead^.sd_Value7;
                end_if;

                //look for CRC error
                if ( aDataObjects[i].p_DataRead^.us_ReceiveState.CRC_Error = TRUE ) then
                  aAxisData[i].ud_CRCError += 1;
                  CRC_ErrorCounter += 1;
                end_if;
              end_if;
            end_for;
          end_if;
        end_if;

      // ******************************************************************************************************************************************
      // now the part for DiasDrive 100/5000 series
      // ******************************************************************************************************************************************
      // ******************************************************************************************************************************************
      InitAxis:
        
        if bAddDOsToListSupport = false then
          AddIsoDOsNew();
        end_if;
                
        //Check if Hardware is already connected (DOs created)
        if b_AlreadyConnected & e_InitSSW = _SetDataObjectOn then
        
        //switch Axis        
          case ( us_AxisNumber ) of
          
            0:	//we must wait 3 secs because in sdrive bootloader is active
              if ( ops.tAbsolute - ud_TimemarkInit > 3secs ) then
                us_AxisNumber += 1;
              end_if;              
          
            1..DIASDRIVE_MAX_AXIS: 	//wait until Axis are initialized
              if us_AxisNumber <= AxisAvailableNo then
                if InitAxisNew( us_AxisNo := us_AxisNumber-1 ) = _CyIdle$DINT then
                  us_AxisNumber 	+=1;
                  e_InitSSW 	:= _SetDataObjectOn;
                end_if;
              else
                us_AxisNumber := DIASDRIVE_MAX_AXIS+1;
              end_if;

            else
              //class is ready
              b_InitOk 	:= TRUE;
              us_AxisNumber 	:= 0;
              e_RtSSW := GetSendParaList;
              
          end_case; 
        end_if;
        
      // ******************************************************************************************************************************************
      WaitForSynchrony:
      //#pragma message("Synchronität wird bei DiasDrive 100/5000 testweise noch nicht überprüft!")
      // evtl. asynchrones DO deaktivieren, wenn keine asynchronen Daten übertragen werden, 
      // kann aber erst mit finalem Mapping entschieden werden, da vielleicht noch IOs dazukommen
          
  //      if AxisAvailableNo & newAsyDO.p_DataRead^[0].us_TransmitControl.SyncLocked then
  
          // before we set state to operational we get the values 1 time otherwise online would be 1 but no actual values are available
          if AxisAvailableNo then
            Synchron := 1;//newAsyDO.p_DataRead^[0].us_TransmitControl.SyncLocked;
            if Synchron then
              for i := 0 to (AxisAvailableNo-1) do
                if ( aAxisData[i].e_AxisState <> _NotUsed ) then
                  aAxisData[i].e_AxisState := _AxisOk;

                  if aAxisData[i].b_ExtendedAxis then
                    _memcpy(#aAxisData[i].s_ReadValues.a_SyncValues[ 0 ], #newIsoDOs[i].p_DataRead^.Value6, sizeof(t_newReadDataOneAxis));
                  else
                    aAxisData[i].s_ReadValues.a_SyncValues[ 0 ] := newIsoDOs[i].p_DataRead^.Value6;
                    aAxisData[i].s_ReadValues.a_SyncValues[ 1 ] := newIsoDOs[i].p_DataRead^.Value7;
                  end_if;
                end_if;
              end_for;
            else
              for i := 0 to (AxisAvailableNo-1) do
                if ( aAxisData[i].e_AxisState <> _NotUsed ) then
                  aAxisData[i].e_AxisState := _NotSynchron;

                  if aAxisData[i].b_ExtendedAxis then
                    _memcpy(#aAxisData[i].s_ReadValues.a_SyncValues[ 0 ], #newIsoDOs[i].p_DataRead^.Value6, sizeof(t_newReadDataOneAxis));
                  else
                    aAxisData[i].s_ReadValues.a_SyncValues[ 0 ] := newIsoDOs[i].p_DataRead^.Value6;
                    aAxisData[i].s_ReadValues.a_SyncValues[ 1 ] := newIsoDOs[i].p_DataRead^.Value7;
                  end_if;            
                end_if;
              end_for;
            end_if;
          end_if;

          if TempFetchDigitalInputs then
            TempInputs := newDigInDO.p_DataRead^;
            Input1 := TempInputs.1;
            Input2 := TempInputs.2;
            Input3 := TempInputs.3;
            Input4 := TempInputs.4;
            Input5 := TempInputs.5;
            Input6 := TempInputs.6;
            Input7 := TempInputs.7;
            Input8 := TempInputs.8;
          end_if;
          
          e_RtSSW := Operational;
          State 		:= _ClassOk;
  //      end_if;
      
      // ******************************************************************************************************************************************
      Operational:

        if AxisAvailableNo then
          Synchron := 1;//newAsyDO.p_DataRead^[0].us_TransmitControl.SyncLocked;
          if Synchron then
            for i := 0 to (AxisAvailableNo-1) do
              if ( aAxisData[i].e_AxisState <> _NotUsed ) then
                aAxisData[i].e_AxisState := _AxisOk;

                if aAxisData[i].b_ExtendedAxis then
                  _memcpy(#aAxisData[i].s_ReadValues.a_SyncValues[ 0 ], #newIsoDOs[i].p_DataRead^.Value6, sizeof(t_newReadDataOneAxis));
                else
                  aAxisData[i].s_ReadValues.a_SyncValues[ 0 ] := newIsoDOs[i].p_DataRead^.Value6;
                  aAxisData[i].s_ReadValues.a_SyncValues[ 1 ] := newIsoDOs[i].p_DataRead^.Value7;
                end_if;
              end_if;
            end_for;
          else
            for i := 0 to (AxisAvailableNo-1) do
              if ( aAxisData[i].e_AxisState <> _NotUsed ) then
                aAxisData[i].e_AxisState := _NotSynchron;

                if aAxisData[i].b_ExtendedAxis then
                  _memcpy(#aAxisData[i].s_ReadValues.a_SyncValues[ 0 ], #newIsoDOs[i].p_DataRead^.Value6, sizeof(t_newReadDataOneAxis));
                else
                  aAxisData[i].s_ReadValues.a_SyncValues[ 0 ] := newIsoDOs[i].p_DataRead^.Value6;
                  aAxisData[i].s_ReadValues.a_SyncValues[ 1 ] := newIsoDOs[i].p_DataRead^.Value7;
                end_if;            
              end_if;
            end_for;
          end_if;
        end_if;

        if TempFetchDigitalInputs then
          TempInputs := newDigInDO.p_DataRead^;
          Input1 := TempInputs.1;
          Input2 := TempInputs.2;
          Input3 := TempInputs.3;
          Input4 := TempInputs.4;
          Input5 := TempInputs.5;
          Input6 := TempInputs.6;
          Input7 := TempInputs.7;
          Input8 := TempInputs.8;
        end_if;

    end_case;
  end_if;
(*
    if ( UseFastAxis ) then
      s_DataFastAxis.p_DataWrite^.sd_Value3 := Axis3_Speed;
      
      //activate DO if deactivated
      if ( b_FastDODeactivate ) then
        b_FastDODeactivate := FALSE;
        s_DataFastAxis.p_DataWrite^.us_TransmittExecution.DirectAccess := FALSE;
        
        ResetDataObject ( p_handleDO  := s_DataFastAxis.p_Handle
                        , us_state    := VARAN_DO_CONT_RUN
                        , ud_bytes    := sizeof( t_FastAxisRead ) + sizeof( t_FastAxisWrite )
                        );
      end_if;
      
    else
*) 

//=================================================================================================
#ifdef VM_CLASS_TIME_MEASUREMENT
	StopTimeMeasurement(VARANTIME_RT);
#endif
//=================================================================================================
END_FUNCTION



FUNCTION _VaranDriveBase::GetObjectValue
	VAR_INPUT
		us_Axis 	: USINT;
	END_VAR
  VAR
    p_Axis			: ^t_AxisData;
    p_DataObject	: ^t_DOOneAxis;
  END_VAR

	//------------------------------------------------------------------------------------------------
	//look which Axis we have and set pointers
//  if (us_Axis >= 0) & (us_Axis <= (AxisAvailableNo-1)) then
  if (us_Axis < DIASDRIVE_MAX_AXIS) & (aAxisData[us_Axis].e_AxisState <> _NotUsed) then
    p_Axis			:= #aAxisData[us_Axis];
    p_DataObject	:= #aDataObjects[us_Axis];
  else
    //else do nothing (should not come here)
    return;
  end_if;
	
	//------------------------------------------------------------------------------------------------
	//get to right step
	case ( p_Axis^.us_ParaReady ) of

		_SendExecution:		//send transmit execution request for object handling
							p_DataObject^.p_DataWrite^.us_TransmitExecution.StartObjectTransfer := TRUE;
							
//              p_Axis^.b_OldToggleState := p_DataObject^.p_DataRead^.us_TransmitControl.ToggleBit;
              
              p_DataObject^.p_DataWrite^.us_DriveControl.ToggleBit := NOT p_DataObject^.p_DataWrite^.us_DriveControl.ToggleBit;
              
							//reset error and go to next step
							p_Axis^.sd_ObjectError := 0;
							p_Axis^.us_ParaReady := _ResetExecution;

		_ResetExecution:	//reset transmit execution request bit
              
              if (p_DataObject^.p_DataRead^.us_ReceiveState.ExecutedObjectTransfer = FALSE) then
                p_DataObject^.p_DataWrite^.us_TransmitExecution.StartObjectTransfer := FALSE;
                p_Axis^.us_ParaReady := _Wait4Response;		              
              end_if;
		
		_Wait4Response:		//wait until receive state is true
							if ( p_DataObject^.p_DataRead^.us_ReceiveState.ExecutedObjectTransfer = TRUE ) then// &
                 //( p_DataObject^.p_DataRead^.us_TransmitControl.ToggleBit <> p_Axis^.b_OldToggleState) then

								//look if we have a parameter list
								if ( p_Axis^.b_ListActive = TRUE ) then
									
                  // skip all defined parameter entries
                  SkipEntries(us_Axis, p_Axis);
                  
									//have we set all parameter
									if ( p_Axis^.ui_ParaListCnt ) then
										
										//set data to object handling registers
										p_DataObject^.p_DataWrite^.us_ObjectAddress					:= p_Axis^.p_ParaList^.us_number;
										p_DataObject^.p_DataWrite^.sd_ObjectValue					:= p_Axis^.p_ParaList^.sd_value;
										p_DataObject^.p_DataWrite^.us_DriveControl.ReadWriteObject	:= TRUE;

										//set next parameter step and set pointer to next parameter data
										p_Axis^.us_ParaReady 	:= _SendExecution;
										p_Axis^.ui_ParaListCnt 	-= 1;
										p_Axis^.p_ParaList 		+= sizeof( t_ParaList );

									else
										//set ssw to idle and deactivate parameter list
										p_Axis^.b_ListActive 	:= FALSE;
										
										//look if we get a parameter list
										if ( p_Axis^.e_AxisState = _NoParaList ) then 
											p_Axis^.e_AxisState		:= _NotSynchron;
										end_if;

										p_Axis^.us_ParaReady 	:= _IdleState;

									end_if;

								else
									//get to idle step
									p_Axis^.us_ParaReady := _IdleState;
									
									//look for an object error
									if ( p_DataObject^.p_DataRead^.us_TransmitControl.ErrorInObjectHandling = TRUE ) then
										p_Axis^.sd_ObjectError := p_DataObject^.p_DataRead^.sd_ObjectValue;
									else
                 		p_Axis^.sd_Asyncdata := p_DataObject^.p_DataRead^.sd_ObjectValue;
                  end_if;
										
								end_if;
							end_if;	
		
		_IdleState:				//do nothing in this step

	end_case;

END_FUNCTION


FUNCTION GLOBAL _VaranDriveBase::SetParameter
	VAR_INPUT
		us_Axis 	: USINT;
		us_para_nr 	: USINT;
		us_rdwr 	: USINT;
		sd_para_value 	: DINT;
	END_VAR
	VAR_OUTPUT
		sd_retval 	: DINT;
	END_VAR
  VAR
    p_Axis			: ^t_AxisData;
    p_data_object	: ^t_DOOneAxis;
    p_Write     : ^t_newASYWrite;
  END_VAR

	sd_retval := -1;

	//look if class is ok
	if ( State <> _ClassOk ) & ( GetDriveIntState()$t_RtSSW <> CompGetSendParaList ) then
		return;
	end_if;

	//look if init was ok
	if ( b_InitOk ) then
	
    // if it's a SDD300 model
    if b_CompatibilityMode then

      //------------------------------------------------------------------------------------------------
      //look which Axis we have and set pointers
//      if (us_Axis >= 0) & (us_Axis <= (AxisAvailableNo-1)) then
      if (us_Axis < DIASDRIVE_MAX_AXIS) & (aAxisData[us_Axis].e_AxisState <> _NotUsed) then
        p_Axis			:= #aAxisData[us_Axis];
        p_data_object	:= #aDataObjects[us_Axis];
      else
        sd_retval := -2;
        return;
      end_if;

      //----------------------------------------------------------------------------------------------
      //look if Axis is in use
      if ( p_Axis^.e_AxisState = _NotUsed ) then
        sd_retval := -3;
        return;
      end_if;

      //look if parameter handling is ready
      if	( p_Axis^.us_ParaReady = _IdleState
        & p_Axis^.b_ListActive = FALSE
        )
      then
    
        //set data for object handling
        p_Axis^.us_ParaReady := _GotValueForExecution;
//        p_data_object^.AsyDataTemp := aDataObjects[us_Axis].p_DataWrite^;
        p_data_object^.AsyDataTemp.us_ObjectAddress	:= us_para_nr;
        p_data_object^.AsyDataTemp.sd_ObjectValue		:= sd_para_value;
        
        if ( us_RdWr ) then
          p_data_object^.AsyDataTemp.us_DriveControl.ReadWriteObject := 1;
        else
          p_data_object^.AsyDataTemp.us_DriveControl.ReadWriteObject := 0;
        end_if;
        
        p_data_object^.b_NewAsyDataTemp := TRUE;
        
        sd_retval := 0;
      end_if;
    else
    // if it's a SDD100/5000 model

      //------------------------------------------------------------------------------------------------
      //look which Axis we have and set pointers
//      if (us_Axis >= 0) & (us_Axis <= (AxisAvailableNo-1)) then
      if (us_Axis < DIASDRIVE_MAX_AXIS) & (aAxisData[us_Axis].e_AxisState <> _NotUsed) then
        p_Axis			:= #aAxisData[us_Axis];
        p_Write := #newAsyDO.AsyDataTemp[us_Axis];
      else
        sd_retval := -2;
        return;
      end_if;

      //----------------------------------------------------------------------------------------------
      //look if Axis is in use
      if ( p_Axis^.e_AxisState = _NotUsed ) then
        sd_retval := -3;
        return;
      end_if;

      //look if parameter handling is ready
      if	( p_Axis^.us_ParaReady = _IdleState
        & p_Axis^.b_ListActive = FALSE
        )
      then
    
        //set data for object handling
        p_Axis^.us_ParaReady := _GotValueForExecution;
        p_Write^ := newAsyDO.p_DataWrite^[us_Axis];
        p_Write^.us_ObjectAddress	:= us_para_nr;
        p_Write^.sd_ObjectValue		:= sd_para_value;
        
        if ( us_RdWr ) then
          p_Write^.us_DriveControl.ReadWriteObject := 1;
        else
          p_Write^.us_DriveControl.ReadWriteObject := 0;
        end_if;
        
        newAsyDO.b_NewAsyDataTemp[us_Axis] := TRUE;
        
        sd_retval := 0;
      end_if;
    end_if;
	end_if;

END_FUNCTION


FUNCTION GLOBAL _VaranDriveBase::GetParameterState
	VAR_INPUT
		us_Axis 	: USINT;
	END_VAR
	VAR_OUTPUT
		sd_para_state 	: DINT;
	END_VAR
  VAR
    p_Axis			: ^t_AxisData;
  END_VAR
  
	sd_para_state := -1;

	//look if class is ok
	if ( State <> _ClassOk ) & ( GetDriveIntState()$t_RtSSW <> CompGetSendParaList ) then
		return;
	end_if;

	//look if init was ok
	if ( b_InitOk ) then

		//------------------------------------------------------------------------------------------------
    //look which Axis we have and set pointers
//    if (us_Axis >= 0) & (us_Axis <= (AxisAvailableNo-1)) then
  if (us_Axis < DIASDRIVE_MAX_AXIS) & (aAxisData[us_Axis].e_AxisState <> _NotUsed) then
      p_Axis			:= #aAxisData[us_Axis];
    else
			sd_para_state := -2;
      return;
    end_if;

		//----------------------------------------------------------------------------------------------
		//look if Axis is in use
		if ( p_Axis^.e_AxisState = _NotUsed ) then
			sd_para_state := -3;
			return;
		end_if;
		
		//look if parameter handling is ready
		if	( p_Axis^.us_ParaReady	= _IdleState 
			& p_Axis^.b_ListActive	= FALSE
			) 
		then
			//look for an object handling error
      if (p_Axis^.sd_ObjectError = 0) then
        sd_para_state := 0;
      else
        sd_para_state := p_Axis^.sd_ObjectError;
      end_if;
		end_if;
	end_if;
      
END_FUNCTION


FUNCTION GLOBAL _VaranDriveBase::GetParameter
	VAR_INPUT
		us_Axis 	: USINT;
	END_VAR
	VAR_OUTPUT
		sd_para_data 	: DINT;
	END_VAR
  
	//get last object value of right Axis
//  if (us_Axis >= 0) & (us_Axis <= (AxisAvailableNo-1)) then
  if (us_Axis < DIASDRIVE_MAX_AXIS) & (aAxisData[us_Axis].e_AxisState <> _NotUsed) then
    sd_para_data := aAxisData[us_Axis].sd_Asyncdata;
  else
    sd_para_data := -1;
  end_if;

END_FUNCTION


FUNCTION GLOBAL _VaranDriveBase::SetParaList
	VAR_INPUT
		us_Axis 	: USINT;
		p_list 	: ^void;
		ui_counter 	: UINT;
	END_VAR
	VAR_OUTPUT
		sd_retval 	: DINT;
	END_VAR
  VAR
    p_Axis			: ^t_AxisData;
  END_VAR

	sd_retval := -1;

	//look if class is ok
	if ( State = _ClassOk ) | ( GetDriveIntState()$t_RtSSW = CompGetSendParaList ) then
   
    // if it's a SDD300 model
    if b_CompatibilityMode then
      //------------------------------------------------------------------------------------------------
      //look which Axis we have and set pointers
//      if (us_Axis >= 0) & (us_Axis <= (AxisAvailableNo-1)) then
      if (us_Axis < DIASDRIVE_MAX_AXIS) & (aAxisData[us_Axis].e_AxisState <> _NotUsed) then
        p_Axis        := #aAxisData[us_Axis];
      else
        sd_retval := -2;
        return;
      end_if;

      //-----------------------------------------------------------------------------------------------
      //look if Axis is in use
      if ( p_Axis^.e_AxisState = _NotUsed ) then
        sd_retval := -3;
        return;
      end_if;

      //-----------------------------------------------------------------------------------------------
      //look if we are in init or we can do it in realtime task

      //mark function as ok
      sd_retval := 0;

      //look if parameter handling is ready and list processing is active
      if	( p_Axis^.us_ParaReady = _IdleState
        & p_Axis^.b_ListActive = FALSE
        )
      then
        p_Axis^.p_ParaList$^void	:= p_list;
        p_Axis^.ui_ParaListCnt		:= ui_counter;
        
        // skip all defined parameter entries
        SkipEntries(us_Axis, p_Axis);

        //take over first parameter
        if ( p_Axis^.ui_ParaListCnt ) then
          IF SetParameter(us_Axis, p_Axis^.p_ParaList^.us_number, 1, p_Axis^.p_ParaList^.sd_value) = 0 THEN
            p_Axis^.b_ListActive		:= TRUE;
          p_Axis^.ui_ParaListCnt 	-= 1;
          p_Axis^.p_ParaList 		+= sizeof( t_ParaList );
          END_IF;
        end_if;

      else
        //not ready
        sd_retval := -1;
      end_if;
    else
    // if it's a SDD100/5000 model

      //------------------------------------------------------------------------------------------------
      //look which Axis we have and set pointers
//      if (us_Axis >= 0) & (us_Axis <= (AxisAvailableNo-1)) then
      if (us_Axis < DIASDRIVE_MAX_AXIS) & (aAxisData[us_Axis].e_AxisState <> _NotUsed) then
        p_Axis  := #aAxisData[us_Axis];
      else
        sd_retval := -2;
        return;
      end_if;

      //-----------------------------------------------------------------------------------------------
      //look if Axis is in use
      if ( p_Axis^.e_AxisState = _NotUsed ) then
        sd_retval := -3;
        return;
      end_if;

      //-----------------------------------------------------------------------------------------------
      //look if we are in init or we can do it in realtime task

      //mark function as ok
      sd_retval := 0;

      //look if parameter handling is ready and list processing is active
      if	( p_Axis^.us_ParaReady = _IdleState
        & p_Axis^.b_ListActive = FALSE
        )
      then
        p_Axis^.p_ParaList$^void	:= p_list;
        p_Axis^.ui_ParaListCnt		:= ui_counter;
        
        // skip all defined parameter entries
        SkipEntries(us_Axis, p_Axis);

        //take over first parameter
        if ( p_Axis^.ui_ParaListCnt ) then
          IF SetParameter(us_Axis, p_Axis^.p_ParaList^.us_number, 1, p_Axis^.p_ParaList^.sd_value) = 0 THEN
            p_Axis^.b_ListActive		:= TRUE;
          p_Axis^.ui_ParaListCnt 	-= 1;
          p_Axis^.p_ParaList 		+= sizeof( t_ParaList );
          END_IF;
        end_if;

      else
        //not ready
        sd_retval := -1;
      end_if;
    end_if;
  else
    //not ready
    sd_retval := -1;
  end_if;

END_FUNCTION


FUNCTION GLOBAL _VaranDriveBase::GetSyncParameter
	VAR_INPUT
		us_Axis 	: USINT;
		us_value 	: USINT;
		p_data 	: ^DINT;
	END_VAR
	VAR_OUTPUT
		sd_retval 	: DINT;
	END_VAR
  VAR
    p_Axis_data		: ^t_AxisData;
    sd_extend		: DINT;
  END_VAR	

	//only if class is ok
	if ( State = _ClassOk ) then
    sd_retval := 0;

		//look for right value
		if ( us_value > 4 ) then
			sd_retval := -2;
			return;
		end_if;

    //look which Axis we have and set pointers
//    if (us_Axis >= 0) & (us_Axis <= (AxisAvailableNo-1)) then
    if (us_Axis < DIASDRIVE_MAX_AXIS) & (aAxisData[us_Axis].e_AxisState <> _NotUsed) then
      p_Axis_data			:= #aAxisData[us_Axis];
    else
      sd_retval := -3;
      return;
    end_if;

    sd_extend	:= aAxisData[us_Axis].b_ExtendedAxis;
		
		//only if Axis is ok
		if ( p_Axis_data^.e_AxisState = _AxisOk ) then

			//look if we have a extended value and extend mode is active else return
			if	( sd_extend	= 0 ) &
			    ( us_value  > 1 ) then

				sd_retval := -4;
				return;
			end_if;

			p_data^ := p_Axis_data^.s_ReadValues.a_SyncValues[ us_value ];	
		end_if;				
	else
		sd_retval := -1;
	end_if;

END_FUNCTION 


FUNCTION GLOBAL _VaranDriveBase::SetSyncParameter
	VAR_INPUT
		us_Axis 	: USINT;
		us_value 	: USINT;
		sd_data 	: DINT;
	END_VAR
	VAR_OUTPUT
		sd_retval 	: DINT;
	END_VAR
  VAR
    p_Axis_data		: ^t_AxisData;
    sd_extend		: DINT;
  END_VAR	

	//only if class is ok
	if ( State = _ClassOk ) then
    sd_retval := 0;

		//look for right value
		if ( us_value > 4 ) then
			sd_retval := -2;
			return;
		end_if;

    //look which Axis we have and set pointers
//    if (us_Axis >= 0) & (us_Axis <= (AxisAvailableNo-1)) then
    if (us_Axis < DIASDRIVE_MAX_AXIS) & (aAxisData[us_Axis].e_AxisState <> _NotUsed) then
      p_Axis_data			:= #aAxisData[us_Axis];
    else
      sd_retval := -3;
      return;
    end_if;

  	sd_extend	:= aAxisData[us_Axis].b_ExtendedAxis;

		//only if Axis is ok
		if ( p_Axis_data^.e_AxisState = _AxisOk ) then

			//look if we have a extended value and extend mode is active else return
			if	( sd_extend	= 0 
				& us_value 	> 1
				) 
			then

				sd_data := -4;
				return;
			end_if;
									
			p_Axis_data^.s_WriteValues.a_SyncValues[ us_value ] := sd_data;
		end_if;				
	else
		sd_retval := -1;
	end_if;

END_FUNCTION


FUNCTION GLOBAL _VaranDriveBase::InitDrive
  VAR
    i : UDINT;
  END_VAR

	if ( b_InitOk ) then

		State := _NotInitialized;
		
    for i := 0 to (AxisAvailableNo-1) do
      if ( aAxisData[i].e_AxisState <> _NotUsed ) then
        aAxisData[i].e_AxisState := _NoInit;
      end_if;
      
      aAxisData[i].us_ParaReady := _IdleState;
    end_for;

		b_InitOk := 0;
    e_InitSSW:= _SetDataObjectOn;
    if b_CompatibilityMode = TRUE then
      e_RtSSW := CompInitAxis;
    else
      e_RtSSW := InitAxis;
    end_if;
	end_if;

END_FUNCTION


FUNCTION VIRTUAL GLOBAL _VaranDriveBase::SetDOsOff
  VAR
  	i : UDINT;
  END_VAR

  if AxisAvailableNo then
    // SDD300 model
    if b_CompatibilityMode then
      
      //disable data objects if Axis are used
      for i := 0 to (AxisAvailableNo-1) do        
        if ( aAxisData[i].e_AxisState <> _NotUsed ) then
          DisableDO(ud_DOHandle:=aDataObjects[i].p_Handle$UDINT);
        end_if;    
      end_for;
    else
    // SDD100/5000 model
      //disable data objects if Axis are used
      for i := 0 to (AxisAvailableNo-1) do
        if ( aAxisData[i].e_AxisState <> _NotUsed ) then
        DisableDO(ud_DOHandle:=newIsoDOs[i].p_Handle$UDINT);
        end_if;    
      end_for;
      DisableDO(ud_DOHandle:=newAsyDO.p_Handle$UDINT);  
    end_if;
  end_if;
  
  if newDigInDO.p_Handle then
    DisableDO(ud_DOHandle:=newDigInDO.p_Handle$UDINT);
  end_if;

(*
  //Fast Axis
  if ( UseFastAxis ) then
    s_DataFastAxis.p_Handle^.ucCtrlStat := VARAN_DO_NO_RUN;
  end_if;
*)
END_FUNCTION 


FUNCTION VIRTUAL GLOBAL _VaranDriveBase::UpdateRetryCounter
  VAR
  	i : UDINT;
    tempRetryCounter : USINT;
  END_VAR

  // SDD300 model
  if b_CompatibilityMode then
    if CreatedCompDOs then
      //look for data object Axis
      if AxisAvailableNo then
        for i := 0 to (AxisAvailableNo-1) do
          if ( aAxisData[i].e_AxisState <> _NotUsed ) then
            tempRetryCounter := GetRetryCounter(ud_DOHandle := aDataObjects[i].p_Handle$UDINT);
            if ( tempRetryCounter <> aDataObjects[i].us_OldRetryCounter ) then
              RetryCounter += TO_USINT( tempRetryCounter - aDataObjects[i].us_OldRetryCounter );
              aDataObjects[i].us_OldRetryCounter := tempRetryCounter;
            end_if;
          end_if;  
        end_for;
      end_if;
    end_if;
  else 
    if CreatedNewIsoDOs then
    // SDD100/5000 model
      //look for data object Axis
      if AxisAvailableNo then
        for i := 0 to (AxisAvailableNo-1) do
          if ( aAxisData[i].e_AxisState <> _NotUsed ) then
            tempRetryCounter := GetRetryCounter(ud_DOHandle := newIsoDOs[i].p_Handle$UDINT);
            if ( tempRetryCounter <> newIsoDOs[i].us_OldRetryCounter ) then
              RetryCounter += TO_USINT( tempRetryCounter - newIsoDOs[i].us_OldRetryCounter );
              newIsoDOs[i].us_OldRetryCounter := tempRetryCounter;
            end_if;
          end_if;  
        end_for;
      end_if;
      
      tempRetryCounter := GetRetryCounter(ud_DOHandle := newDigInDO.p_Handle$UDINT);
      if ( TempFetchDigitalInputs & (tempRetryCounter <> newDigInDO.us_OldRetryCounter) ) then
        RetryCounter += TO_USINT( tempRetryCounter - newDigInDO.us_OldRetryCounter );
        newDigInDO.us_OldRetryCounter := tempRetryCounter;
      end_if;
    end_if;
    
    if CreatedNewAsyDOs then
      tempRetryCounter := GetRetryCounter(ud_DOHandle := newAsyDO.p_Handle$UDINT);
      if ( tempRetryCounter <> newAsyDO.us_OldRetryCounter ) then
        RetryCounter += TO_USINT( tempRetryCounter - newAsyDO.us_OldRetryCounter );
        newAsyDO.us_OldRetryCounter := tempRetryCounter;
      end_if;
    end_if;
  end_if;

(*
  //Fast Axis 
  if ( UseFastAxis ) then
    if ( s_DataFastAxis.p_Handle^.ucRetryCounter <> s_DataFastAxis.us_OldRetryCounter ) then
      RetryCounter += TO_USINT( s_DataFastAxis.p_Handle^.ucRetryCounter - s_DataFastAxis.us_OldRetryCounter );
      s_DataFastAxis.us_OldRetryCounter := s_DataFastAxis.p_Handle^.ucRetryCounter;
    end_if;
  end_if;
*)
  
END_FUNCTION 

#pragma warning(disable:73)
FUNCTION GLOBAL _VaranDriveBase::SetAxisOn
	VAR_INPUT
		ud_Axis 	: BDINT;
	END_VAR
#pragma warning(default:73 )

(*
	//is Axis 1 in use
	if ( ud_Axis.1 ) then
		s_Axis1Data.e_AxisState := _NoInit;
	else
		s_Axis1Data.e_AxisState := _NotUsed;
//		Axis1_Enable.write( 0 );
//		Axis1_ControlWord.DriveEnable := FALSE;

//		s_Axis1Data.s_WriteValues.a_SyncValues[ 0 ] := ( ( Axis1_ControlWord$DINT shl 16 ) or ( Axis1_SetCurrent and 16#FFFF ) )$DINT;
		s_DataObjectA1.p_DataWrite^.sd_Value1 := s_Axis1Data.s_WriteValues.a_SyncValues[ 0 ];

		s_DataObjectA1.p_Handle^.ucCtrlStat := VARAN_DO_SINGLE_RUN;
	end_if;

	//is Axis 2 in use
	if ( ud_Axis.2 ) then
		s_Axis2Data.e_AxisState := _NoInit;
	else
		s_Axis2Data.e_AxisState := _NotUsed;
//		Axis2_Enable.write( 0 );
//		Axis2_ControlWord.DriveEnable := FALSE;

//		s_Axis2Data.s_WriteValues.a_SyncValues[ 0 ] := ( ( Axis2_ControlWord$DINT shl 16 ) or ( Axis2_SetCurrent and 16#FFFF ) )$DINT;
		s_DataObjectA2.p_DataWrite^.sd_Value1 := s_Axis2Data.s_WriteValues.a_SyncValues[ 0 ];

		s_DataObjectA2.p_Handle^.ucCtrlStat := VARAN_DO_SINGLE_RUN;
	end_if;

	//is Axis 3 in use
	if ( ud_Axis.3 ) then
		s_Axis3Data.e_AxisState := _NoInit;
	else
		s_Axis3Data.e_AxisState := _NotUsed;
//		Axis3_Enable.write( 0 );
//		Axis3_ControlWord.DriveEnable := FALSE;

//		s_Axis3Data.s_WriteValues.a_SyncValues[ 0 ] := ( ( Axis3_ControlWord$DINT shl 16 ) or ( Axis3_SetCurrent and 16#FFFF ) )$DINT;
		s_DataObjectA3.p_DataWrite^.sd_Value1 := s_Axis3Data.s_WriteValues.a_SyncValues[ 0 ];

		s_DataObjectA3.p_Handle^.ucCtrlStat := VARAN_DO_SINGLE_RUN;
	end_if;
*)

(*
	b_InitOk := TRUE;

	InitDrive();
*)
END_FUNCTION 


FUNCTION VIRTUAL GLOBAL _VaranDriveBase::State::NewInst
	VAR_INPUT
		pPara 	: ^CmdStruct;
		pResult 	: ^results;
	END_VAR
	VAR_OUTPUT
		ret_code 	: iprStates;
	END_VAR
  VAR  	  
  	pStr_HWTRequested : ^CHAR;
    us_HWTRequestedCurrIndex : USINT;
  END_VAR
  
  pStr_HWTRequested := NIL;
  us_HWTRequestedCurrIndex := 0;

  ret_code:= READY;

	case ( pPara^.uiCmd ) of
		0 : SetAxisOn( pPara^.aPara[ 0 ]$BDINT );
    
    1 : // list with parameternumbers to skip
    
        // check if index in range (0-7)
        //if (pPara^.aPara[2] >= 0) & (pPara^.aPara[2] <= (AxisAvailableNo-1)) then         
        if (pPara^.aPara[2] < DIASDRIVE_MAX_AXIS) & (aAxisData[pPara^.aPara[2]].e_AxisState <> _NotUsed) then
          s_SkipParameter[pPara^.aPara[2]].us_No    := to_usint(pPara^.aPara[1]); // number of values in memory
          s_SkipParameter[pPara^.aPara[2]].p_Values := (pPara^.aPara[0])$^USINT; // pointer on memory
        end_if;
    
    CMD_GET_HARDWARE_DIAGNOSIS :     
        
        ret_code := ERROR;
        pStr_HWTRequested := pPara^.aPara[0]$t_HWCGetHardwareTreeEntryIn.pStr_LastHardewareTreeEntry;
        
        if pStr_HWTRequested & p_ObjectPath then
          // Needed as default for 
          ret_code := READY;

          if (pStr_HWTRequested$^USINT^ = p_ObjectPath^) then // Check if the call was to the Mng
            // Call base 1st as it as info from SPI accesses
            ret_code := Varan_Base::State.NewInst(pPara, pResult);  // Pass on command to base         
          end_if;        
            
          if (p_DriveMngBase) then
             
            // Call Mng, may overwrite some data, has got at least additional info on the FW version                    
            ret_code := p_DriveMngBase$^VirtualBase^.NewInst(pPara,pResult);          
            
          end_if; 
        end_if;

    CMD_GET_HARDWARE_TREE_ENTRY :          
        
        ret_code := ERROR;
        
        pStr_HWTRequested := pPara^.aPara[0]$t_HWCGetHardwareTreeEntryIn.pStr_LastHardewareTreeEntry;      
        
        // Check HWT String
        if pStr_HWTRequested & p_ObjectPath then      
          
          // Check if the passed string is smaller than the own string
          if pStr_HWTRequested$^USINT^ < p_ObjectPath^ then        
        
            // Call base
            ret_code := Varan_Base::State.NewInst(pPara, pResult);  // Pass on command to base 
          
          // Check if last call was to Base itself
          // Compare string content
          elsif _memcmp( ptr1 := pStr_HWTRequested + 2, 
                         ptr2 := p_ObjectPath + 1, 
                         cntr := p_ObjectPath^) = 0 then
                              
            // Compare string length
            if (pStr_HWTRequested$^USINT^ = p_ObjectPath^) then
          
              // Last module called was the Drivemng itself, next module is the 1st axis behind the manager          
              if (p_DriveMngBase) then
              
                ret_code := p_DriveMngBase$^VirtualBase^.NewInst(pPara, pResult); // Pass on command to drive manager
                
              end_if;
            
            elsif (pStr_HWTRequested$^USINT^ > p_ObjectPath^ + 1) then // Must be at least 2 Bytey larger, ESCAPE Sequence + Place
              
              // Check escape sequence
              if ( (pStr_HWTRequested + (p_ObjectPath^) + 2 )^ = HWT_ESCAPE_DRIVE) then // First place after manager Itself is escape sequence + 1 for addional length byte
                // Last Module must have been a Axis Module behind the manager
                // Update index
                pPara^.aPara[0]$t_HWCGetHardwareTreeEntryIn.us_current_index  := p_ObjectPath^ + 3; // Second place after manager Itself is place + 1 for addional length byte
                pPara^.aPara[0]$t_HWCGetHardwareTreeEntryIn.us_current_length := pStr_HWTRequested^ - p_ObjectPath^ - 1;
                
                if (p_DriveMngBase) then
              
                  ret_code := p_DriveMngBase$^VirtualBase^.NewInst(pPara, pResult); // Pass on command to drive manager
                
                end_if;
              
              else // Length not equal and no Escape sequence, = VARAN Module behind CTMS was called 1.st
                
                ret_code := Varan_Base::State.NewInst(pPara, pResult);  // Pass on command to base
              end_if;
            
            else  // Requested string length > this string length, _memcmp failed => Last string was from a differet Varan Port
            
              ret_code := Varan_Base::State.NewInst(pPara, pResult);  // Pass on command to base
            end_if;
            
          else
            ret_code := Varan_Base::State.NewInst(pPara, pResult);  // Pass on command to base            
          end_if;
          
        else
          // pStr_HWTRequested is probably nil, pass on command to base
          ret_code := Varan_Base::State.NewInst(pPara, pResult);  // Pass on command to base            
        end_if;      
        
	  else
      //Pass on command to base
      ret_code := Varan_Base::State.NewInst(pPara:=pPara, pResult:=pResult);
	end_case;

END_FUNCTION 


FUNCTION _VaranDriveBase::SkipEntries
	VAR_INPUT
		us_Axis 	: USINT;
		p_Axis 	: ^t_AxisData;
	END_VAR
  VAR
  	i         : UDINT;
    p_ActPara : ^USINT;
    b_ParaOK  : BOOL;
  END_VAR

  // if there are parameters to skip
  if s_SkipParameter[us_Axis].us_No > 0 then
    b_ParaOK := FALSE;
    
    // as long as the parameter is skipped and we have have still parameters in the list
    while (b_ParaOK = FALSE) & (p_Axis^.ui_ParaListCnt) do
      // set pointer on first value to skip
      p_ActPara := s_SkipParameter[us_Axis].p_Values;
      
      b_ParaOK := TRUE;
      
      // for all skip parameters
      for i := 0 to (s_SkipParameter[us_Axis].us_No - 1) do
        // if the actual parameter number is found in the skip parameter list
        if p_ActPara^ = p_Axis^.p_ParaList^.us_number then
          p_Axis^.ui_ParaListCnt 	-= 1;
          p_Axis^.p_ParaList 		  += sizeof( t_ParaList );
          
          b_ParaOK := FALSE;
          exit;
        end_if;
      
        p_ActPara += sizeof(USINT);
      end_for;
    end_while;
  end_if;

END_FUNCTION


FUNCTION GLOBAL _VaranDriveBase::StartCommunication
	VAR_INPUT
		AxisExtend 	: BDINT;
		AxisFast 	: BDINT;
		pServer4CallBack 	: ^BDINT;
	END_VAR

  ExtendedAxisSettings := AxisExtend;
  FastAxisSettings := AxisFast;

  pCallBackServer := pServer4CallBack - sizeof(SvrCh.pMeth);

END_FUNCTION


FUNCTION GLOBAL _VaranDriveBase::GetAxisRdPtr
	VAR_INPUT
		AxisNr 	: DINT;
	END_VAR
	VAR_OUTPUT
		pReadPara 	: ^t_ReadValuePtr;
	END_VAR

  pReadPara := NIL;

  //look which Axis we have
//  if (AxisNr >= 0) & (AxisNr <= (AxisAvailableNo-1)) then
  if (AxisNr < DIASDRIVE_MAX_AXIS) & (aAxisData[AxisNr].e_AxisState <> _NotUsed) then
    pReadPara := #aAxisData[AxisNr].s_ReadValues;
  end_if;

END_FUNCTION


FUNCTION GLOBAL _VaranDriveBase::GetAxisWrPtr
	VAR_INPUT
		AxisNr 	: DINT;
	END_VAR
	VAR_OUTPUT
		pWritePara 	: ^t_WriteValuePtr;
	END_VAR

  pWritePara := NIL;

  //look which Axis we have
//  if (AxisNr >= 0) & (AxisNr <= (AxisAvailableNo-1)) then
  if (AxisNr < DIASDRIVE_MAX_AXIS) & (aAxisData[AxisNr].e_AxisState <> _NotUsed) then
    pWritePara := #aAxisData[AxisNr].s_WriteValues;
  end_if;

END_FUNCTION


FUNCTION GLOBAL _VaranDriveBase::GetDriveIntState
	VAR_OUTPUT
		retcode 	: DINT;
	END_VAR
  
  // to get the actual state of the rtwork state machine
  // retcode = 3 means Operational (MOD 4 is for model SDD100/5000 to have the same returncodes)
  retcode := e_RtSSW$DINT MOD 4;
 
END_FUNCTION


FUNCTION _VaranDriveBase::GetObjectValueNew
	VAR_INPUT
		us_Axis 	: USINT;
	END_VAR
  VAR
    p_Axis			: ^t_AxisData;
    p_Write     : ^t_newASYWrite;
    p_Read      : ^t_newASYRead;
  END_VAR

	//------------------------------------------------------------------------------------------------
	//look which Axis we have and set pointers
//  if (us_Axis >= 0) & (us_Axis <= (AxisAvailableNo-1)) then
  if (us_Axis < DIASDRIVE_MAX_AXIS) & (aAxisData[us_Axis].e_AxisState <> _NotUsed) then
    p_Axis	:= #aAxisData[us_Axis];
    p_Read 	:= newAsyDO.p_DataRead + us_Axis * sizeof(t_newASYRead);
    p_Write	:= newAsyDO.p_DataWrite + us_Axis * sizeof(t_newASYWrite);
  else
    //else do nothing (should not come her)
    return;
  end_if;

	//------------------------------------------------------------------------------------------------
	//get to right step
	case ( p_Axis^.us_ParaReady ) of

		_SendExecution: // we wait 1 cycle to ensure that the request is written to the Drive (what object number we want to read or write)
							p_Axis^.us_ParaReady := _ResetExecution;
              
    _ResetExecution:// now toggle the togglebit to start tell the drive, that the data are complete (no chance for byte errors in this way)
              
              //send transmit execution request for object handling
							p_Axis^.b_OldToggleState := p_Read^.us_TransmitControl.ToggleBit;

              // toggle toggle bit
              p_Write^.us_DriveControl.ToggleBit := NOT p_Read^.us_TransmitControl.ToggleBit;

							//reset error and go to next step
							p_Axis^.sd_ObjectError := 0;
							p_Axis^.us_ParaReady := _Wait4Response;
		
		_Wait4Response:		//wait until receive state is true
							if ( p_Read^.us_TransmitControl.ToggleBit <> p_Axis^.b_OldToggleState) then

								//look if we have a parameter list
								if ( p_Axis^.b_ListActive = TRUE ) then
									
                  // skip all defined parameter entries
                  SkipEntries(us_Axis, p_Axis);
                  
									//have we set all parameter
									if ( p_Axis^.ui_ParaListCnt ) then
										
										//set data to object handling registers
										p_Write^.us_ObjectAddress					        := p_Axis^.p_ParaList^.us_number;
										p_Write^.sd_ObjectValue					          := p_Axis^.p_ParaList^.sd_value;
										p_Write^.us_DriveControl.ReadWriteObject	:= TRUE;

										//set next parameter step and set pointer to next parameter data
										p_Axis^.us_ParaReady 	:= _SendExecution;
										p_Axis^.ui_ParaListCnt 	-= 1;
										p_Axis^.p_ParaList 		+= sizeof( t_ParaList );

									else
										//set ssw to idle and deactivate parameter list
										p_Axis^.b_ListActive 	:= FALSE;
										
										//look if we get a parameter list
										if ( p_Axis^.e_AxisState = _NoParaList ) then 
											p_Axis^.e_AxisState		:= _NotSynchron;
										end_if;

										p_Axis^.us_ParaReady 	:= _IdleState;

									end_if;

								else
									//get to idle step
									p_Axis^.us_ParaReady := _IdleState;
									
									//look for an object error
									if ( p_Read^.us_TransmitControl.ErrorInObjectHandling = TRUE ) then
										p_Axis^.sd_ObjectError := p_Read^.sd_ObjectValue;
									else
                 		p_Axis^.sd_Asyncdata := p_Read^.sd_ObjectValue;
                  end_if;
										
								end_if;
							end_if;	
		
		_IdleState:				//do nothing in this step

	end_case;

END_FUNCTION


FUNCTION _VaranDriveBase::InitAxisNew
	VAR_INPUT
		us_AxisNo 	: USINT;
	END_VAR
	VAR_OUTPUT
		sd_retval 	: DINT;
	END_VAR
  VAR
    p_Axis			: ^t_AxisData;
    p_Write     : ^t_newASYWrite;
    p_Read      : ^t_newASYRead;
    p_data_object : ^t_newISODO;
  END_VAR

	//we do this only if class is not initialized
	if ( State <> _NotInitialized ) then
		return;
	end_if;

	//------------------------------------------------------------------------------------------------
	//look which Axis we have and set pointers
//  if (us_AxisNo >= 0) & (us_AxisNo <= (AxisAvailableNo-1)) then
  if (us_AxisNo < DIASDRIVE_MAX_AXIS) & (aAxisData[us_AxisNo].e_AxisState <> _NotUsed) then
    p_Axis			:= #aAxisData[us_AxisNo];
    p_data_object	:= #newIsoDOs[us_AxisNo];
    p_Read 	:= newAsyDO.p_DataRead + us_AxisNo * sizeof(t_newASYRead);
    p_Write	:= newAsyDO.p_DataWrite + us_AxisNo * sizeof(t_newASYWrite);
  else
    sd_retval := -2;
    return;
  end_if;

	//------------------------------------------------------------------------------------------------
	//look which case we have
	case ( e_InitSSW ) of 

		//-----------------------------------------------------------------------------------------------
		_SetDataObjectOn:
					//is Axis in use
					if ( p_Axis^.e_AxisState <> _NotUsed ) then

//Revision 1.20 start     
            _memset(p_data_object^.p_DataWrite, 16#00, p_Axis^.ud_DOLength); // reinit the memory before sending
//Revision 1.20 end
            
						//reset data object of Axis
            if b_PayloadSupport then
              if bAddDOsToListSupport then
                sd_retval := MULTI_VARAN_IINSERTDOINTODOL(p_data_object^.p_Handle$UDINT);
              end_if;
              EnableDO(ud_DOHandle:=p_data_object^.p_Handle$UDINT);
            else
                // Payload DOs automatically use the client Timebase to set the Prescaler of the DOs
              //set right multiplier
              p_data_object^.p_Handle^.ucExePrescaler := VaranTimeMultiplier$USINT - 1;
                
              ResetDataObject	( p_handleDO	:= p_data_object^.p_Handle
                              , us_state		:= VARAN_DO_CONT_RUN
                                , ud_bytes		:= p_Axis^.ud_DOLength * 2);
            end_if;                
(*
            if ( us_AxisNo = 3 & UseFastAxis ) then
              
              ResetDataObject	( p_handleDO	:= s_DataFastAxis.p_Handle
                              , us_state		:= VARAN_DO_CONT_RUN
                              , ud_bytes		:= sizeof( t_FastAxisRead ) + sizeof( t_FastAxisWrite )
                              );
              
              s_DataFastAxis.p_DataWrite^.us_TransmittExecution.EnableType2 := TRUE;
            end_if;
*)            
						//next step
						e_InitSSW := _SetInitAxis;
					
					else
						//go to idle state
						e_InitSSW := _CyIdle;
					end_if;

		//-----------------------------------------------------------------------------------------------
		_SetInitAxis:
					//InitAxis
					if ( p_Axis^.e_AxisState = _NoInit ) then

						p_Write^.us_DriveControl.InitCommunication 			:= TRUE;
            
					end_if;
          
          p_Axis^.b_OldToggleState := p_Read^.us_TransmitControl.ToggleBit;

          // toggle toggle bit
          p_Write^.us_DriveControl.ToggleBit := NOT p_Read^.us_TransmitControl.ToggleBit;

					//next step and timestamp
					e_InitSSW 		:= _WaitInit;
					ud_TimemarkInit := ops.tAbsolute;

		//-----------------------------------------------------------------------------------------------
		_WaitInit:	//reset startobjecttransfer bit
					
					//look if Axis 1 must be init
					if ( p_Axis^.e_AxisState = _NoInit ) then
						
						//object must be executed, error in object handling must be set and error code must be 9
						if (( p_Read^.us_TransmitControl.ToggleBit <> p_Axis^.b_OldToggleState)
                & p_Read^.us_TransmitControl.ErrorInObjectHandling	= TRUE
                & p_Read^.sd_ObjectValue 							= 9
                )
						then
							//set Axis to next state	
							p_Axis^.e_AxisState := _NoParaList;
							e_InitSSW := _SetFinishInit;
            
            //after timeout check again
            elsif ( ops.tAbsolute - ud_TimemarkInit > 1sec ) then
              e_InitSSW := _SetInitAxis;
            end_if;	
            
					//after timeout check again
					elsif ( ops.tAbsolute - ud_TimemarkInit > 1sec ) then
						e_InitSSW := _SetInitAxis;
					end_if;	


		//-----------------------------------------------------------------------------------------------
		_SetFinishInit:

					//If Axis is in right state
					if ( p_Axis^.e_AxisState = _NoParaList ) then

						p_Write^.us_DriveControl.InitCommunication 			:= FALSE;
					end_if;

          p_Axis^.b_OldToggleState := p_Read^.us_TransmitControl.ToggleBit;

          // toggle toggle bit
          p_Write^.us_DriveControl.ToggleBit := NOT p_Read^.us_TransmitControl.ToggleBit;

					//next step and timestamp
					e_InitSSW 		:= _GetFinishInit;
					ud_TimemarkInit := ops.tAbsolute;

		//-----------------------------------------------------------------------------------------------
		_GetFinishInit:

					//look if Axis is in use and error bit is reset
					if	( p_Read^.us_TransmitControl.ErrorInObjectHandling = FALSE) &
						  ( p_Read^.us_TransmitControl.ToggleBit <> p_Axis^.b_OldToggleState)
					then
					//reset startobjecttransfer bit
											
						//final step, init ok and class ok
						e_InitSSW := _CyIdle;

					else
												
						//try again if return value is 10 or 8 (see DiasDrive Doku)
						if	( ( p_Read^.sd_ObjectValue = 10 | p_Read^.sd_ObjectValue = 8 )
							& p_Read^.us_TransmitControl.ErrorInObjectHandling = TRUE
							) 
						then
							e_InitSSW 			:= _SetInitAxis;
							p_Axis^.e_AxisState := _NoInit;
						end_if;

						//if timeout check again
						if ( ops.tAbsolute - ud_TimemarkInit > 2sec ) then
							e_InitSSW := _SetFinishInit;
						end_if;	
					end_if;
					
		
		//-----------------------------------------------------------------------------------------------
		_CyIdle:	

	end_case;
  
	//return ssw
	sd_retval := e_InitSSW$DINT;

END_FUNCTION


FUNCTION GLOBAL _VaranDriveBase::ExternInitFinished

  // if all axis parameters have been sent
  if b_CompatibilityMode then
    e_RtSSW := CompWaitForSynchrony;
  else
    e_RtSSW := WaitForSynchrony;
  end_if;
    
END_FUNCTION


FUNCTION _VaranDriveBase::GetDriveType
	VAR_INPUT
		HWCode 	: DINT;
	END_VAR
  VAR_OUTPUT
    AxisNo  : SINT;
  END_VAR
  VAR
  	DriveType : DINT;
  END_VAR
  
  DriveType := HWCode SHR 16;
  
  case DriveType of
  
  // 3 Axis **************************************************************************
    0..4, 6, 12, 16, 20, 26:
      AxisNo := 3;
      AxisAvailableHW := 2#111;
   
   
  // 2 Axis **************************************************************************
    5, 9:// SDD215 and SDD210 special case
      AxisNo := 3; // we need to simulate 3 axis, because of the skipped axis
      AxisAvailableHW := 2#101;
      if ExtendedAxisSettings.2 = TRUE then
        ExtendedAxisSettings.2 := FALSE;
        ExtendedAxisSettings.3 := TRUE;
      end_if;
      if FastAxisSettings.2 = TRUE then
        FastAxisSettings.2 := FALSE;
        FastAxisSettings.3 := TRUE;
      end_if;

      b_IsSDD21x := TRUE;

    22:// SDD205 normal case
      AxisNo := 2;
      AxisAvailableHW := 2#11;
    
   
  // 1 Axis **************************************************************************
    7, 21, 10:
      AxisNo := 1;  
      AxisAvailableHW := 2#1;
  else
    AxisNo := -1;
  end_case;

END_FUNCTION


FUNCTION VIRTUAL GLOBAL _VaranDriveBase::UpdateRtPostScan
  VAR
    i           : UDINT;
  END_VAR

//=================================================================================================
#ifdef VM_CLASS_TIME_MEASUREMENT
	StartTimeMeasurement(VARANTIME_RTPOSTSCAN);
#endif
//=================================================================================================
  
  IF Online & b_CompatibilityMode & AxisAvailableNo THEN
    FOR i := 0 TO (AxisAvailableNo-1) DO
      IF aDataObjects[i].b_NewAsyDataTemp & aDataObjects[i].p_DataWrite THEN
        aAxisData[i].us_ParaReady := _SendExecution;
        
//        _memcpy(  ptr1:= aDataObjects[i].p_DataWrite
//                , ptr2:= #aDataObjects[i].AsyDataTemp
//                , cntr:= aAxisData[i].ud_DOLength
//                );
        aDataObjects[i].p_DataWrite^.us_ObjectAddress := aDataObjects[i].AsyDataTemp.us_ObjectAddress;
        aDataObjects[i].p_DataWrite^.sd_ObjectValue := aDataObjects[i].AsyDataTemp.sd_ObjectValue;
        aDataObjects[i].p_DataWrite^.us_DriveControl.ReadWriteObject := aDataObjects[i].AsyDataTemp.us_DriveControl.ReadWriteObject;
        
        // aDataObjects[i].p_DataWrite^ := aDataObjects[i].AsyDataTemp;
        
        aDataObjects[i].b_NewAsyDataTemp := FALSE;
        EXIT;
      END_IF;
    END_FOR;
  END_IF;
  
  if b_UpdateThisTime then
    
    if Online then
      case e_RtSSW of
      
        // Comp = compatibility mode to dias drive 300 series
      
        // ******************************************************************************************************************************************
        
        CompOperational:

          if AxisAvailableNo then
            for i := 0 to (AxisAvailableNo-1) do
              if ( aAxisData[i].e_AxisState <> _NotUsed ) then
                if aAxisData[i].b_ExtendedAxis then
                  _memcpy(#aDataObjects[i].p_DataWrite^.sd_Value1, #aAxisData[i].s_WriteValues.a_SyncValues[ 0 ], 5 * sizeof(DINT));
                else
                  aDataObjects[i].p_DataWrite^.sd_Value1 := aAxisData[i].s_WriteValues.a_SyncValues[ 0 ];
                  aDataObjects[i].p_DataWrite^.sd_Value2 := aAxisData[i].s_WriteValues.a_SyncValues[ 1 ];
                end_if;
              end_if;
            end_for;
          end_if;

        // ******************************************************************************************************************************************
        // now the part for DiasDrive 100/5000 series

        Operational:

          if AxisAvailableNo then
            for i := 0 to (AxisAvailableNo-1) do
              if ( aAxisData[i].e_AxisState <> _NotUsed ) then
                if aAxisData[i].b_ExtendedAxis then
                  _memcpy(#newIsoDOs[i].p_DataWrite^.Value1, #aAxisData[i].s_WriteValues.a_SyncValues[ 0 ], sizeof(t_newReadDataOneAxis));
                else
                  newIsoDOs[i].p_DataWrite^.Value1 := aAxisData[i].s_WriteValues.a_SyncValues[ 0 ];
                  newIsoDOs[i].p_DataWrite^.Value2 := aAxisData[i].s_WriteValues.a_SyncValues[ 1 ];
                end_if;
              end_if;
            end_for;
          end_if;

      end_case;
    end_if;
  end_if;

//=================================================================================================
#ifdef VM_CLASS_TIME_MEASUREMENT
	StopTimeMeasurement(VARANTIME_RTPOSTSCAN);
#endif
//=================================================================================================

END_FUNCTION


FUNCTION GLOBAL _VaranDriveBase::GetSeries
	VAR_OUTPUT
		retcode 	: USINT;
	END_VAR
  
  if b_CompatibilityMode = TRUE then
    retcode := 0;
  else
    retcode := 1;
  end_if;

END_FUNCTION


FUNCTION GLOBAL _VaranDriveBase::IsSDD21x
	VAR_OUTPUT
		retcode 	: BOOL;
	END_VAR

  retcode := b_IsSDD21x;

END_FUNCTION


FUNCTION VIRTUAL GLOBAL _VaranDriveBase::CheckDeviceID
	VAR_INPUT
		ID2Check 	: UDINT;
	END_VAR
	VAR_OUTPUT
		IsOK 	: BOOL;
	END_VAR

	//look if it is right hardware
	if ((ID2Check <> VAC011_DEVICE_ID )
	&   (ID2Check <> VAC012_DEVICE_ID )
	&   (ID2Check <> VAC013_DEVICE_ID )
  &   (ID2Check <> DIASDRIVE_MINI_DEVICE_ID )
  &   (ID2Check <> DIASDRIVE_MAXI_DEVICE_ID )) then
		IsOK := FALSE;
  else
    IsOK := TRUE;
  end_if;
  
END_FUNCTION


FUNCTION VIRTUAL GLOBAL _VaranDriveBase::UpdateCy
VAR
	i : UDINT;
  sd_retval : DINT;
END_VAR

//=================================================================================================
#ifdef VM_CLASS_TIME_MEASUREMENT
	StartTimeMeasurement(VARANTIME_CY);
#endif
//=================================================================================================

  IF Online THEN
    IF b_CompatibilityMode = FALSE then
      if AxisAvailableNo THEN
        CASE e_RtSSW OF
          // ******************************************************************************************************************************************
          InitAxis, GetSendParaList, Operational, WaitForSynchrony:
            FOR i := 0 TO (AxisAvailableNo-1) DO
              IF newAsyDO.b_NewAsyDataTemp[i] & newAsyDO.p_DataWrite THEN
                aAxisData[i].us_ParaReady := _SendExecution; 
                newAsyDO.p_DataWrite^[i] := newAsyDO.AsyDataTemp[i];
                newAsyDO.b_NewAsyDataTemp[i] := FALSE;
                EXIT;
              END_IF;
            END_FOR;
        END_CASE;
      end_if;
      
      case e_RtSSW of 
        // ******************************************************************************************************************************************
        // now the part for DiasDrive 100/5000 series
        // ******************************************************************************************************************************************
        // ******************************************************************************************************************************************
        InitAxis:
          if bAddDOsToListSupport then
            AddIsoDOsNew();          
          end_if;
          
          // ******************************************************************************************************************************************
          // enable sync of varan and drive for DiasDrive 100/5000 series
          // ******************************************************************************************************************************************        
          if ( b_SyncEnabled = FALSE) 
          & AxisAvailableNo then
            if CreatedNewAsyDOs = FALSE then
              if b_PayloadSupport then
                sd_retval := AddRdWrPayloadDO(  ud_dol_type     :=  VARAN_DOL_ASY
                                              , p_ud_handle     := ( #newAsyDO.p_Handle )$^UDINT
                                              , ud_offset_read  :=  DIASDRIVE_ADR_SERVICE + DIASDRIVE_ADR_SERVICE_READ
                                              , ud_length_read  := AxisAvailableNo * sizeof(t_newASYRead)
                                              , p_ud_data_read  := ( #newAsyDO.p_DataRead )$^UDINT
                                              , ud_offset_write := DIASDRIVE_ADR_SERVICE + DIASDRIVE_ADR_SERVICE_WRITE
                                              , ud_length_write := AxisAvailableNo * sizeof(t_newASYWrite)
                                              , p_ud_data_write := ( #newAsyDO.p_DataWrite )$^UDINT
                                              , ud_type         := VM_MEMORY_ACCESS);

              
                //look if an error occurs
                if ( sd_retval <> VARANMANAGER_OK ) then
                  State := _CreateDOFailed;
                  return;
                end_if;
              else
                // create 1 general ASY RdWrDO with variable size (depending on number of available axis)
                sd_retval := VaranIn.AddRdWrDO	( p_us_position_info:= p_VaranPosition
                                , ud_dol_type		:= VARAN_DOL_ASY
                                , p_ud_handle		:= ( #newAsyDO.p_Handle )$^UDINT
                                , ud_address_read	:= 0
                                , ud_length_read	:= AxisAvailableNo * sizeof(t_newASYRead)
                                , p_ud_data_read	:= ( #newAsyDO.p_DataRead )$^UDINT
                                , ud_address_write	:= 0
                                , ud_length_write	:= AxisAvailableNo * sizeof(t_newASYWrite)
                                , p_ud_data_write	:= ( #newAsyDO.p_DataWrite )$^UDINT
                                , ud_type			:= VM_MEMORY_ACCESS
                                );

                //look if an error occurs
                if ( sd_retval <> VARANMANAGER_OK ) then
                  State := _CreateDOFailed;
                  return;
                end_if;
                
                //get address pointer to change address of access
                newAsyDO.p_DOSettings := (newAsyDO.p_DataWrite)$^t_VaranDOSettingsRdWr - VM_DO_OFFSET_RDWR;
              end_if;
              CreatedNewAsyDOs := TRUE;
            end_if;
            
            if b_PayloadSupport then
              EnableDO(ud_DOHandle:=newAsyDO.p_Handle$UDINT);
            else
              //correct access address
              newAsyDO.p_DOSettings^.ud_AddressRd := DeviceAddress + DIASDRIVE_ADR_SERVICE + DIASDRIVE_ADR_SERVICE_READ;
              newAsyDO.p_DOSettings^.ud_AddressWr := DeviceAddress + DIASDRIVE_ADR_SERVICE + DIASDRIVE_ADR_SERVICE_WRITE;
              
              //reset data object of Axis
              ResetDataObject	( p_handleDO	:= newAsyDO.p_Handle
                              , us_state		:= VARAN_DO_CONT_RUN
                              , ud_bytes		:= AxisAvailableNo * sizeof(t_newASYRead) + AxisAvailableNo * sizeof(t_newASYWrite)
                              );
            end_if;

            sd_retval := EnableSyncOut	( us_sync_nr				:= 0
                                        , sd_offset					:= sd_SyncOffset
                                        , us_period_multiplier		:= VaranTimeMultiplier$USINT
                                        , us_frame_count_treshold	:= 0
                                        , us_enable_frame_count		:= 0
                                        , b_use_divider_sync := FALSE
                                        );

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

            sd_retval := EnableSyncOut	( us_sync_nr				:= 1
                                        , sd_offset					:= sd_SyncOffset MOD 6250
                                        , us_period_multiplier		:= 0
                                        , us_frame_count_treshold	:= 0
                                        , us_enable_frame_count		:= 0
                                        , b_use_divider_sync := TRUE
                                        );

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

            b_SyncEnabled := TRUE;
            return;
          end_if;

          //switch Axis
          if e_InitSSW <> _SetDataObjectOn then
            case ( us_AxisNumber ) of

              1..DIASDRIVE_MAX_AXIS: 	//wait until Axis are initialized
                if us_AxisNumber <= AxisAvailableNo then
                  if InitAxisNew( us_AxisNo := us_AxisNumber-1 ) = _CyIdle$DINT then
                    us_AxisNumber 	+=1;
                    e_InitSSW 	:= _SetDataObjectOn;
                  end_if;
                else
                  us_AxisNumber := DIASDRIVE_MAX_AXIS+1;
                end_if;
            end_case;
          end_if;

        // ******************************************************************************************************************************************
        GetSendParaList, Operational:
          // update asynchron parameters
          if AxisAvailableNo then
            for i := 0 to (AxisAvailableNo-1) do
              //Axis "i" object value
              GetObjectValueNew( us_Axis := to_usint(i) ); 
            end_for;
          end_if;
      end_case;
      
    ELSE  //b_CompatibilityMode = TRUE
      case e_RtSSW of       
        //*****************************************************************************
        //**      Comp = compatibility mode to dias drive 300 series                 **
        //***************************************************************************** 
        CompInitAxis:
          
          if bAddDOsToListSupport then
            InstallDefaultDO();
          end_if;
            
          if b_AlreadyConnected = TRUE then 
        
            //*****************************************************************************
            //**  switch Axis                                                            **
            //*****************************************************************************
            case ( us_AxisNumber ) of
            
              // ***********************************************************************************************************************************
              0:	//is done at rt task
            
              // ***********************************************************************************************************************************
              1: 	//wait until first axis is initialized
              // must be done at realtime task          
       
              // ***********************************************************************************************************************************
              2: // we check how many axis are really available (parameter communication)
                case GetCompAxisSSW of
                  // ***********************************************************************************************************************************
                  0: //is done at rt-task
                  
                  // ***********************************************************************************************************************************
                  1: //is done at rt-task
                  
                  // ***********************************************************************************************************************************
                  2:  
                    //Check if we can use the new interface and add DOs in UpdateCy
                    if bAddDOsToListSupport then
                      //Do nothing, DOs are installed in UpdateCy
                      //We have the old interface, install DOs here
                      AddIsoDOsCompMode();
                    end_if;
                    
                end_case;
            end_case;   
          end_if;
      end_case;
    END_IF;    
  END_IF;

//=================================================================================================
#ifdef VM_CLASS_TIME_MEASUREMENT
	StopTimeMeasurement(VARANTIME_CY);
#endif
//=================================================================================================
  
END_FUNCTION


FUNCTION GLOBAL _VaranDriveBase::SetObjectCallBack
	VAR_INPUT
		p_DriveMngBaseNew 	: ^void;
	END_VAR
  
  p_DriveMngBase := p_DriveMngBaseNew;
  
END_FUNCTION



FUNCTION _VaranDriveBase::AddIsoDOsCompMode
VAR
	i : UDINT;
  sd_retval : DINT;
  tmp_dol_Type: UDINT;
END_VAR

  // if we got more than 1 axis and the last axis has no VARAN handle yet
  if (AxisAvailableNo > 1) & (DataInitFinished = FALSE) then
    if (aDataObjects[AxisAvailableNo-1].p_Handle = NIL) then

      for i := 1 to AxisAvailableNo-1 do  

        if AxisAvailableHW AND (1 SHL i$UDINT) then
                  
          //set right data object length
          if (1 SHL i$UDINT) AND ExtendedAxisSettings then
            aAxisData[i].ud_DOLength := sizeof(t_DataReadOneAxis);
            aAxisData[i].b_ExtendedAxis := TRUE;
          else
            aAxisData[i].ud_DOLength := sizeof(t_DataReadOneAxis) - 3 * sizeof(DINT);
            aAxisData[i].b_ExtendedAxis := FALSE;
          end_if;

          // check for fastaxis
          if (1 SHL i$UDINT) AND FastAxisSettings then
            aAxisData[i].b_FastAxis := TRUE;
          else
            aAxisData[i].b_FastAxis := FALSE;
          end_if;

          //install data object                   
          if b_PayloadSupport then
          
            tmp_dol_type := VARAN_DOL_ISO;
            
            if bAddDOsToListSupport then
              tmp_dol_Type := tmp_dol_Type OR VARAN_DOL_NOT_INSERT_DO_INTO_DOL;
            end_if;
          
            sd_retval := AddRdWrPayloadDO(  ud_dol_type     := tmp_dol_type
                                          , p_ud_handle     := ( #aDataObjects[ i ].p_Handle )$^UDINT
                                          , ud_offset_read  := i$UDINT*DIASDRIVE_OFFSET_Axis + DIASDRIVE_OFFSET_AxisRead
                                          , ud_length_read  := aAxisData[i].ud_DOLength
                                          , p_ud_data_read  := ( #aDataObjects[ i ].p_DataRead )$^UDINT
                                          , ud_offset_write := i$UDINT*DIASDRIVE_OFFSET_Axis
                                          , ud_length_write := aAxisData[i].ud_DOLength
                                          , p_ud_data_write := ( #aDataObjects[ i ].p_DataWrite )$^UDINT
                                          , ud_type         := VM_MEMORY_ACCESS);

          
            //look if an error occurs
            if ( sd_retval <> VARANMANAGER_OK ) then
              State := _CreateDOFailed;
              return;
            end_if;
          else
            sd_retval := VaranIn.AddRdWrDO	( p_us_position_info:= p_VaranPosition
                            , ud_dol_type		:= VARAN_DOL_ISO
                            , p_ud_handle		:= ( #aDataObjects[i].p_Handle )$^UDINT
                            , ud_address_read	:= 0
                            , ud_length_read	:= aAxisData[i].ud_DOLength
                            , p_ud_data_read	:= ( #aDataObjects[i].p_DataRead )$^UDINT
                            , ud_address_write	:= 0
                            , ud_length_write	:= aAxisData[i].ud_DOLength
                            , p_ud_data_write	:= ( #aDataObjects[i].p_DataWrite )$^UDINT
                            , ud_type			:= VM_MEMORY_ACCESS
                            );

            //look if an error occurs
            if ( sd_retval <> VARANMANAGER_OK ) then
              State := _CreateDOFailed;
              return;
            end_if;	
            
//            //get address pointer to change address later when module is connected	
//            aDataObjects[i].p_DOSettings := (aDataObjects[i].p_DataWrite)$^t_VaranDOSettingsRdWr - VM_DO_OFFSET_RDWR;
          end_if;
            //get address pointer to change address later when module is connected	
            aDataObjects[i].p_DOSettings := (aDataObjects[i].p_DataWrite)$^t_VaranDOSettingsRdWr - VM_DO_OFFSET_RDWR;
          
        end_if;
      end_for;
    end_if;
    
    for i := 1 to AxisAvailableNo-1 do  

      if AxisAvailableHW AND (1 SHL i$UDINT) then
        if b_PayloadSupport =FALSE then
        //correct address for data object read/write Axis 1
        aDataObjects[i$UDINT].p_DOSettings^.ud_AddressRd := DeviceAddress + i$UDINT*DIASDRIVE_OFFSET_Axis + DIASDRIVE_OFFSET_AxisRead;
        aDataObjects[i$UDINT].p_DOSettings^.ud_AddressWr := DeviceAddress + i$UDINT*DIASDRIVE_OFFSET_Axis;
        end_if;
        //set enable outputs in DCB
        //with VAC012 the hardware enables the outputs
        if ( DeviceID = VAC011_DEVICE_ID ) then
          aDataObjects[i].p_DataWrite^.us_DriveControl := 2#00111000;
        end_if;

        //set transmit register
        if aAxisData[i$UDINT].b_ExtendedAxis then
          aDataObjects[i$UDINT].p_DataWrite^.us_TransmitExecution.EnableValue3_5 := TRUE;
        end_if;
      
        //set right para state	
        aAxisData[i].us_ParaReady := _IdleState;
        aAxisData[i].e_AxisState := _NoInit;
      end_if;
    end_for;
    
    DataInitFinished := TRUE;
    GetCompAxisSSW += 1;

  elsif AxisAvailableNo = 1 then
  //For SDD115/120, we have to set DataInitFinished TRUE to leave this if. 
  //DataInitFinished will be set in the Method AddIsoDOsCompMode when we have more axis.  
    DataInitFinished := TRUE;
  
  end_if;

END_FUNCTION


FUNCTION _VaranDriveBase::AddIsoDOsNew
VAR
	i : UDINT;
  tmp_dol_type : UDINT;
  sd_retval : DINT;  
END_VAR

  if CreatedNewIsoDOs = FALSE then
    AxisAvailableNo := 0;
    
    // create a ISO RdWr DO for every available axis
    for i := 0 to (DIASDRIVE_MAX_AXIS*DIASDRIVE_MAX_AXIS_PER_MODULE-1) do  

      if (1 SHL i$UDINT) AND AxisAvailableHW then      
        
        if (1 SHL i$UDINT) AND ExtendedAxisSettings then
          aAxisData[AxisAvailableNo].ud_DOLength := sizeof(t_newReadDataOneAxis);
          aAxisData[AxisAvailableNo].b_ExtendedAxis := TRUE;
        else
          aAxisData[AxisAvailableNo].ud_DOLength := sizeof(t_newReadDataOneAxis) - 3 * sizeof(DINT);
          aAxisData[AxisAvailableNo].b_ExtendedAxis := FALSE;
        end_if;

        // check for fastaxis
        if (1 SHL i$UDINT) AND FastAxisSettings then
          aAxisData[AxisAvailableNo].b_FastAxis := TRUE;
        else
          aAxisData[AxisAvailableNo].b_FastAxis := FALSE;
        end_if;

        //install data object
        if b_PayloadSupport then
          
          tmp_dol_type := VARAN_DOL_ISO;
          
          if bAddDOsToListSupport then
            tmp_dol_Type := tmp_dol_Type OR VARAN_DOL_NOT_INSERT_DO_INTO_DOL;
          end_if;

          
          sd_retval := AddRdWrPayloadDO(  ud_dol_type     := tmp_dol_type
                                        , p_ud_handle     := ( #newIsoDOs[AxisAvailableNo].p_Handle )$^UDINT
                                        , ud_offset_read  := DIASDRIVE_ADR_ALT_BUF_RD_OFFSET + AxisAvailableNo$UDINT*DIASDRIVE_OFFSET_AxisRead
                                        , ud_length_read  := aAxisData[AxisAvailableNo].ud_DOLength
                                        , p_ud_data_read  := ( #newIsoDOs[AxisAvailableNo].p_DataRead )$^UDINT
                                        , ud_offset_write :=  DIASDRIVE_ADR_ALT_BUF_WR_OFFSET + AxisAvailableNo$UDINT*DIASDRIVE_OFFSET_AxisRead
                                        , ud_length_write := aAxisData[AxisAvailableNo].ud_DOLength
                                        , p_ud_data_write := ( #newIsoDOs[AxisAvailableNo].p_DataWrite )$^UDINT
                                        , ud_type         := VM_MEMORY_ACCESS);

        
          //look if an error occurs
          if ( sd_retval <> VARANMANAGER_OK ) then
            State := _CreateDOFailed;
            return;
          end_if;
        else
          sd_retval := VaranIn.AddRdWrDO	( p_us_position_info:= p_VaranPosition
                          , ud_dol_type		:= VARAN_DOL_ISO
                          , p_ud_handle		:= ( #newIsoDOs[AxisAvailableNo].p_Handle )$^UDINT
                          , ud_address_read	:= 0
                          , ud_length_read	:= aAxisData[AxisAvailableNo].ud_DOLength
                          , p_ud_data_read	:= ( #newIsoDOs[AxisAvailableNo].p_DataRead )$^UDINT
                          , ud_address_write	:= 0
                          , ud_length_write	:= aAxisData[AxisAvailableNo].ud_DOLength
                          , p_ud_data_write	:= ( #newIsoDOs[AxisAvailableNo].p_DataWrite )$^UDINT
                          , ud_type			:= VM_MEMORY_ACCESS
                          );

          //look if an error occurs
          if ( sd_retval <> VARANMANAGER_OK ) then
            State := _CreateDOFailed;
            return;
          end_if;
        end_if;
        //get address pointer to change address later when module is connected	
        newIsoDOs[AxisAvailableNo].p_DOSettings := (newIsoDOs[AxisAvailableNo].p_DataWrite)$^t_VaranDOSettingsRdWr - VM_DO_OFFSET_RDWR;
        AxisAvailableNo += 1;
        
        if AxisAvailableNo = DIASDRIVE_MAX_AXIS then
          exit;
        end_if;
      end_if;
    end_for;
  
    // check if we need to get the digital Inputs
    if TempFetchDigitalInputs then
      //install data object
      if b_PayloadSupport then

        tmp_dol_type := VARAN_DOL_ISO;
            
        if bAddDOsToListSupport then
          tmp_dol_Type := tmp_dol_Type OR VARAN_DOL_NOT_INSERT_DO_INTO_DOL;
        end_if;

        sd_retval := AddRdPayloadDO(  ud_dol_type   := tmp_dol_Type
                                    , p_ud_handle   := ( #newDigInDO.p_Handle)$^UDINT
                                    , ud_offset_read:= DIASDRIVE_ADR_INPUTS                               
                                    , ud_length_read:= sizeof(USINT)
                                    , p_ud_data_read:= ( #newDigInDO.p_DataRead)$^UDINT
                                    , ud_type       := VM_MEMORY_ACCESS);
        

        
        //look if an error occurs
        if ( sd_retval <> VARANMANAGER_OK ) then
          State := _CreateDOFailed;
          return;
        end_if;	
      else
        sd_retval := VaranIn.AddRdDO 	( p_us_position_info:= p_VaranPosition
                                      , ud_dol_type	:= VARAN_DOL_ISO
                                      , p_ud_handle	:= ( #newDigInDO.p_Handle )$^UDINT
                                      , ud_address	:= 0
                                      , ud_length	  := sizeof(USINT)
                                      , p_ud_data  	:= ( #newDigInDO.p_DataRead )$^UDINT
                                      , ud_type			:= VM_MEMORY_ACCESS
                                      );

        //look if an error occurs
        if ( sd_retval <> VARANMANAGER_OK ) then
          State := _CreateDOFailed;
          return;
        end_if;
        
        //get address pointer to change address later when module is connected	
        newDigInDO.p_DOSettings := (newDigInDO.p_DataRead)$^t_VaranDOSettingsRd - VM_DO_OFFSET_RD;          
      end_if;
    end_if;
  
    AxisAvailable100 := AxisAvailableNo;
    CreatedNewIsoDOs := TRUE;
  else
    AxisAvailableNo := AxisAvailable100;
  end_if;          
  
  //------------------------------------------------------------------------------------------------
  if b_AlreadyConnected = FALSE & AxisAvailableNo then    
  
    //Init all Axis
    for i := 0 to (AxisAvailableNo-1) do               
      // SDD100/5000 model
      if b_PayloadSupport = FALSE then

        //correct address for data object read/write Axis 1
        newIsoDOs[i].p_DOSettings^.ud_AddressRd := DeviceAddress + DIASDRIVE_ADR_ALT_BUF_RD_OFFSET + i$UDINT*DIASDRIVE_OFFSET_AxisRead;
        newIsoDOs[i].p_DOSettings^.ud_AddressWr := DeviceAddress + DIASDRIVE_ADR_ALT_BUF_WR_OFFSET + i$UDINT*DIASDRIVE_OFFSET_AxisRead;
      end_if;
      //set right para state	
      aAxisData[i].us_ParaReady := _IdleState;
      aAxisData[i].e_AxisState := _NoInit;
    end_for;
    
    if TempFetchDigitalInputs then
      if b_PayloadSupport then
        if bAddDOsToListSupport then
          sd_retval := MULTI_VARAN_IINSERTDOINTODOL(newDigInDO.p_Handle$UDINT);
        end_if;
        EnableDO(ud_DOHandle:=newDigInDO.p_Handle$UDINT);
      else
      newDigInDO.p_DOSettings^.ud_Address := DeviceAddress + DIASDRIVE_ADR_INPUTS;
      
      // start getting the inputs
      ResetDataObject	( p_handleDO	:= newDigInDO.p_Handle
                      , us_state		:= VARAN_DO_CONT_RUN
                      , ud_bytes		:= sizeof(USINT)
                      );
      end_if;              
    end_if;            
    b_AlreadyConnected := TRUE;            
  end_if;
          

END_FUNCTION

FUNCTION _VaranDriveBase::InstallDefaultDO
VAR
  sd_retval : DINT;
  tmp_dol_type : UDINT;
END_VAR

  if (CreatedCompDOs = FALSE) then
    //-----------------------------------------------------------------------------------------------
    //install default data object for the first axis

    //set right data object length
    if ExtendedAxisSettings AND 1 then
      aAxisData[0].ud_DOLength := sizeof(t_DataReadOneAxis);
      aAxisData[0].b_ExtendedAxis := TRUE;
    else
      aAxisData[0].ud_DOLength := sizeof(t_DataReadOneAxis) - 3 * sizeof(DINT);
      aAxisData[0].b_ExtendedAxis := FALSE;
    end_if;

    // check for fastaxis
    if FastAxisSettings AND 1 then
      aAxisData[0].b_FastAxis := TRUE;
    else
      aAxisData[0].b_FastAxis := FALSE;
    end_if;

    //install data object
    if b_PayloadSupport then
      tmp_dol_type := VARAN_DOL_ISO;
          
      if bAddDOsToListSupport then
        tmp_dol_Type := tmp_dol_Type OR VARAN_DOL_NOT_INSERT_DO_INTO_DOL;
      end_if;
    
      sd_retval := AddRdWrPayloadDO(  ud_dol_type     := tmp_dol_type
                                    , p_ud_handle     := ( #aDataObjects[0].p_Handle )$^UDINT
                                    , ud_offset_read  := DIASDRIVE_OFFSET_AxisRead
                                    , ud_length_read  := aAxisData[0].ud_DOLength
                                    , p_ud_data_read  := ( #aDataObjects[0].p_DataRead )$^UDINT
                                    , ud_offset_write := 0
                                    , ud_length_write := aAxisData[0].ud_DOLength
                                    , p_ud_data_write := ( #aDataObjects[0].p_DataWrite )$^UDINT
                                    , ud_type         := VM_MEMORY_ACCESS);

    
      //look if an error occurs
      if ( sd_retval <> VARANMANAGER_OK ) then
        State := _CreateDOFailed;
        return;
      end_if;
    else
    sd_retval := VaranIn.AddRdWrDO	( p_us_position_info:= p_VaranPosition
                    , ud_dol_type		:= VARAN_DOL_ISO
                    , p_ud_handle		:= ( #aDataObjects[0].p_Handle )$^UDINT
                    , ud_address_read	:= 0
                    , ud_length_read	:= aAxisData[0].ud_DOLength
                    , p_ud_data_read	:= ( #aDataObjects[0].p_DataRead )$^UDINT
                    , ud_address_write	:= 0
                    , ud_length_write	:= aAxisData[0].ud_DOLength
                    , p_ud_data_write	:= ( #aDataObjects[0].p_DataWrite )$^UDINT
                    , ud_type			:= VM_MEMORY_ACCESS
                    );

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

    //get address pointer to change address later when module is connected	
    aDataObjects[0].p_DOSettings := (aDataObjects[0].p_DataWrite)$^t_VaranDOSettingsRdWr - VM_DO_OFFSET_RDWR;
    
    CreatedCompDOs := TRUE;
  end_if;
  
  if (b_AlreadyConnected = FALSE) & CreatedCompDOs then    
    b_AlreadyConnected := TRUE;
    if b_PayloadSupport =FALSE then
    //correct address for data object read/write Axis 1
    aDataObjects[0].p_DOSettings^.ud_AddressRd := DeviceAddress + DIASDRIVE_OFFSET_AxisRead;
    aDataObjects[0].p_DOSettings^.ud_AddressWr := DeviceAddress;
    end_if;

    //set enable outputs in DCB
    //with VAC012 the hardware enables the outputs
    if ( DeviceID = VAC011_DEVICE_ID ) then
      aDataObjects[0].p_DataWrite^.us_DriveControl := 2#00111000;
    end_if;

    //set transmit register
    if aAxisData[0].b_ExtendedAxis then
      aDataObjects[0].p_DataWrite^.us_TransmitExecution.EnableValue3_5 := TRUE;
    end_if;
  
    //set right para state	
    aAxisData[0].us_ParaReady := _IdleState;
    aAxisData[0].e_AxisState := _NoInit;
  end_if;

END_FUNCTION