//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
// Device ID for the Drive Cards 
#define DRIVEMNG_AXISDEVICEID_SDD_OFFSET         0
#define DRIVEMNG_AXISEVICEID_MDD_OFFSET   16#10000
#define DRIVEMNG_AXISEVICEID_SDIAS_OFFSET 16#20000


#define DRIVEAXIS_SPEED_SFFLIMITATION_USERINFO_0   32767
#define DRIVEAXIS_SPEED_SFFLIMITATION_USERINFO_1    1000
#define DRIVEAXIS_TORQUE_LIMITATION_VALUE           1000
//}}LSL_DEFINES

//{{LSL_DECLARATION
#include "..\..\Class\_DriveMngBase\SDDDefinitions.h"
#include "..\..\Class\HwControl\HwControl.h"
#include "..\..\Class\_DriveAxisBase\_DriveAxis_A_INT_Def.h"

(*!
<Class
	Name               = "_DriveAxisBase"
	Revision           = "1.81"
	GUID               = "{B2F0B15E-D553-4717-AD13-714436E0A3E3}"
	RealtimeTask       = "false"
	CyclicTask         = "false"
	BackgroundTask     = "false"
	Sigmatek           = "true"
	OSInterface        = "false"
	HighPriority       = "false"
	Automatic          = "false"
	UpdateMode         = "Prescan"
	IconPath           = ".\Class\_DriveMngBase\Drive.ico"
	SharedCommandTable = "true"
	Objectsize         = "(494,120)"
	Comment            = "this class prepare the actual values and the incomming setpoints">
	<Channels>
		<Server Name="ActCurrent" GUID="{C242FEDD-FE6C-40BF-8C5D-6F84B9B3430C}" Visualized="true" Initialize="false" WriteProtected="true" Retentive="false" Comment="Actual Current [mA]"/>
		<Server Name="ActPos" GUID="{6F0037A2-4EFC-4C21-858C-56747F96DCF4}" Visualized="true" Initialize="false" WriteProtected="true" Retentive="false" Comment="Actual position"/>
		<Server Name="ActSpeed" GUID="{4BF4E26C-9B5D-4C6B-B539-680C91F94D93}" Visualized="true" Initialize="false" WriteProtected="true" Retentive="false" Comment="Actual speed"/>
		<Server Name="ActXw" GUID="{CA6D2A2C-FA5F-4B90-84A2-7ED7256FED96}" Visualized="true" Initialize="false" WriteProtected="true" Retentive="false" Comment="Position Error"/>
		<Server Name="AxEnable" GUID="{D6308C36-33EB-401B-BF18-9290087CB5EC}" Visualized="true" Initialize="false" WriteProtected="false" Retentive="false" Comment="server to enable the axle"/>
		<Server Name="AxError" GUID="{AB399615-2D37-44C2-8BBF-5D6D506DF075}" Visualized="true" Initialize="false" WriteProtected="true" Retentive="false" Comment="0 .. no error&#13;&#10;1 .. Axis has an error"/>
		<Server Name="AxErrorQuit" GUID="{3AA1B785-46E0-41CD-A4ED-90935075A5E3}" Visualized="true" Initialize="false" WriteProtected="false" Retentive="false" Comment="a write command quits the actual error state of the axle"/>
		<Server Name="AxisState" GUID="{EEED7FBD-A988-45AA-8AB2-7B31AACE0D4D}" Visualized="true" Initialize="false" WriteProtected="true" Retentive="false" Comment="displays the status-bits from the axle&#13;&#10;&#13;&#10;Bit01 .. NoHW =&gt; there is no hardware connected on this Place or AxNo&#13;&#10;Bit02 .. NoParameter =&gt; there are no parameters &#13;&#10;Bit03 .. NotOnline =&gt; the _DriveMng is not online&#13;&#10;Bit04 .. NotInitialized =&gt; the axle has not initialized yet&#13;&#10;Bit05 .. SFFLimitationActive =&gt; Limitation of the speed pre-control active (see description Server SetSpeed)&#13;&#10;Bit06 .. DiagModeActive =&gt; The object is locked by the _DriveAxisDiag class."/>
		<Server Name="AxTorqueControl" GUID="{A4AA77E4-9AAF-4B94-8313-9C5FAF9A43D0}" Visualized="true" Initialize="false" WriteProtected="false" Retentive="false" Comment="the torque limit is set here, the actual limit depends on the controlword.&#13;&#10;16bit Controlword - 0 until 1000 from Peak Current&#13;&#10;32bit Controlword - 0 until 4500 from Stall Current"/>
		<Server Name="CmdState" GUID="{C0257BBF-174C-49D2-8201-0B4BED56BBE1}" Visualized="true" Initialize="false" WriteProtected="true" Retentive="false" Comment="Displays the actual state of the Class&#13;&#10;(QUIT = disabled by client AxisNo)"/>
		<Server Name="ControlWord" GUID="{604148D0-8DFE-480F-B27B-6546BAEE08CB}" Visualized="true" Initialize="false" WriteProtected="false" Retentive="false" Comment="Controlword with DS402 Standard :&#13;&#10;&#13;&#10;Bit00 .. SwitchOn&#13;&#10;Bit01 .. DisableVoltage&#13;&#10;Bit02 .. QuickStop&#13;&#10;Bit03 .. EnableOperation&#13;&#10;Bit04 .. OperationModeSpecific1&#13;&#10;Bit05 .. OperationModeSpecific2&#13;&#10;Bit06 .. OperationModeSpecific3&#13;&#10;Bit07 .. ResetFault&#13;&#10;Bit08 .. Halt&#13;&#10;Bit09 .. Reserved1&#13;&#10;Bit10 .. Reserved2&#13;&#10;Bit11 .. Manufacture Specific1&#13;&#10;Bit12 .. Manufacture Specific2&#13;&#10;Bit13 .. Manufacture Specific3&#13;&#10;Bit14 .. Manufacture Specific4&#13;&#10;Bit15 .. Manufacture Specific5"/>
		<Server Name="I_HC" GUID="{8AFC09FE-5A20-47C3-BC1E-F4D9F439F5BE}" Visualized="true" Initialize="false" WriteProtected="true" Retentive="false" Comment="Shows Hardware Code of this axis&#13;&#10;&#13;&#10;Bit 31..16 Hardware Code of the Control Board&#13;&#10;Bit 15...8 Software version of the feedback CPLD&#13;&#10;Bit   7...0 Hardware Code of the Power Stage"/>
		<Server Name="Input1" GUID="{453B7EB5-CAC8-4C1E-BF02-53163B5841E4}" Visualized="true" Initialize="false" WriteProtected="true" Retentive="false" Comment="value of digital input 1 (if A-VALTT1/2 contains value=23)"/>
		<Server Name="Input2" GUID="{D6FA7D72-5CD5-432D-BA84-B8FFE2954A0A}" Visualized="true" Initialize="false" WriteProtected="true" Retentive="false" Comment="value of digital input 2 (if A-VALTT1/2 contains value=23)"/>
		<Server Name="Input3" GUID="{35987825-0670-4CAA-8166-A25D1CA5384E}" Visualized="true" Initialize="false" WriteProtected="true" Retentive="false" Comment="value of digital input 3 (if A-VALTT1/2 contains value=23)"/>
		<Server Name="Input4" GUID="{E590220A-538D-4CE6-B607-AF8B4EBFB906}" Visualized="true" Initialize="false" WriteProtected="true" Retentive="false" Comment="value of digital input 4 (if A-VALTT1/2 contains value=23)"/>
		<Server Name="Input5" GUID="{6E7F3C54-B89C-45BA-850D-9698CF0F6276}" Visualized="true" Initialize="false" WriteProtected="true" Retentive="false" Comment="value of digital input 5 (if A-VALTT1/2 contains value=23)"/>
		<Server Name="Input6" GUID="{3884FEC0-072E-4CCB-A2E8-FF6ED8C9B025}" Visualized="true" Initialize="false" WriteProtected="true" Retentive="false" Comment="value of digital input 6 (if A-VALTT1/2 contains value=23)"/>
		<Server Name="Input7" GUID="{7F923B72-1779-49F4-AB3E-31ED66CCEF1E}" Visualized="true" Initialize="false" WriteProtected="true" Retentive="false" Comment="value of digital input 7 (if A-VALTT1/2 contains value=23)"/>
		<Server Name="Input8" GUID="{ABA2FEC0-00F4-4673-A989-3DFAA9C6CC33}" Visualized="true" Initialize="false" WriteProtected="true" Retentive="false" Comment="value of digital input 8 (if A-VALTT1/2 contains value=23)"/>
		<Server Name="Online" GUID="{CAF477F1-A28E-4611-B487-DA521DD0D7C0}" Visualized="true" Initialize="false" WriteProtected="true" Retentive="false" Comment="displays if the class is ready to work with the application"/>
		<Server Name="Output1" GUID="{51C979FB-C07B-4E89-A260-796244EE4BF1}" Visualized="true" Initialize="false" WriteProtected="false" Retentive="false" Comment="Digital Output 1&#13;&#10;is only used with 16bit ControlWord"/>
		<Server Name="Output2" GUID="{7CCE096B-881F-46E1-8FD1-CA90A4154931}" Visualized="true" Initialize="false" WriteProtected="false" Retentive="false" Comment="Digital Output 2&#13;&#10;is only used with 16bit ControlWord"/>
		<Server Name="SDDCmdIntfc" GUID="{24EEE8C3-EAC3-433F-ACDD-DAB261FE5FAB}" Visualized="true" Initialize="false" WriteProtected="false" Retentive="false" Comment="Server for user commands to the drive:&#13;&#10;_SDDIDLE     .. default command&#13;&#10;_SDDREADALL  .. read all parameters of the drive &#13;&#10;  and save the parameters in the SRAM or in the file.&#13;&#10;  If any parameter classes are connected to the class SDDMngBase,&#13;&#10;  the servers of the parameter classes are refreshed.&#13;&#10;_SDDINIT     .. Initialize the drive with the saved parameters.&#13;&#10;_SDDURINIT   .. Initialize the drive with the parameters of the table.&#13;&#10;  (Lasal2 table, User Table or default table)&#13;&#10;_SDDEXDATA   .. Export the actual drive parameter into an excel formatted file.&#13;&#10;_SDDEXDATAXML   .. Export the actual drive parameter into an xml formatted file.&#13;&#10;_SDDIMDATAXML   .. Imports the drive parameter from an xml formatted file. User commands &quot;_SDDINIT&quot; must be called to transfer the data to the drive.&#13;&#10;_SDDERROR    .. This value is shown, when the user commands &quot;_SDDEXDATAXML&quot; or &quot;_SDDIMDATAXML&quot; failed. See Log-File for details. New user commands can be set in this state.&#13;&#10;&#13;&#10;User commands are only processed if the server &apos;Online&apos; displays 1. &#13;&#10;If the server &apos;Online&apos; is 0, the execution of the command is delayed until the server &apos;Online&apos; becomes 1."/>
		<Server Name="SerialNo" GUID="{1F2B66E1-39C5-490A-9A9A-D23553AD8EAC}" Visualized="true" Initialize="false" WriteProtected="true" Retentive="false" Comment="Serial number of this axis module (or drive if a SDD is used)"/>
		<Server Name="SetCurrent" GUID="{87B48CDD-0309-480B-8CAB-A29F3177BDDD}" Visualized="true" Initialize="false" WriteProtected="false" Retentive="false" Comment="Current setpoint [mA]&#13;&#10;or&#13;&#10;Torque Feed Forward [mA] in G-MODE 3 (depending on A-VALRT1/2)"/>
		<Server Name="SetPos" GUID="{6DF1B3E9-47D4-4546-8623-8AD85F70BA26}" Visualized="true" Initialize="false" WriteProtected="false" Retentive="false" Comment="Position setpoint"/>
		<Server Name="SetSpeed" GUID="{382251C3-26AE-4ACF-934B-8E791A6D7A7C}" Visualized="true" Initialize="false" WriteProtected="false" Retentive="false" Comment="Speed setpoint&#13;&#10;or&#13;&#10;SpeedFeedForward (depending on A-VALRT1/2)&#13;&#10;&#13;&#10;In case of 2 Bytes for the SpeedFeedForward, this value gets limited to an INT value."/>
		<Server Name="StateWord" GUID="{2D345FE9-CF3F-43E2-A31A-A944ADB63B30}" Visualized="true" Initialize="false" WriteProtected="true" Retentive="false" Comment="Statusword with DS402 Standard :&#13;&#10;&#13;&#10;Bit00 .. ReadyToSwitchOn&#13;&#10;Bit01 .. SwitchedOn&#13;&#10;Bit02 .. OperationEnabled&#13;&#10;Bit03 .. Fault&#13;&#10;Bit04 .. VoltageDisabled&#13;&#10;Bit05 .. QuickStop&#13;&#10;Bit06 .. SwitchOnDisabled&#13;&#10;Bit07 .. Warning&#13;&#10;Bit08 .. ManufactureSpecific1&#13;&#10;Bit09 .. Remote&#13;&#10;Bit10 .. TargetReached&#13;&#10;Bit11 .. InternalLimitActive&#13;&#10;Bit12 .. OperationModeSpecific1&#13;&#10;Bit13 .. OperationModeSpecific2&#13;&#10;Bit14 .. Manufacture Specific2&#13;&#10;Bit15 .. Manufacture Specific3"/>
		<Server Name="ZPulsLatch" GUID="{90CCCE9D-9849-4DA5-9BD8-BF7C7C2A2308}" Visualized="true" Initialize="false" WriteProtected="true" Retentive="false" Comment="latched Zero-Impulse of the axle&#13;&#10;(reset on read-out)&#13;&#10;depends on P-PSCALE"/>
		<Client Name="AxisExtend" Required="false" Internal="false" DefValue="1" Comment="use the extend telegram type&#13;&#10;0 .. 2 synchron parameter for one axle&#13;&#10;1 .. 5 synchron parameter for one axle"/>
		<Client Name="AxisNo" Required="true" Internal="false" Comment="1 - 3: select axis&#13;&#10;&lt;1 or &gt;3: object disabled (Server CmdState will be set to QUIT)"/>
		<Client Name="coLinker" Required="false" Internal="false" Comment="Object Channel to the _Linker"/>
		<Client Name="coStdLib" Required="false" Internal="false" Comment="Object Channel to the _StdLib"/>
		<Client Name="DriveAxisSet" Required="true" Internal="false" Comment="Object Channel to the _DriveAxisSet"/>
		<Client Name="DriveMng" Required="true" Internal="false" Comment="Object Channel to the _DriveMng"/>
		<Client Name="Place" Required="true" Internal="false" Comment="0 - 7"/>
	</Channels>
	<Dependencies>
		<Files>
			<File Path=".\Class\_DriveMngBase\SDDDefinitions.h" Include="true"/>
			<File Path=".\Class\HwControl\HwControl.h" Include="true"/>
			<File Path=".\Class\_DriveAxisBase\_DriveAxis_A_INT_Def.h" Include="true"/>
		</Files>
	</Dependencies>
	<RevDoku>
		<Owner Company="Sigmatek" Author="HasHan"/>
		<Dokumentation Revision="1.81" Date="11.01.2023" Author="StePhi" Company="Sigmatek" Description="Added position of second feedback available on ActPos server when only position of second feedback is used."/>
		<Dokumentation Revision="1.80" Date="02.06.2022" Author="LanSte" Company="Sigmatek" Description="Added support to read the log file from the drive with SDDCmdIntfc =&gt; _SDDEXLOGFILE."/>
		<Dokumentation Revision="1.79" Date="01.12.2021" Author="EisMic" Company="Sigmatek" Description="Removed AVALTT setting 16#20 and added the setting 16#1C for Multiturn Position.&#13;&#10;Added method AddASyncEntryIntHWCValue."/>
		<Dokumentation Revision="1.77" Date="27.07.2021" Author="LanSte" Company="Sigmatek" Description="Added support for encoder parameters for HiperfaceDSL for the MDD2000.&#13;&#10;Added methods to set DriveType-String when exporting driveparameters to xml-File."/>
		<Dokumentation Revision="1.76" Date="21.01.2021&#13;&#10;15.12.2020" Author="ZoePat&#13;&#10;PieSte" Company="Sigmatek" Description="Enable and Speed now get set to zero, in case of an reconnect.&#13;&#10;Add support for new AVALTT setting 16#20 Multiturn Position."/>
		<Dokumentation Revision="1.75" Date="25.05.2020" Author="LanSte" Company="Sigmatek" Description="Added support for ex/importing drive parameters to xml file."/>
		<Dokumentation Revision="1.74" Date="25.10.2019" Author="PieSte" Company="Sigmatek" Description="Support for _DriveAxisDiag class added."/>
		<Dokumentation Revision="1.73" Date="12.10.2018" Author="PieSte" Company="Sigmatek" Description="Added new AVALRT and AVALTT values. Now the config 23 and 27 are supported for SR01x. Add support for drive parameter M-KN and A-ACME."/>
		<Dokumentation Revision="1.72" Date="21.09.2016" Author="EisMic" Company="Sigmatek" Description="Parameter A-CAPREF will now be set every time."/>
		<Dokumentation Revision="1.71" Date="01.09.2016" Author="ZoePat" Company="Sigmatek" Description="Increased the ErrorQuit time at startup from 50ms to 100ms, to ensure the errorquit also if the drive is busy."/>
		<Dokumentation Revision="1.70" Date="04.07.2016" Author="ZoePat" Company="Sigmatek" Description="The client AxisExtend has now a default initvalue of 1."/>
		<Dokumentation Revision="1.69" Date="23.03.2016" Author="EisMic" Company="Sigmatek" Description="Changed some methods to virtual for derivation of class."/>
		<Dokumentation Revision="1.68" Date="02.03.2016" Author="EisMic" Company="Sigmatek" Description="Corrected that the Read method of the Online Server still returned 1 when the Drive gets disconnected."/>
		<Dokumentation Revision="1.67" Date="15.06.2015" Author="EisMic" Company="Sigmatek" Description="Prevent access exception in method SetAxTorque if stateword is parametrized in A-VALRT2"/>
		<Dokumentation Revision="1.66" Date="08.04.2015" Author="RamAnd" Company="Sigmatek" Description="SetAbsolutePositionEncoder now returns -4 if the Axis is enabled. If any other axis of this drive is enabled the method also doesn&apos;t work, but now the error is handled correctly so that after disabling all axis it will work.&#13;&#10;Improvement of AxErrorQuit::Write: ResetFault in control word is now only set if an internal drive error is active (could have lead to a contouring or trajectory error)"/>
		<Dokumentation Revision="1.65" Date="02.04.2015" Author="EisMic" Company="Sigmatek" Description="Data of servers ActPos,ActSpeed.. are now valid in the same cycle as the online server is set to 1."/>
		<Dokumentation Revision="1.64" Date="23.01.2015" Author="EisMic" Company="Sigmatek" Description="Optimization of read methods.&#13;&#10;Implemented NewInstcommando for read and write pdo data."/>
		<Dokumentation Revision="1.63" Date="06.10.2014" Author="LanSte" Company="Sigmatek" Description="Added support for drive parameters P208 amd P122"/>
		<Dokumentation Revision="1.62" Date="08.07.2014" Author="LanSte" Company="Sigmatek" Description="Added Support for reading hardware diagnose."/>
		<Dokumentation Revision="1.61" Date="30.06.2014" Author="PieSte" Company="Sigmatek" Description="Add compability for sdias drive CanOpen parameter."/>
		<Dokumentation Revision="1.60" Date="04.12.2013" Author="RauAnd&#13;&#10;&#13;&#10;ObeChr" Company="Sigmatek" Description="Avoid possible recursion in case the read-method of the server Online was overwritten and another read-methode got called.&#13;&#10;In case of ParaSaveType = 2 / 3 also K-Parameters got stored in the SRAM / RamFile. Now this Parameters are not stored retentive."/>
		<Dokumentation Revision="1.50" Date="21.03.2013" Author="RamAnd" Company="Sigmatek" Description="Since the last change of the class there was a problem if a 32 bit control word has been used. The initial torque value has not been written to the drive, therefore the axis couldn&apos;t move without a manual correction of the torque value."/>
		<Dokumentation Revision="1.40" Date="06.03.2013" Author="ObeChr&#13;&#10;ObeChr&#13;&#10;RamAnd&#13;&#10;RauAnd" Company="Sigmatek" Description="No ActValues are shown on the server and no SetValues can be accessed until Online = 0. SDDCmdInterface is also only processed, if Online = 1.&#13;&#10;Until Online = 0 no error is shown on the server AxError&#13;&#10;An invalid length value for the crc32 calculation of the parameter data could have lead to a runtime error.&#13;&#10;Limitation of SpeedFeedForward in case only 2 bytes for this parameter are used in the HostCommunication"/>
		<Dokumentation Revision="1.30" Date="05.11.2012" Author="ObeChr" Company="Sigmatek" Description="With the method SetAbsolutePositionEncoder an offset can be stored in the feedback."/>
		<Dokumentation Revision="1.21" Date="17.09.2012" Author="RamAnd" Company="Sigmatek" Description="Added new Parameter A-CAPFT (time base for capture inputs)&#13;&#10;Added new Server SerialNo to show the serial number of this axis module"/>
		<Dokumentation Revision="1.20" Date="22.03.2012" Author="ZoePat" Company="Sigmatek" Description="Server Online is now set to 1 after the startup-errorquit is over, and not before."/>
		<Dokumentation Revision="1.19" Date="10.02.2012" Author="ZoePat" Company="Sigmatek" Description="Added headerfile SDDDefinitions.h to prevent errors with projectversion V5"/>
		<Dokumentation Revision="1.18" Date="18.01.2012" Author="ZoePat" Company="Sigmatek" Description="The object can now be disabled by setting the client AxisNo &lt;1 or &gt;3. The cmdstate will be set to QUIT, to show the disabled state."/>
		<Dokumentation Revision="1.17" Date="31.10.2011" Author="RamAnd" Company="Sigmatek" Description="If a state word was mapped but no control word, an access exception occured when the class tried to quit an error automatically."/>
		<Dokumentation Revision="1.16" Date="28.10.2011" Author="RamAnd" Company="Sigmatek" Description="Corrected Name of Bit 1 in Type DS402_Control from &quot;DisableVoltage&quot; to &quot;EnableVoltage&quot; and Bit 4 in Type DS402_State from &quot;VoltageDisabled&quot; to &quot;VoltageEnabled&quot; to be DS402 conform."/>
		<Dokumentation Revision="1.15" Date="15.09.2011" Author="RamAnd" Company="Sigmatek" Description="If the client Extend is not set but there are extended parameters defined (A-VALRT2, A-VALTT2), the class now removes the extended parameters."/>
		<Dokumentation Revision="1.14" 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.13" Date="16.06.2011" Author="RamAnd" Company="Sigmatek" Description="Prevent that user can disturb automatic quitting of the host communication error on startup"/>
		<Dokumentation Revision="1.12" Date="31.05.2011" Author="RamAnd" Company="Sigmatek" Description="Removed unneeded time measurement, which was implemented for testing reasons."/>
		<Dokumentation Revision="1.11" Date="30.11.2010" Author="RamAnd" Company="Sigmatek" Description="When LASAL fetches a parameter value, now this value is also refreshed on the corresponding parameter class."/>
		<Dokumentation Revision="1.10" Date="13.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.9" Date="14.10.2010" Author="RamAnd" Company="Sigmatek" Description="If there was no error active on startup (power on at cpu and drive), the first appearing error was quit automatically.&#13;&#10;New Server I_HC to show the hardwarecode of power stage and control board."/>
		<Dokumentation Revision="1.8" Date="16.09.2010" Author="BerErw" Company="Sigmatek" Description="M-Parameters were not saved if OverwriteMotorPara was set to 1 on EnDat"/>
		<Dokumentation Revision="1.7" Date="09.08.2010" Author="RamAnd" Company="Sigmatek" Description="Bound exceed error could happen while uploading drive parameters."/>
		<Dokumentation Revision="1.6" Date="01.06.2010" Author="HasHan" Company="Sigmatek" Description="Now it&apos;s also possible to configure A-VALTT with value 20 (get current in thousandth of maximum and state word as cyclic values)"/>
		<Dokumentation Revision="1.5" Date="06.04.2010" Author="HasHan" Company="Sigmatek" Description="The Server &quot;Online&quot; is now set to 0 if an axle is configured by software but not available on hardware."/>
		<Dokumentation Revision="1.4" Date="15.02.2010" Author="HasHan" Company="Sigmatek" Description="Show error in Server AxisState if setting of client Place or AxisNo is invalid."/>
		<Dokumentation Revision="1.3" Date="11.01.2010" Author="HasHan" Company="Sigmatek" Description="fetch the M-TYPE twice to avoid an error in fetching the M-TYPE"/>
		<Dokumentation Revision="1.2" Date="20.10.2009" Author="HasHan" Company="Sigmatek" Description="a Torque Feed Forward is now implemented"/>
		<Dokumentation Revision="1.1" Date="29.09.2009" Author="HasHan" Company="Sigmatek" Description="Automatic reset of AxErrorQuit"/>
		<Dokumentation Revision="1.0" Date="05.08.2009" Author="HasHan" Company="Sigmatek" Description="Creation"/>
	</RevDoku>
</Class>
*)
_DriveAxisBase : CLASS
	TYPE
	  _AXIS_SSW :
	  (
	    _SDD_IDLE,
	    _SDD_STARTINIT,
	    _SDD_GETDRIVEINFO,
	    _SDD_WAIT4GETDRIVEINFO,
	    _SDD_CHKFEEDBACK,
	    _SDD_SENDPARA,
	    _SDD_GETSYNCSETTINGS,
	    _SDD_CORRECTSYNCSETTINGS,
	    _SDD_CHECKSYNCSETTINGS,
	    _SDD_SENDPARAFINISH,
	    _SDD_ERRORININIT
	  )$UDINT;
#pragma pack(push, 1)
	  _SDDMEMHEADER : STRUCT  //! <Type Public="true" Name="_SDDMEMHEADER"/>
	    udCRC32 : UDINT;
	    udLen : UDINT;
	    udVersion : UDINT;
	    AxOffset : DINT;
	    AxLength : UDINT;
	    AxName : ARRAY [0..20] OF CHAR;
	  END_STRUCT;
#pragma pack(pop)
#pragma pack(push, 1)
	  _SDDMParaBuffer : STRUCT
	    NoItems : DINT;
	    MBuffer : ARRAY [0..255] OF USINT;
	  END_STRUCT;
#pragma pack(pop)
	  _SDDSTATEWORD : BSINT  //! <Type Comment="Structure for Pdo read stateword.&#13;&#10;If structure changes, also the version number in the newinst command SDD_NEWINSTPDO has to be incremented." Name="_SDDSTATEWORD"/>
	  [
	    1 ReadyToSwitchOn,
	    2 SwitchedOn,
	    3 OperationEnabled,
	    4 Fault,
	  ];
#pragma pack(push, 1)
	  _SDDPDOREAD : STRUCT  //! <Type Comment="Structure for PDO Read Data.&#13;&#10;If structure changes, also the version number in the newinst command SDD_NEWINSTPDO has to be incremented." Name="_SDDPDOREAD"/>
	    Online : BOOL;
	    StateWord : _SDDSTATEWORD;
	    ActPos : DINT;
	    ActXw : DINT;
	  END_STRUCT;
#pragma pack(pop)
#pragma pack(push, 1)
	  _SDDPDOWRITENTRY : STRUCT  //! <Type Comment="Structure for PDO Write Entry Data.&#13;&#10;If structure changes, also the version number in the newinst command SDD_NEWINSTPDO has to be incremented." Name="_SDDPDOWRITENTRY"/>
	    Active : UINT;
	    Value : DINT;
	  END_STRUCT;
#pragma pack(pop)
#pragma pack(push, 1)
	  _SDDPDOWRITE : STRUCT  //! <Type Comment="Structure for PDO Write Data.&#13;&#10;If structure changes, also the version number in the newinst command SDD_NEWINSTPDO has to be incremented." Name="_SDDPDOWRITE"/>
	    SetPos : _SDDPDOWRITENTRY;
	    Enable : _SDDPDOWRITENTRY;
	    SetSpeed : _SDDPDOWRITENTRY;
	  END_STRUCT;
#pragma pack(pop)
	  _SDDSAVTYPE :
	  (
	    _SDDSTDTABLE,
	    _SDDL2TABLE,
	    _SDDRAMEX,
	    _SDDFILE
	  )$UDINT;
#pragma pack(push, 1)
	  SyncSet : STRUCT
	    ptr : ^DINT;
	    size : USINT;
	    userinfo : USINT;
	  END_STRUCT;
#pragma pack(pop)
#pragma pack(push, 1)
	  SyncPara_type : STRUCT
	    SetPos : SyncSet;
	    SetSpeed : SyncSet;
	    SetCurrent : SyncSet;
	    SetTorque : SyncSet;
	    ControlWord : SyncSet;
	    ActPos : SyncSet;
	    ActSpeed : SyncSet;
	    ActCurrent : SyncSet;
	    StateWord : SyncSet;
	    Xw : SyncSet;
	    DigInputs : SyncSet;
	  END_STRUCT;
#pragma pack(pop)
	END_TYPE
  //Servers:
	CmdState 	: SvrChCmd_iprStates;
	Online 	: SvrCh_DINT;
	AxisState 	: SvrCh__SDDAXISSTATE;
	ActPos 	: SvrCh_DINT;
	SetPos 	: SvrCh_DINT;
	ActSpeed 	: SvrCh_DINT;
	SetSpeed 	: SvrCh_DINT;
	ActCurrent 	: SvrCh_DINT;
	SetCurrent 	: SvrCh_DINT;
	ActXw 	: SvrCh_DINT;
	StateWord 	: SvrCh_DS402_State;
	ControlWord 	: SvrCh_DS402_Control;
	AxEnable 	: SvrCh_DINT;
	AxError 	: SvrCh_DINT;
	AxErrorQuit 	: SvrCh_DINT;
	ZPulsLatch 	: SvrCh_DINT;
	AxTorqueControl 	: SvrCh_UDINT;
	SDDCmdIntfc 	: SvrCh__SDDUSERCMD;
	I_HC 	: SvrCh__I_HC_Type;
	SerialNo 	: 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;
	Output1 	: SvrCh_DINT;
	Output2 	: SvrCh_DINT;
  //Clients:
	DriveMng 	: CltChCmd__DriveMngBase;
	Place 	: CltCh_DINT;
	AxisNo 	: CltCh_DINT;
	AxisExtend 	: CltCh_DINT;
	DriveAxisSet 	: CltChCmd__DriveAxisSet;
	coStdLib 	: CltChCmd__StdLib;
	coLinker 	: CltChCmd__Linker;
  //Variables:
		DriveInitType 	: _SDDSAVTYPE;
		szObjName : ARRAY [0..199] OF CHAR;

		pSDDData 	: ^_SDDMEMHEADER;
		bdSettings : BDINT
		[
		  1 bFirsttime,
		  2 bAxInUse,
		  5 bDriveInit,
		  6 bDriveInitialized,
		  7 bGotFeedBackType,
		  8 bFeedbackSend,
		  9 bWaitInitFinished,
		  11 bNoAbsEnc,
		  12 bSendMPara,
		  14 bParaError,
		  15 bAxSetPara,
		  16 bSyncSettings,
		  17 bInitRamAxis,
		  18 bCorrectExtSyncPara,
		  20 bParaInit,
		  21 bStartRead,
		  22 bReadAxFin,
		  23 bReadAx,
		  24 bSetAbsPos,
		  25 bSetAbsPosEncoder,
		  26 bFirstFeedbackTest,
		  27 bFeedbackOkay,
		];

		AxASyncPara 	: _DriveMngBase::_SDDRINGBUFFER;
		tUpdate 	: UDINT;
		InitSSW 	: _AXIS_SSW;
		MParaBuffer 	: _SDDMParaBuffer;
		usAxisIndex 	: USINT;			//! <Variable Comment="laufende Achsnummer" Name="usAxisIndex"/>
		SyncPara 	: SyncPara_type;
		ActValuePtr 	: ^_VaranDriveBase::t_ReadValuePtr;
		SetValuePtr 	: ^_VaranDriveBase::t_WriteValuePtr;
		SetValues : ARRAY [0..4] OF USINT;

		ActValues : ARRAY [0..4] OF USINT;

		CountAval 	: DINT;
		AxSetPara : ARRAY [0..IDX_ERRORHANDLING] OF DINT;

		OldSDDCmdIntfc 	: _SDDUSERCMD;
		ParaReadCmdAx 	: DINT;
		FirstErrorReset 	: USINT;
		FirstPosition 	: BOOL;
		maskZImpulse 	: UDINT;
		oldRevolutions 	: DINT;
		ppscale 	: USINT;
		SyncParaObject 	: DINT;
		ErrorQuitTime 	: UDINT;
		Init_Again 	: BOOL;
		tUpdateZPulse 	: UDINT;
		first_feedback 	: DINT;
		bOnlineFinished 	: BOOL;
		bOnlineState 	: BOOL;
		pDiagThis 	: ^void;
		DriveType 	: _DRIVETYPE;
		FwVersionInt 	: DINT;
		bdGetASyncEntry : BDINT
		[
		  1 bSDD_I_HW,
		  2 bSDD_I_FW,
		  3 bSDD_I_SER,
		];

  //Functions:
	
	FUNCTION VIRTUAL GLOBAL Init;
	
	FUNCTION VIRTUAL GLOBAL CyWork
		VAR_INPUT
			EAX 	: UDINT;
		END_VAR
		VAR_OUTPUT
			state (EAX) 	: UDINT;
		END_VAR;
	
	FUNCTION VIRTUAL GLOBAL AddASyncEntry
		VAR_INPUT
			usParaNr 	: USINT;			//! <Variable Comment="ID number of the drive-parameter.&#13;&#10;&#13;&#10;For a list of all available paramters take a look in the headerfile SDDDefinitions.h" Name="AddASyncEntry.usParaNr"/>
			usRdWr 	: USINT;			//! <Variable Comment="Type of the asynchronous command&#13;&#10;&#13;&#10;0..Read-Command&#13;&#10;1..Write-Command" Name="AddASyncEntry.usRdWr"/>
			dValue 	: DINT;			//! <Variable Comment="Value for setting the parameter if usRdWr = 1" Name="AddASyncEntry.dValue"/>
			pThisObj 	: ^void;			//! <Variable Comment="This-Pointer for the asynchronous command.&#13;&#10;&#13;&#10;If the asynchronous command is finished, the NewInst-Methode of the addressed object gets called." Name="AddASyncEntry.pThisObj"/>
			usEntry 	: USINT;			//! <Variable Comment="Sets the mode for an update after executing the command&#13;&#10;&#13;&#10;0..Default&#13;&#10;1..all connected parameterclasses for this axis get refreshed after the command&#13;&#10;2..Indicates if the first part of the refresh from the paratmerclasses is finished&#13;&#10;3..only used by Lasal2" Name="AddASyncEntry.usEntry"/>
		END_VAR
		VAR_OUTPUT
			retcode 	: DINT;			//! <Variable Comment="Returncode for this methode&#13;&#10;&#13;&#10;  0..successful&#13;&#10; -1..function not ready&#13;&#10; -2..wrong axle&#13;&#10; -3..Axle not in use&#13;&#10; -4..varan error in dataobject&#13;&#10;-10..RingBuffer for parameters is accessed at the moment&#13;&#10;-11..methode is locked by diagnosis class" Name="AddASyncEntry.retcode"/>
		END_VAR;
				//! <Function Comment="Method only for internal use." Name="AddASyncEntryIntHWCValue"/>
	FUNCTION VIRTUAL GLOBAL AddASyncEntryIntHWCValue
		VAR_INPUT
			dIntValueIndex 	: DINT;			//! <Variable Comment="Index are define in headerfile _DriveAxis_A_INT_Def.h." Name="AddASyncEntryIntHWCValue.dIntValueIndex"/>
			pThisObj 	: ^void;
			usEntry 	: USINT;
		END_VAR
		VAR_OUTPUT
			retcode 	: DINT;
		END_VAR;
				//! <Function Comment="With this methode the parameterobjects for the axis gets added" Name="AddParaObjects"/>
	FUNCTION VIRTUAL GLOBAL AddParaObjects
		VAR_INPUT
			Index 	: USINT;			//! <Variable Comment="Type of the parameterobject. For a detailed description take a look in the headerfile SDDDefinitions.h" Name="AddParaObjects.Index"/>
			pThis 	: ^void;			//! <Variable Comment="This-Pointer of the parameterclass." Name="AddParaObjects.pThis"/>
		END_VAR
		VAR_OUTPUT
			retcode 	: BOOL;			//! <Variable Comment="Returncode for this methode&#13;&#10;&#13;&#10;0..failed&#13;&#10;1..successful" Name="AddParaObjects.retcode"/>
		END_VAR;
				//! <Function Comment="With this methode a new synchronous command can be added" Name="AddSyncEntry"/>
	FUNCTION VIRTUAL GLOBAL AddSyncEntry
		VAR_INPUT
			pThis 	: ^void;			//! <Variable Comment="This-Pointer of the object.&#13;&#10;&#13;&#10;With the NewInst-methode the actual state of the communication gets delivered to the addressed object.&#13;&#10;Also the CyWork-methode gets called by the class _DriveAxis" Name="AddSyncEntry.pThis"/>
		END_VAR
		VAR_OUTPUT
			retcode 	: BOOL;			//! <Variable Comment="Returncode for this methode&#13;&#10;&#13;&#10;0..failed&#13;&#10;1..successful" Name="AddSyncEntry.retcode"/>
		END_VAR;
				//! <Function Comment="Returns the state of the axis (server AxisState)" Name="AxOkay"/>
	FUNCTION VIRTUAL GLOBAL AxOkay
		VAR_OUTPUT
			retcode 	: DINT;			//! <Variable Comment="Returns the state of the axis&#13;&#10;&#13;&#10;0..Axis is not Ok&#13;&#10;1..Axis is Ok" Name="AxOkay.retcode"/>
		END_VAR;
				//! <Function Comment="With this methode an error quit for the axis can be executed." Name="ErrorQuitHandling"/>
	FUNCTION VIRTUAL GLOBAL ErrorQuitHandling
		VAR_INPUT
			input 	: DINT;			//! <Variable Comment="With the inputvalue the Bit FAULT RESET in the ControlWord gets set.&#13;&#10;&#13;&#10;0..Reset Bit FAULT RESET&#13;&#10;1..Set Bit FAULT RESET" Name="ErrorQuitHandling.input"/>
		END_VAR
		VAR_OUTPUT
			result 	: DINT;			//! <Variable Comment="Returns the actual state of the Bit FAULT RESET." Name="ErrorQuitHandling.result"/>
		END_VAR;
				//! <Function Comment="With this methode a synchronous parameter can be read." Name="GetSyncEntry"/>
	FUNCTION VIRTUAL GLOBAL GetSyncEntry
		VAR_INPUT
			usValue 	: USINT;			//! <Variable Comment="Index of synchronous value" Name="GetSyncEntry.usValue"/>
			usPData 	: ^DINT;			//! <Variable Comment="Pointer to memory, where the data should be written to." Name="GetSyncEntry.usPData"/>
		END_VAR
		VAR_OUTPUT
			retcode 	: DINT;			//! <Variable Comment="Returncode for the methode&#13;&#10;&#13;&#10; 0..successful&#13;&#10;-1..Drive is not ready&#13;&#10;-2..usvalue &gt; 4&#13;&#10;-3..wrong axis number&#13;&#10;-4..usvalue &gt; 1 &amp; AxisExtend = 0" Name="GetSyncEntry.retcode"/>
		END_VAR;
				//! <Function Comment="Methode is used to get the actual values" Name="GetSynchronPara"/>
	FUNCTION VIRTUAL GLOBAL GetSynchronPara;
				//! <Function Comment="Call this methode to get the actual state of the ZPulse (no latch!)" Name="GetZImpulse"/>
	FUNCTION VIRTUAL GLOBAL GetZImpulse
		VAR_OUTPUT
			retcode 	: USINT;
		END_VAR;
				//! <Function Comment="With this methode the actual state of the Drive can be read" Name="IsOnline"/>
	FUNCTION VIRTUAL GLOBAL IsOnline
		VAR_OUTPUT
			retcode 	: BOOL;			//! <Variable Comment="Actual state of the Drive&#13;&#10;&#13;&#10;0..Drive is not online / initialized&#13;&#10;1..Drive is initialized and online" Name="IsOnline.retcode"/>
		END_VAR;
	
	FUNCTION VIRTUAL GLOBAL SDDProcess;
				//! <Function Comment="With this methode, a positionoffset can be stored in the drive (only available for absolute enocder)&#13;&#10;&#13;&#10;For a detailed description check the Drive documentation =&gt; Paramter K-FBRW" Name="SetAbsolutePosition"/>
	FUNCTION VIRTUAL GLOBAL SetAbsolutePosition
		VAR_INPUT
			AbsPosition 	: DINT;			//! <Variable Comment="I-POS is set to this value. The calculated offset gets stored in the drive." Name="SetAbsolutePosition.AbsPosition"/>
		END_VAR
		VAR_OUTPUT
			retcode 	: DINT;			//! <Variable Comment="Returncode for this methode&#13;&#10;&#13;&#10; 1..Everything was successful&#13;&#10;-1..Drive is not online or initialized&#13;&#10;-2..Operation already in progress&#13;&#10;-3..No AbsoluteEncoder is available&#13;&#10;-4..Not possible if any axis of this drive is enabled" Name="SetAbsolutePosition.retcode"/>
		END_VAR;
				//! <Function Comment="With this methode, a positionoffset can be stored in the feedbacksystem (only available for absolute enocder)&#13;&#10;&#13;&#10;For a detailed description check the Drive documentation =&gt; Paramter K-FBRW" Name="SetAbsolutePositionEncoder"/>
	FUNCTION VIRTUAL GLOBAL SetAbsolutePositionEncoder
		VAR_INPUT
			AbsPosition 	: DINT;			//! <Variable Comment="I-POS is set to this value. The calculated offset gets stored in the feedback." Name="SetAbsolutePositionEncoder.AbsPosition"/>
		END_VAR
		VAR_OUTPUT
			retcode 	: DINT;			//! <Variable Comment="Returncode for this methode&#13;&#10;&#13;&#10; 1..Everything was successful&#13;&#10;-1..Drive is not online or initialized&#13;&#10;-2..Operation already in progress&#13;&#10;-3..No AbsoluteEncoder is available&#13;&#10;-4..Not possible if any axis of this drive is enabled" Name="SetAbsolutePositionEncoder.retcode"/>
		END_VAR;
				//! <Function Comment="With this methode a synchronous parameter can be set." Name="SetSyncEntry"/>
	FUNCTION VIRTUAL GLOBAL SetSyncEntry
		VAR_INPUT
			usValue 	: USINT;			//! <Variable Comment="Index of synchronous value" Name="SetSyncEntry.usValue"/>
			usPData 	: DINT;			//! <Variable Comment="Value for the paramter" Name="SetSyncEntry.usPData"/>
		END_VAR
		VAR_OUTPUT
			retcode 	: DINT;			//! <Variable Comment="Returncode for the methode&#13;&#10;&#13;&#10; 0..successful&#13;&#10;-1..Drive is not ready&#13;&#10;-2..usvalue &gt; 4&#13;&#10;-3..wrong axis number&#13;&#10;-4..usvalue &gt; 1 &amp; AxisExtend = 0" Name="SetSyncEntry.retcode"/>
		END_VAR;
				//! <Function Comment="Methode is used to set the synchronous parameter." Name="SetSynchronPara"/>
	FUNCTION VIRTUAL GLOBAL SetSynchronPara;
	
	FUNCTION AllocMemPara
		VAR_OUTPUT
			retcode 	: BOOL;
		END_VAR;
	
	FUNCTION InitASyncPara;
	
	FUNCTION InitSDDHeader
		VAR_INPUT
			pSDDHeader 	: ^_SDDMEMHEADER;
		END_VAR;
	
	FUNCTION UpdateSvr;
	
	FUNCTION GetFeedBackType;
	
	FUNCTION SendDataToDrive;
	
	FUNCTION DataOfStdTable;
	
	FUNCTION DataOfL2table;
	
	FUNCTION DataOfFile;
	
	FUNCTION DataOfRamEx;
	
	FUNCTION GetTabAdress
		VAR_INPUT
			TabType 	: DINT;
			bMotorPara 	: BOOL;
			pTabLength 	: ^DINT;
		END_VAR
		VAR_OUTPUT
			pTabAdress 	: ^DINT;
		END_VAR;
	
	FUNCTION LoadDataRam;
	
	FUNCTION TAB SDDTabDefault;
	
	FUNCTION DriveInitReady
		VAR_OUTPUT
			retcode 	: BOOL;
		END_VAR;
	
	FUNCTION SetParaState
		VAR_INPUT
			ActState 	: UINT;
		END_VAR;
	
	FUNCTION SavParaValue
		VAR_INPUT
			ParaNo 	: USINT;
			Value 	: DINT;
			bSavSRAM 	: BOOL;
		END_VAR
		VAR_OUTPUT
			retcode 	: BOOL;
		END_VAR;
	
	FUNCTION ParaNrExist
		VAR_INPUT
			ParaNr 	: USINT;
		END_VAR
		VAR_OUTPUT
			udOffset 	: UDINT;
		END_VAR;
	
	FUNCTION InsNewParaNr
		VAR_INPUT
			ParaNr 	: USINT;
			ParaValue 	: DINT;
		END_VAR
		VAR_OUTPUT
			retcode 	: BOOL;
		END_VAR;
				//! <Function Comment="Checks if an absolute encoder is not in use." Name="ChkFb"/>
	FUNCTION ChkFb
		VAR_INPUT
			FbType 	: DINT;			//! <Variable Comment="feedbacktype of the axis" Name="ChkFb.FbType"/>
		END_VAR
		VAR_OUTPUT
			retcode 	: BOOL;			//! <Variable Comment="no absolute encoder in use" Name="ChkFb.retcode"/>
		END_VAR;
	
	FUNCTION CreateDefMPara;
	
	FUNCTION TorqueCalculation
		VAR_INPUT
			cBuffer 	: BDINT;
			input 	: UDINT;
		END_VAR
		VAR_OUTPUT
			result 	: BDINT;
		END_VAR;
	
	FUNCTION LoadDrivePara;
	
	FUNCTION SetListToParObj
		VAR_INPUT
			pData 	: ^DINT;
			udLen 	: UDINT;
		END_VAR
		VAR_OUTPUT
			retcode 	: BOOL;
		END_VAR;
	
	FUNCTION ChkParaRead
		VAR_INPUT
			ChkType 	: DINT;
		END_VAR
		VAR_OUTPUT
			retcode 	: BOOL;
		END_VAR;
	
	FUNCTION ParaReadProc;
	
	FUNCTION SaveDrivePara;
	
	FUNCTION CalcCRC32
		VAR_INPUT
			pData 	: ^UDINT;
			udLen 	: UDINT;
		END_VAR
		VAR_OUTPUT
			CRC32 	: UDINT;
		END_VAR;
	
	FUNCTION SetZPulseMask;
				//! <Function Comment="Refresh Important Asychron Parameters:&#13;&#10;-if there is a change in the following values, first we set the pointers to zero, and then we initialize them, allready with the new value" Name="RefreshIASP"/>
	FUNCTION RefreshIASP
		VAR_INPUT
			Para 	: DINT;
			Value 	: DINT;
		END_VAR;
				//! <Function Comment="Methode to evaluate ErrorBit in StateWord" Name="GetAxError"/>
	FUNCTION VIRTUAL GetAxError
		VAR_OUTPUT
			AxError 	: DINT;			//! <Variable Comment="Equal to ErrorBit in StateWord." Name="GetAxError.AxError"/>
		END_VAR;
	
	FUNCTION SetAxTorque
		VAR_INPUT
			NewTorque 	: UDINT;
		END_VAR;
	
	FUNCTION IsOnlineFinished
		VAR_OUTPUT
			bOnline 	: BOOL;
		END_VAR;
	
	FUNCTION Write_SetSpeed
		VAR_INPUT
			valueIn 	: DINT;
		END_VAR
		VAR_OUTPUT
			valueOut 	: DINT;
		END_VAR;
	
	FUNCTION Write_Enable
		VAR_INPUT
			valueIn 	: DINT;
		END_VAR
		VAR_OUTPUT
			valueOut 	: DINT;
		END_VAR;
	
	FUNCTION VIRTUAL GLOBAL AddASyncEntryDS402
		VAR_INPUT
			uiParaID 	: UINT;
			usParaSubID 	: USINT;
			usRdWr 	: USINT;
			pValue 	: ^USINT;
			bsDataInfo 	: BSINT;
			pThisObj 	: ^void;
			usEntry 	: USINT;
		END_VAR
		VAR_OUTPUT
			retcode 	: DINT;
		END_VAR;
	
	FUNCTION VIRTUAL LogError
		VAR_INPUT
			pMsg 	: ^CHAR;
		END_VAR;
	
	FUNCTION VIRTUAL LogValue
		VAR_INPUT
			pString 	: ^CHAR;
			udValue 	: UDINT;
			udValue2 	: UDINT := 16#FFFFFFFF;
			udValue3 	: UDINT := 16#FFFFFFFF;
		END_VAR;
				//! <Function Comment="Methode to set diag mode to block other accesses. " Name="SetDiagMode"/>
	FUNCTION GLOBAL SetDiagMode
		VAR_INPUT
			bStartDiagMode 	: BOOL;			//! <Variable Comment="0 .. unlock class&#13;&#10;1 .. lock class for diag mode" Name="SetDiagMode.bStartDiagMode"/>
			pThisObj 	: ^void;			//! <Variable Comment="this pointer to diag mode class" Name="SetDiagMode.pThisObj"/>
		END_VAR
		VAR_OUTPUT
			dRetCode 	: DINT;			//! <Variable Comment="  1 .. diag mode activate or deactivate ok&#13;&#10;-1 .. axis is not online or init is not finished&#13;&#10;-2 .. diag mode is already set by other instance&#13;&#10;-3 .. deactivate of diag mode is not possible because&#13;&#10;        it was activated by other instance&#13;&#10;-4 .. pThisObj pointer is not valid" Name="SetDiagMode.dRetCode"/>
		END_VAR;
				//! <Function Comment="Methode to get the connected drive type." Name="GetDriveType"/>
	FUNCTION GLOBAL GetDriveType
		VAR_OUTPUT
			DriveType 	: _DRIVETYPE;			//! <Variable Comment="Returns the drive type." Name="GetDriveType.DriveType"/>
		END_VAR;
	
	FUNCTION VIRTUAL GLOBAL CmdState::NewInst
		VAR_INPUT
			pPara 	: ^CmdStruct;
			pResult 	: ^results;
		END_VAR
		VAR_OUTPUT
			ret_code 	: iprStates;
		END_VAR;
	
	FUNCTION VIRTUAL GLOBAL Online::Read
		VAR_OUTPUT
			output (EAX) 	: DINT;
		END_VAR;
	
	FUNCTION VIRTUAL GLOBAL ActPos::Read
		VAR_OUTPUT
			output (EAX) 	: DINT;
		END_VAR;
	
	FUNCTION VIRTUAL GLOBAL SetPos::Write
		VAR_INPUT
			input (EAX) 	: DINT;
		END_VAR
		VAR_OUTPUT
			result (EAX) 	: DINT;
		END_VAR;
	
	FUNCTION VIRTUAL GLOBAL ActSpeed::Read
		VAR_OUTPUT
			output (EAX) 	: DINT;
		END_VAR;
	
	FUNCTION VIRTUAL GLOBAL SetSpeed::Write
		VAR_INPUT
			input (EAX) 	: DINT;
		END_VAR
		VAR_OUTPUT
			result (EAX) 	: DINT;
		END_VAR;
	
	FUNCTION VIRTUAL GLOBAL ActCurrent::Read
		VAR_OUTPUT
			output (EAX) 	: DINT;
		END_VAR;
	
	FUNCTION VIRTUAL GLOBAL SetCurrent::Write
		VAR_INPUT
			input (EAX) 	: DINT;
		END_VAR
		VAR_OUTPUT
			result (EAX) 	: DINT;
		END_VAR;
	
	FUNCTION VIRTUAL GLOBAL ActXw::Read
		VAR_OUTPUT
			output (EAX) 	: DINT;
		END_VAR;
	
	FUNCTION VIRTUAL GLOBAL StateWord::Read
		VAR_OUTPUT
			output (EAX) 	: DS402_State;
		END_VAR;
	
	FUNCTION VIRTUAL GLOBAL ControlWord::Write
		VAR_INPUT
			input (EAX) 	: DS402_Control;
		END_VAR
		VAR_OUTPUT
			result (EAX) 	: DS402_Control;
		END_VAR;
	
	FUNCTION VIRTUAL GLOBAL AxEnable::Write
		VAR_INPUT
			input (EAX) 	: DINT;
		END_VAR
		VAR_OUTPUT
			result (EAX) 	: DINT;
		END_VAR;
	
	FUNCTION VIRTUAL GLOBAL AxError::Read
		VAR_OUTPUT
			output (EAX) 	: DINT;
		END_VAR;
	
	FUNCTION VIRTUAL GLOBAL AxErrorQuit::Write
		VAR_INPUT
			input (EAX) 	: DINT;
		END_VAR
		VAR_OUTPUT
			result (EAX) 	: DINT;
		END_VAR;
	
	FUNCTION VIRTUAL GLOBAL ZPulsLatch::Read
		VAR_OUTPUT
			output (EAX) 	: DINT;
		END_VAR;
	
	FUNCTION VIRTUAL GLOBAL AxTorqueControl::Write
		VAR_INPUT
			input (EAX) 	: UDINT;
		END_VAR
		VAR_OUTPUT
			result (EAX) 	: UDINT;
		END_VAR;
	
	FUNCTION VIRTUAL GLOBAL SDDCmdIntfc::Write
		VAR_INPUT
			input (EAX) 	: _SDDUSERCMD;
		END_VAR
		VAR_OUTPUT
			result (EAX) 	: _SDDUSERCMD;
		END_VAR;
	
	FUNCTION VIRTUAL GLOBAL Input1::Read
		VAR_OUTPUT
			output (EAX) 	: DINT;
		END_VAR;
	
	FUNCTION VIRTUAL GLOBAL Input2::Read
		VAR_OUTPUT
			output (EAX) 	: DINT;
		END_VAR;
	
	FUNCTION VIRTUAL GLOBAL Input3::Read
		VAR_OUTPUT
			output (EAX) 	: DINT;
		END_VAR;
	
	FUNCTION VIRTUAL GLOBAL Input4::Read
		VAR_OUTPUT
			output (EAX) 	: DINT;
		END_VAR;
	
	FUNCTION VIRTUAL GLOBAL Input5::Read
		VAR_OUTPUT
			output (EAX) 	: DINT;
		END_VAR;
	
	FUNCTION VIRTUAL GLOBAL Input6::Read
		VAR_OUTPUT
			output (EAX) 	: DINT;
		END_VAR;
	
	FUNCTION VIRTUAL GLOBAL Input7::Read
		VAR_OUTPUT
			output (EAX) 	: DINT;
		END_VAR;
	
	FUNCTION VIRTUAL GLOBAL Input8::Read
		VAR_OUTPUT
			output (EAX) 	: DINT;
		END_VAR;
	
	FUNCTION VIRTUAL GLOBAL Output1::Write
		VAR_INPUT
			input (EAX) 	: DINT;
		END_VAR
		VAR_OUTPUT
			result (EAX) 	: DINT;
		END_VAR;
	
	FUNCTION VIRTUAL GLOBAL Output2::Write
		VAR_INPUT
			input (EAX) 	: DINT;
		END_VAR
		VAR_OUTPUT
			result (EAX) 	: DINT;
		END_VAR;
  //Tables:
	FUNCTION @STD
		VAR_OUTPUT
			ret_code	: CONFSTATES;
		END_VAR;
	FUNCTION GLOBAL TAB @CT_;
END_CLASS;

#pragma usingLtd _DriveAxisSet
#pragma usingLtd _DriveMngBase
#pragma usingLtd _Linker
#pragma usingLtd _StdLib


//}}LSL_DECLARATION


FUNCTION GLOBAL TAB _DriveAxisBase::@CT_
0$UINT,
2#0100000000000000$UINT, //TY__DRIVEAXISBASE
1$UINT, 81$UINT, (SIZEOF(::_DriveAxisBase))$UINT, 
30$UINT, 7$UINT, 0$UINT, 
TO_UDINT(4124502522), "_DriveAxisBase", //Class
TO_UDINT(0), 0, 0$UINT, 0$UINT, //Baseclass
//Servers:
(::_DriveAxisBase.CmdState.pMeth)$UINT, _CH_CMD$UINT, 2#0000000000000000$UINT, TO_UDINT(3787497970), "CmdState", 
(::_DriveAxisBase.Online.pMeth)$UINT, _CH_SVR$UINT, 2#0000000000000000$UINT, TO_UDINT(1858763116), "Online", 
(::_DriveAxisBase.AxisState.pMeth)$UINT, _CH_SVR$UINT, 2#0000000000000000$UINT, TO_UDINT(1615808060), "AxisState", 
(::_DriveAxisBase.ActPos.pMeth)$UINT, _CH_SVR$UINT, 2#0000000000000000$UINT, TO_UDINT(3351625522), "ActPos", 
(::_DriveAxisBase.SetPos.pMeth)$UINT, _CH_SVR$UINT, 2#0000000000000000$UINT, TO_UDINT(110881026), "SetPos", 
(::_DriveAxisBase.ActSpeed.pMeth)$UINT, _CH_SVR$UINT, 2#0000000000000000$UINT, TO_UDINT(1555690308), "ActSpeed", 
(::_DriveAxisBase.SetSpeed.pMeth)$UINT, _CH_SVR$UINT, 2#0000000000000000$UINT, TO_UDINT(33026088), "SetSpeed", 
(::_DriveAxisBase.ActCurrent.pMeth)$UINT, _CH_SVR$UINT, 2#0000000000000000$UINT, TO_UDINT(3663451001), "ActCurrent", 
(::_DriveAxisBase.SetCurrent.pMeth)$UINT, _CH_SVR$UINT, 2#0000000000000000$UINT, TO_UDINT(2317024038), "SetCurrent", 
(::_DriveAxisBase.ActXw.pMeth)$UINT, _CH_SVR$UINT, 2#0000000000000000$UINT, TO_UDINT(3335054416), "ActXw", 
(::_DriveAxisBase.StateWord.pMeth)$UINT, _CH_SVR$UINT, 2#0000000000000000$UINT, TO_UDINT(1307193485), "StateWord", 
(::_DriveAxisBase.ControlWord.pMeth)$UINT, _CH_SVR$UINT, 2#0000000000000000$UINT, TO_UDINT(2412184912), "ControlWord", 
(::_DriveAxisBase.AxEnable.pMeth)$UINT, _CH_SVR$UINT, 2#0000000000000000$UINT, TO_UDINT(582292701), "AxEnable", 
(::_DriveAxisBase.AxError.pMeth)$UINT, _CH_SVR$UINT, 2#0000000000000000$UINT, TO_UDINT(4083589877), "AxError", 
(::_DriveAxisBase.AxErrorQuit.pMeth)$UINT, _CH_SVR$UINT, 2#0000000000000000$UINT, TO_UDINT(157825597), "AxErrorQuit", 
(::_DriveAxisBase.ZPulsLatch.pMeth)$UINT, _CH_SVR$UINT, 2#0000000000000000$UINT, TO_UDINT(1574207087), "ZPulsLatch", 
(::_DriveAxisBase.AxTorqueControl.pMeth)$UINT, _CH_SVR$UINT, 2#0000000000000000$UINT, TO_UDINT(1527467955), "AxTorqueControl", 
(::_DriveAxisBase.SDDCmdIntfc.pMeth)$UINT, _CH_SVR$UINT, 2#0000000000000000$UINT, TO_UDINT(2224557350), "SDDCmdIntfc", 
(::_DriveAxisBase.I_HC.pMeth)$UINT, _CH_SVR$UINT, 2#0000000000000000$UINT, TO_UDINT(2009953281), "I_HC", 
(::_DriveAxisBase.SerialNo.pMeth)$UINT, _CH_SVR$UINT, 2#0000000000000000$UINT, TO_UDINT(1856804640), "SerialNo", 
(::_DriveAxisBase.Input1.pMeth)$UINT, _CH_SVR$UINT, 2#0000000000000000$UINT, TO_UDINT(1344628668), "Input1", 
(::_DriveAxisBase.Input2.pMeth)$UINT, _CH_SVR$UINT, 2#0000000000000000$UINT, TO_UDINT(3375117830), "Input2", 
(::_DriveAxisBase.Input3.pMeth)$UINT, _CH_SVR$UINT, 2#0000000000000000$UINT, TO_UDINT(3190490768), "Input3", 
(::_DriveAxisBase.Input4.pMeth)$UINT, _CH_SVR$UINT, 2#0000000000000000$UINT, TO_UDINT(542085939), "Input4", 
(::_DriveAxisBase.Input5.pMeth)$UINT, _CH_SVR$UINT, 2#0000000000000000$UINT, TO_UDINT(1464378277), "Input5", 
(::_DriveAxisBase.Input6.pMeth)$UINT, _CH_SVR$UINT, 2#0000000000000000$UINT, TO_UDINT(3460428319), "Input6", 
(::_DriveAxisBase.Input7.pMeth)$UINT, _CH_SVR$UINT, 2#0000000000000000$UINT, TO_UDINT(3108422281), "Input7", 
(::_DriveAxisBase.Input8.pMeth)$UINT, _CH_SVR$UINT, 2#0000000000000000$UINT, TO_UDINT(704241432), "Input8", 
(::_DriveAxisBase.Output1.pMeth)$UINT, _CH_SVR$UINT, 2#0000000000000000$UINT, TO_UDINT(2425114930), "Output1", 
(::_DriveAxisBase.Output2.pMeth)$UINT, _CH_SVR$UINT, 2#0000000000000000$UINT, TO_UDINT(159711368), "Output2", 
//Clients:
(::_DriveAxisBase.DriveMng.pCh)$UINT, _CH_CLT_OBJ$UINT, 2#0000000000000010$UINT, TO_UDINT(2977008139), "DriveMng", TO_UDINT(496739206), "_DriveMngBase", 1$UINT, 63$UINT, 
(::_DriveAxisBase.Place.pCh)$UINT, _CH_CLT_DATA$UINT, 2#0000000000000010$UINT, TO_UDINT(2202636669), "Place", 
(::_DriveAxisBase.AxisNo.pCh)$UINT, _CH_CLT_DATA$UINT, 2#0000000000000010$UINT, TO_UDINT(2111456692), "AxisNo", 
(::_DriveAxisBase.AxisExtend.pCh)$UINT, _CH_CLT_DATA$UINT, 2#0000000000000000$UINT, TO_UDINT(85254755), "AxisExtend", 
(::_DriveAxisBase.DriveAxisSet.pCh)$UINT, _CH_CLT_OBJ$UINT, 2#0000000000000010$UINT, TO_UDINT(1810900605), "DriveAxisSet", TO_UDINT(833307860), "_DriveAxisSet", 1$UINT, 22$UINT, 
(::_DriveAxisBase.coStdLib.pCh)$UINT, _CH_CLT_OBJ$UINT, 2#0000000000000000$UINT, TO_UDINT(3815072667), "coStdLib", TO_UDINT(3689364044), "_StdLib", 2$UINT, 0$UINT, 
(::_DriveAxisBase.coLinker.pCh)$UINT, _CH_CLT_OBJ$UINT, 2#0000000000000000$UINT, TO_UDINT(1382361455), "coLinker", TO_UDINT(1793552568), "_Linker", 0$UINT, 5$UINT, 
END_FUNCTION


#define USER_CNT__DriveAxisBase 19

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

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

	//Command Methods
	InitCmdTable (nCmd := nSTDCMD + USER_CNT__DriveAxisBase, pCmd := #vmt.CmdTable);
	vmt.CmdTable.NewInstr		:= #NewInst();
	vmt.CmdTable.Init		:= #Init();
	vmt.CmdTable.CyWork		:= #CyWork();
#pragma warning (disable : 74)
	vmt.UserFcts[0]		:= #AddASyncEntry();

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	IF CmdState.pMeth THEN
		ret_code	:= C_OK;
	ELSE
		ret_code	:= C_OUTOF_NEAR;
		RETURN;
	END_IF;
	Online.pMeth			:= StoreMethod( #Online::Read(), #M_NO_F() );
	IF Online.pMeth THEN
		ret_code	:= C_OK;
	ELSE
		ret_code	:= C_OUTOF_NEAR;
		RETURN;
	END_IF;
	ActPos.pMeth			:= StoreMethod( #ActPos::Read(), #M_NO_F() );
	IF ActPos.pMeth THEN
		ret_code	:= C_OK;
	ELSE
		ret_code	:= C_OUTOF_NEAR;
		RETURN;
	END_IF;
	SetPos.pMeth			:= StoreMethod( #M_RD_DIRECT(), #SetPos::Write() );
	IF SetPos.pMeth THEN
		ret_code	:= C_OK;
	ELSE
		ret_code	:= C_OUTOF_NEAR;
		RETURN;
	END_IF;
	ActSpeed.pMeth			:= StoreMethod( #ActSpeed::Read(), #M_NO_F() );
	IF ActSpeed.pMeth THEN
		ret_code	:= C_OK;
	ELSE
		ret_code	:= C_OUTOF_NEAR;
		RETURN;
	END_IF;
	SetSpeed.pMeth			:= StoreMethod( #M_RD_DIRECT(), #SetSpeed::Write() );
	IF SetSpeed.pMeth THEN
		ret_code	:= C_OK;
	ELSE
		ret_code	:= C_OUTOF_NEAR;
		RETURN;
	END_IF;
	ActCurrent.pMeth			:= StoreMethod( #ActCurrent::Read(), #M_NO_F() );
	IF ActCurrent.pMeth THEN
		ret_code	:= C_OK;
	ELSE
		ret_code	:= C_OUTOF_NEAR;
		RETURN;
	END_IF;
	SetCurrent.pMeth			:= StoreMethod( #M_RD_DIRECT(), #SetCurrent::Write() );
	IF SetCurrent.pMeth THEN
		ret_code	:= C_OK;
	ELSE
		ret_code	:= C_OUTOF_NEAR;
		RETURN;
	END_IF;
	ActXw.pMeth			:= StoreMethod( #ActXw::Read(), #M_NO_F() );
	IF ActXw.pMeth THEN
		ret_code	:= C_OK;
	ELSE
		ret_code	:= C_OUTOF_NEAR;
		RETURN;
	END_IF;
	StateWord.pMeth			:= StoreMethod( #StateWord::Read(), #M_NO_F() );
	IF StateWord.pMeth THEN
		ret_code	:= C_OK;
	ELSE
		ret_code	:= C_OUTOF_NEAR;
		RETURN;
	END_IF;
	ControlWord.pMeth			:= StoreMethod( #M_RD_DIRECT(), #ControlWord::Write() );
	IF ControlWord.pMeth THEN
		ret_code	:= C_OK;
	ELSE
		ret_code	:= C_OUTOF_NEAR;
		RETURN;
	END_IF;
	AxEnable.pMeth			:= StoreMethod( #M_RD_DIRECT(), #AxEnable::Write() );
	IF AxEnable.pMeth THEN
		ret_code	:= C_OK;
	ELSE
		ret_code	:= C_OUTOF_NEAR;
		RETURN;
	END_IF;
	AxError.pMeth			:= StoreMethod( #AxError::Read(), #M_NO_F() );
	IF AxError.pMeth THEN
		ret_code	:= C_OK;
	ELSE
		ret_code	:= C_OUTOF_NEAR;
		RETURN;
	END_IF;
	AxErrorQuit.pMeth			:= StoreMethod( #M_RD_DIRECT(), #AxErrorQuit::Write() );
	IF AxErrorQuit.pMeth THEN
		ret_code	:= C_OK;
	ELSE
		ret_code	:= C_OUTOF_NEAR;
		RETURN;
	END_IF;
	ZPulsLatch.pMeth			:= StoreMethod( #ZPulsLatch::Read(), #M_NO_F() );
	IF ZPulsLatch.pMeth THEN
		ret_code	:= C_OK;
	ELSE
		ret_code	:= C_OUTOF_NEAR;
		RETURN;
	END_IF;
	AxTorqueControl.pMeth			:= StoreMethod( #M_RD_DIRECT(), #AxTorqueControl::Write() );
	IF AxTorqueControl.pMeth THEN
		ret_code	:= C_OK;
	ELSE
		ret_code	:= C_OUTOF_NEAR;
		RETURN;
	END_IF;
	SDDCmdIntfc.pMeth			:= StoreMethod( #M_RD_DIRECT(), #SDDCmdIntfc::Write() );
	IF SDDCmdIntfc.pMeth THEN
		ret_code	:= C_OK;
	ELSE
		ret_code	:= C_OUTOF_NEAR;
		RETURN;
	END_IF;
	Input1.pMeth			:= StoreMethod( #Input1::Read(), #M_NO_F() );
	IF Input1.pMeth THEN
		ret_code	:= C_OK;
	ELSE
		ret_code	:= C_OUTOF_NEAR;
		RETURN;
	END_IF;
	Input2.pMeth			:= StoreMethod( #Input2::Read(), #M_NO_F() );
	IF Input2.pMeth THEN
		ret_code	:= C_OK;
	ELSE
		ret_code	:= C_OUTOF_NEAR;
		RETURN;
	END_IF;
	Input3.pMeth			:= StoreMethod( #Input3::Read(), #M_NO_F() );
	IF Input3.pMeth THEN
		ret_code	:= C_OK;
	ELSE
		ret_code	:= C_OUTOF_NEAR;
		RETURN;
	END_IF;
	Input4.pMeth			:= StoreMethod( #Input4::Read(), #M_NO_F() );
	IF Input4.pMeth THEN
		ret_code	:= C_OK;
	ELSE
		ret_code	:= C_OUTOF_NEAR;
		RETURN;
	END_IF;
	Input5.pMeth			:= StoreMethod( #Input5::Read(), #M_NO_F() );
	IF Input5.pMeth THEN
		ret_code	:= C_OK;
	ELSE
		ret_code	:= C_OUTOF_NEAR;
		RETURN;
	END_IF;
	Input6.pMeth			:= StoreMethod( #Input6::Read(), #M_NO_F() );
	IF Input6.pMeth THEN
		ret_code	:= C_OK;
	ELSE
		ret_code	:= C_OUTOF_NEAR;
		RETURN;
	END_IF;
	Input7.pMeth			:= StoreMethod( #Input7::Read(), #M_NO_F() );
	IF Input7.pMeth THEN
		ret_code	:= C_OK;
	ELSE
		ret_code	:= C_OUTOF_NEAR;
		RETURN;
	END_IF;
	Input8.pMeth			:= StoreMethod( #Input8::Read(), #M_NO_F() );
	IF Input8.pMeth THEN
		ret_code	:= C_OK;
	ELSE
		ret_code	:= C_OUTOF_NEAR;
		RETURN;
	END_IF;
	Output1.pMeth			:= StoreMethod( #M_RD_DIRECT(), #Output1::Write() );
	IF Output1.pMeth THEN
		ret_code	:= C_OK;
	ELSE
		ret_code	:= C_OUTOF_NEAR;
		RETURN;
	END_IF;
	Output2.pMeth			:= StoreMethod( #M_RD_DIRECT(), #Output2::Write() );
	IF Output2.pMeth THEN
		ret_code	:= C_OK;
	ELSE
		ret_code	:= C_OUTOF_NEAR;
		RETURN;
	END_IF;

END_FUNCTION

//{{LSL_IMPLEMENTATION
VAR_PRIVATE  
  p_this            : ^void;
  //Private Variables for CMD_GET_HARDWARE_DIAGNOSIS AND CMD_GET_HARDWARE_TREE_ENTRY  
  a_SerialNo			: ARRAY[0..31] OF CHAR;
END_VAR


FUNCTION VIRTUAL GLOBAL _DriveAxisBase::Init
  VAR
    retcode         : BOOL;
  END_VAR
    
  if bdSettings.bFirsttime = FALSE then
  
    bdSettings.bFirsttime       := TRUE;
    bdSettings.bDriveInit       := TRUE;
    bdSettings.bFeedbackSend    := FALSE;
    bdSettings.bGotFeedBackType := FALSE;
    
    // read the clients
    Place := Place.read();
    AxisNo := AxisNo.read();
    AxisExtend := AxisExtend.Read();
    
    // check for valid axis no
    if (AxisNo < 1) | (AxisNo > 3) then
      // disable object
      AxisNo := -1;
      CmdState := QUIT;
      AxisState.NotInitialized := true;
      return;
    end_if;

    // allocate the memory for the ringbuffer
    AxASyncPara.pStart$^void := coStdLib.Malloc(SDDBUFFERENTRY * sizeof(_DriveMngBase::_SDDBFENTRY));

    if AxASyncPara.pStart = NIL then
      return;
    end_if;
    
    InitASyncPara(); // initialize the structure
    
    // add the object into the list of the sddmanager
    DriveMng.AddAxObj(pThis:=this, Place:= Place, AxisNo:= AxisNo, #AxASyncPara, AxisExtend, 0);
    
    _GetObjName(this, #szObjName[0]); // get the object name
    
    InitSSW := _SDD_STARTINIT;
    
    usAxisIndex := 16#FF; // initialize the AxisIndex
    
  end_if;
  

  if _firstscan & (AxisNo <> -1) then
    //********************************************\\
    //** check the type of saving the parameter **\\
    //********************************************\\
    DriveInitType$DINT := DriveAxisSet.GetInitType();
    
    if DriveInitType = _SDDFILE then
      retcode := DriveAxisSet.ChkFileHandle();
      if retcode = FALSE then
        DriveInitType := _SDDL2TABLE;
        LogValue("@04C1 (_DriveAxisBase::Init) No file handling for object '{0}' available! Saving type is changed!", szObjName[0]);
      end_if;
    end_if;

    if (DriveInitType = _SDDRAMEX) | (DriveInitType = _SDDFILE) then
      retcode := AllocMemPara();
      if retcode = FALSE then
        DriveInitType := _SDDL2TABLE;
        LogValue("@04C2 (_DriveAxisBase::Init) No memory for object '{0}' available! Saving type is changed!", szObjName[0]);
      end_if;
    end_if;
    
    AxTorqueControl := 4500;  // set the torque control
    FirstErrorReset := 1;
    FirstPosition   := FALSE;
    ppscale         := 16;    // initialize p-pscale
    CmdState        := ERROR;
    Init_Again      := FALSE;
    
    SetZPulseMask();          // initialize the ZImpulse-Mask
    AxisState.NotInitialized := true;
        
  end_if;
  
END_FUNCTION


FUNCTION VIRTUAL GLOBAL _DriveAxisBase::CmdState::NewInst
	VAR_INPUT
		pPara 	: ^CmdStruct;
		pResult 	: ^results;
	END_VAR
	VAR_OUTPUT
		ret_code 	: iprStates;
	END_VAR
  VAR
    pThisNewInst  : ^void;
    UserPara		: CmdStruct;
    UserResult		: Results;
    ud_TempSerNo    : UDINT;
    si_i            : SINT;
    pPDORead      : ^_SDDPDOREAD;
    pPDOWrite     : ^_SDDPDOWRITE;
    dValue        : DINT;    
  END_VAR
  
  ret_code:= READY;

  CASE pPara^.uiCmd OF

  //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  SDD_ASYNC_READY :
  
    // check the parameter number 
    case (pPara^.aPara[0]) of
    
    SDD_M_TYPE :
      // was the command a read or a write command
      if (pPara^.aPara[1] = 0) then
      
        bdSettings.bGotFeedBackType := FALSE;
        
        if bdSettings.bFirstFeedbackTest = FALSE then
          first_feedback := pPara^.aPara[2];
          bdSettings.bFirstFeedbackTest := TRUE;
          bdSettings.bFeedBackSend := FALSE; //catch an M-TYPE once more
        elsif first_feedback = pPara^.aPara[2] then //two times the same value for the M-TYPE?
          bdSettings.bFeedbackOkay := TRUE;
        else //there was a difference => we need a value once more
          bdSettings.bFeedbackOkay := FALSE;
          first_feedback := pPara^.aPara[2];
          bdSettings.bFeedBackSend := FALSE;
        end_if;

        if bdSettings.bFeedbackOkay = TRUE then
          if ChkFb(pPara^.aPara[2]) = TRUE then
            bdSettings.bNoAbsEnc := TRUE; // kein Absolutwertgeber in Verwendung
          else
            bdSettings.bNoAbsEnc := FALSE;
          end_if;
          bdSettings.bGotFeedBackType := TRUE;
        end_if;      
      end_if;
      
    
    SDD_K_FBRW :
      if (pPara^.aPara[1] = 1) then     // command was a write command
        if pPara^.aPara[2] = 3 then     // command was to marry the motor with the drive
          bdSettings.bSetAbsPos := FALSE;
        elsif pPara^.aPara[2] = 2 then   //command was to calculate the offsetposition and save it to the feedbacksystem
          bdSettings.bSetAbsPosEncoder := FALSE;
        end_if;      
      end_if;
      
    SDD_A_VALRT1 :
      
      if (pPara^.aPara[1] = 0) then
        // read command
        // save the value in the array SetValues
        SetValues[0] := to_usint( pPara^.aPara[2] AND 16#000000FF);
        SetValues[1] := to_usint((pPara^.aPara[2] AND 16#0000FF00) SHR 8);
        RefreshIASP(pPara^.aPara[0],pPara^.aPara[2]); //that is just to init the servers of a connected SyncExtend class
        CountAval -= 1;
      end_if;
      
    SDD_A_VALRT2 :
      
      if (pPara^.aPara[1] = 0) then
        // read command
        
        // if this is now extended axis, but we got extended parameters => delete them
        if (AxisExtend = 0) & (pPara^.aPara[2] AND 16#00FFFFFF) then
          pPara^.aPara[2] := 0;
          bdSettings.bCorrectExtSyncPara := TRUE;
        end_if;
        
        // save the value in the array SetValues
        SetValues[2] := to_usint( pPara^.aPara[2] AND 16#000000FF);
        SetValues[3] := to_usint((pPara^.aPara[2] AND 16#0000FF00) SHR 8);
        SetValues[4] := to_usint((pPara^.aPara[2] AND 16#00FF0000) SHR 16);
        RefreshIASP(pPara^.aPara[0],pPara^.aPara[2]); //that is just to init the servers of a connected SyncExtend class
        CountAval -= 1;
      end_if;
    
    SDD_A_VALTT1 :
      
      if (pPara^.aPara[1] = 0) then
        // read command
        // save the value in the array SetValues
        ActValues[0] := to_usint( pPara^.aPara[2] AND 16#000000FF);
        ActValues[1] := to_usint((pPara^.aPara[2] AND 16#0000FF00) SHR 8);
        RefreshIASP(pPara^.aPara[0],pPara^.aPara[2]); //that is just to init the servers of a connected SyncExtend class
        CountAval -= 1;
      end_if;
    
    SDD_A_VALTT2 :
      
      if (pPara^.aPara[1] = 0) then
        // read command

        // if this is now extended axis, but we got extended parameters => delete them
        if (AxisExtend = 0) & (pPara^.aPara[2] AND 16#00FFFFFF) then
          pPara^.aPara[2] := 0;
          bdSettings.bCorrectExtSyncPara := TRUE;
        end_if;

        // save the value in the array SetValues
        ActValues[2] := to_usint( pPara^.aPara[2] AND 16#000000FF);
        ActValues[3] := to_usint((pPara^.aPara[2] AND 16#0000FF00) SHR 8);
        ActValues[4] := to_usint((pPara^.aPara[2] AND 16#00FF0000) SHR 16);
        RefreshIASP(pPara^.aPara[0],pPara^.aPara[2]); //that is just to init the servers of a connected SyncExtend class
        CountAval -= 1;
      end_if;
      
    SDD_P_PSCALE:
    
      if (pPara^.aPara[1] = 0) then
        ppscale:=to_usint(pPara^.aPara[2]);
        CountAval -=1;
        SetZPulseMask();
      end_if;

    SDD_I_HW :
      
      if (pPara^.aPara[1] = 0) then
        I_HC := (pPara^.aPara[2])$_I_HC_Type;
        bdGetASyncEntry.bSDD_I_HW := FALSE;
        
        DriveType := DriveMng.GetDriveType(HWCode:=pPara^.aPara[2]);
      end_if;
    
    SDD_I_SER :

      if (pPara^.aPara[1] = 0) then
        SerialNo := pPara^.aPara[2];
        bdGetASyncEntry.bSDD_I_SER := FALSE;
      end_if;
      
    SDD_A_CAPREF:
    
      //Check if it was a write command
      if (pPara^.aPara[1] = 1) then 
        CountAval -= 1;
      end_if;
      
    SDD_I_FW:
    
      if (pPara^.aPara[1] = 0) then
        FwVersionInt := pPara^.aPara[2];
        bdGetASyncEntry.bSDD_I_FW  := FALSE;
      end_if;
    
    end_case;
    
  //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  SDD_ASYNC_ERROR :
		case pPara^.aPara[0] of
    
    SDD_M_TYPE :
      if (pPara^.aPara[1] = 0) then
        bdSettings.bGotFeedBackType := TRUE;
      end_if;
    
    SDD_K_FBRW :
      if (pPara^.aPara[1] = 1) then  // was a write command
        if pPara^.aPara[2] = 3 then  // command was to marry the motor with the drive
          bdSettings.bSetAbsPos := FALSE;
        elsif pPara^.aPara[2] = 2 then   //command was to calculate the offsetposition and save it to the feedbacksystem
          bdSettings.bSetAbsPosEncoder := FALSE;
        end_if;
      elsif (pPara^.aPara[1] = 3) & (pPara^.aPara[2] = 5) then
        //axis enabled => cannot change value
        bdSettings.bSetAbsPosEncoder := FALSE;
      end_if;
    
    SDD_A_VALRT1 :
      
      // save the value in the array SetValues
      SetValues[0] := 0;
      SetValues[1] := 0;
      CountAval -= 1;
      
    SDD_A_VALRT2 :
      
      // save the value in the array SetValues
      SetValues[2] := 0;
      SetValues[3] := 0;
      SetValues[4] := 0;
      CountAval -= 1;
    
    SDD_A_VALTT1 :
      
        // save the value in the array SetValues
      ActValues[0] := 0;
      ActValues[1] := 0;
      CountAval -= 1;
    
    SDD_A_VALTT2 :
      
      // save the value in the array SetValues
      ActValues[2] := 0;
      ActValues[3] := 0;
      ActValues[4] := 0;
      CountAval -= 1;
      
    SDD_I_HW :
      
      bdGetASyncEntry.bSDD_I_HW := FALSE;

    SDD_I_SER :
      
      bdGetASyncEntry.bSDD_I_SER := FALSE;
      
    SDD_A_CAPREF:
    
      CountAval -= 1;
      
    SDD_I_FW:
      
      bdGetASyncEntry.bSDD_I_FW  := FALSE;

    end_case;

  //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  SDD_SETHWSTATE :
  //*************************************************************************
  //** set the state of the axis                                           **
  //*************************************************************************

     case pPara^.aPara[0]$iprStates of
      
      READY :
         
         CmdState := READY;
         usAxisIndex := to_usint(pPara^.aPara[1]);
         bdSettings.bAxInUse := TRUE;
         AxisState.NotInitialized := false;
          
      ERROR :
      
        CmdState := ERROR;
        Online := 0; //HasHan
        bOnlineFinished := FALSE;
        bOnlineState    := FALSE;
        //reset diagnose mode if online state is set to zero
        if pDiagThis <> NIL then
          SetDiagMode(bStartDiagMode:=FALSE, pThisObj:=pDiagThis);
        end_if;

        case pPara^.aPara[1] of
        
        SDD_NO_HW :
          AxisState.NoHW := 1;
          AxisState.NotInitialized := false;
        end_case; 
        
        SetParaState(SDD_GENERAL_ERROR);
        
      end_case;
      
  //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  SDD_SETSTATE:
      
      DriveMng:=DriveMng.Read();
      
      if DriveMng = _ClassOk then
        SetParaState(SDD_GENERAL_READY);
      else
        SetParaState(SDD_GENERAL_ERROR);
      end_if;

  //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
  SDD_SAVPARAVALUE :
    
    //K-Parameters are not stored
    if pPara^.aPara[0] < SDD_K_EN then
      SavParaValue(ParaNo:= to_usint(pPara^.aPara[0]), Value:= pPara^.aPara[2], bSavSRAM:= to_bool(pPara^.aPara[4]));
    end_if;

    if ((pPara^.aPara[0] = SDD_A_VALTT1) | (pPara^.aPara[0] = SDD_A_VALRT1) |
        (pPara^.aPara[0] = SDD_A_VALTT2) | (pPara^.aPara[0] = SDD_A_VALRT2) | 
        (pPara^.aPara[0] = SDD_P_PSCALE)) & (pPara^.aPara[1]<>0) then
      RefreshIASP(pPara^.aPara[0],pPara^.aPara[2]);
    end_if;

  //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++  
  SDD_REFRESHPARA :
    
    bdSettings.bReadAxFin := TRUE;
    
  //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  SDD_INITAXLE :
    
    Init_Again:=true;
    bdSettings.bDriveInitialized := false;
    AxisState.NotInitialized:=false;
    
  //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  SDD_URINITAXLE :
    
    Init_Again:=true;
    bdSettings.bDriveInitialized := true;
    AxisState.NotInitialized:=false;
  
  //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  SDD_REFRESHPARAOBJECTS :

    pThisNewInst := NIL;
    if pPara^.aPara[0] <= MAX_MOTOR_PARA then
      pThisNewInst$DINT := AxSetPara[IDX_MOTOR_PARA];
    elsif pPara^.aPara[0] <= MAX_DRIVE_PARA then
      pThisNewInst$DINT := AxSetPara[IDX_DRIVE_PARA];
    elsif pPara^.aPara[0] <= MAX_CURRENT_PARA then
      pThisNewInst$DINT := AxSetPara[IDX_CURRENT_PARA];
    elsif pPara^.aPara[0] <= MAX_VEL_PARA then
      pThisNewInst$DINT := AxSetPara[IDX_VEL_PARA];
    elsif pPara^.aPara[0] <= MAX_POS_PARA then
      pThisNewInst$DINT := AxSetPara[IDX_POS_PARA];
    elsif pPara^.aPara[0] <= MAX_FD_PARA then
      pThisNewInst$DINT := AxSetPara[IDX_FD_PARA];
    elsif pPara^.aPara[0] <= MAX_APPLI_PARA then
      pThisNewInst$DINT := AxSetPara[IDX_APPLI_PARA];
    elsif pPara^.aPara[0] <= MAX_ERRORHANDLING then
      pThisNewInst$DINT := AxSetPara[IDX_ERRORHANDLING];
    end_if;
      
    if pThisNewInst <> NIL then
      UserPara.uiCmd := SDD_REFRESH_SETPARA;
      UserPara.aPara[0] := to_dint(pPara^.aPara[0]);  // parameter number
      UserPara.aPara[1] := pPara^.aPara[2];           // value
      pThisNewInst$^VirtualBase^.NewInst(#UserPara, #UserResult);
    end_if;

  //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  SDD_GET_ANY_AXIS_ENABLED : 
    pResult^.uiLng := 1;
    pResult^.aData[0] := to_bool(AxEnable);

  //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  CMD_GET_HARDWARE_DIAGNOSIS : 

    pResult^.aData$t_HWCGetHardwareDiagnosisOut.retcode := _HWC_RETVAL_ERROR;
    ret_code := ERROR;
    
    // Get Place --------------------------------------------------------------------------------------------
    pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.ud_Place := Place$UDINT;
    
    // Get AxisNo --------------------------------------------------------------------------------------------
    pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.ud_AxisNo := AxisNo$UDINT;
    
    // Get Serialno -----------------------------------------------------------------------------------------
    pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.pStr_SerialNo  := #a_SerialNo[0];  // Will be overwritten if this pointer is not equal 
    
    // Get FPGA Version -----------------------------------------------------------------------------------------  
    pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.hd_FPGAVersion := I_HC.FPGAVersion; 
    
    // Get DeviceID -----------------------------------------------------------------------------------------  
    
    if (pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.ud_DeviceID AND DRIVEMNG_AXISEVICEID_MDD_OFFSET) = DRIVEMNG_AXISEVICEID_MDD_OFFSET then // Check if MDD offset was set
      // 16#10000 is  set
      pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.ud_DeviceID := pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.ud_DeviceID AND 16#FFFF0000;                           // Clear ID set be DriveMng
      pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.ud_DeviceID := pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.ud_DeviceID OR (I_HC.HardwareCodeControlBoard shr 8);  // Set ID
    else
      // 16#00000 or 16#20000 are set
      pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.ud_DeviceID := pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.ud_DeviceID AND 16#FFFF0000;                           // Clear ID set be DriveMng
      pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.ud_DeviceID := pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.ud_DeviceID OR I_HC.HardwareCodeControlBoard;          // Set ID
    end_if;  
     
    if (this <> p_this) then

      ud_TempSerNo := SerialNo$UDINT;
      
      for si_i := 9 to 0 by -1 do
        a_SerialNo[si_i] := to_usint(ud_TempSerNo mod 10) + '0';
        ud_TempSerNo  := ud_TempSerNo/10;
      end_for;            
      
      a_SerialNo[10] := 0;
      
      pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.pStr_SerialNo   := #a_SerialNo[0];
      
    end_if;
    
    if Online = 0 then
      ret_code := ERROR;
      pResult^.aData$t_HWCGetHardwareDiagnosisOut.retcode := _HWC_RETVAL_ERROR_CLASS_NOT_ONLINE;
    else
      ret_code := READY;
      pResult^.aData$t_HWCGetHardwareDiagnosisOut.retcode := _HWC_RETVAL_OK;
    end_if;
    
    
  SDD_NEWINSTPDO :
    
    pResult^.uiLng := 1;
    
    //We use this as version request in DrivePosControl to ensure that both classes have the same structure type (_SDDPDOREAD, _SDDPDOWRITE)
    //If the structure is changed, we need to increment the version number in pResult^.aData[0]
    pResult^.aData[0] := 1; //Version 1
  
  SDD_READPDODATA :
    pPDORead := pPara^.aPara[0]$^_SDDPDOREAD;
    if bOnlineFinished = TRUE then
      pPDORead^.Online := TRUE;
      // StatusWord (nur die ersten 4 Bits
      if SyncPara.StateWord.ptr <> NIL then
        pPdoRead^.StateWord := to_usint(SyncPara.StateWord.ptr^); //HasHan
      else
        pPdoRead^.StateWord := 0;
      end_if;
      // ActPos
      if SyncPara.ActPos.ptr <> NIL then
        pPdoRead^.ActPos := SyncPara.ActPos.ptr^;
      else
        pPdoRead^.ActPos := 0;
      end_if;
      // XW 
      pPdoRead^.ActXw := 0;
      if SyncPara.Xw.ptr <> NIL then
        if SyncPara.Xw.size = 4 then
          pPdoRead^.ActXw:=SyncPara.Xw.ptr^;
        elsif SyncPara.Xw.size = 2 then
          pPdoRead^.ActXw := to_dint(SyncPara.Xw.ptr^$INT); 
        end_if;
      end_if;
    else
      pPdoRead^.Online := FALSE;
    end_if;
    
  SDD_WRITEPDODATA :
    pPDOWrite := pPara^.aPara[0]$^_SDDPDOWRITE;
    if bOnlineFinished = TRUE then
    
      // SetPos
      if (SyncPara.SetPos.ptr <> NIL) & (pPDOWrite^.SetPos.Active = 1) then
        SyncPara.SetPos.ptr^:=pPDOWrite^.SetPos.Value; 
      end_if;
      
      // Enable 
      if (SyncPara.ControlWord.ptr <> NIL) & (pPDOWrite^.Enable.Active = 1) then
        dValue := pPDOWrite^.Enable.Value;
        if (SyncPara.ControlWord.userinfo=0) then 
          SyncPara.ControlWord.ptr^$BINT.1:=dValue$BOOL; //DRIVE ENABLE
        elsif(SyncPara.ControlWord.userinfo=1) then
          SyncPara.ControlWord.ptr^$BINT.4:=dValue$BOOL; //DRIVE ENABLE
        end_if;
        
        Controlword.EnableOperation := dValue$BOOL;

      end_if;      
      
      // SetSpeed
      if (SyncPara.SetSpeed.ptr <> NIL) & (pPDOWrite^.SetSpeed.Active = 1) then
        dValue := pPDOWrite^.SetSpeed.Value;
        if (SyncPara.SetSpeed.size=4) then
          SyncPara.SetSpeed.ptr^:=dValue;
        elsif (SyncPara.SetSpeed.size=2) then
          if SyncPara.SetSpeed.userinfo = 0 then
            if dValue > DRIVEAXIS_SPEED_SFFLIMITATION_USERINFO_0 then
              dValue := DRIVEAXIS_SPEED_SFFLIMITATION_USERINFO_0;
              AxisState.SFFLimitationActive := TRUE;
            elsif dValue < -DRIVEAXIS_SPEED_SFFLIMITATION_USERINFO_0-1 then
              dValue := -DRIVEAXIS_SPEED_SFFLIMITATION_USERINFO_0-1;
              AxisState.SFFLimitationActive := TRUE;
            else
              AxisState.SFFLimitationActive := FALSE;
            end_if;
            SyncPara.SetSpeed.ptr^$INT := to_int(dValue);
          elsif SyncPara.SetSpeed.userinfo = 1 then
             if dValue > DRIVEAXIS_SPEED_SFFLIMITATION_USERINFO_1 then
              dValue := DRIVEAXIS_SPEED_SFFLIMITATION_USERINFO_1;
              AxisState.SFFLimitationActive := TRUE;
            elsif dValue < -DRIVEAXIS_SPEED_SFFLIMITATION_USERINFO_1 then
              dValue := -DRIVEAXIS_SPEED_SFFLIMITATION_USERINFO_1;
              AxisState.SFFLimitationActive := TRUE;
            else
              AxisState.SFFLimitationActive := FALSE;
            end_if;
           SyncPara.SetSpeed.ptr^$INT := to_int(dValue);
          end_if;
        end_if;
      end_if;
      
    end_if;
    
  END_CASE;

END_FUNCTION


FUNCTION _DriveAxisBase::AllocMemPara
	VAR_OUTPUT
		retcode 	: BOOL;
	END_VAR
	
  retcode := FALSE;
	pSDDData$^void := DriveAxisSet.GetMemPtr();
	if pSDDData <> NIL then
		InitSDDHeader(pSDDData); // initialize the data of the header
		retcode := TRUE;
	end_if;

END_FUNCTION


FUNCTION _DriveAxisBase::InitSDDHeader
	VAR_INPUT
		pSDDHeader 	: ^_SDDMEMHEADER;
	END_VAR
  //Preparation of Data headerfor the Excel data exportation
  
  pSDDHeader^.udCRC32 := 0;
  pSDDHeader^.udLen := sizeof(_SDDMEMHEADER);
  pSddHeader^.udVersion := 1;
  pSDDHeader^.AxOffset := sizeof(_SDDMEMHEADER);
  pSDDHeader^.AxLength := 0;

END_FUNCTION


FUNCTION _DriveAxisBase::InitASyncPara
  
  AxASyncPara.pEnd := AxASyncPara.pStart + SDDBUFFERENTRY * sizeof(_DriveMngBase::_SDDBFENTRY);
  AxASyncPara.pRead := AxASyncPara.pStart;
  AxASyncPara.pWrite := AxASyncPara.pStart;
  AxASyncPara.ActEntries := 0;
  
  _memset(AxASyncPara.pStart, 16#00, SDDBUFFERENTRY*sizeof(_DriveMngBase::_SDDBFENTRY));
  
END_FUNCTION


FUNCTION VIRTUAL GLOBAL _DriveAxisBase::CyWork
	VAR_INPUT
		EAX 	: UDINT;
	END_VAR
	VAR_OUTPUT
		state (EAX) 	: UDINT;
	END_VAR
  VAR
    retZImpuls : USINT;
    pTabAdress : ^DINT;
    TabLength   : DINT;
    i : USINT;
  END_VAR  
  
  if (DriveMng.CommunicationState() = 0) | (Init_Again = true) then
    if bdSettings.bDriveInitialized = TRUE then
      InitASyncPara(); // to initialize the buffer only once time
    end_if;
    
    CmdState                      := ERROR;
    bdSettings.bDriveInitialized  := FALSE;
    bdSettings.bGotFeedBackType   := FALSE;
    bdSettings.bFeedbackSend      := FALSE;
    bdSettings.bDriveInit         := TRUE;
    bdSettings.bSyncSettings        := FALSE;
    bdSettings.bCorrectExtSyncPara  := FALSE;
    bdSettings.bParaInit          := FALSE;
    InitSSW                       := _SDD_STARTINIT;
    AxisState.NotOnline           := 1;
    AxisState.NotInitialized      := 1;
    FirstErrorReset               := 1; //0...no error to handle , 1...quit the first error
    FirstPosition                 := FALSE; //that is for Hot-Plug 
    Init_Again                    := FALSE;
    Online                        := 0;
    bOnlineFinished               := FALSE;
    bOnlineState                  := FALSE;
    
    //reset diagnose mode if online state is set to zero
    if pDiagThis <> NIL then
      SetDiagMode(bStartDiagMode:=FALSE, pThisObj:=pDiagThis);
    end_if;
    
    // disable drive and reset speed (no online check, directly in the PDO data)
    AxEnable                     := 0;
    SetSpeed := 0;
    Write_Enable(0);
    Write_SetSpeed(0);
  end_if;
  
//***********************************************\\
//** minimal 4 ms refresh time of all servers	**\\
//***********************************************\\
  if (bdSettings.bDriveInitialized = TRUE) & (ops.tabsolute - tUpdate >= MINTIMESVRUPDATE) then
    UpdateSvr(); // update all server parameters
    tUpdate := ops.tabsolute;
  end_if;

//*************************************\\
//** update the ZPulse just all 10ms **\\
//*************************************\\
  if (bdSettings.bDriveInitialized = TRUE) & (ops.tabsolute - tUpdateZPulse >= 10) then
    if (FirstPosition = false) then //when it is the first time, we check out the actual position
      oldRevolutions := (ActPos.Read() and maskZImpulse$DINT);	
      ZPulsLatch.Read();
      FirstPosition:=true;
    end_if;

    //Here we check the ZImpulse every 10ms
    retZImpuls:=GetZImpulse();
    if retZImpuls=1 then
      ZPulsLatch:=retZImpuls;
    end_if;
    tUpdateZPulse := ops.tabsolute;
  end_if;
  
// *********************************************************************************************************
// ** check if a successfully HW Connect was given
// ** and we have to initialize the axis
// *********************************************************************************************************
  if (DriveMng.CommunicationState() = 1) & (bdSettings.bAxInUse = TRUE) & (DriveMng.GetVaranDriveState() > 0) then

    AxisState.NotOnline := 0;
    if bdSettings.bDriveInit = TRUE then
      case InitSSW of
      
      _SDD_IDLE :
        // do nothing :
        
      _SDD_STARTINIT,
      _SDD_GETDRIVEINFO :
        // Get FW Version and Drive Type
        // Values SDD_I_FW and SDD_I_HW are needed for step _SDD_CHKFEEDBACK
        
        AddASyncEntry(usParaNr:=SDD_I_FW,   usRdWr:=0, dValue:=0, pThisObj:=this, usEntry:=0);
        AddASyncEntry(usParaNr:=SDD_I_HW,   usRdWr:=0, dValue:=0, pThisObj:=this, usEntry:=0); // ramand: get hw code as sync setting (use existing channel)
        AddASyncEntry(usParaNr:=SDD_I_SER,  usRdWr:=0, dValue:=0, pThisObj:=this, usEntry:=0); // ramand: serial number as sync setting (use existing channel)
        bdGetASyncEntry := 0;
        bdGetASyncEntry.bSDD_I_FW  := TRUE;
        bdGetASyncEntry.bSDD_I_HW  := TRUE;
        bdGetASyncEntry.bSDD_I_SER := TRUE;
        
        InitSSW := _SDD_WAIT4GETDRIVEINFO;
      
      _SDD_WAIT4GETDRIVEINFO :
      
        if bdGetASyncEntry = 0 then
          InitSSW := _SDD_CHKFEEDBACK;
        end_if;
        
      _SDD_CHKFEEDBACK :
        // überprüfen welches Feedback vorhanden ist
        if bdSettings.bGotFeedBackType = FALSE then 
          GetFeedBackType();
        else
         InitSSW := _SDD_SENDPARA;
        end_if;
        
      _SDD_SENDPARA :
      
        if bdSettings.bWaitInitFinished = FALSE then
          // Send all parameters to the drive
          SendDataToDrive();
          bdSettings.bWaitInitFinished := TRUE;
        else
          if DriveInitReady() = TRUE then
            InitSSW := _SDD_GETSYNCSETTINGS; 
          end_if;
        end_if;    
      
      
       _SDD_GETSYNCSETTINGS :
        
        if bdSettings.bSyncSettings = FALSE then
          AddASyncEntry(usParaNr:=SDD_A_VALTT1, usRdWr:=0, dValue:=0, pThisObj:=this, usEntry:=0);
          AddASyncEntry(usParaNr:=SDD_A_VALTT2, usRdWr:=0, dValue:=0, pThisObj:=this, usEntry:=0);
          AddASyncEntry(usParaNr:=SDD_A_VALRT1, usRdWr:=0, dValue:=0, pThisObj:=this, usEntry:=0);
          AddASyncEntry(usParaNr:=SDD_A_VALRT2, usRdWr:=0, dValue:=0, pThisObj:=this, usEntry:=0);
          AddASyncEntry(usParaNr:=SDD_P_PSCALE, usRdWr:=0, dValue:=0, pThisObj:=this, usEntry:=0);
          CountAval := 5;

          //Get Paravalue of A_CAPREF parameter
          //***********************************
          case DriveInitType of
            _SDDSTDTABLE, _SDDL2TABLE :
             pTabAdress := GetTabAdress(TabType:= DriveInitType$USINT, bdSettings.bSendMPara, #TabLength);
            _SDDRAMEX, _SDDFILE :	
              pTabAdress$^void := DriveAxisSet.GetMemPtr();	
              if pTabAdress then
                TabLength := pTabAdress^$_SDDMEMHEADER.AxLength$DINT;
                pTabAdress += pTabAdress^$_SDDMEMHEADER.AxOffset;
              end_if;
          end_case;
          
          //Search for para value in para tab
          if pTabAdress then
            for i := 0 to TabLength / PARAENTRYSIZE do
              if (pTabAdress)^$USINT = SDD_A_CAPREF then
                
                (* The reason why this parameter is written to the drive again after all values were written is because
                depending on A_EDGE parameter it can lead to a problem that the parameter A_CAPREF will not be accepted by the FW.
                If Bit 16 of SDD_A_EDGE is set then the parameter is used for all axes. If e.g. axis 1 is successfully configured with A_EDGE = 16#FFFF
                and then axis 2 will be configured and A_EDGE is still zero (uninitialized) then the value of A_CAPREF will not be accepted because A_EDGE is different
                for the two axes. After we send A_EDGE to the drive we can send A_CAPREF again to ensure that the parameter will be set right.*)
                
                AddASyncEntry(usParaNr:=SDD_A_CAPREF, usRdWr:=1, dValue:=(pTabAdress + 1)^$DINT, pThisObj:=this, usEntry:=0);  //+ 1 to get parameter data   
                CountAval += 1;      
                exit; //exit if para was found
              end_if;
              pTabAdress += PARAENTRYSIZE;      
            end_for;            
          end_if;
          
          bdSettings.bSyncSettings := TRUE;
        else
          if CountAval <= 0 then //when we got all parameters we can go on
            SetSynchronPara(); //here all the pointers will be set to the right place
            GetSynchronPara(); //here all the pointers will be set to the right place
            if bdSettings.bCorrectExtSyncPara then
              InitSSW := _SDD_CORRECTSYNCSETTINGS;
            else
            InitSSW := _SDD_SENDPARAFINISH;
            end_if;
          end_if;
        end_if;
      

      _SDD_CORRECTSYNCSETTINGS : // we got no extended axis but parameter say we do => correct parameter in drive
        AddASyncEntry(usParaNr:=SDD_A_VALTT2, usRdWr:=1, dValue:=0, pThisObj:=this, usEntry:=0);
        AddASyncEntry(usParaNr:=SDD_A_VALRT2, usRdWr:=1, dValue:=0, pThisObj:=this, usEntry:=0);
        InitSSW := _SDD_CHECKSYNCSETTINGS;

      
      _SDD_CHECKSYNCSETTINGS :
        if bdSettings.bCorrectExtSyncPara = TRUE then
          bdSettings.bCorrectExtSyncPara := FALSE;
          AddASyncEntry(usParaNr:=SDD_A_VALTT2, usRdWr:=0, dValue:=0, pThisObj:=this, usEntry:=0);
          AddASyncEntry(usParaNr:=SDD_A_VALRT2, usRdWr:=0, dValue:=0, pThisObj:=this, usEntry:=0);
          CountAval := 2;
        else
          if CountAval <= 0 then //when we got all parameters we can go on
            // if we still got a problem, we go to errorstep
            if bdSettings.bCorrectExtSyncPara then
              AxisState.NoParameter := TRUE;
              CmdState := ERROR;
              InitSSW := _SDD_ERRORININIT;
              LogError("@04C3 (_DriveAxisBase::CyWork) Failed to reset A_VALRT2 or A_VALTT2 (Extend is not set at DriveAxis, but extended Parameter is not zero).");
            else
              InitSSW := _SDD_SENDPARAFINISH;
            end_if;
          end_if;
        end_if;
      
      _SDD_SENDPARAFINISH : 
      
        bdSettings.bDriveInit        := FALSE;
        bdSettings.bWaitInitFinished := FALSE;
        bdSettings.bDriveInitialized := TRUE;
        AxisState.NotInitialized     := FALSE;
        CmdState                     := READY;
        
        // set the torque reduction
//        AxTorqueControl.Write(4500); //it does not matter which controlword we have, because the internal function reduced this amount to the top limit
        SetAxTorque(4500);
        
        DriveMng.AxisInitFinished(AxisNo:=usAxisIndex);

        // Set finish info to the parameter classes
        bdSettings.bParaError := FALSE;
        
        SetParaState(SDD_GENERAL_READY); //Now we tell all the connected classes, that our initialization is done and okay
        
        SDDCmdIntfc := _SDDIDLE; 
        InitSSW     := _SDD_IDLE;
        
      end_case;
    end_if;
  end_if;
      
// *********************************************************************************************************
// ** Drive is initialized and ok                                               												  **
// *********************************************************************************************************
  
  if bdSettings.bDriveInitialized = TRUE then

    case FirstErrorReset of
      0: //it is nothing to do for the error quit
      1:
        if IsOnline() = TRUE then
          if (GetAxError() = 1)  then
            ErrorQuitTime:=ops.tAbsolute; 
            FirstErrorReset := 2;
          else
            FirstErrorReset := 0;
          end_if;
        end_if;
      2:
        if ((ops.tAbsolute - ErrorQuitTime) > 100) then
          ErrorQuitHandling(input := 1);
          ErrorQuitTime:=ops.tAbsolute;
          FirstErrorReset := 3;
        end_if;
      3:
        if ((ops.tAbsolute - ErrorQuitTime) > 100) then
          ErrorQuitHandling(input:= 0);
          FirstErrorReset:=0;
        end_if;
      4: //that is for resetting the AxErrorQuit after 100ms, when a user writes a 1 on it
        if ((ops.tAbsolute - ErrorQuitTime) > 100) | (GetAxError() = 0) then
          ErrorQuitHandling(input:= 0);
          FirstErrorReset:=0;
        end_if;
    end_case;
    
    if (AxisExtend = 1) & (SyncParaObject<>NIL) then //it is time for the SyncExtend class
      SyncParaObject$^VirtualBase^.CyWork(EAX);
    end_if;


// *********************************************************************************************************
// ** Save the drive parameter in the ramex or in the file											                      	  **
// *********************************************************************************************************
    if bdSettings.bInitRamAxis = TRUE then
      SaveDrivePara();
      bdSettings.bInitRamAxis := FALSE;
    end_if;
    
    //write the actual datas to the parameter objects
    if bdSettings.bParaInit = FALSE & IsOnline() = TRUE then
      //check if we use absolute feedback or not
      if bdSettings.bNoAbsEnc = TRUE then
        //no absolute feedback -> get parameters from file or ram to set it to the parameterclasses
        LoadDrivePara();
      else
        //absolute feedback -> get parameters from drive and set it to the parameterclasses
        SDDCmdIntfc := _SDDREADALL;
      end_if;
      bdSettings.bParaInit := TRUE;
    end_if;
    
// *********************************************************************************************************
// ** command interface for the drive                                           												  **
// *********************************************************************************************************
    SDDProcess();
  end_if;
  
  state := READY;
  
END_FUNCTION


FUNCTION _DriveAxisBase::UpdateSvr
  
  if (IsOnlineFinished() = 1) then    
    bOnlineState := TRUE;
    //disable set online finished flag if diag mode is active
    if AxisState.DiagModeActive = FALSE then  
      bOnlineFinished := TRUE;
    end_if;  
  end_if;
  
  Online.read();
  ActPos.Read();
  ActSpeed.Read();
  ActCurrent.Read();
  StateWord.Read();
  AxError.Read();
  ActXw.Read();
  Input1.Read();
  Input2.Read();
  Input3.Read();
  Input4.Read();
  Input5.Read();
  Input6.Read();
  Input7.Read();
  Input8.Read();

END_FUNCTION


FUNCTION _DriveAxisBase::GetFeedBackType

  // Es wird zwischen Absolutwertgebern und sonstigen Rückführungssystem unterschieden.
  // Grund : bei Absolutwertgebern dürfen die Motorparameter nicht gesendet werden
  
  if bdSettings.bFeedbackSend = FALSE then
    // get the feedbacktype for the axis
    if bdSettings.bAxInUse = TRUE then
      AddASyncEntry(SDD_M_TYPE, 0, 0, this, 0);
    else
      bdSettings.bGotFeedBackType := TRUE;
    end_if;

    bdSettings.bFeedBackSend := TRUE;
  end_if;
  
END_FUNCTION


FUNCTION VIRTUAL GLOBAL _DriveAxisBase::AddASyncEntry
	VAR_INPUT
		usParaNr 	: USINT;
		usRdWr 	: USINT;
		dValue 	: DINT;
		pThisObj 	: ^void;
		usEntry 	: USINT;
	END_VAR
	VAR_OUTPUT
		retcode 	: DINT;
	END_VAR
  
  //check if diag mode is activated, block all other accesses if it is active
  if AxisState.DiagModeActive = FALSE | pThisObj = pDiagThis then
    retcode := DriveMng.AddASyncEntry(AxisNo:=usAxisIndex, usParaNr, usRdWr, dValue, pThisObj, usEntry);
  else 
    retcode := -11;
  end_if;

END_FUNCTION


FUNCTION VIRTUAL GLOBAL _DriveAxisBase::AddASyncEntryIntHWCValue
	VAR_INPUT
		dIntValueIndex 	: DINT;
		pThisObj 	: ^void;
		usEntry 	: USINT;
	END_VAR
	VAR_OUTPUT
		retcode 	: DINT;
	END_VAR

  //check if diag mode is activated, block all other accesses if it is active
  if AxisState.DiagModeActive = FALSE | pThisObj = pDiagThis then
    retcode := DriveMng.AddASyncEntryIntHWCValue(usAxisIndex, dIntValueIndex, pThisObj, usEntry);
  else 
    retcode := -11;
  end_if;

END_FUNCTION


FUNCTION _DriveAxisBase::SendDataToDrive

  
  CreateDefMPara(); // now check if an absolute encoder is used

  case  DriveInitType of
  
    _SDDSTDTABLE:       // Standard Table check if a UserTable is given or not

      DataOfStdTable(); 
    
    _SDDL2TABLE:        // Lasal 2 Table check if the tables are available, 
                        // is there no Lasal2 table available, use the standard table (see step 0)
      DataOfL2table();
    
    _SDDRAMEX:          // Data of the RamEx
      DataOfRamEx();
    
    _SDDFILE:           // Data of the file
      DataOfFile();
  
  end_case;

END_FUNCTION



FUNCTION _DriveAxisBase::CreateDefMPara
  VAR
    CmdPara : CmdStruct;
    Results : results;
  END_VAR

  case DriveAxisSet.GetFeedBackInfo() of
    
    0 : // When using absolutefeedback don't download the Motorparameters
      if bdSettings.bNoAbsEnc = TRUE then
        bdSettings.bSendMPara := TRUE;
      else
        bdSettings.bSendMPara := FALSE;
      end_if;
    
    1 : // When using absolutefeedback all parameters except the M-ROFF will be downloaded
      bdSettings.bSendMPara := TRUE;
      
      // Set what motorparameter we can't send to the drive when absolutefeedback is used
      if bdSettings.bNoAbsEnc = FALSE then
        MParaBuffer.NoItems := 1;
        MParaBuffer.MBuffer[0] := SDD_M_ROFF;
          
        CmdPara.uiCmd     := 1;  // This is the command for avoid sending parameters
        CmdPara.aPara[0]  := (#MParaBuffer.MBuffer[0])$DINT;
        CmdPara.aPara[1]  := MParaBuffer.NoItems;
        CmdPara.aPara[2]  := usAxisIndex;
        DriveMng.CreateDefParaBase(#CmdPara, #Results);
          
      end_if;

    99 : // When using absolutefeedback all motorparameters will be downloaded, including the M-ROFF
         // this should not be used!
        bdSettings.bSendMPara := TRUE;
         
    else
    
      // When using absolutefeedback, no motorparameters will be downloaded
        if bdSettings.bNoAbsEnc = TRUE then
          bdSettings.bSendMPara := TRUE;
        else
          bdSettings.bSendMPara := FALSE;
        end_if;

  end_case;

END_FUNCTION


FUNCTION _DriveAxisBase::DataOfStdTable 
  VAR
    TabAdress  : ^DINT;
    TabLength   : DINT;
  END_VAR

  TabAdress := GetTabAdress(TabType:=0, bMotorPara:=bdSettings.bSendMPara, #TabLength);
  DriveMng.SetParaList(usAxisIndex, adress:=(TabAdress)$^void, ui_counter:=((TabLength)/5)$USINT);
  bdSettings.bInitRamAxis := TRUE;
  
END_FUNCTION


FUNCTION _DriveAxisBase::DataOfL2table 
  VAR
    TabAdress  : ^DINT;
    TabLength   : DINT;
  END_VAR

  // check if a L2 table for the axis exists
  TabAdress := GetTabAdress(TabType:= 1, bMotorPara := bdSettings.bSendMPara, #TabLength);
  DriveMng.SetParaList(usAxisIndex, adress:=(TabAdress)$^void, ui_counter:=((TabLength)/5)$USINT);
  bdSettings.bInitRamAxis := TRUE;
  
END_FUNCTION


FUNCTION _DriveAxisBase::DataOfRamEx 
  VAR
    udRamExLength	: UDINT;
  END_VAR

  // first check if RamEx Data is available
  udRamExLength := DriveAxisSet.GetRamExLength();
  if (udRamExLength > 0) & (SDDCmdIntfc <> _SDDURINIT) then 
    LoadDataRam();
  else
    // load the table info to the drive
    DataOfL2Table();
    bdSettings.bInitRamAxis := TRUE;
  end_if;

END_FUNCTION


FUNCTION _DriveAxisBase::DataOfFile
  VAR
    udRamFileLen	: UDINT;
  END_VAR

  // first check if RamEx Data is available
  udRamFileLen := DriveAxisSet.GetRamFileLen();
  if (udRamFileLen > 0) & (SDDCmdIntfc <> _SDDURINIT) then 
    LoadDataRam();
  else
    // load the table info to the drive
    DataOfL2Table();
    bdSettings.bInitRamAxis := TRUE;
  end_if;
  
END_FUNCTION


FUNCTION _DriveAxisBase::GetTabAdress
	VAR_INPUT
		TabType 	: DINT;
		bMotorPara 	: BOOL;
		pTabLength 	: ^DINT;
	END_VAR
	VAR_OUTPUT
		pTabAdress 	: ^DINT;
	END_VAR
 
  if TabType = 0 then
    pTabAdress := DriveAxisSet.GetUserTab(bMotorPara, pTabLength);
  elsif TabType = 1 then
    pTabAdress := DriveAxisSet.GetL2Tab(this$^void,bMotorPara,pTabLength);
    if pTabAdress = NIL then
      pTabAdress := DriveAxisSet.GetUserTab(bMotorPara,pTabLength);
    end_if; 
  end_if;

  if pTabAdress = NIL then
  
    // errorcode setzen
    CmdState := ERROR;
    AxisState.NoParameter := TRUE;
    AxisState.NotInitialized := FALSE;
    bdSettings.bDriveInit := FALSE;
    bdSettings.bWaitInitFinished := FALSE;
    bdSettings.bDriveInitialized := TRUE;
    DriveMng.AxisInitFinished(AxisNo:=usAxisIndex);
    InitSSW := _SDD_IDLE;

  end_if;

END_FUNCTION


FUNCTION TAB _DriveAxisBase::SDDTabDefault
// nur damit wir keine relevanten Daten verändern wenn keine Achsparameter vorhanden sind

// M-NAME1	P01	Beginning 4 Characters of the Motor Name	
001$USINT,	0$DINT

END_FUNCTION


FUNCTION _DriveAxisBase::LoadDataRam
  VAR
    udCRC32		: UDINT;
    pHlp		: ^DINT;
    retcode		: BOOL;
  END_VAR	
	// get actual ramex data
	
  retcode := FALSE;
  
  if DriveInitType = _SDDRAMEX then
    retcode := DriveAxisSet.CpyRamExMem();
  elsif DriveInitType = _SDDFILE then
    retcode := DriveAxisSet.CpyRamFileMem();
  end_if;
  
  if retcode = FALSE then
    return;
  end_if;
  // get the actual ptr of the memory
  pSDDData$^void := DriveAxisSet.GetMemPtr();	

  if pSDDData <> NIL then	
    // if the length is at least enough for the CRC
    if pSDDData^.udLen > sizeof(UDINT) then
      // check the crc32 of the ramex
      udCRC32 := DriveAxisSet.CalcCRC32(pData:=(pSDDData + sizeof(UDINT))$^UDINT, udLen:=pSDDData^.udLen - sizeof(UDINT));
    end_if;
    
    // if the length is not ok or the CRC doesn't match
    if (pSDDData^.udLen <= sizeof(UDINT)) | (udCRC32 <> pSDDData^.udCRC32) then
      // invalid CRC32 or wrong length information
      DataOfL2Table();
      bdSettings.bInitRamAxis := TRUE;
      return;
    end_if;

    pHlp$DINT := pSDDData$DINT + pSDDData^.AxOffset; 
    // set the parameters
    DriveMng.SetParaList(usAxisIndex, adress:=pHlp$^void, ui_counter:=(pSDDData^.AxLength/5)$USINT);

  else
    // load the table info to the drive
    DataOfL2Table();
    bdSettings.bInitRamAxis := TRUE;	
  end_if;

END_FUNCTION


FUNCTION _DriveAxisBase::DriveInitReady
	VAR_OUTPUT
		retcode 	: BOOL;
	END_VAR
  VAR
    AxisState       : DINT;
  END_VAR
   
  retcode := FALSE;
  
  if bdSettings.bAxInUse then
    
    AxisState := DriveMng.GetParameterState(usAxisIndex);
    
    if AxisState = 0 then
      retcode := TRUE;
    end_if;
  else
    retcode := TRUE;
  end_if;

END_FUNCTION


FUNCTION _DriveAxisBase::SetParaState
	VAR_INPUT
		ActState 	: UINT;
	END_VAR
  VAR
    x     : UDINT;
    pThisNewInst  : ^void;
    UserPara      : CmdStruct;
    UserResult    : Results;
  END_VAR
  
  if bdSettings.bAxSetPara = TRUE then
    for x := IDX_MOTOR_PARA to IDX_ERRORHANDLING do
      pThisNewInst$DINT := AxSetPara[x];
      if pThisNewInst <> NIL then
        UserPara.uiCmd := ActState;
        pThisNewInst$^VirtualBase^.NewInst(#UserPara, #UserResult);
      end_if;
    end_for;
  end_if;
  
  if SyncParaObject<>NIL then //Tell the SyncExtend class also the news
    UserPara.uiCmd := ActState;
    SyncParaObject$^VirtualBase^.pSvrChCmd.NewInst(#UserPara, #UserResult);
  end_if;

END_FUNCTION


FUNCTION _DriveAxisBase::SavParaValue
	VAR_INPUT
		ParaNo 	: USINT;
		Value 	: DINT;
		bSavSRAM 	: BOOL;
	END_VAR
	VAR_OUTPUT
		retcode 	: BOOL;
	END_VAR
  VAR
    udOffset    : UDINT;
    pHlp        : ^DINT;
  END_VAR
  
  retcode := FALSE;
    
  // check the saving type
  case DriveInitType of
  
  _SDDSTDTABLE,
  _SDDL2TABLE :
    
    retcode := TRUE;
    
  _SDDRAMEX :
    
    // now check if the parameter exists
    udOffset := ParaNrExist(ParaNo); 
    // get the actual ptr of the memory
    pSDDData$^void := DriveAxisSet.GetMemPtr();	
    
    if udOffset <> 16#FFFFFFFF then
      // entry is already available
      pHlp$UDINT := pSDDData$UDINT + udOffset;
      pHlp^$DINT := Value;
      // now calculate the checksum
      pSDDData^.udCRC32 := DriveAxisSet.CalcCRC32((pSDDData + sizeof(UDINT))$^UDINT, pSDDData^.udLen - sizeof(UDINT));
      if bSavSRAM = TRUE then
        // save the new value
        DriveAxisSet.SaveRamExData(pData:=#Value, udLen:=sizeof(DINT), udOffset:=udOffset);
        // save the new chksum
        DriveAxisSet.SaveRamExData(pData:=#pSDDData^.udCRC32, udLen:=sizeof(DINT), udOffset:=0);
      end_if;
    else
      // new entry in the buffer
      if InsNewParaNr(ParaNo, Value) = TRUE then
    
        // get the actual ptr of the memory
        pSDDData$^void := DriveAxisSet.GetMemPtr();	
        
        // now calculate the checksum
        pSDDData^.udCRC32 := DriveAxisSet.CalcCRC32((pSDDData + sizeof(UDINT))$^UDINT, pSDDData^.udLen - sizeof(UDINT));
        if bSavSRAM = TRUE then
          DriveAxisSet.SaveRamExData(pData:= pSDDData, udLen:= pSDDData^.udLen, udOffset:= 0);
        end_if;
      end_if;
    end_if;
    
  _SDDFILE :
    
    // now check if the parameter exists
    udOffset := ParaNrExist(ParaNo);
    // get the actual ptr of the memory
    pSDDData$^void := DriveAxisSet.GetMemPtr();	
    
    if udOffset <> 16#FFFFFFFF then
      // entry is already available
      pHlp$UDINT := pSDDData$UDINT + udOffset;
      pHlp^$DINT := Value;
      // now calculate the checksum
      pSDDData^.udCRC32 := DriveAxisSet.CalcCRC32((pSDDData + sizeof(UDINT))$^UDINT, pSDDData^.udLen - sizeof(UDINT));
      if bSavSRAM = TRUE then
        // save the new value
        DriveAxisSet.SaveRamFileData(pData:= #Value, udLen:= sizeof(DINT), udOffset:= udOffset);
        // save the new chksum
        DriveAxisSet.SaveRamFileData(pData:= #pSDDData^.udCRC32, udLen:= sizeof(DINT), udOffset:= 0);
      end_if;
    else
      // new entry in the buffer
      if InsNewParaNr(ParaNo, Value) = TRUE then
    
        // get the actual ptr of the memory
        pSDDData$^void := DriveAxisSet.GetMemPtr();	
        
        // now calculate the checksum
        pSDDData^.udCRC32 := DriveAxisSet.CalcCRC32((pSDDData + sizeof(UDINT))$^UDINT, pSDDData^.udLen - sizeof(UDINT));
        if bSavSRAM = TRUE then
          DriveAxisSet.SaveRamFileData(pData:= pSDDData, udLen:= pSDDData^.udLen, udOffset:= 0);
        end_if;
      end_if;
    end_if;
  end_case;
  
END_FUNCTION


FUNCTION _DriveAxisBase::ParaNrExist
	VAR_INPUT
		ParaNr 	: USINT;
	END_VAR
	VAR_OUTPUT
		udOffset 	: UDINT;
	END_VAR
  VAR
    pHlp    : ^DINT;
    x       : UDINT;
  END_VAR
  
  udOffset := 16#FFFFFFFF;
  // get the actual ptr of the memory
  pSDDData$^void := DriveAxisSet.GetMemPtr();


  if bdSettings.bAxInUse = TRUE then
    pHlp$DINT := pSDDData$DINT + pSDDData^.AxOffset;
    x := 0;
    while x < pSDDData^.AxLength$UDINT do
      if pHlp^$USINT = ParaNr then
        udOffset := pSDDData^.AxOffset$UDINT + x + sizeof(USINT);
        return;
      end_if;
      pHlp += PARAENTRYSIZE;
      x += PARAENTRYSIZE;
    end_while;
  end_if;
  
END_FUNCTION


FUNCTION _DriveAxisBase::InsNewParaNr
	VAR_INPUT
		ParaNr 	: USINT;
		ParaValue 	: DINT;
	END_VAR
	VAR_OUTPUT
		retcode 	: BOOL;
	END_VAR
  VAR
    pMove     : ^DINT;
    udLen     : UDINT;
  END_VAR
  
  retcode := FALSE;
  
  // get the actual ptr of the memory
  pSDDData$^void := DriveAxisSet.GetMemPtr();	
  
  if (pSDDData^.udLen + PARAENTRYSIZE) >= SDDMAXMEM then
    return;
  end_if;
  
  if bdSettings.bAxInUse = TRUE then
    pMove$DINT := pSDDData$DINT + pSDDData^.AxOffset + pSDDData^.AxLength$DINT;
    udLen := pSDDData^.udLen - (pMove$UDINT - pSDDData$UDINT); 
    _memmove((pMove + PARAENTRYSIZE)$^void, pMove$^void, udLen);
    pMove^$USINT := ParaNr;
    pMove += sizeof(USINT);
    pMove^$DINT := ParaValue;
    pSDDData^.udLen += PARAENTRYSIZE;
    pSDDData^.AxLength += PARAENTRYSIZE;
    
    retcode := TRUE;
  end_if;
  
END_FUNCTION


FUNCTION _DriveAxisBase::ChkFb
	VAR_INPUT
		FbType 	: DINT;
	END_VAR
	VAR_OUTPUT
		retcode 	: BOOL;
	END_VAR
  VAR
    FbInfo  : DINT;
  END_VAR
  
  retcode := TRUE;
  // get the first Byte of the Feedback info
  FbInfo := FbType AND 16#FF;
  
  case FbInfo of
    0 : // Resolver
        
    1 : // Resolver with multi turn feedback
    
    2 : // Endat
      retcode := FALSE;
      
    3 : // Hiperface
      retcode := FALSE;
      
    4 : // Sin/Cos Encoder
      
    5 : // sensorless
    
    6 : // incremental encoder
    
    7 : // EnDat with Drive multi turn extension
      retcode := FALSE;
      
    15 :// HiperfaceDLS
      
      // The MDD2000 supports the reading of encoder parameters for HiperfaceDSL encoders starting with FW version v1.30.
      if (DriveType = _MDD_2000) then  
        if ( abs(FwVersionInt) >= DRIVEMNG_MDD2000FWVERSION_HIPERFACEDSL) then
          retcode := FALSE;
        end_if;
      else
        // It is assumed that new developed drives with this encoder will support the reading of encoder parameters with the first release version.
        retcode := FALSE;
      end_if;
    
  end_case;
  
END_FUNCTION


FUNCTION VIRTUAL GLOBAL _DriveAxisBase::IsOnline
	VAR_OUTPUT
		retcode 	: BOOL;
	END_VAR
  
  retcode := to_bool(DriveMng.Online.read());
  
END_FUNCTION


FUNCTION VIRTUAL GLOBAL _DriveAxisBase::AddParaObjects
	VAR_INPUT
		Index 	: USINT;
		pThis 	: ^void;
	END_VAR
	VAR_OUTPUT
		retcode 	: BOOL;
	END_VAR
  
  retcode := FALSE;
  // check if we are inside the limits
  if (Index >= IDX_MOTOR_PARA) & (Index <= IDX_ERRORHANDLING) & (pThis <> NIL) then
    
    AxSetPara[Index] := pThis$DINT;
    bdSettings.bAxSetPara := TRUE;
    retcode := TRUE;

  end_if;

END_FUNCTION


FUNCTION VIRTUAL GLOBAL _DriveAxisBase::SetSynchronPara
  VAR
  	x         : SINT;
    SetAVALRT : HSINT;
  END_VAR

  SetValuePtr := DriveMng.GetAxisWrPtr(usAxis:=usAxisIndex); // Zeiger auf die Sollwerte von der Struktur t_WriteValuePtr
  
  for x:=4 to 0 by -1 do

    SetAVALRT:=SetValues[x]; //A-VALRT values
    
    case SetAVALRT of
    
      16#01: //-> Current setpoint in mA
      
        SyncPara.SetCurrent.size:=4;
        SyncPara.SetCurrent.ptr := #SetValuePtr^.a_SyncValues[x];
        SyncPara.SetCurrent.userinfo := 0;
        
      16#02: //-> Velocity set point in rpm 
      
        SyncPara.SetSpeed.size:=4;
        SyncPara.SetSpeed.ptr := #SetValuePtr^.a_SyncValues[x];
        SyncPara.SetSpeed.userinfo := 0;
        
      16#03: //-> Position set point in counts 
      
        SyncPara.SetPos.size:=4;
        SyncPara.SetPos.ptr := #SetValuePtr^.a_SyncValues[x];
        
      16#04: //-> Speed feed forward of the position controller in counts per cycle time
      
        SyncPara.SetSpeed.size:=4;
        SyncPara.SetSpeed.ptr := #SetValuePtr^.a_SyncValues[x];
      
      16#05: //-> controlword + Current setpoint in cA 
      
        SyncPara.SetCurrent.size := 2;
        SyncPara.SetCurrent.ptr := #SetValuePtr^.a_SyncValues[x];
        SyncPara.SetCurrent.userinfo := 1;
        
        SyncPara.ControlWord.size := 2;
        SyncPara.ControlWord.ptr := #SetValuePtr^.a_SyncValues[x] + sizeof(UINT);
        SyncPara.ControlWord.userinfo := 0;
        
        SyncPara.SetTorque.size := 2;
        SyncPara.SetTorque.ptr := #SetValuePtr^.a_SyncValues[x] + sizeof(UINT);
        SyncPara.SetTorque.userinfo := 0;
        
      16#06: //-> controlword + Velocity set point in rpm 
      
        SyncPara.SetSpeed.size := 2;
        SyncPara.SetSpeed.ptr := #SetValuePtr^.a_SyncValues[x];
        SyncPara.SetSpeed.userinfo := 0;
        
        SyncPara.ControlWord.size := 2;
        SyncPara.ControlWord.ptr := #SetValuePtr^.a_SyncValues[x] + sizeof(UINT);
        SyncPara.ControlWord.userinfo := 0;
        
        SyncPara.SetTorque.size := 2;
        SyncPara.SetTorque.ptr := #SetValuePtr^.a_SyncValues[x] + sizeof(UINT);
        SyncPara.SetTorque.userinfo := 0;
        
      16#07: //-> controlword + Speed feed forward of the position controller in counts per cycle time 
      
        SyncPara.SetSpeed.size := 2;
        SyncPara.SetSpeed.ptr := #SetValuePtr^.a_SyncValues[x];
        SyncPara.SetSpeed.userinfo := 0; 
        
        SyncPara.ControlWord.size := 2;
        SyncPara.ControlWord.ptr := #SetValuePtr^.a_SyncValues[x] + sizeof(UINT);
        SyncPara.ControlWord.userinfo := 0;
        
        SyncPara.SetTorque.size := 2;
        SyncPara.SetTorque.ptr := #SetValuePtr^.a_SyncValues[x] + sizeof(UINT);
        SyncPara.SetTorque.userinfo := 0;
        
      16#08: //-> Velocity set point in mrpm 
        
        SyncPara.SetSpeed.size := 4;
        SyncPara.SetSpeed.ptr := #SetValuePtr^.a_SyncValues[x];
        SyncPara.SetSpeed.userinfo := 0; 
        
      16#09: //32 bit controlword
        
        SyncPara.ControlWord.size := 2;
        SyncPara.ControlWord.ptr := #SetValuePtr^.a_SyncValues[x] + sizeof(UINT);
        SyncPara.ControlWord.userinfo := 1; 
        
        SyncPara.SetTorque.size := 2;
        SyncPara.SetTorque.ptr := #SetValuePtr^.a_SyncValues[x];
        SyncPara.SetTorque.userinfo := 1; 
        
      16#0D: //13 -> controlword + Current feed forward in cA 
      
        SyncPara.SetCurrent.size := 2;
        SyncPara.SetCurrent.ptr := #SetValuePtr^.a_SyncValues[x];
        SyncPara.SetCurrent.userinfo := 1;
        
        SyncPara.ControlWord.size := 2;
        SyncPara.ControlWord.ptr := #SetValuePtr^.a_SyncValues[x] + sizeof(UINT);
        SyncPara.ControlWord.userinfo := 0;
        
        SyncPara.SetTorque.size := 2;
        SyncPara.SetTorque.ptr := #SetValuePtr^.a_SyncValues[x] + sizeof(UINT);
        SyncPara.SetTorque.userinfo := 0;
                
      16#1B: //27-> PWM setvalue for G-MODE=7 + controlword
        //PWM from -1000 to 1000 for -100% to 100% is preset via SetSpeed
        SyncPara.SetSpeed.size := 2;
        SyncPara.SetSpeed.ptr := #SetValuePtr^.a_SyncValues[x];
        SyncPara.SetSpeed.userinfo := 1; 

        SyncPara.ControlWord.size := 2;
        SyncPara.ControlWord.ptr := #SetValuePtr^.a_SyncValues[x] + sizeof(UINT);
        SyncPara.ControlWord.userinfo := 0;

        SyncPara.SetTorque.size := 2;
        SyncPara.SetTorque.ptr := #SetValuePtr^.a_SyncValues[x] + sizeof(UINT);
        SyncPara.SetTorque.userinfo := 0;
                
    end_case;

  end_for;

END_FUNCTION


FUNCTION VIRTUAL GLOBAL _DriveAxisBase::SetPos::Write
	VAR_INPUT
		input (EAX) 	: DINT;
	END_VAR
	VAR_OUTPUT
		result (EAX) 	: DINT;
	END_VAR
  
  if (SyncPara.SetPos.ptr <> NIL) & bOnlineFinished then
    SetPos:=input;
    SyncPara.SetPos.ptr^:=input; 
  end_if;
  
 	result := SetPos;

END_FUNCTION


FUNCTION VIRTUAL GLOBAL _DriveAxisBase::SetSpeed::Write
	VAR_INPUT
		input (EAX) 	: DINT;
	END_VAR
	VAR_OUTPUT
		result (EAX) 	: DINT;
	END_VAR

	if bOnlineFinished then
    SetSpeed := Write_SetSpeed(input);  //write value to PDO data, and set possible statusflags.
        end_if;
 	result := SetSpeed;

END_FUNCTION


FUNCTION VIRTUAL GLOBAL _DriveAxisBase::SetCurrent::Write
	VAR_INPUT
		input (EAX) 	: DINT;
	END_VAR
	VAR_OUTPUT
		result (EAX) 	: DINT;
	END_VAR

  if (SyncPara.SetCurrent.ptr <> NIL) & bOnlineFinished then
    SetCurrent:=input;
    if (SyncPara.SetCurrent.size=4) then
      SyncPara.SetCurrent.ptr^:=input;
    elsif (SyncPara.SetCurrent.size=2) then
      if SyncPara.SetCurrent.userinfo = 1 then
        SyncPara.SetCurrent.ptr^$INT:=to_int(input / 10); //because we always get mA and in one case we must send cA
      else
        SyncPara.SetCurrent.ptr^$INT:=to_int(input); //32-Bit-Steuerwort
      end_if;
    end_if;
  end_if;
  
  result := SetCurrent;

END_FUNCTION


FUNCTION VIRTUAL GLOBAL _DriveAxisBase::ControlWord::Write
	VAR_INPUT
		input (EAX) 	: DS402_Control;
	END_VAR
	VAR_OUTPUT
		result (EAX) 	: DS402_Control;
	END_VAR
  VAR
  	cBuffer : BDINT; //ControlWord Buffer
  END_VAR
  
  cBuffer := 0; // local variable 
  
  if (SyncPara.ControlWord.ptr <> NIL) & bOnlineFinished then
    
    if (SyncPara.ControlWord.userinfo=0) then //normal controlword
            
      cBuffer.1  :=input.EnableOperation;   //DRIVE ENABLE
      cBuffer.2  :=input.ResetFault;        //FAULT RESET
      cBuffer.3  :=input.ManufactureSpec1;  //AMODE2
      cBuffer.4  :=input.ManufactureSpec2;  //KFBRW3
      cBuffer.5  :=input.ManufactureSpec4;  //Output1
      cBuffer.6  :=input.ManufactureSpec5;  //Output2
      cBuffer.7  :=input.ManufactureSpec3;  //KBRAKE
      cBuffer.8  :=input.Reserved1;         //ECHO
      cBuffer.9  :=input.OperationModeSpec1;//SINGLE CAPTURE
      
      cBuffer:=TorqueCalculation(cBuffer, AxTorqueControl); //cBuffer -> we must add TorqueControl
      
      SyncPara.ControlWord.ptr^$INT:=to_int(cBuffer);
      
    elsif(SyncPara.ControlWord.userinfo=1)then
      
      cBuffer.1 :=input.SwitchOn;   
      cBuffer.2 :=input.EnableVoltage;        
      cBuffer.3 :=input.QuickStop;  
      cBuffer.4 :=input.EnableOperation;    //DRIVE ENABLE
      cBuffer.5 :=input.OperationModeSpec1;  
      cBuffer.6 :=input.OperationModeSpec2; 
      cBuffer.7 :=input.OperationModeSpec3;  
      cBuffer.8 :=input.ResetFault;         //FAULT RESET
      cBuffer.9 :=input.Halt;
      cBuffer.10 :=input.Reserved1;
      cBuffer.11 :=input.Reserved2;
      cBuffer.12 :=input.ManufactureSpec1;  //AMODE2
      cBuffer.13 :=input.ManufactureSpec2;  //KFBRW3
      cBuffer.14 :=input.ManufactureSpec3;  //KBRAKE
      cBuffer.15 :=input.ManufactureSpec4;  //Output1
      cBuffer.16 :=input.ManufactureSpec5;  //Output2
      
      SyncPara.ControlWord.ptr^$INT:=to_int(cBuffer);
      
    end_if;
    
  end_if;
  
  ControlWord := input;
  result := ControlWord;

END_FUNCTION


FUNCTION VIRTUAL GLOBAL _DriveAxisBase::AxEnable::Write
	VAR_INPUT
		input (EAX) 	: DINT;
	END_VAR
	VAR_OUTPUT
		result (EAX) 	: DINT;
	END_VAR
  
  if (SyncPara.ControlWord.ptr <> NIL) & bOnlineFinished then
    AxEnable:= Write_Enable( input AND 1 );
  end_if;
  result:=AxEnable;
  
END_FUNCTION


FUNCTION VIRTUAL GLOBAL _DriveAxisBase::AxErrorQuit::Write
	VAR_INPUT
		input (EAX) 	: DINT;
	END_VAR
	VAR_OUTPUT
		result (EAX) 	: DINT;
	END_VAR
  
  if SyncPara.ControlWord.ptr & (FirstErrorReset = 0) & bOnlineFinished then

    if (AxError = 1) then

      ErrorQuitHandling(input);

    end_if;
    
  end_if;
  
  result := AxErrorQuit;

END_FUNCTION


FUNCTION VIRTUAL GLOBAL _DriveAxisBase::AxTorqueControl::Write
	VAR_INPUT
		input (EAX) 	: UDINT;
	END_VAR
	VAR_OUTPUT
		result (EAX) 	: UDINT;
	END_VAR

  if (SyncPara.SetTorque.ptr <> NIL) & bOnlineFinished then
    SetAxTorque(input);    
  end_if;
  
  result := AxTorqueControl;
  
END_FUNCTION


FUNCTION _DriveAxisBase::TorqueCalculation
	VAR_INPUT
		cBuffer 	: BDINT;
		input 	  : UDINT;
	END_VAR
	VAR_OUTPUT
		result 	  : BDINT;
	END_VAR
  VAR
  	IReduce   : UDINT;
  END_VAR

  IReduce := ((DRIVEAXIS_TORQUE_LIMITATION_VALUE - input) * 63) / DRIVEAXIS_TORQUE_LIMITATION_VALUE; // calculate the bits for the current reducing
  
  IReduce := IReduce SHL 10 ;
  cBuffer := cBuffer AND 16#3FF;
  cBuffer+=IReduce$BDINT;
      
  result:=cBuffer;
      
END_FUNCTION


//****************************************************************************************************\\
//**################################################################################################**\\
//**************************** everything for getting the actual values!! ****************************\\
//**################################################################################################**\\
//****************************************************************************************************\\

FUNCTION VIRTUAL GLOBAL _DriveAxisBase::GetSynchronPara
  VAR
  	x:SINT;
    SetAVALTT:HSINT;
  END_VAR
  
  ActValuePtr := DriveMng.GetAxisRdPtr(usAxisIndex); // Zeiger auf die Sollwerte von der Struktur t_ReadValuePtr
  
  for x:=4 to 0 by -1 do
    SetAVALTT:=ActValues[x];
      
    case SetAVALTT of
      
      16#01: //1 -> I-N
        SyncPara.ActSpeed.ptr:=#ActValuePtr^.a_SyncValues[x];
        SyncPara.ActSpeed.size:=4;
        SyncPara.ActSpeed.userinfo:=0;
      
      16#02: //2 -> I-NFILT
        SyncPara.ActSpeed.ptr:=#ActValuePtr^.a_SyncValues[x];
        SyncPara.ActSpeed.size:=4;
        SyncPara.ActSpeed.userinfo:=0;
                  
//      16#03:
//      
//        SyncPara.SetPos
                 
      16#05: //5 -> I-IQ
        SyncPara.ActCurrent.ptr:=#ActValuePtr^.a_SyncValues[x];
        SyncPara.ActCurrent.size:=4; 
        SyncPara.ActCurrent.userinfo:=0;
      
      16#07: //7 -> I-POS
        SyncPara.ActPos.ptr:=#ActValuePtr^.a_SyncValues[x];
        SyncPara.ActPos.size:=4;
        SyncPara.ActPos.userinfo:=0;
      
      16#09: //9 -> I-PE 
        SyncPara.Xw.ptr:=#ActValuePtr^.a_SyncValues[x];
        SyncPara.Xw.size:=4;
        SyncPara.Xw.userinfo:=0;
        
      16#0A: //10 -> I-IQ + stateword (cA!)
        SyncPara.ActCurrent.ptr:=#ActValuePtr^.a_SyncValues[x]; 
        SyncPara.ActCurrent.size:=2;
        SyncPara.ActCurrent.userinfo:=1;
        
        SyncPara.StateWord.ptr:=#ActValuePtr^.a_SyncValues[x]+sizeof(UINT); 
        SyncPara.StateWord.size:=2;
        SyncPara.StateWord.userinfo:=0;
      
      16#0E: //14 -> I-PE + stateword
        SyncPara.Xw.ptr:=#ActValuePtr^.a_SyncValues[x];
        SyncPara.Xw.size:=2;
        SyncPara.Xw.userinfo:=0;
        
        SyncPara.StateWord.ptr:=#ActValuePtr^.a_SyncValues[x]+sizeof(UINT);
        SyncPara.StateWord.size:=2;
        SyncPara.StateWord.userinfo:=0;
      
      16#14: //20 -> Current in Promille + stateword
        SyncPara.ActCurrent.ptr:=#ActValuePtr^.a_SyncValues[x];
        SyncPara.ActCurrent.size:=2;
        SyncPara.ActCurrent.userinfo:=0;
        
        SyncPara.StateWord.ptr:=#ActValuePtr^.a_SyncValues[x]+sizeof(UINT);
        SyncPara.StateWord.size:=2;
        SyncPara.StateWord.userinfo:=1;
        
      16#15: //21 -> I-POS 2 position of optional encoder
        if (SyncPara.ActPos.ptr = NIL) then
          SyncPara.ActPos.ptr:=#ActValuePtr^.a_SyncValues[x];
          SyncPara.ActPos.size:=4;
          SyncPara.ActPos.userinfo:=0;
        end_if;
       
      16#17: //23 -> digital inputs + stateword
        SyncPara.DigInputs.ptr:=#ActValuePtr^.a_SyncValues[x];
        SyncPara.DigInputs.size:=8; //no inputs
        SyncPara.DigInputs.userinfo:=0;
        
        SyncPara.StateWord.ptr:=#ActValuePtr^.a_SyncValues[x]+sizeof(UINT);
        SyncPara.StateWord.size:=2;
        SyncPara.StateWord.userinfo:=0;
        
      16#1C: //28 -> MultiTurn Pos VSDC151
        SyncPara.ActPos.ptr:=#ActValuePtr^.a_SyncValues[x];
        SyncPara.ActPos.size:=4;
        SyncPara.ActPos.userinfo:=0;
       
    end_case;

  end_for;

END_FUNCTION


FUNCTION VIRTUAL GLOBAL _DriveAxisBase::ActPos::Read
	VAR_OUTPUT
		output (EAX) 	: DINT;
	END_VAR

  if (SyncPara.ActPos.ptr <> NIL) & bOnlineFinished then
    ActPos:=SyncPara.ActPos.ptr^;
  else
    ActPos:=0;
  end_if;
  
  output := ActPos;

END_FUNCTION


FUNCTION VIRTUAL GLOBAL _DriveAxisBase::ActSpeed::Read
	VAR_OUTPUT
		output (EAX) 	: DINT;
	END_VAR
  
  if (SyncPara.ActSpeed.ptr <> NIL) & bOnlineFinished then
    ActSpeed:=SyncPara.ActSpeed.ptr^;
  else
    ActSpeed:=0;
  end_if;
  
  output := ActSpeed;

END_FUNCTION


FUNCTION VIRTUAL GLOBAL _DriveAxisBase::ActCurrent::Read
	VAR_OUTPUT
		output (EAX) 	: DINT;
	END_VAR

  if (SyncPara.ActCurrent.ptr <> NIL) & bOnlineFinished then
    if SyncPara.ActCurrent.size = 4 then
      ActCurrent:=SyncPara.ActCurrent.ptr^;
    
    elsif SyncPara.ActCurrent.size = 2 then
      if SyncPara.ActCurrent.userinfo = 1 then 
        ActCurrent := to_dint(SyncPara.ActCurrent.ptr^$INT) * 10; //because we want to see mA and not cA
      else
        ActCurrent := to_dint(SyncPara.ActCurrent.ptr^$INT); 
      end_if;
    end_if;
  else
    ActCurrent:=0;
  end_if;

  output := ActCurrent;

END_FUNCTION


FUNCTION VIRTUAL GLOBAL _DriveAxisBase::ActXw::Read
	VAR_OUTPUT
		output (EAX) 	: DINT;
	END_VAR
  
  if (SyncPara.Xw.ptr <> NIL) & bOnlineFinished then
    if SyncPara.Xw.size = 4 then
      ActXw:=SyncPara.Xw.ptr^;
    elsif SyncPara.Xw.size = 2 then
      ActXw := to_dint(SyncPara.Xw.ptr^$INT); 
    end_if;
  else
    ActXw:=0;
  end_if;

  output := ActXw;

END_FUNCTION


FUNCTION VIRTUAL GLOBAL _DriveAxisBase::StateWord::Read
	VAR_OUTPUT
		output (EAX) 	: DS402_State;
	END_VAR
  VAR
  	sBuffer : BDINT; //StateWord Buffer
  END_VAR

  if (SyncPara.StateWord.ptr <> NIL) & bOnlineFinished then
    sBuffer := SyncPara.StateWord.ptr^$BDINT; //normales Statuswort

    if (SyncPara.StateWord.userinfo=0) then
      StateWord.ReadyToSwitchOn     :=  sBuffer.1;  //READY TO SWITCH ON 
      StateWord.SwitchedOn          :=  sBuffer.2;  //EXT ENABLE LOCKED&ENABLE
      StateWord.OperationEnabled    :=  sBuffer.3;  //OPERATION_ENABLE
      StateWord.Fault               :=  sBuffer.4;  //ERROR
      StateWord.Warning             :=  sBuffer.5;  //WARNING
      StateWord.Remote              :=  sBuffer.6;  //PLL Bit0
      StateWord.VoltageEnabled      :=  sBuffer.7;  //PLL Bit1
      StateWord.SwitchOnDisabled    :=  sBuffer.8;  //ECHO
      StateWord.OperationModeSpec1  :=  sBuffer.9;  //Capture Toggle Bit (I-CAP)
      StateWord.OperationModeSpec2  :=  sBuffer.10; //Capture 4 Toggle Bit (I-CAP4)
      StateWord.InternalLimitActive :=  sBuffer.11; //MULTITURN REVOLUTION ERROR 
      StateWord.ManufactureSpec1    :=  sBuffer.12; //Digital Input 1
      StateWord.ManufactureSpec2    :=  sBuffer.13; //Digital Input 2
      StateWord.ManufactureSpec3    :=  sBuffer.14; //Digital Input 3
      StateWord.QuickStop           :=  sBuffer.15; //Digital Input 4
      StateWord.TargetReached       :=  sBuffer.16; //Digital Input 5
      
    elsif(SyncPara.StateWord.userinfo=1) then
      StateWord.ReadyToSwitchOn     :=  sBuffer.1;  //READY TO SWITCH ON 
      StateWord.SwitchedOn          :=  sBuffer.2;  //EXT.ENABLE=LOCKED&ENABLE
      StateWord.OperationEnabled    :=  sBuffer.3;  //OPERATION_ENABLE
      StateWord.Fault               :=  sBuffer.4;  //ERROR
      StateWord.Warning             :=  sBuffer.5;  //WARNING
      StateWord.QuickStop           :=  sBuffer.6;  
      StateWord.SwitchOnDisabled    :=  sBuffer.7;  
      StateWord.VoltageEnabled      :=  sBuffer.8; 
      StateWord.ManufactureSpec1    :=  sBuffer.9;  
      StateWord.ManufactureSpec2    :=  sBuffer.10; 
      StateWord.TargetReached       :=  sBuffer.11; 
      StateWord.ManufactureSpec3    :=  sBuffer.12; 
      StateWord.OperationModeSpec1  :=  sBuffer.13; 
      StateWord.OperationModeSpec2  :=  sBuffer.14; 
      StateWord.Remote              :=  sBuffer.15; //PLL nicht eingerastet
      StateWord.InternalLimitActive :=  sBuffer.16; //MULTITURN REVOLUTION ERROR
    end_if;
   
  else
    StateWord := 0;
  end_if;

  output := StateWord;

END_FUNCTION


FUNCTION VIRTUAL GLOBAL _DriveAxisBase::AxError::Read
	VAR_OUTPUT
		output (EAX) : DINT;
	END_VAR

  //Error of Axis gets only shown, if Axis is Online
  if bOnlineFinished then
    AxError := GetAxError();
  else
    AxError := 0;
  end_if;

  output := AxError;

END_FUNCTION


FUNCTION _DriveAxisBase::LoadDrivePara
  VAR
    pTabAdress : ^DINT;
    TabLength   : DINT;
  END_VAR

  // load the parameter data to the para objects
  case DriveInitType of

    _SDDSTDTABLE :
      
     pTabAdress := GetTabAdress(TabType:= 0, bdSettings.bSendMPara, #TabLength);
     SetListToParObj(pData:= (pTabAdress)$^DINT, udLen:=TabLength$UDINT);
      

    _SDDL2TABLE :	
    // load the data of the table
      pTabAdress := GetTabAdress(TabType:= 1, bdSettings.bSendMPara, #TabLength);
      SetListToParObj(pData:= (pTabAdress)$^DINT, udLen:=TabLength$UDINT);
    
    _SDDRAMEX,	
    _SDDFILE :	
      pSDDData$^void := DriveAxisSet.GetMemPtr();	
      if pSDDData <> NIL then
        // load the data of the memory
        SetListToParObj(pData:= (pSDDData$DINT + pSDDData^.AxOffset)$^DINT, udLen:=pSDDData^.AxLength);
      end_if;
    
  end_case;
  
END_FUNCTION


FUNCTION _DriveAxisBase::SetListToParObj
	VAR_INPUT
		pData 	: ^DINT;
		udLen 	: UDINT;
	END_VAR
	VAR_OUTPUT
		retcode 	: BOOL;
	END_VAR
  VAR
    pHlp          : ^DINT;
    x             : UDINT;
    pThisNewInst  : ^void;
    usParaNr      : USINT;
    ParaValue     : DINT;
    UserPara      : CmdStruct;
    UserResult    : Results;
  END_VAR
  
  retcode := FALSE;
  
  //hier konnte es zu einem Problem kommen kann wenn pThisNewInst nicht init war.
  pThisNewInst := NIL; //BleErn 19.08.2010 11:27
  
  if (bdSettings.bAxSetPara = FALSE) | (pData = NIL) then
    return;
  end_if;
    
  x := 0;
  pHlp := pData;
    
  while x < udLen do
    
    usParaNr := pHlp^$USINT;
    pHlp += sizeof(USINT);
    x += sizeof(USINT);
      
    if usParaNr <= MAX_MOTOR_PARA then
      pThisNewInst$DINT := AxSetPara[IDX_MOTOR_PARA];
    elsif usParaNr <= MAX_DRIVE_PARA then
      pThisNewInst$DINT := AxSetPara[IDX_DRIVE_PARA];
    elsif usParaNr <= MAX_CURRENT_PARA then
      pThisNewInst$DINT := AxSetPara[IDX_CURRENT_PARA];
    elsif usParaNr <= MAX_VEL_PARA then
      pThisNewInst$DINT := AxSetPara[IDX_VEL_PARA];
    elsif usParaNr <= MAX_POS_PARA then
      pThisNewInst$DINT := AxSetPara[IDX_POS_PARA];
    elsif usParaNr <= MAX_FD_PARA then
      pThisNewInst$DINT := AxSetPara[IDX_FD_PARA];
    elsif usParaNr <= MAX_APPLI_PARA then
      pThisNewInst$DINT := AxSetPara[IDX_APPLI_PARA];
    elsif usParaNr <= MAX_ERRORHANDLING then
      pThisNewInst$DINT := AxSetPara[IDX_ERRORHANDLING];
    end_if;
      
      
    ParaValue := pHlp^$DINT;
    if pThisNewInst <> NIL then
      UserPara.uiCmd := SDD_REFRESH_SETPARA;
      UserPara.aPara[0] := to_dint(usParaNr);
      UserPara.aPara[1] := ParaValue;
      pThisNewInst$^VirtualBase^.NewInst(#UserPara, #UserResult);
    end_if;
      
    pHlp += sizeof(UDINT);
    x += sizeof(UDINT);
      
  end_while;
  
END_FUNCTION


FUNCTION VIRTUAL GLOBAL _DriveAxisBase::SDDProcess
  VAR
    tmpStr : array [0..20] of char;
    retcode : iprStates;
    dError : DINT;
  END_VAR
  
  //SA 23391 - ObeChr: Wait for Online before starting SDDCmdInterface
  if Online = 1 then
    
    case SDDCmdIntfc of
    
    _SDDIDLE :
      // do nothing
      
    _SDDREADALL :
      if bdSettings.bStartRead = FALSE then
        bdSettings.bStartRead := TRUE;
        // check if a read is possible
        if ChkParaRead(0) = FALSE then
          SDDCmdIntfc := _SDDIDLE;
        else
          ParaReadProc();
        end_if;
      else
        // überprüfen ob alle Parameter schon vorhanden sind
        ParaReadProc();
        if (bdSettings.bReadAxFin = TRUE) then
          SDDCmdIntfc := _SDDIDLE;
          bdSettings.bStartRead := FALSE;
        end_if;
      end_if;
    
    _SDDINIT :
      
      if (AxEnable = 0)  then
        if OldSDDCmdIntfc <> SDDCmdIntfc then
          DriveMng.InitDrive(0); // start the initialisation of the drive
          Init_Again:=true;
          //bdSettings.bDriveInitialized:=true;
        end_if;
      else
        SDDCmdIntfc := _SDDIDLE;
      end_if;
      
    _SDDURINIT :
      
      if (AxEnable = 0) then
        if OldSDDCmdIntfc <> SDDCmdIntfc then
          DriveMng.InitDrive(1); // start the initialisation of the drive
          InitASyncPara(); // initialize the structure
          Init_Again:=true;
        end_if;
      else
        SDDCmdIntfc := _SDDIDLE;
      end_if;
      
    _SDDEXDATA, 
    _SDDEXDATAXML:
    
      // only if a object of the correct class is connected
      if DriveAxisSet.ChkFileHandle() then
     
        if OldSDDCmdIntfc <> SDDCmdIntfc then
          pSDDData$^void := DriveAxisSet.GetMemPtr();
          
          // Always Call SetDriveType incause GetDriveTypeStr fails or an older Version of _DriveFileHandling is used
          DriveAxisSet.SetDriveType(eDriveType:=GetDriveType());
          
          _strcpy(#pSDDData^.AxName[0],#szObjName[0]); //here the name of the object is set to the struct
          
          // Set tmpStr to 0 incase GetDriveTypeStr does not return a valid string.
          tmpStr[0] := 0;
          DriveMng.GetDriveTypeStr(eDriveType:=GetDriveType(), pDriveTypeStr:=#tmpStr[0], DriveTypeStrSize:=sizeof(tmpStr) );
          if tmpStr[0] then
            DriveAxisSet.SetDriveTypeStr(pDriveTypeStr:= #tmpStr[0]);
          end_if; 
          DriveAxisSet.SetUserSSDCmd(SDDCmdIntfc, pSDDData);
          
        else
          SDDCmdIntfc := DriveAxisSet.GetUserSSDCmd();
        end_if;
      else
        LogError(pMsg:="@06F3 (_DriveAxisBase::SDDProcess) Failed export drive parameters. Check if client 'FileHandle' is connected.");
        SDDCmdIntfc := _SDDERROR;
      end_if;
      
    _SDDIMDATAXML:
    
      if DriveAxisSet.ChkFileHandle() then
     
        if OldSDDCmdIntfc <> SDDCmdIntfc then
          pSDDData$^void := DriveAxisSet.GetMemPtr();
          
          _strcpy(#pSDDData^.AxName[0],#szObjName[0]); //here the name of the object is set to the struct
          DriveAxisSet.SetUserSSDCmd(SDDCmdIntfc, pSDDData);
          
        else
          
          if DriveAxisSet.GetUserSSDCmd() = _SDDIDLE then
            // Read xml file done
            
            // Insert Crc into the imported Data
            pSDDData^.udCRC32 := DriveAxisSet.CalcCRC32((pSDDData + sizeof(UDINT))$^UDINT, pSDDData^.udLen - sizeof(UDINT));
            
            // now save all parameters in the SRAM / FILE
            if DriveInitType = _SDDRAMEX then
              pSDDData$^void := DriveAxisSet.GetMemPtr();
              DriveAxisSet.SaveRamExData(pData:= pSDDData, udLen:= pSDDData^.udLen, udOffset:= 0);
              
            elsif DriveInitType = _SDDFILE then
              pSDDData$^void := DriveAxisSet.GetMemPtr();
              DriveAxisSet.SaveRamFileData(pData:= pSDDData, udLen:= pSDDData^.udLen, udOffset:= 0);
            
            end_if;
            
            // Use _SDDINIT to tranfer Parametera from ramfile/sram to drive
            SDDCmdIntfc := _SDDINIT;  // Set after SaveRamExData, SaveRamFileData because Filehandling may suspend task
            
            return; // Return needed here so that _SDDINIT is registered as a new command
          end_if;

        end_if;
      else
        LogError(pMsg:="@06F5 (_DriveAxisBase::SDDProcess) Failed import drive parameters. Check if client 'FileHandle' is connected.");
        SDDCmdIntfc := _SDDERROR;
      end_if;
    
      _SDDEXLOGFILE:
        
        // First call since SDDCmdIntfc was set.
        if OldSDDCmdIntfc <> SDDCmdIntfc then
        
          retcode := DriveMng.GetLogFile(pDestinationDPNE:=NIL, pdError:=#dError);
          
          if retcode = ERROR then
            
            LogValue("@0846 (_DriveAxisBase::SDDProcess) Failed to start read logfile. Error code: -0x{0}", (-dError)$UDINT);
            SDDCmdIntfc := _SDDERROR;
        
          end_if;
          
        else
        
          retcode := DriveMng.GetFileState(pdError:=#dError);
          
          if retcode = READY then
          
            SDDCmdIntfc := _SDDIDLE;
            
          elsif retcode = ERROR then
            
            LogValue("@0847 (_DriveAxisBase::SDDProcess) Failed read logfile. Error code: -0x{0}", (-dError)$UDINT);
            SDDCmdIntfc := _SDDERROR;
        
          end_if;          
        
        end_if;
        
        
    end_case;
    
    OldSDDCmdIntfc := SDDCmdIntfc;
  
  end_if;
   
END_FUNCTION


FUNCTION VIRTUAL GLOBAL _DriveAxisBase::SDDCmdIntfc::Write
	VAR_INPUT
		input (EAX) 	: _SDDUSERCMD;
	END_VAR
	VAR_OUTPUT
		result (EAX) 	: _SDDUSERCMD;
	END_VAR

  if ((SDDCmdIntfc = _SDDIDLE) | 
      (SDDCmdIntfc = _SDDERROR)) then
    SDDCmdIntfc := input;
    result := SDDCmdIntfc;
  else
    result$DINT := ACCESS_DENIED;
  end_if;

END_FUNCTION


FUNCTION _DriveAxisBase::ChkParaRead
	VAR_INPUT
		ChkType 	: DINT;
	END_VAR
	VAR_OUTPUT
		retcode 	: BOOL;
	END_VAR
  
  retcode := FALSE;

  case ChkType of
  0 : // check if a reading command is allowed
  
    bdSettings.bReadAx := FALSE;
  
    bdSettings.bReadAxFin := FALSE;
    
    if (bdSettings.bAxSetPara = TRUE)then
      bdSettings.bReadAx := TRUE;
      ParaReadCmdAx := 1;
      retcode := TRUE;
    else
      bdSettings.bReadAxFin := TRUE;
    end_if;

  1 : // check if we can send the next reading commands
    if ParaReadCmdAx = 2 then
      if AxASyncPara.ActEntries < 10 then
        retcode := TRUE;
      end_if;
    end_if;

  end_case;
  
END_FUNCTION


FUNCTION _DriveAxisBase::ParaReadProc
  VAR
    dValue      : DINT;
    pThis       : ^void;
    i           : DINT;
    UserPara    : CmdStruct;
    UserResult  : Results;
  END_VAR
        // Start laden aller Parameter vom Drive
        // folgender Ablauf :
        // 1. Es wird für jede Achse die Anforderung in den Ringbuffer geschrieben (30mal).(Eigene Kennung erforderlich ?);
        // 2. Warten bis nur mehr 10 Einträge vorhanden sind, und dann die nächsten Einträge absetzen
        // 3. wenn alle Einträge abgesetzt sind, (letzter Eintrag muss eine extra Kennung haben), wird überprüft wann alle Daten vorhanden sind
        // 4. Wenn ein Wert eines Parameters ankommt, wird dieser in den Speicher geschrieben, dies ist abhängig von der Sicherungsauswahl. Ist eine Tabelle ausgewählt
        //    werden die Daten sofort an die Parameterklassen gesendet, sind keine Parameterobjekte vorhanden, so wird der Vorgang gar nicht durchgeführt.
        // 5. Wenn der letzte Wert des Parameters kommt, wird die Chksumme neu berechnet, die Daten weggesichert, und die Parameterobjekte aktualisiert

  dValue := 0;
  
 if bdSettings.bReadAx = TRUE then
    case ParaReadCmdAx of
  
    0 : //idle step
      
    1 : // set the first entries in the buffer 
      // set the info busy to all para classes
      UserPara.uiCmd := SDD_ASYNC_BUSY;
      
      for i := IDX_MOTOR_PARA to IDX_ERRORHANDLING do
        pThis$DINT := AxSetPara[i];
        if pThis <> NIL then
          // Set the state BUSY
          pThis$^VirtualBase^.NewInst(#UserPara, #UserResult);
        end_if;
      end_for;
      
      if AxSetPara[IDX_MOTOR_PARA] <> 0 then
        pThis$DINT := AxSetPara[IDX_MOTOR_PARA];
        
        AddASyncEntry(usParaNr:= SDD_M_NAME1, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_M_NAME2, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_M_NAME3, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_M_INULL, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_M_IPEAK, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_M_NMAX, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_M_POL, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_M_TORQUE, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_M_L, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_M_R, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_M_J, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_M_TYPE, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_M_RPOL, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_M_ROFF, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_M_RPULSE, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_M_RTEMP, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_M_SER, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_M_BRAKE, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_M_IFWEAK, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_M_BRDIS, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_M_BREN, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_M_IMAG, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_M_TROT, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_M_UN, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_M_UBOOST, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_M_KN, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
      end_if;
      
      if AxSetPara[IDX_DRIVE_PARA] <> 0 then
        pThis$DINT := AxSetPara[IDX_DRIVE_PARA];
        AddASyncEntry(usParaNr:= SDD_G_MODE, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_G_CETIME, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_G_VMAINS, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_G_VBUSM, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_G_VBUSM, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_G_MTEMPK, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_G_MTEMPE, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_G_PWM, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_G_DELAY, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_G_FTEMP, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_G_EMRAMP, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_G_MASKE1, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_G_MASKE2, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_G_MASKW, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_G_MASKD, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_G_VRAMP, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_G_SRAMP, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_G_RBAL, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
      end_if;
      
      ParaReadCmdAx := 2;
      
        
    2 :
      // wait until only 10 entries in the buffer
      
      if ChkParaRead(ChkType:= 1) = TRUE then
        ParaReadCmdAx := 3;
      end_if;
      
    3 :
      // send the rest
      
      if AxSetPara[IDX_CURRENT_PARA] <> 0 then
        pThis$DINT := AxSetPara[IDX_CURRENT_PARA];
        AddASyncEntry(usParaNr:= SDD_C_KPQ, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_C_TN, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_C_KDREL, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_C_KPDREL, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_C_KPNULL, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_C_KPPEAK, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_C_ICONT, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_C_IPEAK, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_C_IPEAKN, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
      end_if;                 
                             
      if AxSetPara[IDX_VEL_PARA] <> 0 then
        pThis$DINT := AxSetPara[IDX_VEL_PARA];
        AddASyncEntry(usParaNr:= SDD_V_KP, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_V_TN, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_V_T, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_V_T2, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_V_FILT, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_V_NMAX, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_V_KPREL, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
      end_if;

      if AxSetPara[IDX_POS_PARA] <> 0 then
        pThis$DINT := AxSetPara[IDX_POS_PARA];
        AddASyncEntry(usParaNr:= SDD_P_KV, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_P_SFF, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_P_PSCALE, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_P_SSCALE, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_P_TFF, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_P_PEMAX, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_P_SMODE, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
      end_if;
      
      if AxSetPara[IDX_FD_PARA] <> 0 then
        pThis$DINT := AxSetPara[IDX_FD_PARA];
        AddASyncEntry(usParaNr:= SDD_F_BW, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_F_FF, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_F_RK, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
      end_if;
      
      if AxSetPara[IDX_APPLI_PARA] <> 0 then
        pThis$DINT := AxSetPara[IDX_APPLI_PARA];
        AddASyncEntry(usParaNr:= SDD_A_JRATIO, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_A_VALRT1, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_A_VALRT2, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_A_VALTT1, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_A_VALTT2, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_A_CTIME, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_A_STIME, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_A_STYPE, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_A_AVSW, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_A_I2TERR, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_A_TEMPDE, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_A_TEMPMW, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_A_STRED, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_A_STDT, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_A_POS, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_A_DNAME1, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_A_DNAME2, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_A_DNAME3, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_A_MODE2, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_A_MULTI, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_A_CAPREF, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_A_EDGE, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_A_STTH, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_A_INT1, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_A_INT2, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_A_ICOM, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);  
        AddASyncEntry(usParaNr:= SDD_A_ICOMP, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);  
        AddASyncEntry(usParaNr:= SDD_A_CMIN, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);  
        AddASyncEntry(usParaNr:= SDD_A_BIQCF, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);  
        AddASyncEntry(usParaNr:= SDD_A_BIQFR, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);  
        AddASyncEntry(usParaNr:= SDD_A_BIQCD, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);  
        AddASyncEntry(usParaNr:= SDD_A_BIQDR, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);  
        AddASyncEntry(usParaNr:= SDD_A_CAPFT, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);   
        AddASyncEntry(usParaNr:= SDD_A_ACME, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);  
      end_if;
      
      if AxSetPara[IDX_ERRORHANDLING] <> 0 then
        pThis$DINT := AxSetPara[IDX_ERRORHANDLING];
        AddASyncEntry(usParaNr:= SDD_I_STATUS, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
        AddASyncEntry(usParaNr:= SDD_I_DERROR, usRdWr:= 0, dValue:= dValue, pThisObj:= pThis, usEntry:= 1);
      end_if;
      
      // get the number of parameters in the drive (only to know if we are at the end of the reading process
      AddASyncEntry(usParaNr:= 0, usRdWr:= 0, dValue:= dValue, pThisObj:= NIL, usEntry:= 2);
      ParaReadCmdAx := 4;
    4 :
      
      if bdSettings.bReadAxFin = TRUE then
      // wait until the last entry is send the value back
        
        // now save all parameters in the SRAM / FILE
        if DriveInitType = _SDDRAMEX then
          pSDDData$^void := DriveAxisSet.GetMemPtr();
          DriveAxisSet.SaveRamExData(pData:= pSDDData, udLen:= pSDDData^.udLen, udOffset:= 0);
          
        elsif DriveInitType = _SDDFILE then
          pSDDData$^void := DriveAxisSet.GetMemPtr();
          DriveAxisSet.SaveRamFileData(pData:= pSDDData, udLen:= pSDDData^.udLen, udOffset:= 0);
        
        end_if;
        ParaReadCmdAx := 0;
        
      end_if;
    end_case;
  end_if;
  
END_FUNCTION


FUNCTION VIRTUAL GLOBAL _DriveAxisBase::SetAbsolutePosition
	VAR_INPUT
		AbsPosition 	: DINT;
	END_VAR
	VAR_OUTPUT
		retcode 	: DINT;
	END_VAR
  
  retcode := 1;
  if IsOnline() = FALSE then
    retcode := -1;  // no communication available or the initialisation isn't finished
    return;
  end_if;
 
  //Check if operation is already in progress
  if bdSettings.bSetAbsPos = true then
    retcode := -2;
    return;
  end_if;

  // check if the axis is with an absolute encoder
  if (bdSettings.bNoAbsEnc = FALSE) then
    // if any axis is enabled, the parameter K-FBRW cannot be written
    if DriveMng.IsAnyAxisEnabled() then
      retcode := -4;
      return;
    end_if;

    // set the value of the parameter A-MULTI to 1
    AddASyncEntry(SDD_A_MULTI, 1, 1, this, 0);
    // set the new position to the parameter 
    AddASyncEntry(SDD_A_POS, 1, AbsPosition, this, 1);
    // marry the motor with the Drive
    AddASyncEntry(SDD_K_FBRW, 1, 3, this, 1);
      
    bdSettings.bSetAbsPos := TRUE;
  else
    retcode := -3; // no absolute encoder available
  end_if;
  
END_FUNCTION


FUNCTION VIRTUAL GLOBAL _DriveAxisBase::SetAbsolutePositionEncoder
	VAR_INPUT
		AbsPosition 	: DINT;
	END_VAR
	VAR_OUTPUT
		retcode 	: DINT;
	END_VAR

  //Init Returncode
  retcode := true;
  
  //Check if Drive is Online and the Initialization is finished
  if IsOnline() = false then
    retcode := -1;
    return;
  end_if;
  
  //Check if operation is already in progress
  if bdSettings.bSetAbsPosEncoder = true then
    retcode := -2;
    return;
  end_if;
  
  //Check if the Axis got an AbsoluteEncoder
  if bdSettings.bNoAbsEnc = false then
    // if axis is enabled, the parameter K-FBRW cannot be written
    if DriveMng.IsAnyAxisEnabled() then
      retcode := -4;
      return;
    end_if;
  
    //Set A-MULTI to 1
    AddASyncEntry(SDD_A_MULTI, true, 0, this, 0);
    
    //Set A-POS to InputParamter
    AddASyncEntry(SDD_A_POS, true, AbsPosition, this, 1);
    
    //Set K-FBRW to 5 => Calculate Offset
    AddASyncEntry(SDD_K_FBRW, true, 5, this, 1);

    //Set K-FBRW to 2 => Save Offset in Feedback
    AddASyncEntry(SDD_K_FBRW, true, 2, this, 1);
    
    bdSettings.bSetAbsPosEncoder := true;
  else
    retcode := -3;
  end_if;

END_FUNCTION


FUNCTION _DriveAxisBase::SaveDrivePara
  VAR
    TabAddress 	: ^DINT;
    pHlpSDD		: ^void;
    TabLength   : DINT;
  END_VAR
	
  // get the actual ptr of the memory
  pSDDData$^void := DriveAxisSet.GetMemPtr();	

  if pSDDData <> NIL then	
    
    pSDDData^.udLen := sizeof(_SDDMEMHEADER); // initialize the length of the data 
    pSDDData^.AxOffset := sizeof(_SDDMEMHEADER); // set the offset
    TabAddress := GetTabAdress(1, bdSettings.bSendMPara, #TabLength);
    
    if TabAddress = NIL then
      return;
    end_if;
    
    pSDDData^.AxLength := TabLength$UDINT;
  
    pHlpSDD := pSDDData + pSDDData^.AxOffset;
        
    _memcpy(pHlpSDD, (TabAddress)$^void, (TabLength)$UDINT);

    pSDDData^.udLen += pSDDData^.AxLength;

    // calculate the crc of the sdd parameters
    pSDDData^.udCRC32 := CalcCRC32((pSDDData + sizeof(UDINT))$^UDINT, pSDDData^.udLen - sizeof(UDINT));
   
    case DriveInitType of
    
    _SDDRAMEX :
    
      // save the data in the ramex
      DriveAxisSet.SaveRamExData(pSDDData, pSDDData^.udLen, 0);
          
    _SDDFILE :
      // save the data in the ramfile
      DriveAxisSet.SaveRamFileData(pSDDData, pSDDData^.udLen, 0);
      
    end_case;
  end_if;
  
END_FUNCTION


FUNCTION _DriveAxisBase::CalcCRC32
	VAR_INPUT
		pData 	: ^UDINT;
		udLen 	: UDINT;
	END_VAR
	VAR_OUTPUT
		CRC32 	: UDINT;
	END_VAR
	
	CRC32 := coLinker.CRC32(0, pData$^void, udLen);

END_FUNCTION


FUNCTION VIRTUAL GLOBAL _DriveAxisBase::GetZImpulse
	VAR_OUTPUT
		retcode 	: USINT;
	END_VAR
  
  retcode:=0;
  
  if ( ( ActPos and maskZImpulse$DINT ) <> oldRevolutions ) then
    retcode := 1;
    oldRevolutions := (ActPos and maskZImpulse$DINT);	
  end_if;
  
END_FUNCTION


FUNCTION VIRTUAL GLOBAL _DriveAxisBase::ZPulsLatch::Read
	VAR_OUTPUT
		output (EAX) 	: DINT;
	END_VAR
  
  if bOnlineFinished then
  
    if ZPulsLatch = 0 then
      output := ZPulsLatch := GetZImpulse();
    else
      output := ZPulsLatch;
      ZPulsLatch := 0;
    end_if;
  
  else
    ZPulsLatch := 0;
    output := ZPulsLatch;
  end_if;

END_FUNCTION


FUNCTION _DriveAxisBase::SetZPulseMask
  
  maskZImpulse:=16#FFFFFFFF;
  maskZImpulse:=maskZImpulse SHL (32-ppscale);

  //P-PSCALE  0: 00000000 00000000 00000000 00000000
  //P-PSCALE 10: 11111111 11000000 00000000 00000000
  //P-PSCALE 16: 11111111 11111111 00000000 00000000
      
END_FUNCTION


FUNCTION VIRTUAL GLOBAL _DriveAxisBase::GetSyncEntry
	VAR_INPUT
		usValue 	: USINT;
		usPData 	: ^DINT;
	END_VAR
	VAR_OUTPUT
		retcode 	: DINT;
	END_VAR
  
  retcode:=DriveMng.GetSyncEntry(usAxis:=usAxisIndex, usValue:=usValue, usPData:=usPData);

END_FUNCTION


FUNCTION VIRTUAL GLOBAL _DriveAxisBase::AddSyncEntry
	VAR_INPUT
		pThis 	: ^void;
	END_VAR
	VAR_OUTPUT
		retcode 	: BOOL;
	END_VAR
  
  retcode := FALSE;
  
  if pThis <> NIL then
    SyncParaObject := pThis$DINT;
    retcode := TRUE;
  end_if;

END_FUNCTION


FUNCTION VIRTUAL GLOBAL _DriveAxisBase::SetSyncEntry
	VAR_INPUT
		usValue 	: USINT;
		usPData 	: DINT;
	END_VAR
	VAR_OUTPUT
		retcode 	: DINT;
	END_VAR
  
  retcode:=DriveMng.SetSyncEntry(usAxis:=usAxisIndex, usValue:=usValue, usPData:=usPData);

END_FUNCTION


FUNCTION _DriveAxisBase::RefreshIASP
	VAR_INPUT
		Para 	  : DINT;
		Value 	: DINT;
	END_VAR
  VAR
  	UserPara      : CmdStruct;
    UserResult    : Results;
  END_VAR
  
  // if there is a change in the following values, first we set the pointers to zero, and then we initialize them, allready with the new value

  if AxEnable = 0 then //just do some changes when the axis does not run
    case Para of
      SDD_A_VALTT1:
                
        _memset(#SyncPara.ActCurrent,0,sizeof(SyncPara.ActCurrent));
        _memset(#SyncPara.ActPos,    0,sizeof(SyncPara.ActPos));
        _memset(#SyncPara.ActSpeed,  0,sizeof(SyncPara.ActSpeed));
        _memset(#SyncPara.Xw,        0,sizeof(SyncPara.Xw));
        _memset(#SyncPara.StateWord, 0,sizeof(SyncPara.StateWord));
        _memset(#SyncPara.DigInputs, 0,sizeof(SyncPara.DigInputs));
        
        ActValues[0] := to_usint( Value AND 16#000000FF);
        ActValues[1] := to_usint((Value AND 16#0000FF00) SHR 8);

        GetSynchronPara();
        
      SDD_A_VALTT2:
                
        _memset(#SyncPara.ActCurrent,0,sizeof(SyncPara.ActCurrent));
        _memset(#SyncPara.ActPos,    0,sizeof(SyncPara.ActPos));
        _memset(#SyncPara.ActSpeed,  0,sizeof(SyncPara.ActSpeed));
        _memset(#SyncPara.Xw,        0,sizeof(SyncPara.Xw));
        _memset(#SyncPara.StateWord, 0,sizeof(SyncPara.StateWord));
        _memset(#SyncPara.DigInputs, 0,sizeof(SyncPara.DigInputs));
        
        ActValues[2] := to_usint( Value AND 16#000000FF);
        ActValues[3] := to_usint((Value AND 16#0000FF00) SHR 8);
        ActValues[4] := to_usint((Value AND 16#00FF0000) SHR 16);
        
        if (AxisExtend = 1) & (SyncParaObject<>NIL) then
          UserPara.uiCmd := 10;
          UserPara.aPara[2]:=ActValues[2];
          UserPara.aPara[3]:=ActValues[3];
          UserPara.aPara[4]:=ActValues[4];
          SyncParaObject$^VirtualBase^.pSvrChCmd.NewInst(#UserPara, #UserResult); //initialize also the extend class
        end_if;
        
        GetSynchronPara();
        
      SDD_A_VALRT1:
                
        _memset(#SyncPara.SetCurrent, 0,sizeof(SyncPara.SetCurrent));
        _memset(#SyncPara.SetPos,     0,sizeof(SyncPara.SetPos));
        _memset(#SyncPara.SetSpeed,   0,sizeof(SyncPara.SetSpeed));
        _memset(#SyncPara.SetTorque,  0,sizeof(SyncPara.SetTorque));
        _memset(#SyncPara.ControlWord,0,sizeof(SyncPara.ControlWord));
        
        SetValues[0] := to_usint( Value AND 16#000000FF);
        SetValues[1] := to_usint((Value AND 16#0000FF00) SHR 8);
        
        SetSynchronPara();
//        AxTorqueControl.Write(4500); //it does not matter which controlword we have, because the internal function reduced this amount to the top limit
        SetAxTorque(4500);

        
      SDD_A_VALRT2:
        
        _memset(#SyncPara.SetCurrent, 0,sizeof(SyncPara.SetCurrent));
        _memset(#SyncPara.SetPos,     0,sizeof(SyncPara.SetPos));
        _memset(#SyncPara.SetSpeed,   0,sizeof(SyncPara.SetSpeed));
        _memset(#SyncPara.SetTorque,  0,sizeof(SyncPara.SetTorque));
        _memset(#SyncPara.ControlWord,0,sizeof(SyncPara.ControlWord));
        
        SetValues[2] := to_usint( Value AND 16#000000FF);
        SetValues[3] := to_usint((Value AND 16#0000FF00) SHR 8);
        SetValues[4] := to_usint((Value AND 16#00FF0000) SHR 16);
        
        
        if (AxisExtend = 1) & (SyncParaObject<>NIL) then
          UserPara.uiCmd := 11;
          UserPara.aPara[2]:=SetValues[2];
          UserPara.aPara[3]:=SetValues[3];
          UserPara.aPara[4]:=SetValues[4];
          SyncParaObject$^VirtualBase^.pSvrChCmd.NewInst(#UserPara, #UserResult); //if there is a extend class connected, we have to initialize it
        end_if;
        
        SetSynchronPara();
//        AxTorqueControl.Write(4500); //it does not matter which controlword we have, because the internal function reduced this amount to the top limit
        SetAxTorque(4500);
        
      SDD_P_PSCALE:
        ppscale:=to_usint(Value);
        SetZPulseMask();
        
    end_case;
  end_if;

END_FUNCTION


FUNCTION VIRTUAL GLOBAL _DriveAxisBase::AxOkay
	VAR_OUTPUT
		retcode 	: DINT;
	END_VAR
  
  retcode := false;
  if AxisState = 0 then
    retcode := true;
  end_if;

END_FUNCTION


FUNCTION VIRTUAL GLOBAL _DriveAxisBase::Online::Read
	VAR_OUTPUT
		output (EAX) 	: DINT;
	END_VAR

  //--- if DriveMng is online, we have no internal error, and the error-reset after startup is ready, we say Online = 1
//  Online := bOnlineFinished;
  Online := bOnlineState;

  output := Online;

END_FUNCTION


FUNCTION VIRTUAL GLOBAL _DriveAxisBase::ErrorQuitHandling
	VAR_INPUT
		input 	: DINT;
	END_VAR
	VAR_OUTPUT
		result 	: DINT;
	END_VAR

  AxErrorQuit:=input AND 1;
  
  // check if there is a control word mapped, before accessing the data
  if SyncPara.ControlWord.ptr then
    if (SyncPara.ControlWord.userinfo=0) then 
      SyncPara.ControlWord.ptr^$BINT.2:=AxErrorQuit$BOOL; //FAULT RESET
    elsif(SyncPara.ControlWord.userinfo=1) then
      SyncPara.ControlWord.ptr^$BINT.8:=AxErrorQuit$BOOL; //FAULT RESET
    end_if;
  end_if;
  
  if AxErrorQuit = 1 then
    FirstErrorReset := 4;
    ErrorQuitTime:=ops.tAbsolute;
  end_if;

  Controlword.ResetFault := AxErrorQuit$BOOL;

  result := AxErrorQuit;

END_FUNCTION


FUNCTION VIRTUAL _DriveAxisBase::GetAxError
	VAR_OUTPUT
		AxError 	: DINT;
	END_VAR
  VAR
  	sBuffer      : BDINT; //StateWord Buffer
  END_VAR

  if SyncPara.StateWord.ptr<>NIL  then
    sBuffer := SyncPara.StateWord.ptr^$BDINT; 
    AxError:=sBuffer.4; //the error is at both control words on the same place
  else
    AxError:=0;
  end_if;

END_FUNCTION


FUNCTION _DriveAxisBase::SetAxTorque
	VAR_INPUT
		NewTorque 	: UDINT;
	END_VAR
  VAR
    cBuffer       : BDINT; //ControlWord Buffer
  END_VAR

  // if we have a 16-Bit Controlword
  if SyncPara.SetTorque.userinfo = 0 then

    if NewTorque < 0 then
      NewTorque := 0;
    end_if;
      
    if NewTorque > DRIVEAXIS_TORQUE_LIMITATION_VALUE then
      NewTorque := DRIVEAXIS_TORQUE_LIMITATION_VALUE;
    end_if;
    
    AxTorqueControl := NewTorque;
    
    //Check if pointer is valid
    if SyncPara.ControlWord.ptr then
      cBuffer:=SyncPara.ControlWord.ptr^$BDINT;
      SyncPara.SetTorque.ptr^$INT:= to_int(TorqueCalculation(cBuffer,NewTorque));
    end_if;

  elsif SyncPara.SetTorque.userinfo=1 then //that is for the 32-Bit Controlword
    
    if NewTorque < 0 then
      NewTorque := 0;
    end_if;
      
    if NewTorque > 4500 then
      NewTorque := 4500;
    end_if;
    
    AxTorqueControl := NewTorque;
    
    if SyncPara.SetTorque.ptr then
      SyncPara.SetTorque.ptr^$INT:=to_int(NewTorque);
    end_if;
    
  end_if;

END_FUNCTION

FUNCTION _DriveAxisBase::IsOnlineFinished
	VAR_OUTPUT
		bOnline 	: BOOL;
	END_VAR

  if (IsOnline() = TRUE) & (CmdState <> ERROR) & ((FirstErrorReset = 0) | (FirstErrorReset >= 4)) then
    bOnline := 1;
  else
    bOnline := 0;
  end_if;
  
END_FUNCTION

FUNCTION VIRTUAL GLOBAL _DriveAxisBase::AddASyncEntryDS402
	VAR_INPUT
		uiParaID 	  : UINT;
		usParaSubID : USINT;
		usRdWr 	    : USINT;
		pValue 	    : ^USINT;
		bsDataInfo 	: BSINT;
		pThisObj 	  : ^void;
		usEntry 	  : USINT;
	END_VAR
	VAR_OUTPUT
		retcode 	  : DINT;
	END_VAR
  
  retcode := DriveMng.AddASyncEntryDS402(AxisNo     := usAxisIndex
                                      , uiParaID    := uiParaID
                                      , usParaSubID := usParaSubID
                                      , usRdWr      := usRdWr
                                      , pValue      := pValue
                                      , bsDataInfo  := bsDataInfo
                                      , pThisObj    := pThisObj
                                      , usEntry     := usEntry
                                      );

END_FUNCTION

FUNCTION VIRTUAL GLOBAL _DriveAxisBase::Input1::Read
	VAR_OUTPUT
		output (EAX) 	: DINT;
	END_VAR

  if (SyncPara.DigInputs.ptr <> NIL) & bOnlineFinished then
    if SyncPara.DigInputs.size >= 1 then
      Input1:=SyncPara.DigInputs.ptr^$BSINT.1;
    else
      Input1:=0;
    end_if;
  else
    Input1:=0;
  end_if;

	output := Input1;

END_FUNCTION


FUNCTION VIRTUAL GLOBAL _DriveAxisBase::Input2::Read
	VAR_OUTPUT
		output (EAX) 	: DINT;
	END_VAR

  if (SyncPara.DigInputs.ptr <> NIL) & bOnlineFinished then
    if SyncPara.DigInputs.size >= 2 then
      Input2:=SyncPara.DigInputs.ptr^$BSINT.2;
    else
      Input2:=0;
    end_if;
  else
    Input2:=0;
  end_if;

	output := Input2;

END_FUNCTION


FUNCTION VIRTUAL GLOBAL _DriveAxisBase::Input3::Read
	VAR_OUTPUT
		output (EAX) 	: DINT;
	END_VAR

  if (SyncPara.DigInputs.ptr <> NIL) & bOnlineFinished then
    if SyncPara.DigInputs.size >= 3 then
      Input3:=SyncPara.DigInputs.ptr^$BSINT.3;
    else
      Input3:=0;
    end_if;
  else
    Input3:=0;
  end_if;

	output := Input3;

END_FUNCTION


FUNCTION VIRTUAL GLOBAL _DriveAxisBase::Input4::Read
	VAR_OUTPUT
		output (EAX) 	: DINT;
	END_VAR

  if (SyncPara.DigInputs.ptr <> NIL) & bOnlineFinished then
    if SyncPara.DigInputs.size >= 4 then
      Input4:=SyncPara.DigInputs.ptr^$BSINT.4;
    else
      Input4:=0;
    end_if;
  else
    Input4:=0;
  end_if;

	output := Input4;

END_FUNCTION


FUNCTION VIRTUAL GLOBAL _DriveAxisBase::Input5::Read
	VAR_OUTPUT
		output (EAX) 	: DINT;
	END_VAR

  if (SyncPara.DigInputs.ptr <> NIL) & bOnlineFinished then
    if SyncPara.DigInputs.size >= 5 then
      Input5:=SyncPara.DigInputs.ptr^$BSINT.5;
    else
      Input5:=0;
    end_if;
  else
    Input5:=0;
  end_if;

	output := Input5;

END_FUNCTION


FUNCTION VIRTUAL GLOBAL _DriveAxisBase::Input6::Read
	VAR_OUTPUT
		output (EAX) 	: DINT;
	END_VAR

  if (SyncPara.DigInputs.ptr <> NIL) & bOnlineFinished then
    if SyncPara.DigInputs.size >= 6 then
      Input6:=SyncPara.DigInputs.ptr^$BSINT.6;
    else
      Input6:=0;
    end_if;
  else
    Input6:=0;
  end_if;

	output := Input6;

END_FUNCTION


FUNCTION VIRTUAL GLOBAL _DriveAxisBase::Input7::Read
	VAR_OUTPUT
		output (EAX) 	: DINT;
	END_VAR

  if (SyncPara.DigInputs.ptr <> NIL) & bOnlineFinished then
    if SyncPara.DigInputs.size >= 7 then
      Input7:=SyncPara.DigInputs.ptr^$BSINT.7;
    else
      Input7:=0;
    end_if;
  else
    Input7:=0;
  end_if;

	output := Input7;

END_FUNCTION


FUNCTION VIRTUAL GLOBAL _DriveAxisBase::Input8::Read
	VAR_OUTPUT
		output (EAX) 	: DINT;
	END_VAR

  if (SyncPara.DigInputs.ptr <> NIL) & bOnlineFinished then
    if SyncPara.DigInputs.size >= 8 then
      Input8:=SyncPara.DigInputs.ptr^$BSINT.8;
    else
      Input8:=0;
    end_if;
  else
    Input8:=0;
  end_if;

	output := Input8;

END_FUNCTION


FUNCTION VIRTUAL GLOBAL _DriveAxisBase::Output1::Write
	VAR_INPUT
		input (EAX) 	: DINT;
	END_VAR
	VAR_OUTPUT
		result (EAX) 	: DINT;
	END_VAR

  if (SyncPara.ControlWord.ptr <> NIL) & bOnlineFinished then
       
    if (SyncPara.ControlWord.userinfo=0) then 
      Output1 := input AND 1;
      SyncPara.ControlWord.ptr^$BINT.5:=Output1$BOOL; //ManufactureSpec4;  //Output1
      Controlword.ManufactureSpec4 := Output1$BOOL;
    elsif(SyncPara.ControlWord.userinfo=1) then
      //not available in 32bit controlword
      Output1 := 0;
    end_if;
    
  end_if;
  
	result := Output1;
  
END_FUNCTION


FUNCTION VIRTUAL GLOBAL _DriveAxisBase::Output2::Write
	VAR_INPUT
		input (EAX) 	: DINT;
	END_VAR
	VAR_OUTPUT
		result (EAX) 	: DINT;
	END_VAR

  if (SyncPara.ControlWord.ptr <> NIL) & bOnlineFinished then
       
    if (SyncPara.ControlWord.userinfo=0) then 
      Output2 := input AND 1;
      SyncPara.ControlWord.ptr^$BINT.6:=Output2$BOOL; //ManufactureSpec5;  //Output2
      Controlword.ManufactureSpec5 := Output2$BOOL;
    elsif(SyncPara.ControlWord.userinfo=1) then
      //not available in 32bit controlword
      Output2 := 0;
    end_if;
    
  end_if;
  
	result := Output2;

END_FUNCTION

#pragma warning(disable: 73);
FUNCTION VIRTUAL _DriveAxisBase::LogError
	VAR_INPUT
		pMsg 	: ^CHAR;
	END_VAR

#ifdef HWC_LogError
  HWC_LogError(this, pMsg);
#endif

END_FUNCTION


FUNCTION VIRTUAL _DriveAxisBase::LogValue
	VAR_INPUT
		pString 	: ^CHAR;
		udValue 	: UDINT;
		udValue2 	: UDINT;(* := 16#FFFFFFFF *)
		udValue3 	: UDINT;(* := 16#FFFFFFFF *)
	END_VAR

#ifdef HWC_LogValue3
  HWC_LogValue3(this, pString, udValue, udValue2, udValue3);
#endif

END_FUNCTION
#pragma warning(default: 73);


FUNCTION GLOBAL _DriveAxisBase::SetDiagMode
	VAR_INPUT
		bStartDiagMode 	: BOOL;
		pThisObj 	: ^void;
	END_VAR
	VAR_OUTPUT
		dRetCode 	: DINT;
	END_VAR
  
  // initialize return code with ok
  dRetCode := 1;
  if pThisObj <> NIL then
    if bStartDiagMode = TRUE then
      if AxisState.DiagModeActive = FALSE then
        if bOnlineFinished = TRUE then
          AxisState.DiagModeActive := TRUE;
          pDiagThis       := pThisObj;
          bOnlineFinished := FALSE;
        else
          //axis is not online or init is not finished
          dRetCode := -1;
        end_if;
      else
        if pThisObj <> pDiagThis then
          //diag mode is already set by other instance
          dRetCode := -2; 
        end_if;
      end_if;

    else
      if pThisObj = pDiagThis then
        //diag mode is deactivated - reset values
        AxisState.DiagModeActive := FALSE;
        pDiagThis := NIL;
        //set act state
        bOnlineFinished := IsOnlineFinished();
      else
        //class was locked by other object
        dRetCode := -3;
      end_if;    
    end_if;
  else
    //this pointer is not valid
    dRetCode := -4;
  end_if;


END_FUNCTION


FUNCTION GLOBAL _DriveAxisBase::GetDriveType
	VAR_OUTPUT
		DriveType 	: _DRIVETYPE;
	END_VAR
  
  DriveType := DriveMng.DriveType;
  
END_FUNCTION


FUNCTION _DriveAxisBase::Write_SetSpeed
	VAR_INPUT
		valueIn 	: DINT;
	END_VAR
	VAR_OUTPUT
		valueOut 	: DINT;
	END_VAR

  // writes the value to the PDO data.
  // online is not checked on purpose. It is needed to initialize the PDO data for a reconnect.
  // The value may be truncated to 16bit in the PDO, but is not for the return value.

  valueOut := 0;// zero in case we have no access
	if (SyncPara.SetSpeed.ptr <> NIL) then
    
    if (SyncPara.SetSpeed.size=4) then
      SyncPara.SetSpeed.ptr^ := valueIn;
      valueOut := valueIn;

    elsif (SyncPara.SetSpeed.size=2) then
      if SyncPara.SetSpeed.userinfo = 0 then
        if valueIn > DRIVEAXIS_SPEED_SFFLIMITATION_USERINFO_0 then
          valueIn := DRIVEAXIS_SPEED_SFFLIMITATION_USERINFO_0;
          AxisState.SFFLimitationActive := TRUE;
        elsif valueIn < -DRIVEAXIS_SPEED_SFFLIMITATION_USERINFO_0-1 then
          valueIn := -DRIVEAXIS_SPEED_SFFLIMITATION_USERINFO_0-1;
          AxisState.SFFLimitationActive := TRUE;
        else
          AxisState.SFFLimitationActive := FALSE;
        end_if;
        SyncPara.SetSpeed.ptr^$INT := to_int(valueIn);
        valueOut := valueIn;
      elsif SyncPara.SetSpeed.userinfo = 1 then
        if valueIn > DRIVEAXIS_SPEED_SFFLIMITATION_USERINFO_1 then
          valueIn := DRIVEAXIS_SPEED_SFFLIMITATION_USERINFO_1;
          AxisState.SFFLimitationActive := TRUE;
        elsif valueIn < -DRIVEAXIS_SPEED_SFFLIMITATION_USERINFO_1 then
          valueIn := -DRIVEAXIS_SPEED_SFFLIMITATION_USERINFO_1;
          AxisState.SFFLimitationActive := TRUE;
        else
          AxisState.SFFLimitationActive := FALSE;
        end_if;
        SyncPara.SetSpeed.ptr^$INT := to_int(valueIn);
        valueOut := valueIn;
      end_if;
    end_if;
  end_if;
  
END_FUNCTION


FUNCTION _DriveAxisBase::Write_Enable
	VAR_INPUT
		valueIn 	: DINT;
	END_VAR
	VAR_OUTPUT
		valueOut 	: DINT;
	END_VAR

  // writes the value to the PDO data.
  // online is not checked on purpose. It is needed to initialize the PDO data for a reconnect.

  valueOut := 0;// zero in case we have no access
  if (SyncPara.ControlWord.ptr <> NIL) then
    if (SyncPara.ControlWord.userinfo=0) then 
      SyncPara.ControlWord.ptr^$BINT.1:=valueIn$BOOL; //DRIVE ENABLE
    elsif(SyncPara.ControlWord.userinfo=1) then
      SyncPara.ControlWord.ptr^$BINT.4:=valueIn$BOOL; //DRIVE ENABLE
    end_if;
    
    Controlword.EnableOperation := valueIn$BOOL;
    valueOut := to_dint(valueIn$BOOL);
  end_if;

END_FUNCTION
