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

//{{LSL_DEFINES
#define SDIAS_SDO_MAX_LENGTH              128
#define SDIAS_SDO_RINGBUFFER_NO            64
#define SDIAS_SDO_CHANNEL_NO                3   // fixed in the VI hardware to be 3

// watchdog trigger interval (after 130ms of no trigger the SDIAS HW goes into reset again and takes at least another 10ms to be ready again)
#define SDIAS_WATCHDOG_TRIGGER_TIME        40

// time needed by sdias modules to start up after the watchdog is triggered the first time in ms
#define SDIAS_HARDWARE_STARTUP_TIME        15

// sdias manager needs 2 ticks to handle event for read task (measure sync time)
#define SDIAS_SYNC_MEASURE_TICKS            2

// after activating the PLL SyncOut it takes 3 cycles until the SDIAS sync can be injected
#define SDIAS_CYCLES_WAIT_AFTER_SYNC_ENABLE 3

// wait 1 bus cycle at start to get valid numbers in the task info
#define SDIAS_TASKINFO_READY_TICKS          1

// time to wait (in ms) until other tasks in the same or lower priority than post init have done their stuff
#define SDIAS_WAIT_TIME_IN_POST_INIT        1

#define SIZE_PER_SDIAS_CLIENT               16#0400

// for far memory accesses: 1 module can hold maximum 256 1K blocks (0-255)
#define SDIAS_1K_BLOCK_NO                       256

// far memory accesses maximum length in bytes
#define SDIAS_MAX_SIZE_FAR_MEM_ACCESS           127


#define SDIAS_OFFSET_HW_CONFIG              16#FF00
#define SDIAS_OFFSET_TASK_EVENT_IDS         16#FF10
#define SDIAS_OFFSET_FEATURE_INFO           16#FF18
#define SDIAS_OFFSET_APPLI_LED_STATES       16#FF20
#define SDIAS_OFFSET_SYNC_INJECTION_CFG     16#FF3D
#define SDIAS_OFFSET_TRIGGER_UNIT_SETUP_0   16#FF41
#define SDIAS_OFFSET_TRIGGER_UNIT_SETUP_1   16#FF45
#define SDIAS_OFFSET_TASK_START_CFG_0       16#FF60
#define SDIAS_OFFSET_TASK_CONFIG_0          16#FF86
#define SDIAS_OFFSET_TASK_CONFIG_1          16#FF96
#define SDIAS_OFFSET_TASK_INFO_1            16#FF94
#define SDIAS_OFFSET_TASK_HANDSHAKE_1       16#FF9B
#define SDIAS_OFFSET_TASK_DURATION_TIME_1   16#FF9C
#define SDIAS_OFFSET_TASK_DURATION_TIME_2   16#FFAC
#define SDIAS_OFFSET_TASK_CONFIG_2          16#FFA6

#define SDIAS_RETRIES_ALLOWED         2

// mask to get global error flag out of message counter byte of SDO responses
#define SDIAS_MASK_GLOBAL_ERROR_FLAG        16#80

// mask to get message counter out of message counter byte of SDO responses
#define SDIAS_MASK_MESSAGE_COUNTER          16#3F


#define SDIAS_EVENT_MASK_ID_SYNC_OUT0       16#10
#define SDIAS_EVENT_MASK_ID_SYNC_OUT1       16#11
#define SDIAS_EVENT_MASK_ID_SYNC_OUT2       16#12
#define SDIAS_EVENT_MASK_ID_SYNC_OUT3       16#13

#define SDIAS_MANAGER_SYNC_SYNCOUT_ID       16#85
#define SDIAS_TASK_START_EVENT_SYNCOUT_ID   16#86


#define SDIAS_PLACE_NO_MODULE_ADDED_SO_FAR  16#80000000

#define SDIAS_TRIGGER_UNIT_BYTE_SIZE        2

#define SDIAS_WAIT_TIME_FIRMWARE_HANDSHAKE  5 * 1000

// if the firmware version is below this, there might be problems with SCP111 and other modules => print warning at startup
#define SDIAS_FW_VERSION_SDO_ERROR_FIXED    16#120

// if the protocol version ist below this, Control Read/Broadcast Write Command is not supported by sdiasmanager
#define SDIAS_PROTOCOLVERSION_BROADCAST     16#120

// if the cil version ist below this, Control Read/Broadcast Write Command is not supported by OS for local SDIAS.
#define SDIAS_CILVERSION_BROADCAST         16#5001 

// timeout for blocking the init during initialisation (in ms)
#define SDIAS_INIT_BLOCK_TIMEOUT            20 * 1000

#define SDIAS_MUTEX_NAME_END_LENGTH 3
#define SDIAS_MUTEX_NAME_MAX_LENGTH 32
#define SDIAS_MUTEX_STR_SEPERATOR   ".."

//#define SDIAS_RT_TIME_MEASUREMENT
#ifdef SDIAS_RT_TIME_MEASUREMENT
  #pragma message("ATTENTION: SDIAS real time measurement is active and needs additional ressources in the realtime task")
#endif

(* SDIAS data object commands  *)
#define	 SDIAS_CMD_END							  0x00			(* End command										          *)
#define	 SDIAS_CMD_ACC_MEMORY				  0x01			(* Access dpram memory								      *)
#define	 SDIAS_CMD_ACC_CONTROL				0x02			(* Access dpram control memory						  *)
#define	 SDIAS_CMD_GLOBAL						  0x03			(* SDIAS global command								      *)
#define	 SDIAS_CMD_COPY_LOCAL					0x04			(* DPRAM copy command in local dpram				*)
#define	 SDIAS_CMD_JMP_LOCAL					0x05			(* DPRAM jump command in local dpram 				*)
#define  SDIAS_CMD_ACC_MEMORY_FAR     0x07      (* SDIAS Far Memory Access                  *)

(* SDIAS defines for data object handling *)
// Write data oject list
#define	 SDIAS_DOL_WRITE_USAGE_DOL_EMPTY	  0x20			(* Usage of empty write dol list (wachtdog trigger + end command)   *)
#define	 SDIAS_DOL_WRITE_USAGE_DTA_EMPTY	  0x03			(* Usage of empty write dol data (DO ctrl of 2x copy command for task information + DO ctrl of watchdog trigger      *)
#define	 SDIAS_DOL_WRITE_OFFSET_END_CMD			0x10			(* One data object in list - offset = 1 DO size = 0x10						  *)
#define	 SDIAS_DOL_WRITE_OFFSET_FIRST_DTA		0x02			(* Offset of first data byte of second copy command = 2 (DO ctrl)   *)
#define	 SDIAS_DOL_WRITE_OFFSET_LAST_DTA		0x02			(* Offset of last data byte of second copy command = 2 (DO ctrl )   *)

// Read data oject list
#define	 SDIAS_DOL_READ_USAGE_DOL_EMPTY	    0x30			(* Usage of empty read dol list (2x task info copy command + end command)   *)
#define	 SDIAS_DOL_READ_USAGE_DTA_EMPTY	    0x0D			(* Usage of empty write dol data (DO ctrl of 2x copy command for task information + DO ctrl of watchdog trigger      *)
#define	 SDIAS_DOL_READ_OFFSET_END_CMD			0x20			(* One data object in list - offset = 1 DO size = 0x10						          *)
#define	 SDIAS_DOL_READ_OFFSET_FIRST_DTA		0x07			(* Offset of first data byte of second copy command = 7 = DO state          *)
#define	 SDIAS_DOL_READ_OFFSET_LAST_DTA		  0x0C			(* Offset of last data byte of second copy command = 12 (last byte of task information)       *)

//Versionsnumber where SDIAS SPI Read Accesses are available
#define  SDIAS_SDO_SPI_FIRMWARE_VERSION_AVAILABLE 16#0120

//error info mask
#define  SDIAS_ERROR_INFO_MASK    2#1000011000011111

// Broadcast DO Info
#define SDIAS_OFFSET_CLIENT_CTRLTIMESTAMP   16#0190
#define SDIAS_NR_TIMEBROADCAST_DOS 2
#define SDIAS_TIMEBROADCAST_SUBCMD 16#B0
//}}LSL_DEFINES

//{{LSL_DECLARATION
#include "..\..\Class\SdiasManager\SdiasManager.h"
#include "..\..\Source\BusInterface.h"
#include "..\..\Class\HwControl\HwControl.h"
#include "..\..\source\interfaces\lsl_st_pll.h"
#include "..\..\Source\interfaces\lsl_st_mt.h"

(*!
<Class
	Name               = "SdiasManager"
	Revision           = "1.97"
	GUID               = "{394AF67B-8CC6-416D-B09C-7933A3E56E13}"
	RealtimeTask       = "false"
	CyclicTask         = "false"
	BackgroundTask     = "false"
	Sigmatek           = "true"
	OSInterface        = "false"
	HighPriority       = "false"
	Automatic          = "false"
	UpdateMode         = "Prescan"
	IconPath           = ".\Class\s-dias.ico"
	SharedCommandTable = "true"
	Objectsize         = "(568,120)">
	<Channels>
		<Server Name="ClassState" GUID="{E6C8CCE7-B734-4664-8812-F515E1FE477F}" Visualized="true" Initialize="false" WriteProtected="true" Retentive="false" Comment="Shows the state of the SDIAS Manager."/>
		<Server Name="FirmwareVersion" GUID="{33D83E48-6798-4F71-8AEC-B390D678A708}" Visualized="true" Initialize="false" WriteProtected="true" Retentive="false" Comment="Server shows the actual FW Version of the Module in the format xx.yy&#13;&#10;&#13;&#10;e.g. 16#0130 means v01.30"/>
		<Server Name="IsoRdTaskDuration" GUID="{84AD2B57-3AC4-4538-BDB4-2DAEE2EFB169}" Visualized="true" Initialize="false" WriteProtected="true" Retentive="false" Comment="Time measurement of last iso read task at SDIAS in [µs]&#13;&#10;The measured time could be higher then the calculated time according to bit 4 &#13;&#10;of the manager option bits (0 .. with preprocessor time, 1 .. only execution time)."/>
		<Server Name="IsoRdTaskMaxDuration" GUID="{EF301307-DE27-43B6-A903-8B0CC8527A83}" Visualized="true" Initialize="false" WriteProtected="false" Retentive="false" Comment="Maximal time measurement of iso read task at SDIAS in [µs].&#13;&#10;The measured time could be higher then the calculated time according to bit 4 &#13;&#10;of the manager option bits (0 .. with preprocessor time, 1 .. only execution time)."/>
		<Server Name="IsoTaskErrorCount" GUID="{FA87199C-1736-4C34-AA25-9B13716E0332}" Visualized="true" Initialize="false" WriteProtected="true" Retentive="false" Comment="number of errors occured in isochronous task handling of SDIAS&#13;&#10;&#13;&#10;this server counts if:&#13;&#10; - error bit of task-handshake is set at iso read or write task&#13;&#10; - toggle bit has the wrong value at iso read or iso write task"/>
		<Server Name="IsoWrTaskDuration" GUID="{FA10A8DF-3224-4BE8-BB1A-0F7DC484B45D}" Visualized="true" Initialize="false" WriteProtected="true" Retentive="false" Comment="time measurement of last iso write task at SDIAS in [µs]"/>
		<Server Name="IsoWrTaskMaxDuration" GUID="{A06F001F-ACF6-457D-95D0-C51681D1E93C}" Visualized="true" Initialize="false" WriteProtected="false" Retentive="false" Comment="maximal time measurement of iso write task at SDIAS in [µs]"/>
		<Server Name="ManagerOptionBits" GUID="{4DB931BE-ED72-4899-84E6-9E3B1687227E}" Visualized="true" Initialize="false" WriteProtected="true" Retentive="false" Comment="Option Bits:&#13;&#10;Bit 1: Interrupts supported&#13;&#10;Bit 2: Half duplex (SDIAS S2), bus scan required&#13;&#10;Bit 3: Far Memory access supported&#13;&#10;Bit 4: Status wait supported (to differ TimeSliceError and TimeSliceErrorIRQ)&#13;&#10;Bit 5: Execution time selection supported 1&#13;&#10;Bit 6: Task interruption detection supported&#13;&#10;Bit 7: Execution time selection supported 2&#13;&#10;"/>
		<Server Name="ManagerProtocolVersion" GUID="{75B29CE6-59BC-47BB-8C78-CA10EA7CDA8B}" Visualized="false" Initialize="false" WriteProtected="true" Retentive="false" Comment="Server shows the SDIAS Manager Protocol Version of the Module in the format xx.y.z&#13;&#10;e.g. 16#0130 means v01.3.0"/>
		<Server Name="RetryCounter" GUID="{137B93FA-1521-4EAB-847F-D714446F712A}" Visualized="true" Initialize="false" WriteProtected="true" Retentive="false" Comment="Actual Number of Retries on SDIAS-Bus."/>
		<Client Name="AutoFarMem" Required="true" Internal="false" DefValue="0" Comment="Only valid for simple master CPUs (CP101 or CP102):&#13;&#10;Parameter Values:&#13;&#10;0 ... AutoFarMem is not activated&#13;&#10;1 ... AutoFarMem shall be activated if possible&#13;&#10;Defaultvalue: 0 (deactivated)&#13;&#10;Shown Values:&#13;&#10;1 ... AutoFarMem is activated&#13;&#10;-1 ... AutoFarMem is NOT activated (OS is too old)&#13;&#10;-2 ... AutoFarMem is NOT activated (FPGA is too old)&#13;&#10;-99 ... AutoFarMem is NOT activated (other error)&#13;&#10;AutoFarMem:&#13;&#10;far memory accesses and&#13;&#10;128 byte SDIAS-accesses&#13;&#10;are possible  (not AutoFarMem only 4 Byte)."/>
		<Client Name="DeviceID" Required="false" Internal="false" DefValue="0"/>
		<Client Name="ToBusInterface" Required="true" Internal="false"/>
		<Client Name="ToMultiTask" Required="false" Internal="false"/>
		<Client Name="ToStdLib" Required="false" Internal="false"/>
	</Channels>
	<Dependencies>
		<Files>
			<File Path=".\Class\SdiasManager\SdiasManager.h" Include="true"/>
			<File Path=".\Source\BusInterface.h" Include="true"/>
			<File Path=".\Class\HwControl\HwControl.h" Include="true"/>
			<File Path=".\source\interfaces\lsl_st_pll.h" Include="true"/>
			<File Path=".\Source\interfaces\lsl_st_mt.h" Include="true"/>
			<File Path=".\Source\interfaces\lsl_st_sdias.h" Include="true"/>
		</Files>
	</Dependencies>
	<RevDoku>
		<Owner Company="Sigmatek" Author="RamAnd"/>
		<Dokumentation Revision="1.97" Date="08.07.2021" Author="RamAnd" Company="Sigmatek" Description="There could have been default read accesses active, which might have interfered when reading latched values.&#13;&#10;Default read accesses are now disabled after the class took over the control of the local SDIAS from the OS."/>
		<Dokumentation Revision="1.96" Date="30.07.2020" Author="HaeTho" Company="Sigmatek" Description="AutoFarMem (far memory access and 128byte access on SDIAS bus) may be activated for local SDIAS on Simple Master CPUs (CP101 and CP102)"/>
		<Dokumentation Revision="1.95" Date="24.11.2020" Author="PieSte&#13;&#10;EisMic" Company="Sigmatek" Description="Clear the ISO Write memory at connect from VI02x.&#13;&#10;Added a check if the length of the isochronous read/write DO from VARAN is big enough after a reconnect.&#13;&#10;Internal methods were set to virtual.&#13;&#10;Forwarded the CMD_HWC_REQ_PLLNS_REGULATION NewInst cmd to the businterface class."/>
		<Dokumentation Revision="1.94" Date="06.02.2020" Author="PieSte" Company="Sigmatek" Description="(SA 54165) Since v1.85 the new asynchronous access at initialisation is not unlocked. Due to this the SDO&apos;s at AddAccess() methode failed for modules behind varan (DC06x, SR01x, ..) with VI02x fpga version &gt; 1.6 &amp; &lt; 2.0. Due to this the &quot;Execution Time Selection Supported&quot; Flag at the ManagerOptionBits has moved to Bit 7."/>
		<Dokumentation Revision="1.93" Date="14.11.2018" Author="PieSte" Company="Sigmatek" Description="Add retry timeout calculation for the TaskInfoDO if module is connected over varan. Now, when the module is reconnected, the retry timeout is also recalculated (TaskInfoDO, IsoReadDO, IsoWriteDO)."/>
		<Dokumentation Revision="1.92" Date="30.04.2018" Author="LanSte" Company="Sigmatek" Description="Added support for startsynchronisation of modules."/>
		<Dokumentation Revision="1.91" Date="27.04.2018" Author="PieSte" Company="Sigmatek" Description="The behavior of Local SDIAS and SDIAS behind Varan was adjusted in the initialization phase. For local SDIAS the bus cycle time is passed to the SDIAS clients before the method AddAccesses() and for SDIAS after VARAN after the method. Now the bus cycle time is available in both variants in the method AddAccesses()."/>
		<Dokumentation Revision="1.90" Date="06.04.2018" Author="LanSte" Company="Sigmatek" Description="Added Server ManagerProtocolVersion"/>
		<Dokumentation Revision="1.89" Date="08.03.2018" Author="LanSte" Company="Sigmatek" Description="Added Broadcast commands with HWTimestamp + ISO Startpoint."/>
		<Dokumentation Revision="1.88" Date="23.01.2018" Author="RamAnd" Company="Sigmatek" Description="Log messages have been standardized for easier maintenance, easier use in any class and to allow spam filtering. Code for the logging functions is now only located in HwControl."/>
		<Dokumentation Revision="1.87" Date="19.12.2017" Author="EisMic" Company="Sigmatek" Description="Since v1.86 the SDIAS Bus of the CP212 wasn&apos;t working anymore. (SyncOut ID was not found)"/>
		<Dokumentation Revision="1.86" Date="10.08.2017" Author="PieSte&#13;&#10;EisMic" Company="Sigmatek" Description="Added support for far memory access at SdiasManager. &#13;&#10;Added support for IPC321 (improved search of SyncOut-ID for Sdiasmanager)"/>
		<Dokumentation Revision="1.85" Date="20.04.2017" Author="PieSte&#13;&#10;EisMic" Company="Sigmatek" Description="Added sdias time calculation at hardware description file.&#13;&#10;Added manager options bit and steps in initialisation for execution time selection.&#13;&#10;TimeSliceErrorIRQ is now supported if feature is available in FPGA."/>
		<Dokumentation Revision="1.84" Date="12.12.2016" Author="PieSte&#13;&#10;EisMic&#13;&#10;ZoePat" Company="Sigmatek" Description="Changed &quot;Online&quot; server behavior to set online first if cyclic data is valid due to SA35740.&#13;&#10;Feature Support Bits are now shown on server ManagerOptionBits if available.&#13;&#10;SdiasModules can now request to increase the PostInit timeout."/>
		<Dokumentation Revision="1.83" Date="14.11.2016" Author="EisMic" Company="Sigmatek" Description="Removed check for TimeSliceErrorIRQ if write task is interrupted by read task. The check could have led to a SDIAS-Error if SDIAS Safety modules were used or only a small amount of SDIAS modules were used."/>
		<Dokumentation Revision="1.82" Date="11.10.2016" Author="EisMic" Company="Sigmatek" Description="Added support that modules can access the Default-Access-Info in the AddAccesses Method.&#13;&#10;Corrected that the Iso Read task is started with the sync after plug&amp;play.&#13;&#10;Added support for Feature Support Bits via NewInst."/>
		<Dokumentation Revision="1.81" Date="08.09.2016" Author="ZoePat" Company="Sigmatek" Description="TimeSliceError and TimeSliceErrorIRQ are now differentiated."/>
		<Dokumentation Revision="1.80" Date="22.04.2016" Author="ZoePat" Company="Sigmatek" Description="Since V1.76 the RT-Postscan of the modules was called 1 rt-cycle to early. This led to a SDIAS-Error if a ICA011/111 was used on a Simple-Master CPU (e.g.: CP101/102)."/>
		<Dokumentation Revision="1.79" Date="17.02.2016" Author="RamAnd" Company="Sigmatek" Description="Calculation of pointers for move DOs and access info has been corrected. If the original pointer is NIL now the resulting pointer also is NIL."/>
		<Dokumentation Revision="1.78" Date="27.01.2016" Author="EisMic" Company="Sigmatek" Description="Added servers for maximal IsoRd/IsoWrTaskDuration."/>
		<Dokumentation Revision="1.77" Date="22.01.2016" Author="PieSte" Company="Sigmatek" Description="Add support for read/write of userflash commando at sdiasmanager.h file."/>
		<Dokumentation Revision="1.76" Date="09.12.2015" Author="EisMic" Company="Sigmatek" Description="It is now ensured that the SDIAS-hardwareclasses displays valid server values after Plug&amp;Play, if the classstate is _ClassOk."/>
		<Dokumentation Revision="1.75" Date="27.08.2015" Author="EisMic" Company="Sigmatek" Description="Corrected handling of valid DeviceIds due to a timeout when a wrong module was connected."/>
		<Dokumentation Revision="1.74" Date="11.05.2015" Author="RamAnd" Company="Sigmatek" Description="Corrected initialisation: It could have happened that a partial read list has been executed during startup, which could cause problems on SDIAS modules with FIFO-Buffers."/>
		<Dokumentation Revision="1.73" Date="15.04.2015" Author="RamAnd" Company="Sigmatek" Description="Added another step in initialisation to prevent watchdog error."/>
		<Dokumentation Revision="1.72" Date="15.04.2015" Author="EisMic" Company="Sigmatek" Description="Added support for VaranMux."/>
		<Dokumentation Revision="1.71" Date="17.03.2015" Author="RamAnd" Company="Sigmatek" Description="Added HW Version for sdias clients."/>
		<Dokumentation Revision="1.70" Date="11.02.2015" Author="PieSte" Company="Sigmatek" Description="Avoid error at iso write task on local sdias, if there is no or wrong hardware."/>
		<Dokumentation Revision="1.69" Date="24.01.2015" Author="RamAnd" Company="Sigmatek" Description="Increased the size of the SDO buffer from 30 to 64 (1 SDO for every module).&#13;&#10;Added a timeout for the firmware handshake.&#13;&#10;After getting the firmware handshake the read task is triggered every 40ms to prevent a timeout in the firmware (3 seconds) during initialisation.&#13;&#10;If there are errors on single modules which are not required, other modules now work properly.&#13;&#10;The cyclic-method of SDIAS objects is now only called if the correct module hardware is available.&#13;&#10;The class waits now in the initialisation until the OS has enumerated the SDIAS modules (e.g. needed for communication with safety modules)"/>
		<Dokumentation Revision="1.68" Date="09.12.2014" Author="RamAnd" Company="Sigmatek" Description="It has been possible that a SDIAS error has been triggered caused by issues which were corrected by the following retries."/>
		<Dokumentation Revision="1.67" Date="06.11.2014" Author="LanSte" Company="Sigmatek" Description="Added support for reading the ManagerInfoblock when the Classstate is _ModuleFoundButManagerIsOff."/>
		<Dokumentation Revision="1.66" Date="03.11.2014" Author="RamAnd" Company="Sigmatek" Description="Refresh Retrycounters before crashing with a required or SDIAS error.&#13;&#10;Removed call in interrupt method to save time and stack size."/>
		<Dokumentation Revision="1.65" Date="13.10.2014" Author="RamAnd" Company="Sigmatek" Description="If an error occurs and the project should not crash with SDIAS error, the bus is turned off now."/>
		<Dokumentation Revision="1.64" Date="30.09.2014" Author="EisMic" Company="Sigmatek" Description="Added command to add valid device ids to check in _Bus_IF_Check_Device_ID. Support for VI022."/>
		<Dokumentation Revision="1.63" Date="30.09.2014" Author="RamAnd" Company="Sigmatek" Description="Added possibility to create a SDIAS control access.&#13;&#10;At the start of the module initialisation only 2 of the 3 available SDO channels have been used.&#13;&#10;Realtime-Method is no longer called after a timeslice error occured.&#13;&#10;Starttime of first watchdog trigger is now remembered for a correct wait time until the modules are ready to access them."/>
		<Dokumentation Revision="1.62" Date="30.06.2014" Author="EisMic" Company="Sigmatek" Description="Added support for reading hardware diagnosis and hardwaretree entry."/>
		<Dokumentation Revision="1.61" Date="18.07.2014" Author="RamAnd" Company="Sigmatek" Description="Corrected handling of SDO channel usage, because a problem could have lead to a timeout in the SDO communication."/>
		<Dokumentation Revision="1.60" Date="17.07.2014" Author="ZoePat" Company="Sigmatek" Description="Added new intelligent SDO-access SDIAS_SDO_CMD_READ_UC_RAM to t_SDIAS_SDO_Cmd."/>
		<Dokumentation Revision="1.59" Date="08.07.2014" Author="PieSte" Company="Sigmatek" Description="Maximal read sdo response request was not correct."/>
		<Dokumentation Revision="1.58" Date="17.06.2014" Author="RamAnd" Company="Sigmatek" Description="The class no longer crashes if there are no required modules connected or no modules projected."/>
		<Dokumentation Revision="1.57" Date="28.04.2014" Author="ZoePat" Company="Sigmatek" Description="Added support for CP112 (Before a SDIAS error occured at startup)."/>
		<Dokumentation Revision="1.56" Date="24.04.2014" Author="RamAnd" Company="Sigmatek" Description="SDIAS Errors now only occur if the SDIAS manager (or any connected module) is required."/>
		<Dokumentation Revision="1.55" Date="14.04.2014" Author="RamAnd" Company="Sigmatek" Description="If the module is connected during runtime, the ISO DOs are now created in realtime instead of cyclic task priority."/>
		<Dokumentation Revision="1.54" Date="14.04.2014" Author="RamAnd" Company="Sigmatek" Description="Added new interface which waits until the OS is ready for the SDIAS requests to safety components."/>
		<Dokumentation Revision="1.53" Date="10.04.2014" Author="RamAnd" Company="Sigmatek" Description="Corrected initialisation of data objects which could have lead to problems with time synchronisation at safety modules."/>
		<Dokumentation Revision="1.52" Date="12.03.2014" Author="RamAnd" Company="Sigmatek" Description="Added dynamic read and write access, which can change it&apos;s size and offset during runtime."/>
		<Dokumentation Revision="1.51" Date="07.04.2014" Author="RamAnd" Company="Sigmatek" Description="Init start time wasn&apos;t set correctly for the timeout detection during initialization."/>
		<Dokumentation Revision="1.50" Date="12.02.2014" Author="RamAnd&#13;&#10;&#13;&#10;RamAnd&#13;&#10;RamAnd" Company="Sigmatek" Description="Corrected error in SDO handling at local SDIAS, where the offset and length of read or write accesses was always delivered as 0 in the callback.&#13;&#10;Added interface to get task info before the payload to detect task errors more accurately.&#13;&#10;A SDIAS Error is triggered if a timeslice error or other error in the isochronous SDIAS tasks occur."/>
		<Dokumentation Revision="1.40" Date="22.01.2014" Author="RamAnd&#13;&#10;&#13;&#10;RamAnd&#13;&#10;RamAnd&#13;&#10;&#13;&#10;RamAnd&#13;&#10;RamAnd&#13;&#10;&#13;&#10;RamAnd&#13;&#10;RamAnd&#13;&#10;KamMic" Company="Sigmatek" Description="Initialisation of VaranManager and SdiasManager has been reworked for cases where multiple Safety cpus are connected via VI021.&#13;&#10;Corrected creation of DOs if SDIAS Manager is connected via VARAN.&#13;&#10;Timeslice errors could not be detected correctly. Taskinfo is now fetched via seperate VARAN DO if the SDIAS Manager is connected via VARAN.&#13;&#10;Get required setting of bus interface to set required error correctly if an isochronous task fails.&#13;&#10;Corrected error in SDO communication (response has been read before the message counter of the request has been incremented) which could have lead to a timeout.&#13;&#10;Added support for SDIAS PC.&#13;&#10;Added parameter for Post Init login to define if DOs via VARAN are necessary.&#13;&#10;Added Cmd SDIAS_CMD_GET_MOI_ADDR to get the Pointer of the Variable ModuleObjInfo via NewInst"/>
		<Dokumentation Revision="1.30" Date="06.12.2013" Author="RamAnd" Company="Sigmatek" Description="If a SPI Error occured the class stuck in the current step of the initialisation.&#13;&#10;Optimized InfoBlock readout to save time.&#13;&#10;Corrected handling of volatile wait flag (Pointer to DO has been used instead of pointer to Read Payload of the DO)&#13;&#10;Update of retry counters and checking of errors on single accesses is now only done if there is a bit set in the global section of the FPGA (saves time in RT)"/>
		<Dokumentation Revision="1.20" Date="30.08.2013" Author="LoeHan&#13;&#10;RamAnd" Company="Sigmatek" Description="Added dynamic DO creation.&#13;&#10;Added UpdateCy for SDIAS modules."/>
		<Dokumentation Revision="1.10" Date="01.08.2013" Author="ObeChr&#13;&#10;RamAnd&#13;&#10;RamAnd&#13;&#10;RamAnd" Company="Sigmatek" Description="Added Comments&#13;&#10;Changed initialisation order to prevent using an older hardware configuration than the actual.&#13;&#10;Changes to show FPGA Version on SDIAS Client objects.&#13;&#10;In the first realtime cycles the classes showed _ClassOk, but there was no actual IO information. Now the ClassState of SDIAS Clients is stored temporary during init and shown at the server after init."/>
		<Dokumentation Revision="1.0" Date="18.07.2013" Author="RamAnd" Company="Sigmatek" Description="First library version"/>
	</RevDoku>
</Class>
*)
SdiasManager : CLASS
	TYPE
#pragma pack(push, 1)
	  t_AccessControl : STRUCT
	    AccessHandle : UDINT;
	    pControlByte : t_SDIAS_pControlByte;
	    pStateByte : t_SDIAS_pStateByte;
	  END_STRUCT;
#pragma pack(pop)
	  t_AppliLEDStates : ARRAY [0..15] OF BSINT
	  [
	  ];
	  t_AsyDOUsage :
	  (
	    _NotUsed:=0,
	    _UsedBySSW:=1,
	    _UsedBySDO:=2,
	    _UsedByLED:=3,
	    _UsedByWD:=4
	  )$USINT;
#pragma pack(push, 1)
	  t_BroadCastTime : STRUCT
	    pWriteData : ^UINT;
	    Access : t_AccessControl;
	  END_STRUCT;
#pragma pack(pop)
#pragma pack(push, 1)
	  t_CyclicMsgMarker : STRUCT
	    AlreadyPosted : BDINT
	    [
	      1 GetDeviceBitmap,
	      2 ToggleErrorWrTask,
	      3 ToggleErrorRdTask,
	      4 ErrorWrTask,
	      5 ErrorRdTask,
	      6 GetRdInfoFailed,
	      7 GetWrInfoFailed,
	      8 SetSyncFailed,
	      9 GetFrameCounterFailed,
	      10 WrTaskNotFinished,
	      11 RdTaskNotFinished,
	      12 RdTaskNoEvent,
	      13 WrTaskInterruptedByRdTask,
	    ];
	    PostIt : BDINT
	    [
	      1 IsoReadRunFailed,
	      2 IsoWriteRunFailed,
	      3 RequiredError,
	      4 ForwardRequiredErrorFailed,
	      5 ToggleErrorWrTask,
	      6 ToggleErrorRdTask,
	      7 ErrorWrTask,
	      8 ErrorRdTask,
	      9 GetRdInfoFailed,
	      10 GetWrInfoFailed,
	      11 SetSyncFailed,
	      12 GetFrameCounterFailed,
	      13 WrTaskNotFinished,
	      14 RdTaskNotFinished,
	      15 TaskInfoRunFailed,
	      16 IsoConfigWrTaskConfigFailed,
	      17 IsoConfigWrTriggerUnitFailed,
	      18 IsoConfigWrChangeFailed,
	      19 IsoTaskConfigFailed,
	      20 IsoTriggerUnitConfigFailed,
	      21 IsoConfigWrChange2Failed,
	      22 IsoConfigWrSyncInjFailed,
	      23 IsoSyncInjFailed,
	      24 RdTaskNoEvent,
	      25 WrTaskInterruptedByRdTask,
	      26 SetOnlineStateFailed,
	    ];
	  END_STRUCT;
#pragma pack(pop)
#pragma pack(push, 1)
	  t_DARdPayloadFrame : STRUCT
	    StateByte : t_SDIAS_StateByte;
	    Data : ARRAY [0..126] OF DINT;
	  END_STRUCT;
#pragma pack(pop)
#pragma pack(push, 1)
	  t_DAWrPayloadFrame : STRUCT
	    TriggerUnit : UINT;
	    ContolByte : t_SDIAS_ControlByte;
	    ReadLength : USINT;
	    ReadOffset : HINT;
	    WriteLength : USINT;
	    WriteOffset : HINT;
	    Data : ARRAY [0..118] OF USINT;
	  END_STRUCT;
#pragma pack(pop)
	  t_DeviceBitmap : ARRAY [0..1] OF BDINT
	  [
	  ];
	  t_FarMemoryAccessInfo : BSINT
	  [
	    1 IsAvailable,
	    2 IsAvailableIsValid,
	  ];
	  t_OptionBits : BDINT
	  [
	    1 InterruptsSupported,
	    2 HalfDuplex,
	    3 FarMemoryAccessSupported,
	    4 StatusWaitSupported,
	    5 ExecutionTimeSelectionSupported1,  //! <Type Comment="This bit was used for ExecutionTimeSelectionSupported but there was an error at SdiasManager class. Due to this it has moved to bit 7." Name="t_OptionBits.ExecutionTimeSelectionSupported1"/>
	    6 TaskInterruptionDetectionSupported,
	    7 ExecutionTimeSelectionSupported2,
	    17 SimpleMaster,
	  ];
#pragma pack(push, 1)
	  t_FeatureInfo : STRUCT
	    ProtocolVersion : HINT;
	    Reserved : HINT;
	    OptionBits : t_OptionBits;
	  END_STRUCT;
#pragma pack(pop)
#pragma pack(push, 1)
	  t_HardwareConfiguration : STRUCT
	    DeviceBitmap : t_DeviceBitmap;
	    MirroredHWInfoSize : HSINT;
	    NoOfMirroredDevices : USINT;
	    DPRAMReservedAtBottom : UINT;
	    DPRAMSize : UINT;
	    TasksAvailableNo : BSINT
	    [
	      1 ImplementedTasksBit0,
	      2 ImplementedTasksBit1,
	      3 ImplementedTasksBit2,
	      4 ImplementedTasksBit3,
	      5 Reserved4uCBit0,
	      6 Reserved4uCBit1,
	      7 Reserved4uCBit2,
	      8 Reserved4uCBit3,
	    ];
	    PortsAndTriggerUnits : BSINT
	    [
	      1 PortNoBit0,
	      2 PortNoBit1,
	      3 PortNoBit2,
	      4 PortNoBit3,
	      5 TriggerUnitNoBit0,
	      6 TriggerUnitNoBit1,
	      7 TriggerUnitNoBit2,
	      8 TriggerUnitNoBit3,
	    ];
	  END_STRUCT;
#pragma pack(pop)
	  t_InitSSW :
	  (
	    _StartInit:=0,
	    _GetHandshake:=5,
	    _CheckHandshake:=10,
	    _WaitForDisabledTasks:=15,
	    _GetHWInfo:=20,
	    _Wait4HWInfo:=25,
	    _Wait4MatchingDeviceBitmap:=30,
	    _GetInfoBlockAvailableModules:=35,
	    _GetInfoBlockMappingInfo:=40,
	    _GetFeatureInfo:=42,
	    _Wait4FeatureInfo:=43,
	    _SetExecutionTimeSelectionIsoRd:=44,
	    _SetExecutionTimeSelectionIsoWr:=45,
	    _GetSDOMessageCounters:=46,
	    _Wait4MessageCounters:=50,
	    _InitAccesses:=55,
	    _StartRtIsoDOCreation:=60,
	    _Wait4RtIsoDOCreation:=65,
	    _CheckInfoBlock:=70,
	    _PrepareResetIsoRdPayload:=75,
	    _ResetIsoRdPayload:=80,
	    _PrepareResetIsoWrPayload:=85,
	    _ResetIsoWrPayload:=90,
	    _CheckModule_Valid:=95,  //! <Type Comment="Verify module ID" Name="t_InitSSW._CheckModule_Valid"/>
	    _SetModAccess:=100,  //! <Type Comment="Build DO for module access " Name="t_InitSSW._SetModAccess"/>
	    _WriteModAccess:=105,  //! <Type Comment="Transmitt module access to sdias manager" Name="t_InitSSW._WriteModAccess"/>
	    _SetNextModAccess:=110,  //! <Type Comment="Wait until module access has been transmitted" Name="t_InitSSW._SetNextModAccess"/>
	    _CheckNextModule:=115,  //! <Type Comment="Switch to next module" Name="t_InitSSW._CheckNextModule"/>
	    _SetBroadCastAccess:=117,
	    _WriteSetBroadCastAccess:=118,
	    _WaitSetBroadCastAccess:=119,
	    _WriteDOL_Offsets:=120,
	    _WaitReq_DOL_Offsets:=125,  //! <Type Comment="Wait for request of new data object offsets" Name="t_InitSSW._WaitReq_DOL_Offsets"/>
	    _GetEventIDs:=127,
	    _SetStartConfigIsoRd:=130,
	    _SelectTaskStartConfigIsoRd:=135,
	    _SelectTaskStartConfigIsoWr:=140,
	    _SetTriggerUnits:=145,
	    _WriteDAList:=150,
	    _ResetDARdPayload:=155,
	    _ConfigDATask:=160,
	    _DeactivateSyncInjection:=165,
	    _PrepareModuleInitialisation:=170,
	    _Wait4OtherModules:=175,
	    _Wait4VaranManager:=180,
	    _Wait4HardwareReady:=185,
	    _ModuleInitialisation:=190,
	    _SetActualLEDStates:=195,
	    _FinishInitialisation:=200,
	    _WaitForRtOperational:=205,
	    _InitFinished:=210,
	    _PrepareError:=215,
	    _ErrorOccured:=220
	  )$UDINT;
	  t_LoginSettings : BSINT
	  [
	    1 Wait4DOCreation,
	    2 Wait4MoveDOCreation,
	    3 Wait4SyncSend,
	  ];
#pragma pack(push, 1)
	  t_PayloadAccess : STRUCT
	    Handle : UDINT;
	    AccessHandle : UDINT;
	    pData : pVoid;
	    pDataDPRAM : pVoid;
	    Offset : HINT;
	    Length : UINT;
	  END_STRUCT;
#pragma pack(pop)
	  t_RtSSW :
	  (
	    _RtIdle:=0,
	    _CreateAndModifyDOs:=5,
	    _Wait4DOs:=10,
	    _Wait4PllSync:=11,
	    _Wait2Ticks:=12,
	    _CntDownSyncStart,
	    _PreOperationalWait4DataReady:=14,
	    _PreOperational:=15,
	    _Operational:=20
	  )$UDINT;
#pragma pack(push, 1)
	  t_s_DOLengths_FirstConnect : STRUCT
	    udISOReadLength : UDINT;
	    udISOWriteLength : UDINT;
	    udISOReadActUsage : UDINT;
	    udISOWriteActUsage : UDINT;
	  END_STRUCT;
#pragma pack(pop)
#pragma pack(push, 1)
	  t_SDIAS_DOListEntry : STRUCT
	    OffsetWritePayload : HINT;
	    OffsetReadPayload : HINT;
	    OffsetVolatileWaitFlag : HINT;
	    ErrorInfo : BINT
	    [
	    ];
	    CmdRetries : BSINT
	    [
	      1 CmdTypeBit0,
	      2 CmdTypeBit1,
	      3 CmdTypeBit2,
	      4 CmdTypeBit3,
	      5 Reserved,
	      6 AllowedRetriesBit0,
	      7 AllowedRetriesBit1,
	      8 AllowedRetriesBit2,
	    ];
	    ReadLength : USINT;
	    ReadOffset : HINT;
	    Reserved : USINT;
	    WriteLength : USINT;
	    WriteOffset : HINT;
	  END_STRUCT;
#pragma pack(pop)
	  t_SDIAS_DOListEntryX2 : ARRAY [0..1] OF t_SDIAS_DOListEntry;
#pragma pack(push, 1)
	  t_SDOChannel : STRUCT
	    MessageCounter : USINT;
	    NMT : USINT;
	    SDIASPlace : USINT;
	    Command : USINT;
	    SubCommand : USINT;
	    LengthOfData : USINT;
	    Data : ARRAY [0..35] OF USINT;
	  END_STRUCT;
#pragma pack(pop)
#pragma pack(push, 1)
	  t_SDORingBufEntry : STRUCT
	    pCallBackSvr : ^SvrChCmd;
	    MessageCounter : USINT;
	    NMTCommand : USINT;
	    SDIASPlace : USINT;
	    Command : t_SDIAS_SDO_Cmd;
	    CmdLength : USINT;
	    ReqBufData : ARRAY [0..35] OF USINT;
	    RdWrHead : t_SDIAS_SDO_RdWr_Head;
	    BusyChannelNo : USINT;  //! <Type Comment="0..no channel busy with this&#13;&#10;1..channel 1&#13;&#10;2..channel 2&#13;&#10;3..channel 3" Name="t_SDORingBufEntry.BusyChannelNo"/>
	  END_STRUCT;
#pragma pack(pop)
#pragma pack(push, 1)
	  t_SDOChannelData : STRUCT
	    MessageCnt : USINT;
	    pActElement : ^t_SDORingBufEntry;
	    WaitForResponse : BOOL;
	    RequestTime : UDINT;
	    SdoHandle : UDINT;
	    ChannelData : t_SDOChannel;
	  END_STRUCT;
#pragma pack(pop)
	  t_SDOChannels : ARRAY [0..SDIAS_SDO_CHANNEL_NO-1] OF t_SDOChannel;
#pragma pack(push, 1)
	  t_SDOHandling : STRUCT
	    pRingBufMemStart : ^t_SDORingBufEntry;
	    pLastEntry : ^t_SDORingBufEntry;
	    pWrite : ^t_SDORingBufEntry;
	    pRead : ^t_SDORingBufEntry;
	    RingBufSize : UDINT;
	    EntriesUsed : UDINT;
	    aChannelData : ARRAY [0..SDIAS_SDO_CHANNEL_NO-1] OF t_SDOChannelData;
	    OffsetSDOReq : HINT;
	    OffsetSDOResp : HINT;
	    IncrementMsgCnt : BSINT
	    [
	      1 Channel1,
	      2 Channel2,
	      3 Channel3,
	    ];
	  END_STRUCT;
#pragma pack(pop)
	  t_SyncInjectionCfg : BSINT
	  [
	    1 SyncEnable,
	    2 TaskSelectBit0,
	    3 TaskSelectBit1,
	    4 TaskSelectBit2,
	    5 AllowedSyncLossesBit0,
	    6 AllowedSyncLossesBit1,
	    7 AllowedSyncLossesBit2,
	    8 AllowedSyncLossesBit3,
	  ];
#pragma pack(push, 1)
	  t_TaskConfig : STRUCT
	    TaskDurationTimeout_us : UINT;
	    Config : BINT
	    [
	      1 SynchronizedStartEnable,
	      2 TaskStartCfgSelectBit0,
	      3 TaskStartCfgSelectBit1,
	      4 TaskStartCfgSelectBit2,
	      5 DOListStartAddrBit0,
	      6 DOListStartAddrBit1,
	      7 DOListStartAddrBit2,
	      8 DOListStartAddrBit3,
	      9 DOListStartAddrBit4,
	      10 DOListStartAddrBit5,
	      11 DOListStartAddrBit6,
	      12 DOListStartAddrBit7,
	      13 DOListStartAddrBit8,
	      14 DOListStartAddrBit9,
	      15 DOListStartAddrBit10,
	      16 DOListStartAddrBit11,
	    ];
	  END_STRUCT;
#pragma pack(pop)
	  t_TaskEventIDs : ARRAY [0..7] OF HSINT;
#pragma pack(push, 1)
	  t_TaskInfoData : STRUCT
	    ErrorInfoFlags : BINT
	    [
	      1 AccessCanceled,  //! <Type Comment="Task execution has been cancelled. Other bits are scratchpad content and should be ignored, when this bit is set" Name="t_TaskInfoData.ErrorInfoFlags.AccessCanceled"/>
	      2 CmdTypeInvalid,  //! <Type Comment="The CMD type of this data object is invalid and was ignored in task execution." Name="t_TaskInfoData.ErrorInfoFlags.CmdTypeInvalid"/>
	      3 LengthFieldInvalid,  //! <Type Comment="One of the length fields has an invalid value. The CMD was ignored in task execution. " Name="t_TaskInfoData.ErrorInfoFlags.LengthFieldInvalid"/>
	      4 AddressFieldLength,  //! <Type Comment="One of the SDIAS address fields has an invalid value. The CMD was ignored in task execution." Name="t_TaskInfoData.ErrorInfoFlags.AddressFieldLength"/>
	      5 PointerInvalid,  //! <Type Comment="One of the DPRAM address fields has an invalid value. The CMD was ignored in task execution." Name="t_TaskInfoData.ErrorInfoFlags.PointerInvalid"/>
	      6 AccessFailed,  //! <Type Comment="After executing all allowed retries there was no valid result received." Name="t_TaskInfoData.ErrorInfoFlags.AccessFailed"/>
	      7 MessageCounterInvalidWarning,  //! <Type Comment="While waiting for a response the manager received a message with an invalid message counter (not the message counter of the command). " Name="t_TaskInfoData.ErrorInfoFlags.MessageCounterInvalidWarning"/>
	      8 AnswerTimeoutWarning,  //! <Type Comment="While waiting for a response the manager received no valid message." Name="t_TaskInfoData.ErrorInfoFlags.AnswerTimeoutWarning"/>
	      9 DependencyFailure,  //! <Type Comment="The CMD DO, on which this CMD was waiting to complete, terminated with an error." Name="t_TaskInfoData.ErrorInfoFlags.DependencyFailure"/>
	      10 TaskCancelled,  //! <Type Comment="The task execution was cancelled (wishbone error or timeout occurred)." Name="t_TaskInfoData.ErrorInfoFlags.TaskCancelled"/>
	      12 _4B5BError,  //! <Type Comment="LVDS interface received an invalid 5b code." Name="t_TaskInfoData.ErrorInfoFlags._4B5BError"/>
	      13 SOFWarning,  //! <Type Comment="LVDS interface received an invalid frame start sequence." Name="t_TaskInfoData.ErrorInfoFlags.SOFWarning"/>
	      14 CRCError,  //! <Type Comment="Receive MAC detected a CRC error." Name="t_TaskInfoData.ErrorInfoFlags.CRCError"/>
	      15 CommandError,  //! <Type Comment="Receive MAC detected an invalid command." Name="t_TaskInfoData.ErrorInfoFlags.CommandError"/>
	      16 WishboneError,  //! <Type Comment="A wishbone access terminated with error." Name="t_TaskInfoData.ErrorInfoFlags.WishboneError"/>
	    ];
	    Reserved : ARRAY [0..4] OF USINT;
	    Handshake : BSINT
	    [
	      1 Enabled,
	      2 ExecutionRequest,
	      3 InProgress,
	      4 Executed,
	      5 Error,
	      6 Toggle,
	      7 AnyRetries,
	      8 StatusWait,
	    ];
	    DurationTime : UINT;
	    ExecutionTime : UINT;
	  END_STRUCT;
#pragma pack(pop)
#pragma pack(push, 1)
	  t_TaskInfoReadData : STRUCT
	    ReadTaskInfo : t_TaskInfoData;
	    Reserved : ARRAY [0..3] OF USINT;
	    WriteTaskInfo : t_TaskInfoData;
	  END_STRUCT;
#pragma pack(pop)
#pragma pack(push, 1)
	  t_TaskInfoStruct : STRUCT
	    pControlByte : ^t_SDIAS_ControlByte;
	    pReadData : ^t_TaskInfoData;
	    MaxDuration : UDINT;
	    bOldToggle : BOOL;
	    ToggleErrorCount : DINT;
	    ErrorCount : DINT;
	  END_STRUCT;
#pragma pack(pop)
	  t_TaskSelect : BSINT
	  [
	    1 DirectAccess,
	    2 IsoRead,
	    3 IsoWrite,
	    4 Asynchronous,
	    5 Administration,
	  ];
#pragma pack(push, 1)
	  t_TaskStartConfig : STRUCT
	    EventSelection : BINT
	    [
	      1 Wait4EventBit0,
	      2 Wait4EventBit1,
	      3 Wait4EventBit2,
	      4 Wait4EventBit3,
	      5 Wait4EventBit4,
	      6 Wait4EventBit5,
	      7 Wait4EventBit6,
	      8 Wait4EventBit7,
	    ];
	    StartDelay_us : UINT;
	  END_STRUCT;
#pragma pack(pop)
#pragma pack(push, 1)
	  t_TriggerUnitSetup : STRUCT
	    TaskSelect : t_TaskSelect;
	    StartAddress : BINT
	    [
	      1 UnitEnable,
	    ];
	    Reserved : USINT;
	  END_STRUCT;
#pragma pack(pop)
	  t_TriggerUnitSetupX2 : ARRAY [0..1] OF t_TriggerUnitSetup;
#pragma pack(push, 1)
	  t_WatchdogTriggerData : STRUCT
	    TriggerUnitSizeInfo : UINT;
	    ControlByte : t_SDIAS_ControlByte;
	  END_STRUCT;
#pragma pack(pop)
	END_TYPE
  //Servers:
	ClassState 	: SvrChCmd_t_e_VaranErrors;
	RetryCounter 	: SvrCh_UDINT;
	FirmwareVersion 	: SvrCh_HDINT;
	IsoWrTaskDuration 	: SvrCh_UDINT;
	IsoWrTaskMaxDuration 	: SvrCh_UDINT;
	IsoRdTaskDuration 	: SvrCh_UDINT;
	IsoRdTaskMaxDuration 	: SvrCh_UDINT;
	IsoTaskErrorCount 	: SvrCh_DINT;
	ManagerOptionBits 	: SvrCh_DINT;
	ManagerProtocolVersion 	: SvrCh_HDINT;
  //Clients:
	ToBusInterface 	: CltChCmd_DINT;
	DeviceID 	: CltCh_UDINT;
	ToStdLib 	: CltChCmd__StdLib;
	ToMultiTask 	: CltChCmd__MultiTask;
	AutoFarMem 	: CltCh_DINT;
  //Variables:
		Online 	: DINT;
		InitSSW 	: t_InitSSW;
		ErrorInitStep 	: t_InitSSW;
		RtSSW 	: t_RtSSW;
		MaxPlace 	: UDINT;
		ModuleObjInfo : ARRAY [0..SDIAS_MAX_PLACE_NR] OF t_ModuleObjectInfo;

		ManagerInfoBlock 	: t_ManagerInfoBlock;
		HardwareConfig 	: t_HardwareConfiguration;
		OldDeviceBitmap 	: t_DeviceBitmap;
		AppliLEDStates 	: t_AppliLEDStates;
		WriteTaskInfo 	: t_TaskInfoStruct;
		ReadTaskInfo 	: t_TaskInfoStruct;
		TaskInfoDO 	: t_PayloadAccess;
		InitDuration 	: UDINT;
		HandshakeWaitDuration 	: UDINT;
		ISOReadDO 	: t_PayloadAccess;
		ISOWriteDO 	: t_PayloadAccess;
		ISOConfigWrDO 	: t_PayloadAccess;
		ASYReadDO 	: t_PayloadAccess;
		AsyReadUsage 	: t_AsyDOUsage;
		ASYWriteDO 	: t_PayloadAccess;
		AsyWriteUsage 	: t_AsyDOUsage;
		TaskEventIDs 	: t_TaskEventIDs;
		AccessProgress 	: UINT;
		ModuleSizeNeeded 	: UINT;
		NewDataSize 	: UINT;
		NextPlace 	: UDINT;
		ActModule : ARRAY [0..SDIAS_SDO_CHANNEL_NO-1] OF UDINT;

		us_Firstscan 	: USINT;
		b_Ready4Rt 	: BOOL;
		b_NewLEDStates 	: BOOL;
		ud_BusTime_ns 	: UDINT;
		ud_IsoStartpoint 	: UDINT;
		ud_MainTimer 	: UDINT;
		ud_SystemPeriodTime 	: UDINT;
		ud_SystemPeriodDivider 	: UDINT;
		b_PostInitFinished 	: BOOL;
		DaWriteOffset 	: HDINT;
		DaReadOffset 	: HDINT;
		DaWriteBuffer 	: t_DAWrPayloadFrame;
		DaReadBuffer 	: t_DARdPayloadFrame;
		SDOHandling 	: t_SDOHandling;
		InitStartTime 	: UDINT;
		StartTimeHandshake 	: UDINT;
		pSDIAS 	: ^LSL_SDIAS;
		pHwPath 	: ^USINT;
		pv_Mutex 	: pVoid;
		mt_api 	: ^LSL_MT_TYPE;
		DOStartTime 	: UDINT;
		ModuleInitStartTime : ARRAY [0..SDIAS_SDO_CHANNEL_NO-1] OF UDINT;

		RequiredPlace 	: DINT;
		CyclicMsgMarker 	: t_CyclicMsgMarker;
		InitError 	: t_e_VaranErrors;
		b_SDIASModulesRequired 	: BOOL;
		b_Deactivated 	: BOOL;
		RtPreDuration 	: UDINT;
		RtPostDuration 	: UDINT;
		gcRead_DOL_Desc 	: t_SDIAS_DOL_DESC;
		gcWrite_DOL_Desc 	: t_SDIAS_DOL_DESC;
		gcMapping_Informations : ARRAY [0..15] OF t_MappingInfo;

		udCurCheckedMod 	: USINT;
		pCurCheckModAccPtr 	: ^t_AccessElement;
		cModulAccessCmds 	: t_SDIAS_DOListEntryX2;
		uiWriteCmdAddr 	: HINT;
		bReceivedNewEndRsp 	: BOOL;
		ConnectionType 	: t_SDIAS_ConnectionType;
		ActInitAccessIndex 	: UDINT;
		b_IsoDOsCreated 	: BOOL;
		b_IsoDOsJustCreated 	: BOOL;
		udNodeHandle 	: UDINT;
		RdTaskInfo 	: t_TaskInfoData;
		WrTaskInfo 	: t_TaskInfoData;
		b_IsRequired 	: BOOL;
		b_BusReadyAvailable 	: BOOL;
		b_WdTriggerActive 	: BOOL;
		b_SendWdTrigger 	: BOOL;
		ud_LastWdTime 	: UDINT;
		WdTriggerData 	: t_WatchdogTriggerData;
		PreOpCount 	: DINT;
		ISOTriggerUnitSetup 	: t_TriggerUnitSetup;
		ISOTaskConfig 	: t_TaskConfig;
		aValidDeviceIDs : ARRAY [0..9] OF UDINT;

		WdSSW 	: DINT;
		WaitAfterWd 	: UDINT;
		ToggleReadTaskActive 	: BOOL;
		ConnectDuringPostInitCounter 	: DINT;
		b_MultipleConnectInInit 	: BOOL;
		b_CallbackAdded 	: BOOL;
		FeatureInfo 	: t_FeatureInfo;
		SupportedFeatures 	: t_SDIAS_SupportedFeatureBits1;			//! <Variable Comment="Supported Features of the Sdiasmanager hardwareclass." Name="SupportedFeatures"/>
		AdditionalPostInitTime 	: UDINT;
		bUnknownCmdLogged 	: BOOL;
		FarMemoryAccessInfo 	: t_FarMemoryAccessInfo;
		pPLL 	: ^LSL_PLL;
		ud_NodeHandlePLL 	: UDINT;
		udCurCheckdMngAcc 	: UDINT;
		uiHWTimestamp 	: UINT;
		uiSDIASSyncoffset_us 	: UINT;
		aBroadCastTime : ARRAY [0..SDIAS_NR_TIMEBROADCAST_DOS-1] OF t_BroadCastTime;

		uiSyncCountDown 	: UINT;
		udTimeMark1stSync 	: UDINT;
		sDOLengthsFirstConnect 	: t_s_DOLengths_FirstConnect;
  //Functions:
	
	FUNCTION SdiasManager
		VAR_OUTPUT
			ret_code 	: ConfStates;
		END_VAR;
	
	FUNCTION VIRTUAL GLOBAL Init;
	
	FUNCTION VIRTUAL GLOBAL CyWork
		VAR_INPUT
			DummyInput (EAX) 	: UDINT;
		END_VAR
		VAR_OUTPUT
			state (EAX) 	: UDINT;
		END_VAR;
	
	FUNCTION VIRTUAL GLOBAL RtWork
		VAR_INPUT
			EAX 	: UDINT;
		END_VAR
		VAR_OUTPUT
			state (EAX) 	: UDINT;
		END_VAR;
	
	FUNCTION VIRTUAL AddAccess
		VAR_INPUT
			AccessType 	: t_eAccessType;
			pThis 	: ^SdiasBase;
			Place 	: UDINT;
			Required 	: DINT;
			Offset 	: HINT;
			Length 	: UINT;
			ppData 	: pVoid;
			ppStateByte 	: pVoid;
			ppControlByte 	: pVoid;
			pAccessHandle 	: ^UDINT;
			WaitForAccessHandle 	: UDINT;
			bCtrlAcc0 	: BOOL;
		END_VAR
		VAR_OUTPUT
			Success 	: BOOL;
		END_VAR;
	
	FUNCTION VIRTUAL AddAccessToList
		VAR_INPUT
			AccessType 	: t_eAccessType;
			Place 	: UDINT;
			Offset 	: HINT;
			Length 	: UINT;
			ppData 	: pVoid;
			ppStateByte 	: pVoid;
			ppControlByte 	: pVoid;
			pAccessHandle 	: ^UDINT;
			WaitForAccessHandle 	: UDINT;
			bCtrlAcc0 	: BOOL;
			bIsFarAcc 	: BOOL;
		END_VAR
		VAR_OUTPUT
			Success 	: BOOL;
		END_VAR;
	
	FUNCTION VIRTUAL ChangeDynAccess
		VAR_INPUT
			AccessHandle 	: UDINT;
			NewOffset 	: HDINT;
			NewLength 	: UDINT;
		END_VAR
		VAR_OUTPUT
			Success 	: BOOL;
		END_VAR;
	
	FUNCTION VIRTUAL ConnectEvent;
	
	FUNCTION VIRTUAL DisconnectEvent;
	
	FUNCTION VIRTUAL InterruptEvent;
	
	FUNCTION VIRTUAL ChangeAsyRd
		VAR_INPUT
			Offset 	: HINT;
			Length 	: USINT;
			RunState 	: t_BusIFRunState;
			UsageType 	: t_AsyDOUsage;
		END_VAR
		VAR_OUTPUT
			Success 	: BOOL;
		END_VAR;
	
	FUNCTION VIRTUAL ChangeAsyWr
		VAR_INPUT
			Offset 	: HINT;
			Length 	: USINT;
			RunState 	: t_BusIFRunState;
			UsageType 	: t_AsyDOUsage;
		END_VAR
		VAR_OUTPUT
			Success 	: BOOL;
		END_VAR;
	
	FUNCTION VIRTUAL AddSDOReq
		VAR_INPUT
			pCmdSvr 	: ^SvrChCmd;
			Command 	: t_SDIAS_SDO_Cmd;
			Place 	: USINT;
			CmdLength 	: USINT;
			pReqBuf 	: ^USINT;
		END_VAR
		VAR_OUTPUT
			sd_retval 	: DINT;
		END_VAR;
	
	FUNCTION VIRTUAL ReceiveSDOResponse
		VAR_INPUT
			Command 	: t_SDIAS_SDO_Cmd;
			Offset 	: HINT;
			Length 	: USINT;
			Result 	: iprStates;
			pResponseBuffer 	: ^USINT;
			ResponseLength 	: USINT;
		END_VAR
		VAR_OUTPUT
			ret_code 	: iprStates;
		END_VAR;
	
	FUNCTION VIRTUAL CyclicSDOHandling;
	
	FUNCTION VIRTUAL SetRequiredError
		VAR_INPUT
			pTargetThis 	: ^SdiasBase := NIL;
			Place 	: UDINT := SDIAS_PLACE_NO_MODULE_ADDED_SO_FAR;
		END_VAR;
	
	FUNCTION VIRTUAL DOL_Handling_Add_DO_TO_List
		VAR_INPUT
			bIsWriteAcc0 	: BOOL;
			usModulePlace0 	: USINT;
			iModAddr0 	: HINT;
			iDataLen0 	: UINT;
			bCtrlAcc0 	: BOOL;
			iWaitDOOffset0 	: UINT;
			bIsDynamic0 	: BOOL;
			pActAccess0 	: ^t_AccessElement;
			bIsBroadCast 	: BOOL := FALSE;
		END_VAR
		VAR_OUTPUT
			iRetCode 	: DINT;
		END_VAR;
	
	FUNCTION VIRTUAL DOL_Handling_Create_End_Cmd
		VAR_INPUT
			pEndCmdBuffer 	: ^t_SDIAS_DOListEntry;
		END_VAR;
	
	FUNCTION VIRTUAL LogSDOErrorInfo
		VAR_INPUT
			OSRetVal 	: DINT;
		END_VAR;
	
	FUNCTION VIRTUAL CheckAccess
		VAR_INPUT
			bsStateByte 	: t_SDIAS_StateByte;
			sdRequired 	: DINT;
			sdPlace 	: DINT;
			pCrashThisTime 	: ^USINT;
			pCrashMessage 	: ^CHAR;
		END_VAR
		VAR_OUTPUT
			usRetryCounter 	: USINT;
		END_VAR;
	
	FUNCTION VIRTUAL PostRtMessages;
	
	FUNCTION VIRTUAL CreateAndModifyIsoDOs;
				//! <Function Comment="Method checks if the place is set in the Device Bitmap (8Byte). Return True if the bit is set" Name="IsDeviceBitSet"/>
	FUNCTION VIRTUAL IsDeviceBitSet
		VAR_INPUT
			pDeviceBitMap 	: ^BDINT;
			Place 	: UDINT;
		END_VAR
		VAR_OUTPUT
			bIsSet 	: BOOL;
		END_VAR;
	
	FUNCTION VIRTUAL DisableBus;
	
	FUNCTION VIRTUAL GLOBAL BusIFLogIn;
	
	FUNCTION VIRTUAL SendPostInitFinished
		VAR_INPUT
			DisableThisObject 	: BOOL := FALSE;
		END_VAR;
	
	FUNCTION VIRTUAL FarMemoryAccessAvailable
		VAR_OUTPUT
			IsAvailable 	: BOOL;
		END_VAR;
	
	FUNCTION VIRTUAL AddBroadCastAccessesToList;
	
	FUNCTION VIRTUAL CheckTimeBroadCastSupported
		VAR_OUTPUT
			bTimeBroadCastSupported 	: BOOL;
		END_VAR;
	
	FUNCTION VIRTUAL SendTimeBroadCast;
	
	FUNCTION VIRTUAL SendSyncCntDown
		VAR_OUTPUT
			SyncCountDown 	: UINT;
		END_VAR;
	
	FUNCTION VIRTUAL GLOBAL ClassState::NewInst
		VAR_INPUT
			pPara 	: ^CmdStruct;
			pResult 	: ^results;
		END_VAR
		VAR_OUTPUT
			ret_code 	: iprStates;
		END_VAR;
  //Tables:
	FUNCTION @STD
		VAR_OUTPUT
			ret_code	: CONFSTATES;
		END_VAR;
	FUNCTION GLOBAL TAB @CT_;
END_CLASS;

#pragma usingLtd _MultiTask
#pragma usingLtd _StdLib


//}}LSL_DECLARATION


FUNCTION GLOBAL TAB SdiasManager::@CT_
0$UINT,
2#0100000000000000$UINT, //TY_SDIASMANAGER
1$UINT, 97$UINT, (SIZEOF(::SdiasManager))$UINT, 
10$UINT, 5$UINT, 0$UINT, 
TO_UDINT(2118381352), "SdiasManager", //Class
TO_UDINT(0), 0, 0$UINT, 0$UINT, //Baseclass
//Servers:
(::SdiasManager.ClassState.pMeth)$UINT, _CH_CMD$UINT, 2#0000000000000000$UINT, TO_UDINT(1096059024), "ClassState", 
(::SdiasManager.RetryCounter.pMeth)$UINT, _CH_SVR$UINT, 2#0000000000000000$UINT, TO_UDINT(3383993698), "RetryCounter", 
(::SdiasManager.FirmwareVersion.pMeth)$UINT, _CH_SVR$UINT, 2#0000000000000000$UINT, TO_UDINT(389440282), "FirmwareVersion", 
(::SdiasManager.IsoWrTaskDuration.pMeth)$UINT, _CH_SVR$UINT, 2#0000000000000000$UINT, TO_UDINT(2734486445), "IsoWrTaskDuration", 
(::SdiasManager.IsoWrTaskMaxDuration.pMeth)$UINT, _CH_SVR$UINT, 2#0000000000000000$UINT, TO_UDINT(4219599171), "IsoWrTaskMaxDuration", 
(::SdiasManager.IsoRdTaskDuration.pMeth)$UINT, _CH_SVR$UINT, 2#0000000000000000$UINT, TO_UDINT(851305671), "IsoRdTaskDuration", 
(::SdiasManager.IsoRdTaskMaxDuration.pMeth)$UINT, _CH_SVR$UINT, 2#0000000000000000$UINT, TO_UDINT(3130606261), "IsoRdTaskMaxDuration", 
(::SdiasManager.IsoTaskErrorCount.pMeth)$UINT, _CH_SVR$UINT, 2#0000000000000000$UINT, TO_UDINT(508772881), "IsoTaskErrorCount", 
(::SdiasManager.ManagerOptionBits.pMeth)$UINT, _CH_SVR$UINT, 2#0000000000000000$UINT, TO_UDINT(3554748146), "ManagerOptionBits", 
(::SdiasManager.ManagerProtocolVersion.pMeth)$UINT, _CH_SVR$UINT, 2#0000000000000000$UINT, TO_UDINT(1336107588), "ManagerProtocolVersion", 
//Clients:
(::SdiasManager.ToBusInterface.pCh)$UINT, _CH_CLT_CMD$UINT, 2#0000000000000010$UINT, TO_UDINT(1682766337), "ToBusInterface", 
(::SdiasManager.DeviceID.pCh)$UINT, _CH_CLT_DATA$UINT, 2#0000000000000000$UINT, TO_UDINT(4261957967), "DeviceID", 
(::SdiasManager.ToStdLib.pCh)$UINT, _CH_CLT_OBJ$UINT, 2#0000000000000000$UINT, TO_UDINT(2501598121), "ToStdLib", TO_UDINT(3689364044), "_StdLib", 2$UINT, 0$UINT, 
(::SdiasManager.ToMultiTask.pCh)$UINT, _CH_CLT_OBJ$UINT, 2#0000000000000000$UINT, TO_UDINT(4206025932), "ToMultiTask", TO_UDINT(2641766936), "_MultiTask", 1$UINT, 1$UINT, 
(::SdiasManager.AutoFarMem.pCh)$UINT, _CH_CLT_DATA$UINT, 2#0000000000000010$UINT, TO_UDINT(3920576290), "AutoFarMem", 
END_FUNCTION


#define USER_CNT_SdiasManager 27

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	IF ClassState.pMeth THEN
		ret_code	:= C_OK;
	ELSE
		ret_code	:= C_OUTOF_NEAR;
		RETURN;
	END_IF;
	IsoWrTaskMaxDuration.pMeth			:= StoreMethod( #M_RD_DIRECT(), #M_WR_DIRECT() );
	IF IsoWrTaskMaxDuration.pMeth THEN
		ret_code	:= C_OK;
	ELSE
		ret_code	:= C_OUTOF_NEAR;
		RETURN;
	END_IF;
	IsoRdTaskMaxDuration.pMeth			:= StoreMethod( #M_RD_DIRECT(), #M_WR_DIRECT() );
	IF IsoRdTaskMaxDuration.pMeth THEN
		ret_code	:= C_OK;
	ELSE
		ret_code	:= C_OUTOF_NEAR;
		RETURN;
	END_IF;
	ret_code	:= SdiasManager();

END_FUNCTION

#pragma usingLtd SdiasBase

//{{LSL_IMPLEMENTATION
#pragma UsingLtd SdiasBase


FUNCTION VIRTUAL GLOBAL SdiasManager::Init
  VAR
  	tempCmd         : CmdStruct;
    _result         : results;
    dataADDDO       : t_AddDOCfg;
    dataADDTASK     : t_TaskCfg;  
    dataADDCallback : t_BusIFAddCallback;
    dataSyncData    : t_SyncData;
    TempStr         : ARRAY [0..9] OF CHAR;
    BusIFType       : t_BusIFType;
    i               : UDINT;
    retcode         : DINT;
  END_VAR

  // don't initialize anything if the module is deactivated
  if b_Deactivated then
    return;
  end_if;

  us_Firstscan += 1;
  
  case us_Firstscan of
//**********************************************************************************************************************************************************
    1:
      // first check if the module may be deactivated
      tempCmd.uiCmd     := _BUS_IF_GET_DEACTIVATED_STATE;
      ToBusInterface.NewInst(pPara:=#tempCmd, pResult:=#_result);
      if _result.aData[0]$t_BusIFRetvalErrorcode = _BUS_IF_RETVAL_OK then
        b_Deactivated := _result.aData[4]$BOOL;
        if b_Deactivated then
#ifdef HWC_LogError
          HWC_LogError(this, "@0029 (SdiasManager::Init) SDIAS Manager object inactive");
#endif
          return;
        end_if;
      else
#ifdef HWC_LogError
        HWC_LogError(this, "@002A (SdiasManager::Init) Failed to get deactivation state via BusInterface");
#endif
      end_if;

      tempCmd.uiCmd     := _BUS_IF_GET_BUS_READY_AVAILABLE;
      ToBusInterface.NewInst(pPara:=#tempCmd, pResult:=#_result);
      if _result.aData[0]$t_BusIFRetvalErrorcode = _BUS_IF_RETVAL_OK then
        b_BusReadyAvailable := _result.aData[4]$BOOL;
      else
#ifdef HWC_LogError
        HWC_LogError(this, "@002B (SdiasManager::Init) Failed to get bus ready availability via bus interface");
#endif
        InitError := _CallBackError;
      end_if;

      // allocate memory for the SDO ringbuffer and initialize the pointers
      SDOHandling.pRingBufMemStart$^void := ToStdLib.Malloc(size:=SDIAS_SDO_RINGBUFFER_NO * sizeof(t_SDORingBufEntry));
      if SDOHandling.pRingBufMemStart then
        SDOHandling.RingBufSize := SDIAS_SDO_RINGBUFFER_NO * sizeof(t_SDORingBufEntry);
        _memset(dest:=SDOHandling.pRingBufMemStart, usByte:=0, cntr:=SDOHandling.RingBufSize);
        SDOHandling.pWrite := SDOHandling.pRead := SDOHandling.pRingBufMemStart;
        SDOHandling.pLastEntry := SDOHandling.pRingBufMemStart + (SDIAS_SDO_RINGBUFFER_NO-1) * sizeof(t_SDORingBufEntry);
      else
#ifdef HWC_LogError
        HWC_LogError(this, "@002C (SdiasManager::Init) Failed to allocate memory for the SDO Ringbuffer");
#endif
        InitError := _NoMem;
      end_if;

      // install mutex for adding SDOs
      _strcpy(dest:=#TempStr[0], src:="AddSDOs");
      tempCmd.uiCmd := _BUS_IF_CREATE_MUTEX;
      tempCmd.aPara[0] := (#TempStr)$DINT;
      tempCmd.aPara[1] := this$DINT;
      ToBusInterface.NewInst(pPara:=#tempCmd, pResult:=#_result);
      
      if _result.aData[0]$t_GetBusCycleTime.retcode <> _BUS_IF_RETVAL_OK then
#ifdef HWC_LogError
        HWC_LogError(this, "@002D (SdiasManager::Init) Failed to create Mutex for adding SDOs");
#endif
      else
        pv_Mutex := _result.aData[4]$^void;
      end_if;    

      if b_CallbackAdded = FALSE then
        // Set this class as the operator class of the BusInterface
        dataADDCallback.pthis := this$pVirtualBase;
      
        tempCmd.uiCmd     := _BUS_IF_ADD_CALLBACK;
        tempCmd.aPara[0]  := (#dataADDCallback)$DINT;      
        ToBusInterface.NewInst(pPara:=#tempCmd, pResult:=#_result);
        if _result.aData[0]$t_BusIFRetvalErrorcode <> _BUS_IF_RETVAL_OK then
#ifdef HWC_LogError
          HWC_LogError(this, "@002E (SdiasManager::Init) Failed to install callback at bus interface");
#endif
        end_if;
      end_if;

      // get connection type of SDIAS 
      tempCmd.uiCmd := _BUS_IF_GET_INTERFACE_TYPE;
      ToBusInterface.NewInst(pPara:=#tempCmd, pResult:=#_result);
      
      if _result.aData[0]$t_GetBusCycleTime.retcode <> _BUS_IF_RETVAL_OK then
#ifdef HWC_LogError
        HWC_LogError(this, "@002F (SdiasManager::Init) Failed to get interface type");
#endif
      else
        BusIFType := _result.aData[4]$t_BusIFType;
        if BusIFType = _BUS_IF_TYPE_VARAN then
          ConnectionType := SDIAS_CON_VIA_VARAN_uC;
        elsif BusIFType = _BUS_IF_TYPE_LOCAL then
          ConnectionType := SDIAS_CON_LOCAL_uC;

          // if the version doesn't support local SDIAS => we can't use it
          if pSdias & (pSdias^.udVersion < SDIAS_CIL_VERSION_SUPPORTS_LOCAL) then
            pSdias := NIL;
#ifdef HWC_LogError
            HWC_LogError(this, "@0030 (SdiasManager::Init) Failed to get SDIAS OS-Interface. A newer OS is necessary to use SDIAS");
#endif
          end_if;
        else
#ifdef HWC_LogError
          HWC_LogError(this, "@0031 (SdiasManager::Init) Type of bus interface is not supported");
#endif
        end_if;
      end_if;    


      // Get VaranTime and IsoStartpoint
      tempCmd.uiCmd := _BUS_IF_GET_BUSCYCLE_TIME;
      ToBusInterface.NewInst(pPara:=#tempCmd, pResult:=#_result);
      
      if _result.aData[0]$t_GetBusCycleTime.retcode <> _BUS_IF_RETVAL_OK then
#ifdef HWC_LogError
        HWC_LogError(this, "@0032 (SdiasManager::Init) Failed to get bus cycle time via BusInterface");
#endif
      end_if;    
      
      ud_BusTime_ns    := _result.aData[0]$t_GetBusCycleTime.udBusCycleTime;
      ud_IsoStartpoint := _result.aData[0]$t_GetBusCycleTime.udIsoStartPoint;
      ud_MainTimer  := _result.aData[0]$t_GetBusCycleTime.udMainTimer;
      
      if ConnectionType = SDIAS_CON_VIA_VARAN_uC then
        uiSDIASSyncoffset_us := (ud_BusTime_ns/1000)$UINT;    // SDIAS Sync is set during start RT 
      elsif ConnectionType = SDIAS_CON_LOCAL_uC then 
        uiSDIASSyncoffset_us := (ud_IsoStartpoint/1000)$UINT;
//      else
//        // Is already checked directly above
      end_if;

      // get hardware path
      tempCmd.uiCmd     := _BUS_IF_GET_HW_PATH;
      
      ToBusInterface.NewInst(pPara:=#tempCmd, pResult:=#_result);
      if _result.aData[0]$t_BusIFRetvalErrorcode = _BUS_IF_RETVAL_OK then
        pHwPath := _result.aData[4]$^USINT;
        
        if pPLL then
          retcode := PLL_iGetNodeHandle(pPLL, pszHardwarePath:=pHwPath$^USINT, phNodeHandle:=#ud_NodeHandlePLL);
          
          if retcode <> PLL_OK then    
#ifdef HWC_LogError
            HWC_LogError(this, "@00DC (SdiasManager::Init) Error: Failed fetching the node handle for PLL");
#endif
            ClassState := _ComponentNotExists;
            return;
          end_if;
        end_if;
      else
#ifdef HWC_LogError
        HWC_LogError(this, "@0033 (SdiasManager::Init) Failed to get HW Path via BusInterface");
#endif
        InitError := _CreateDOFailed;
      end_if; 

      // sync out for local sdias is set from RT
      if ConnectionType = SDIAS_CON_VIA_VARAN_uC then          
      
        // Set SyncOut
        tempCmd.uiCmd := _BUS_IF_SET_SYNC;
        
        dataSyncData.us_sync_nr := 0;
        dataSyncData.us_period_multiplier := 0;
        dataSyncData.sd_offset := (ud_BusTime_ns - ud_IsoStartpoint)$DINT / 10;
        dataSyncData.us_enable_frame_count := 0;
        dataSyncData.us_frame_count_threshold := 0;        
        tempCmd.aPara[0] := (#dataSyncData)$DINT;
        
        ToBusInterface.NewInst(pPara:=#tempCmd, pResult:=#_result);

        if _result.aData[0]$t_BusIFRetvalErrorcode <> _BUS_IF_RETVAL_OK then
#ifdef HWC_LogError
          HWC_LogError(this, "@0034 (SdiasManager::Init) Failed to set sync out of pll");
#endif
          InitError := _PllError;
        end_if;  
      end_if;

//**********************************************************************************************************************************************************
    4:    
      // check for missing places
      if MaxPlace <> SDIAS_PLACE_NO_MODULE_ADDED_SO_FAR then
        for i := 0 to MaxPlace do
          if ModuleObjInfo[i].pThis = NIL then
#ifdef HWC_LogValue1
            HWC_LogValue1(this, "@0035 (SdiasManager::Init) Missing SDIAS Place 0x{0} in Configuration!", i);
#endif
          end_if;
        end_for;
      end_if;
            
//**********************************************************************************************************************************************************
    5:

      if ConnectionType = SDIAS_CON_VIA_VARAN_uC then          
        // in this case we need asynchron data objects to configure the SDIAS manager
        
        // DO for ASY Read
        dataADDDO.Priority            := _BUS_IF_ASY;
        dataADDDO.RdWr                := _BUS_IF_READ;
        dataADDDO.ud_addressoff_read  := 0;
        dataADDDO.ui_length_read      := 128;
        dataADDDO.b_UseLocalCopy      := FALSE;

        tempCmd.uiCmd     := _BUS_IF_ADD_DO;
        tempCmd.aPara[0]  := (#dataADDDO)$DINT;
        
        ToBusInterface.NewInst(pPara:=#tempCmd, pResult:=#_result);
        if _result.aData[0]$t_BusIFRetvalErrorcode = _BUS_IF_RETVAL_OK then
          ASYReadDO.Handle        := _result.aData$t_AddDORet.Handle;
          ASYReadDO.pData         := _result.aData$t_AddDORet.pDataRead;
          ASYReadDO.AccessHandle  := _result.aData$t_AddDORet.AccessHandle;
        else
#ifdef HWC_LogError
          HWC_LogError(this, "@0036 (SdiasManager::Init) Failed to add DO for the asynchronous read data");
#endif
          InitError := _CreateDOFailed;
        end_if;


        // DO for ASY Write
        dataADDDO.Priority            := _BUS_IF_ASY;
        dataADDDO.RdWr                := _BUS_IF_WRITE;
        dataADDDO.ud_addressoff_write := 0;
        dataADDDO.ui_length_write     := 128;
        dataADDDO.b_UseLocalCopy      := FALSE;

        tempCmd.uiCmd     := _BUS_IF_ADD_DO;
        tempCmd.aPara[0]  := (#dataADDDO)$DINT;
        
        ToBusInterface.NewInst(pPara:=#tempCmd, pResult:=#_result);
        if _result.aData[0]$t_BusIFRetvalErrorcode = _BUS_IF_RETVAL_OK then
          ASYWriteDO.Handle       := _result.aData$t_AddDORet.Handle;
          ASYWriteDO.pData        := _result.aData$t_AddDORet.pDataWrite;
          ASYWriteDO.AccessHandle := _result.aData$t_AddDORet.AccessHandle;
        else
#ifdef HWC_LogError
          HWC_LogError(this, "@0037 (SdiasManager::Init) Failed to add DO for the asynchronous write data");
#endif
          InitError := _CreateDOFailed;
        end_if;
      else
        // in this case we need a node handle to configure the SDIAS manager
        tempCmd.uiCmd     := _BUS_IF_GET_NODE_HANDLE;
        tempCmd.aPara[0]  := (#dataADDDO)$DINT;
        
        ToBusInterface.NewInst(pPara:=#tempCmd, pResult:=#_result);
        if _result.aData[0]$t_BusIFRetvalErrorcode = _BUS_IF_RETVAL_OK then
          udNodeHandle := _result.aData[4]$UDINT;

          if SDIAS_iGetNodeProperty(hNodeHandle      :=udNodeHandle
                                  , udPropertyId     :=SDM_PROP_PLL_SYSTEM_PERIOD_TIME_10NS
                                  , pudPropertyValue :=#ud_SystemPeriodTime
                                  ) = SDIAS_OK then
            
            // recalculate it to get micro seconds
            ud_SystemPeriodTime /= 100;
          else
#ifdef HWC_LogError
            HWC_LogError(this, "@0038 (SdiasManager::Init) Failed to get the system period time via OS interface!");
#endif
            InitError := _ManagerError;
          end_if;

          if SDIAS_iGetNodeProperty(hNodeHandle      :=udNodeHandle
                                  , udPropertyId     :=SDM_PROP_PLL_SYSTEM_PERIOD_DIVIDER
                                  , pudPropertyValue :=#ud_SystemPeriodDivider
                                  ) = SDIAS_OK then
            // now we got the divider
          else  
#ifdef HWC_LogError
            HWC_LogError(this, "@0039 (SdiasManager::Init) Failed to get the system period divider via OS interface!");
#endif
            InitError := _ManagerError;
          end_if;
        else
#ifdef HWC_LogError
          HWC_LogError(this, "@003A (SdiasManager::Init) Failed to get a valid nodehandle for the device");
#endif
          InitError := _ComponentNotExists;
        end_if;
      end_if;

      // initialize watchdog trigger data
      
      // we only write the control byte (with enable TRUE) for triggering the watchdog
      WdTriggerData.TriggerUnitSizeInfo   := sizeof(t_SDIAS_ControlByte);
      WdTriggerData.ControlByte           := 0;
      WdTriggerData.ControlByte.EnableDO  := TRUE;

      // Add Tasks --------------------------------------------------------------------------
      // Iso Task
      dataADDTASK.Priority    := _BUS_IF_ISO;
      dataADDTASK.callOptions := (CALL_OPTION_RT_PRESCAN or CALL_OPTION_RT_POSTSCAN);
      dataADDTASK.pthis       := this$UDINT;
       
      tempCmd.uiCmd     := _BUS_IF_ADD_TASK;
      tempCmd.aPara[0]  := (#dataADDTASK)$DINT;
      ToBusInterface.NewInst(pPara:=#tempCmd, pResult:=#_result);
      
      if _result.aData[0]$t_BusIFRetvalErrorcode <> _BUS_IF_RETVAL_OK then
#ifdef HWC_LogError
        HWC_LogError(this, "@003B (SdiasManager::Init) Failed to add realtime tasks to a SDIAS Manager object");
#endif
        InitError := _CallBackError;
      end_if;
      
       // Asy Task
      dataADDTASK.Priority    := _BUS_IF_ASY;
      dataADDTASK.callOptions := 0;
      dataADDTASK.pthis       := this$UDINT;
       
      tempCmd.uiCmd     := _BUS_IF_ADD_TASK;
      tempCmd.aPara[0]  := (#dataADDTASK)$DINT;
      ToBusInterface.NewInst(pPara:=#tempCmd, pResult:=#_result);
      
      if _result.aData[0]$t_BusIFRetvalErrorcode <> _BUS_IF_RETVAL_OK then
#ifdef HWC_LogError
        HWC_LogError(this, "@003C (SdiasManager::Init) Failed to add a cyclic task to a SDIAS Manager object");
#endif
        InitError := _CallBackError;
      end_if;

//**********************************************************************************************************************************************************
    10:
      tempCmd.uiCmd     := _BUS_IF_GET_REQUIRED_SETTING;
      ToBusInterface.NewInst(pPara:=#tempCmd, pResult:=#_result);
      if _result.aData[0]$t_BusIFRetvalErrorcode = _BUS_IF_RETVAL_OK then
        b_IsRequired := _result.aData[4]$USINT;
      else
#ifdef HWC_LogError
        HWC_LogError(this, "@003D (SdiasManager::Init) Failed to get required setting from bus interface");
#endif
        InitError := _CallBackError;
      end_if;

//**********************************************************************************************************************************************************
  end_case;

END_FUNCTION


FUNCTION VIRTUAL GLOBAL SdiasManager::CyWork
	VAR_INPUT
		DummyInput (EAX) 	: UDINT;
	END_VAR
	VAR_OUTPUT
		state (EAX) 	: UDINT;
	END_VAR
  VAR
  	i                     : UDINT;
    RetcodeIPR            : iprStates;
    b_ModulInitFinished   : BOOL;
    b_ModulInitComplete   : BOOL;
    pModuleInfo           : ^t_ModuleObjectInfo;
  	tempCmd               : CmdStruct;
    _result               : results;
    b_FoundIt             : BOOL;
    b_Ready               : BOOL;
    TriggerUnitSetup      : t_TriggerUnitSetupX2;
    TempLEDState          : USINT;
    ByteNr                : USINT;
    PosInByte             : USINT;
    ModuleNr              : USINT;
    TaskStartConfig       : t_TaskStartConfig;
    TaskConfig            : t_TaskConfig;
    DAListOfDOs           : t_SDIAS_DOListEntryX2;
    SDOChannels           : t_SDOChannels;
    CompareBitmap         : t_DeviceBitmap;
    ResultBitmap          : t_DeviceBitmap;
    WriteLength           : USINT;
    sd_retval             : DINT;
    TempNewDataSize       : UINT;
    TempTime              : UDINT;
    TempUDINT             : UDINT;
    SyncInjectionCfg      : t_SyncInjectionCfg;
    TempControlByte       : t_SDIAS_ControlByte;
    LastSelected          : UDINT;
    iRetCode              : DINT;
    iDataOffsets          : ARRAY [0..3] OF UDINT;
    pWaitAccess           : ^t_AccessElement;
    iWaitOffset           : UINT;
    aProperties           : ARRAY [0..4] OF SDM_PROPERTY_VALUE_PAIR;
    pTaskHelp             : ^t_TaskInfoReadData;
    pControlStruct        : ^t_SDIAS_ControlStructDynamic;
    pControlStructFar     : ^t_SDIAS_ControlStructDynamicFar;
    localAccess           : t_AccessElement;
    bError                : BOOL;
  END_VAR

  // if the module is connected, we start initialisation
  if Online then

    // check if a watchdog command has to be sent
    if b_WdTriggerActive | ToggleReadTaskActive then


      // check if there is a watchdog trigger active
      if b_SendWdTrigger then
        if ConnectionType = SDIAS_CON_VIA_VARAN_uC then
          if (AsyWriteUsage = _UsedByWD) & (WdSSW = 0) then
            AsyWriteUsage := _NotUsed;
            b_SendWdTrigger := FALSE;
          end_if;
        else
          b_SendWdTrigger := FALSE;
        end_if;
      end_if;

      // check if it's time for the next watchdog trigger action
      if ((ops.tAbsolute - ud_LastWdTime) > (SDIAS_WATCHDOG_TRIGGER_TIME-3)) then
      
        // remember that it's time for the watchdog (no other new Asy write commands allowed)
        b_SendWdTrigger := TRUE;
        
        if ConnectionType = SDIAS_CON_VIA_VARAN_uC then
          if (WdSSW = 0) & b_WdTriggerActive then
            // log message if it has been too long since the last watchdog trigger
            if (ops.tAbsolute - ud_LastWdTime > 128) then
#ifdef HWC_LogValue2
              HWC_LogValue2(this, "@003E (SdiasManager::CyWork) Too much time between watchdog triggering! TimeSinceLast: 0x{0}, ops.tAbsolute: 0x{1}", ops.tAbsolute - ud_LastWdTime, ops.tAbsolute);
#endif
            end_if;
            
            // copy the prepared data for triggering the watchdog to the write DO memory
            ASYWriteDO.pData^$t_WatchdogTriggerData := WdTriggerData;

            if ChangeAsyWr(Offset:=gcMapping_Informations[IsoWrPayload].StartAddress - SDIAS_TRIGGER_UNIT_BYTE_SIZE, 
                           Length:= sizeof(t_WatchdogTriggerData), 
                           RunState:=_BUS_IF_RUN_STATE_SINGLE_RUN,
                           UsageType:=_UsedByWD) then

              WaitAfterWd := OS_READMICROSEC();
              
              WdSSW += 1;
            else
              // failed to add watchdog this time
              b_SendWdTrigger := FALSE;
            end_if;
          else
            // wait at least 1ms after starting the iso write task before starting the iso read task
            TempTime := OS_READMICROSEC();
            if TempTime - WaitAfterWd > 1000 then
              // Start the ISO Read Task manually to force the toggle bit toggle => needed for the firmware: if not toggled after 3 seconds the firmware takes over again
              ASYWriteDO.pData^$USINT := 2#10;

              if ChangeAsyWr(Offset:=SDIAS_OFFSET_TASK_HANDSHAKE_1, 
                             Length:= 1, 
                             RunState:=_BUS_IF_RUN_STATE_SINGLE_RUN,
                             UsageType:=_UsedByWD) then
                
                ud_LastWdTime := ops.tAbsolute;
                if WdSSW then
                  if DOStartTime = 0 then
                    DOStartTime := ops.tAbsolute; // remember time of first WD                
                  end_if;
                end_if;
              else
                // failed to add watchdog this time
                b_SendWdTrigger := FALSE;
              end_if;

              WdSSW := 0;
            end_if;
          end_if;
        else
          // local SDIAS
          tempCmd.uiCmd         := _BUS_IF_TRIGGER_ISO_TASK;  
          ToBusInterface.NewInst(pPara:=#tempCmd, pResult:=#_result); 
          if _result.aData[0]$t_BusIFRetvalErrorcode <> _BUS_IF_RETVAL_OK then  
#ifdef HWC_LogError
            HWC_LogError(this, "@003F (SdiasManager::CyWork) Failed to trigger watchdog of SDIAS modules on local SDIAS");
#endif
          else           
            ud_LastWdTime := ops.tAbsolute;
            
            if b_WdTriggerActive then
              if DOStartTime = 0 then
                DOStartTime := ops.tAbsolute; // remember time of first WD                
              end_if;
            end_if;
          end_if;
        end_if;
      end_if;
    end_if;
    
    case InitSSW of
//**********************************************************************************************************************************************************
      _StartInit:
        // remember when we started (for timeout and init time measure)
        InitStartTime := ops.tAbsolute;
        
        //reset iso payload data to avoid problems with control byte if vi is reconnected
        if ISOWriteDO.pData & (ISOWriteDO.Length > SDIAS_TRIGGER_UNIT_BYTE_SIZE) then        
          //reset memory of write data
          _memset(dest:=ISOWriteDO.pData+SDIAS_TRIGGER_UNIT_BYTE_SIZE, usByte:=0x00, cntr:=ISOWriteDO.Length-SDIAS_TRIGGER_UNIT_BYTE_SIZE); 
        end_if;
      
        // check for the OS SDIAS Interface first
        if pSDIAS = NIL then
          // we already have a log entry from the constructor
          ClassState := _ComponentNotExists;
          ErrorInitStep := InitSSW;
          InitSSW := _PrepareError;          
          return;
        end_if;

        // check if we have a valid pointer to multi task api
        if mt_api = NIL then
          // we already have a log entry from the init
          ClassState := _ComponentNotExists;
          ErrorInitStep := InitSSW;
          InitSSW := _PrepareError;          
          return;
        end_if;

        // check if we have a valid mutex
        if pv_Mutex = NIL then
          // we already have a log entry from the init
          ClassState := _NoMutex;
          ErrorInitStep := InitSSW;
          InitSSW := _PrepareError;          
          return;
        end_if;
      
        // check if we had an error before
        if InitError <> _ClassOk then
          // we already have a log entry from the init
          ClassState := InitError;
          ErrorInitStep := InitSSW;
          InitSSW := _PrepareError;          
          return;
        end_if;
        
        InitSSW := _GetHandshake;

//**********************************************************************************************************************************************************
      _GetHandshake:
        if ConnectionType = SDIAS_CON_VIA_VARAN_uC then

          // we got the complete info block now => get the handshake
          if ChangeAsyRd(Offset:=t_ManagerInfoBlock.GeneralInfo, 
                         Length:=sizeof(t_ManagerInfoBlock.GeneralInfo), 
                         RunState:=_BUS_IF_RUN_STATE_CONT_RUN,
                         UsageType:=_UsedBySSW) then

            StartTimeHandshake := ops.tAbsolute;

            InitSSW := _CheckHandshake;
          else
            NewDataSize := 0;
          end_if;
        else
          InitSSW := _CheckHandshake;
        end_if;

//**********************************************************************************************************************************************************
      _CheckHandshake:
        if ConnectionType = SDIAS_CON_VIA_VARAN_uC then
          _memcpy(ptr1:=#ManagerInfoBlock.GeneralInfo, ptr2:=ASYReadDO.pData, cntr:=sizeof(t_ManagerInfoBlock.GeneralInfo));
        else
          if SDIAS_iGetNodeProperty(hNodeHandle      :=udNodeHandle
                                  , udPropertyId     :=SDM_PROP_HANDSHAKE_TO_HWK
                                  , pudPropertyValue :=(#ManagerInfoBlock.GeneralInfo.HandshakeFrom_uC)$^UDINT
                                  ) = SDIAS_OK then
            
            StartTimeHandshake := ops.tAbsolute;
          else
#ifdef HWC_LogError
            HWC_LogError(this, "@0040 (SdiasManager::CyWork) Failed to get the handshake info via OS interface!");
#endif
            ErrorInitStep := InitSSW;
            InitSSW := _PrepareError;
            ClassState := _ManagerError;
          end_if;
        end_if;
      
        // if iso task is running
        if ManagerInfoBlock.GeneralInfo.HandshakeFrom_uC.IsoTaskRunning then
          // stop iso tasks
          ManagerInfoBlock.GeneralInfo.HandshakeTo_uC.Request2StopIso := TRUE;

          if ConnectionType = SDIAS_CON_VIA_VARAN_uC then
            ASYWriteDO.pData^$BSINT := ManagerInfoBlock.GeneralInfo.HandshakeTo_uC;
            
            if ChangeAsyWr(Offset:=t_ManagerInfoBlock.GeneralInfo.HandshakeTo_uC, 
                           Length:=sizeof(t_ManagerInfoBlock.GeneralInfo.HandshakeTo_uC), 
                           RunState:=_BUS_IF_RUN_STATE_SINGLE_RUN,
                           UsageType:=_UsedBySSW) then
            
              InitSSW := _WaitForDisabledTasks;
            end_if;
          else
            aProperties[0].udPropertyId     := SDM_PROP_HANDSHAKE_TO_UC;
            aProperties[0].udPropertyValue  := ManagerInfoBlock.GeneralInfo.HandshakeTo_uC;
            
            if SDIAS_iSetNodeProperties(hNodeHandle         := udNodeHandle
                                      , udPropertyCount     := 1
                                      , psPropertyValuePairs:= #aProperties[0]
                                      ) = SDIAS_OK then
              
              StartTimeHandshake := ops.tAbsolute;

              InitSSW := _WaitForDisabledTasks;
            else
#ifdef HWC_LogError
              HWC_LogError(this, "@0041 (SdiasManager::CyWork) Failed to set the handshake info via OS interface!");
#endif
              ErrorInitStep := InitSSW;
              InitSSW := _PrepareError;
              ClassState := _ManagerError;
            end_if;            
          end_if;
        elsif (ops.tAbsolute - InitStartTime) > SDIAS_WAIT_TIME_FIRMWARE_HANDSHAKE then
#ifdef HWC_LogError
          HWC_LogError(this, "@0042 (SdiasManager::CyWork) Timeout while waiting for the µc Handshake to be set!");
#endif
          ErrorInitStep := InitSSW;
          InitSSW := _PrepareError;
          ClassState := _ManagerError;
        end_if;

//**********************************************************************************************************************************************************
      _WaitForDisabledTasks:
        if ConnectionType = SDIAS_CON_VIA_VARAN_uC then
          _memcpy(ptr1:=#ManagerInfoBlock.GeneralInfo, ptr2:=ASYReadDO.pData, cntr:=sizeof(t_ManagerInfoBlock.GeneralInfo));
        else
          // post init blocks the tasks in cyclic priority (the SDIAS Manager Code is running in lower priority than cyclic and has no time during the postinit) => give it some time
          if (b_PostInitFinished = FALSE) then
            ToMultiTask.TASKDELAY(timeout0:=SDIAS_WAIT_TIME_IN_POST_INIT);
          end_if;

          if SDIAS_iGetGeneralInfo(hNodeHandle    :=udNodeHandle
                                 , udBufferLength :=sizeof(t_ManagerInfoBlock.GeneralInfo)
                                 , pucData        :=(#ManagerInfoBlock.GeneralInfo)$^USINT
                                 ) <> SDIAS_OK then
#ifdef HWC_LogError
            HWC_LogError(this, "@0043 (SdiasManager::CyWork) Failed to get the general info of the info block via OS interface!");
#endif
            ErrorInitStep := InitSSW;
            InitSSW := _PrepareError;
            ClassState := _ManagerError;
            return;
          end_if; 
        end_if;

        // if the iso tasks are no longer started by the µC => continue with initialisation
        if ManagerInfoBlock.GeneralInfo.HandshakeFrom_uC.IsoTaskRunning = FALSE then
        
          ToggleReadTaskActive := TRUE;
        
          if ConnectionType = SDIAS_CON_VIA_VARAN_uC then
            AsyWriteUsage := _NotUsed;
          
            // stop the DO
            if ChangeAsyRd(Offset:=0, 
                           Length:=0, 
                           RunState:=_BUS_IF_RUN_STATE_NO_RUN,
                           UsageType:=_UsedBySSW) then

              HandshakeWaitDuration := ops.tAbsolute - StartTimeHandshake;
              
              // show the µC Version of the SDIAS Manager
              FirmwareVersion := ManagerInfoBlock.GeneralInfo.FirmwareVersion;
              
              InitSSW := _GetHWInfo;
            end_if;
          else
            HandshakeWaitDuration := ops.tAbsolute - StartTimeHandshake;
            
            // show the µC Version of the SDIAS Manager
            FirmwareVersion := ManagerInfoBlock.GeneralInfo.FirmwareVersion;
            
            InitSSW := _Wait4HWInfo;
          end_if;
          
          // here we have the firmware version => check version number
          if FirmwareVersion < SDIAS_FW_VERSION_SDO_ERROR_FIXED then
#ifdef HWC_LogError
            HWC_LogError(this, "@0044 (SdiasManager::CyWork) Warning: The current firmware can cause problems with SDIAS SDO communication!");
#endif
          end_if;
          
        elsif (ops.tAbsolute - InitStartTime) > SDIAS_WAIT_TIME_FIRMWARE_HANDSHAKE then
#ifdef HWC_LogError
          HWC_LogError(this, "@0045 (SdiasManager::CyWork) Timeout while waiting for the µc Handshake to be reset!");
#endif
          ErrorInitStep := InitSSW;
          InitSSW := _PrepareError;
          ClassState := _ManagerError;
        end_if;

//**********************************************************************************************************************************************************
      _GetHWInfo:      
        if ConnectionType = SDIAS_CON_VIA_VARAN_uC then
          // get the hardware info
          if ChangeAsyRd(Offset:=SDIAS_OFFSET_HW_CONFIG, 
                         Length:=sizeof(t_HardwareConfiguration), 
                         RunState:=_BUS_IF_RUN_STATE_SINGLE_RUN,
                         UsageType:=_UsedBySSW) then

            InitSSW := _Wait4HWInfo;
          end_if;
        end_if;
        
//**********************************************************************************************************************************************************     
      _Wait4HWInfo:
        // store the hardware configuration
        if ConnectionType = SDIAS_CON_VIA_VARAN_uC then
          HardwareConfig := ASYReadDO.pData^$t_HardwareConfiguration;     
        else
          if SDIAS_iGetNodeProperty(hNodeHandle      :=udNodeHandle
                                  , udPropertyId     :=SDM_PROP_BITMAP_DETECTED_CLIENTS_0_31
                                  , pudPropertyValue :=#HardwareConfig.DeviceBitmap[0]
                                  ) <> SDIAS_OK then
#ifdef HWC_LogError
            HWC_LogError(this, "@0046 (SdiasManager::CyWork) Failed to get the device bitmap (part 1) via OS interface!");
#endif
            ErrorInitStep := InitSSW;
            InitSSW := _PrepareError;
            ClassState := _ManagerError;
            return;
          end_if;
          
          if SDIAS_iGetNodeProperty(hNodeHandle      :=udNodeHandle
                                  , udPropertyId     :=SDM_PROP_BITMAP_DETECTED_CLIENTS_32_63
                                  , pudPropertyValue :=#HardwareConfig.DeviceBitmap[1]
                                  ) <> SDIAS_OK then
#ifdef HWC_LogError
            HWC_LogError(this, "@0047 (SdiasManager::CyWork) Failed to get the device bitmap (part 2) via OS interface!");
#endif
            ErrorInitStep := InitSSW;
            InitSSW := _PrepareError;
            ClassState := _ManagerError;
            return;
          end_if;

          if SDIAS_iGetNodeProperty(hNodeHandle      :=udNodeHandle
                                  , udPropertyId     :=SDM_PROP_SIZE_MIRRORED_HW_INFO
                                  , pudPropertyValue :=(#HardwareConfig.MirroredHWInfoSize)$^UDINT
                                  ) <> SDIAS_OK then
#ifdef HWC_LogError
            HWC_LogError(this, "@0048 (SdiasManager::CyWork) Failed to get the size of the hardware info via OS interface!");
#endif
            ErrorInitStep := InitSSW;
            InitSSW := _PrepareError;
            ClassState := _ManagerError;
            return;
          end_if;

        end_if;
        
        InitSSW := _Wait4MatchingDeviceBitmap;

//**********************************************************************************************************************************************************     
      _Wait4MatchingDeviceBitmap:
        // if the VI hast just been connected, we wait here until the OS has enumerated all modules, because if there are safety modules we need the OS for transferring the SDOs
        sd_retval := SDIAS_iGetBitmapOfDevices(uiMaster:=0, pucNode:=pHwPath, udBufferLength:=8, pucData:=(#CompareBitmap)$^USINT);

        if sd_retval = 0 then
          if CompareBitmap = HardwareConfig.DeviceBitmap then         
            // prepare fetching the infoblock
            AccessProgress := 0;
            
            // get last available module
            if HardwareConfig.DeviceBitmap[1] then
              // module with highest place number is > 31
              ModuleNr := 64;
              TempUDINT := HardwareConfig.DeviceBitmap[1];
              b_FoundIt := FALSE;
              while b_FoundIt = FALSE do
                if TempUDINT AND 16#80000000 then
                  b_FoundIt := TRUE;
                  exit;
                else
                  TempUDINT := TempUDINT SHL 1;
                end_if;

                ModuleNr -= 1;
              end_while;
              
              // the size of the info block we need = number of modules * size of info per module
              NewDataSize := ModuleSizeNeeded := ModuleNr * HardwareConfig.MirroredHWInfoSize;
              
            elsif HardwareConfig.DeviceBitmap[0] then
              // module with highest place number is < 32
              ModuleNr := 32;
              TempUDINT := HardwareConfig.DeviceBitmap[0];
              b_FoundIt := FALSE;
              while b_FoundIt = FALSE do
                if TempUDINT AND 16#80000000 then
                  b_FoundIt := TRUE;
                  exit;
                else
                  TempUDINT := TempUDINT SHL 1;
                end_if;

                ModuleNr -= 1;
              end_while;
              
              // the size of the info block we need = number of modules * size of info per module
              NewDataSize := ModuleSizeNeeded := ModuleNr * HardwareConfig.MirroredHWInfoSize;
              
            else
              if ConnectionType = SDIAS_CON_VIA_VARAN_uC then

                // no module connected to sdias => get the mapping info
                if ChangeAsyRd(Offset:=t_ManagerInfoBlock.MappingInfo, 
                               Length:=sizeof(t_ManagerInfoBlock.MappingInfo), 
                               RunState:=_BUS_IF_RUN_STATE_CONT_RUN,
                               UsageType:=_UsedBySSW) then

                  if MaxPlace <> SDIAS_PLACE_NO_MODULE_ADDED_SO_FAR then
                    InitSSW := _GetInfoBlockMappingInfo;
                  else
#ifdef HWC_LogError
                    HWC_LogError(this, "@004A (SdiasManager::CyWork) No SDIAS Client objects projected/connected to the SDIAS Manager! Unable to continue with Initialisation!");
#endif
                    ErrorInitStep := InitSSW;
                    InitSSW := _PrepareError;
                    ClassState := _NoHardware;
                  end_if;
                  return;
                else
                  NewDataSize := 0;
                end_if;
              else
                if MaxPlace <> SDIAS_PLACE_NO_MODULE_ADDED_SO_FAR then
                  InitSSW := _GetInfoBlockMappingInfo;
                else
#ifdef HWC_LogError
                  HWC_LogError(this, "@004A (SdiasManager::CyWork) No SDIAS Client objects projected/connected to the SDIAS Manager! Unable to continue with Initialisation!");
#endif
                  ErrorInitStep := InitSSW;
                  InitSSW       := _PrepareError;
                  ClassState    := _NoHardware;
                end_if;
                return;            
              end_if;
            end_if;

            // if there is module info to fetch
            if NewDataSize then
              if ConnectionType = SDIAS_CON_VIA_VARAN_uC then
                if NewDataSize > 128 then
                  NewDataSize := 128;
                end_if;
                
                if ChangeAsyRd(Offset     := 0, 
                               Length     := NewDataSize$USINT, 
                               RunState   := _BUS_IF_RUN_STATE_CONT_RUN,
                               UsageType  := _UsedBySSW) then

                  InitSSW := _GetInfoBlockAvailableModules;
                end_if;
              else
                if SDIAS_iGetInfoBlock(hNodeHandle    := udNodeHandle
                                     , udBufferLength := NewDataSize
                                     , pucData        := (#ManagerInfoBlock.ModuleInfos[0])$^USINT) = SDIAS_OK then
                  if MaxPlace <> SDIAS_PLACE_NO_MODULE_ADDED_SO_FAR then
                    InitSSW := _GetInfoBlockMappingInfo;
                  else
#ifdef HWC_LogError
                    HWC_LogError(this, "@004A (SdiasManager::CyWork) No SDIAS Client objects projected/connected to the SDIAS Manager! Unable to continue with Initialisation!");
#endif
                    ErrorInitStep := InitSSW;
                    InitSSW := _PrepareError;
                    ClassState := _NoHardware;
                  end_if;
                else
#ifdef HWC_LogError
                  HWC_LogError(this, "@004B (SdiasManager::CyWork) Failed to get the mapping info via OS interface!");
#endif
                  ErrorInitStep := InitSSW;
                  InitSSW       := _PrepareError;
                  ClassState    := _ManagerError; 
                end_if;
              end_if;
            end_if;
          end_if;
        elsif sd_retval & (CyclicMsgMarker.AlreadyPosted.GetDeviceBitmap = FALSE) then
#ifdef HWC_LogValue1
          HWC_LogValue1(this, "@0049 (SdiasManager::CyWork) [SL] SDIAS_iGetBitmapOfDevices failed with error code -0x{0}", ABS(sd_retval)$UDINT);
#endif
          CyclicMsgMarker.AlreadyPosted.GetDeviceBitmap := TRUE;
          ErrorInitStep := InitSSW;
          InitSSW := _PrepareError;
          ClassState := _RootError;
        end_if;

//**********************************************************************************************************************************************************
      _GetInfoBlockAvailableModules:
        if NewDataSize then
          _memcpy(ptr1:=#ManagerInfoBlock + AccessProgress, ptr2:=ASYReadDO.pData, cntr:=NewDataSize);
          AccessProgress += NewDataSize;
        end_if;
        
        if AccessProgress < ModuleSizeNeeded then
          if (ModuleSizeNeeded - AccessProgress) > 128 then
            // we need more than 128 bytes => get the next 128
            TempNewDataSize := 128;
          else
            // we need to get the rest (last package)
            TempNewDataSize := (ModuleSizeNeeded - AccessProgress);
          end_if;
          
          if ChangeAsyRd(Offset     := AccessProgress, 
                         Length     := TempNewDataSize$USINT, 
                         RunState   := _BUS_IF_RUN_STATE_CONT_RUN,
                         UsageType  := _UsedBySSW) then
                         
            NewDataSize := TempNewDataSize;
          else
            NewDataSize := 0;
          end_if;
        else
          // we got the info of the available modules => get the mapping info
          if ChangeAsyRd(Offset:=t_ManagerInfoBlock.MappingInfo, 
                         Length:=sizeof(t_ManagerInfoBlock.MappingInfo), 
                         RunState:=_BUS_IF_RUN_STATE_CONT_RUN,
                         UsageType:=_UsedBySSW) then

            if MaxPlace <> SDIAS_PLACE_NO_MODULE_ADDED_SO_FAR then
              InitSSW := _GetInfoBlockMappingInfo;
            else
#ifdef HWC_LogError
              HWC_LogError(this, "@004A (SdiasManager::CyWork) No SDIAS Client objects projected/connected to the SDIAS Manager! Unable to continue with Initialisation!");
#endif
              ErrorInitStep := InitSSW;
              InitSSW := _PrepareError;
              ClassState := _NoHardware;
            end_if;
            return;
          else
            NewDataSize := 0;
          end_if;
        end_if;
        
//**********************************************************************************************************************************************************     
      _GetInfoBlockMappingInfo:
        if ConnectionType = SDIAS_CON_VIA_VARAN_uC then
          _memcpy(ptr1:=#ManagerInfoBlock.MappingInfo, ptr2:=ASYReadDO.pData, cntr:=sizeof(t_ManagerInfoBlock.MappingInfo));

          b_Ready := FALSE;
          if ChangeAsyRd(Offset:=0, 
                         Length:=0, 
                         RunState:=_BUS_IF_RUN_STATE_NO_RUN,
                         UsageType:=_UsedBySSW) then
            b_Ready := TRUE;
          end_if;
        else
          b_Ready := TRUE;
          if SDIAS_iGetMappingInfo(hNodeHandle    := udNodeHandle
                                 , udBufferLength := sizeof(t_ManagerInfoBlock.MappingInfo)
                                 , pucData        := (#ManagerInfoBlock.MappingInfo)$^USINT
                                 ) <> SDIAS_OK then
#ifdef HWC_LogError
            HWC_LogError(this, "@004B (SdiasManager::CyWork) Failed to get the mapping info via OS interface!");
#endif
            ErrorInitStep := InitSSW;
            InitSSW := _PrepareError;
            ClassState := _ManagerError; 
            return;
          end_if;
        end_if;

        if b_Ready then

          // LoeHan 2013-07-26 :Start 
          // Store memory mapping information
          for i := 0 to ManagerInfoBlock.MappingInfo.MappingInfoNo - 1 do
            if ((ManagerInfoBlock.MappingInfo.aMappingInfos[i].MappingID > UnusedMapping) & (ManagerInfoBlock.MappingInfo.aMappingInfos[i].MappingID <= IsoRdPayload)) then
              gcMapping_Informations[ManagerInfoBlock.MappingInfo.aMappingInfos[i].MappingID$USINT] := ManagerInfoBlock.MappingInfo.aMappingInfos[i];
            end_if;
          end_for;

          // Create necessary mapping informations for data object handling
          gcWrite_DOL_Desc.iBaseAddr      := gcMapping_Informations[IsoWrList].StartAddress;
          gcWrite_DOL_Desc.iEndAddr       := gcMapping_Informations[IsoWrList].EndAddress;
          gcWrite_DOL_Desc.iBaseAddrData  := gcMapping_Informations[IsoWrPayload].StartAddress;
          gcWrite_DOL_Desc.iEndAddrData   := gcMapping_Informations[IsoWrPayload].EndAddress;
          gcWrite_DOL_Desc.iMaxUsage      := gcWrite_DOL_Desc.iEndAddr - gcWrite_DOL_Desc.iBaseAddr;
          gcWrite_DOL_Desc.iUsageDOL      := gcMapping_Informations[IsoWrList].ActUsage;//SDIAS_DOL_WRITE_USAGE_DOL_EMPTY;
          gcWrite_DOL_Desc.iUsageData     := gcMapping_Informations[IsoWrPayload].ActUsage;//SDIAS_DOL_WRITE_USAGE_DTA_EMPTY;
          gcWrite_DOL_Desc.iOffEndCmd     := gcWrite_DOL_Desc.iUsageDOL - sizeof(t_SDIAS_STD_CMD_DO);//SDIAS_DOL_WRITE_OFFSET_END_CMD;
          gcWrite_DOL_Desc.iOffFirstData  := SDIAS_DOL_WRITE_OFFSET_FIRST_DTA;
          gcWrite_DOL_Desc.iOffLastData   := gcWrite_DOL_Desc.iUsageData-1;//SDIAS_DOL_WRITE_OFFSET_LAST_DTA;

          gcRead_DOL_Desc.iBaseAddr      := gcMapping_Informations[IsoRdList].StartAddress;
          gcRead_DOL_Desc.iEndAddr       := gcMapping_Informations[IsoRdList].EndAddress;
          gcRead_DOL_Desc.iBaseAddrData  := gcMapping_Informations[IsoRdPayload].StartAddress;
          gcRead_DOL_Desc.iEndAddrData   := gcMapping_Informations[IsoRdPayload].EndAddress;
          gcRead_DOL_Desc.iMaxUsage      := gcRead_DOL_Desc.iEndAddr - gcRead_DOL_Desc.iBaseAddr;
          gcRead_DOL_Desc.iUsageDOL      := gcMapping_Informations[IsoRdList].ActUsage;//SDIAS_DOL_READ_USAGE_DOL_EMPTY;
          gcRead_DOL_Desc.iUsageData     := gcMapping_Informations[IsoRdPayload].ActUsage;//SDIAS_DOL_READ_USAGE_DTA_EMPTY;
          gcRead_DOL_Desc.iOffEndCmd     := gcRead_DOL_Desc.iUsageDOL - sizeof(t_SDIAS_STD_CMD_DO);//SDIAS_DOL_READ_OFFSET_END_CMD;
          gcRead_DOL_Desc.iOffFirstData  := SDIAS_DOL_READ_OFFSET_FIRST_DTA;
          gcRead_DOL_Desc.iOffLastData   := gcRead_DOL_Desc.iUsageData-1;//SDIAS_DOL_READ_OFFSET_LAST_DTA;
        // LoeHan 2013-07-26 :End 
        
          // if no modules connected => stop initializing
          if (HardwareConfig.DeviceBitmap[0] = 0) & (HardwareConfig.DeviceBitmap[1] = 0) then
#ifdef HWC_LogError
            HWC_LogError(this, "@004C (SdiasManager::CyWork) No connected SDIAS Client found! Unable to continue with Initialisation!");
#endif
            ErrorInitStep := InitSSW;
            InitSSW := _PrepareError;
            ClassState := _NoHardware;
          else
            InitSSW := _GetFeatureInfo;
          end_if;
        end_if;

//**********************************************************************************************************************************************************     
      _GetFeatureInfo:
        if ConnectionType = SDIAS_CON_VIA_VARAN_uC then
          // we start a read access here, so we got the data in the next step
          if ChangeAsyRd(Offset:=SDIAS_OFFSET_FEATURE_INFO, 
                         Length:=sizeof(t_FeatureInfo), 
                         RunState:=_BUS_IF_RUN_STATE_SINGLE_RUN,
                         UsageType:=_UsedBySSW) then
        
            InitSSW := _Wait4FeatureInfo;
          end_if;
        else
          
          // get it via API
#pragma warning(disable:74);  // Return value only needed for debugging
          sd_retval := SDIAS_iGetNodeProperty(hNodeHandle       := udNodeHandle
                                            , udPropertyId      := SDM_PROP_FEATURE_BITS,
                                            , pudPropertyValue  := (#FeatureInfo.OptionBits)$^UDINT
                                            );
#pragma warning(default:74);

          // if the feature bits can't be fetched because of old OS or whatever, they stay 0 and a far access is not possible
          ManagerOptionBits := FeatureInfo.OptionBits$DINT;

          // Simple master CPU - set AutoFarMem according to client
          if FeatureInfo.OptionBits.SimpleMaster then
            // property id for AutoFarMem          
            aProperties[0].udPropertyId := SDM_PROP_SDIAS_AUTOFARMEM;
            // activate/deactivate AutoFarMem
            if AutoFarMem.Read() then
              aProperties[0].udPropertyValue  := 1;
            else
              aProperties[0].udPropertyValue  := 0;
            end_if;
            sd_retval := SDIAS_iSetNodeProperties( hNodeHandle          := udNodeHandle
                                              , udPropertyCount      := 1
                                              , psPropertyValuePairs := #aProperties[0]
                                              );
            if sd_retval <> SDIAS_OK then
#ifdef HWC_LogError
              HWC_LogError(this, "@06C3 (SdiasManager::CyWork) Failed to set/unset AutoFarMem!");
#endif
              case sd_retval of
                // *** -17 ... OS does not know the property id (OS too old) ***
                -17: 
                  AutoFarMem := -1;
                  AutoFarMem.Write(input:=AutoFarMem);
                // *** -18 ... FPGA/System does not support AutoFarMem *********
                -18: 
                  AutoFarMem := -2;
                  AutoFarMem.Write(input:=AutoFarMem);
              else
                // *** other error *********************************************
                AutoFarMem := -99;
                AutoFarMem.Write(input:=AutoFarMem);
              end_case;
            end_if;
            
          end_if;

                    
#pragma warning(disable:74);  // Return value only needed for debugging          
          sd_retval := SDIAS_iGetNodeProperty(hNodeHandle       := udNodeHandle
                                            , udPropertyId      := SDM_PROP_SDIAS_PROTOCOL_VERSION,
                                            , pudPropertyValue  := (#FeatureInfo.ProtocolVersion)$^UDINT
                                            );          
#pragma warning(default:74);
          
          // if the SDIAS protocol version can't be fetched because of old OS or whatever, it stays 0 and broadcast access is not possible
          ManagerProtocolVersion := FeatureInfo.ProtocolVersion;

          SupportedFeatures.TimeBroadCastSupported := CheckTimeBroadCastSupported();
          
          //Check for supported execution time selection option bits, at new fpga versions only bit 7 is set because of an error at reset asy write access
          if FeatureInfo.OptionBits.ExecutionTimeSelectionSupported1 = TRUE 
          | FeatureInfo.OptionBits.ExecutionTimeSelectionSupported2 = TRUE then
            InitSSW := _SetExecutionTimeSelectionIsoRd;
          else
            InitSSW := _GetSDOMessageCounters;
          end_if;
          
        end_if;
//**********************************************************************************************************************************************************     
      _Wait4FeatureInfo:
        FeatureInfo := ASYReadDO.pData^$t_FeatureInfo;
        ManagerOptionBits       := FeatureInfo.OptionBits$DINT;
        ManagerProtocolVersion  := FeatureInfo.ProtocolVersion;
        
        SupportedFeatures.TimeBroadCastSupported := CheckTimeBroadCastSupported();
        
        //Check for supported execution time selection option bits, at new fpga versions only bit 7 is set because of an error at reset asy write access
        if FeatureInfo.OptionBits.ExecutionTimeSelectionSupported1 = TRUE 
        | FeatureInfo.OptionBits.ExecutionTimeSelectionSupported2 = TRUE then
          InitSSW := _SetExecutionTimeSelectionIsoRd;
        else
          InitSSW := _GetSDOMessageCounters;
        end_if;
        
//**********************************************************************************************************************************************************     
      _SetExecutionTimeSelectionIsoRd:
        
        //Disable that Pre-processor time is contributed into duration time by writing 1 to register          
        if ConnectionType = SDIAS_CON_VIA_VARAN_uC then
        
          ASYWriteDO.pData^$USINT := 1;          
          
          //Set Task duration time for read task
          if ChangeAsyWr(Offset:=SDIAS_OFFSET_TASK_DURATION_TIME_1, 
                        Length:= 1, 
                        RunState:=_BUS_IF_RUN_STATE_SINGLE_RUN,
                        UsageType:=_UsedBySSW) then
            
            InitSSW := _SetExecutionTimeSelectionIsoWr;
          end_if;

        else
        
          InitSSW := _SetExecutionTimeSelectionIsoWr;
          
          aProperties[0].udPropertyId     := SDM_PROP_TASK_INFO_DURATION_TIME;
          aProperties[0].udPropertyValue  := 1;
                  
          //Set Properties for Read Task       
          if SDIAS_iSetNodePropertiesIndex(hNodeHandle      := udNodeHandle
                                         , udIndex               := 1
                                         , udPropertyCount       := 1
                                         , psPropertyValuePairs  := #aProperties[0]
                                         ) <> SDIAS_OK then
                                         
            //Reset Feature Bit for display (not the internal one) if we cannot set it via os interface                                    
            ManagerOptionBits$t_FeatureInfo.OptionBits.ExecutionTimeSelectionSupported1 := FALSE;                                     
            ManagerOptionBits$t_FeatureInfo.OptionBits.ExecutionTimeSelectionSupported2 := FALSE;
#ifdef HWC_LogError
            HWC_LogError(this, "@004D (SdiasManager::CyWork) Couldn't set execution time selection for Iso Rd Task! Newer OS is required");
#endif
          end_if;
        end_if;
        

//**********************************************************************************************************************************************************     
      _SetExecutionTimeSelectionIsoWr:

        //Disable that Pre-processor time is contributed into duration time by writing 1 to register          
        if ConnectionType = SDIAS_CON_VIA_VARAN_uC then
        
          ASYWriteDO.pData^$USINT := 1;          
          
          //Set Task duration time for write task
          if ChangeAsyWr(Offset:=SDIAS_OFFSET_TASK_DURATION_TIME_2, 
                        Length:= 1, 
                        RunState:=_BUS_IF_RUN_STATE_SINGLE_RUN,
                        UsageType:=_UsedBySSW) then
            
            InitSSW := _GetSDOMessageCounters;            
          end_if;                        

        else

          InitSSW := _GetSDOMessageCounters;            
          aProperties[0].udPropertyId     := SDM_PROP_TASK_INFO_DURATION_TIME;
          aProperties[0].udPropertyValue  := 1;

          //Set Properties for Write Task         
          if SDIAS_iSetNodePropertiesIndex(hNodeHandle      := udNodeHandle
                                         , udIndex               := 2
                                         , udPropertyCount       := 1
                                         , psPropertyValuePairs  := #aProperties[0]
                                         ) <> SDIAS_OK then
                                         
            //Reset Feature Bit for display (not the internal one) if we cannot set it via os interface
            ManagerOptionBits$t_FeatureInfo.OptionBits.ExecutionTimeSelectionSupported1 := FALSE;                                     
            ManagerOptionBits$t_FeatureInfo.OptionBits.ExecutionTimeSelectionSupported2 := FALSE;
#ifdef HWC_LogError
            HWC_LogError(this, "@004E (SdiasManager::CyWork) Couldn't set execution time selection for Iso Wr Task! Newer OS is required");
#endif
          end_if;        
        end_if;
        
        
//**********************************************************************************************************************************************************     
      _GetSDOMessageCounters:
        // check if we got mapping infos
        if ManagerInfoBlock.MappingInfo.MappingInfoNo then
          // remember the adresses of the first SDO channel for request and response
          SDOHandling.OffsetSDOResp := gcMapping_Informations[SDORespBufCh1].StartAddress;
          SDOHandling.OffsetSDOReq  := gcMapping_Informations[SDOReqBufCh1].StartAddress;
          
          if SDOHandling.OffsetSDOReq then
            if ConnectionType = SDIAS_CON_VIA_VARAN_uC then
              // start read access on the SDO request buffer to the the actual message counters
              if ChangeAsyRd(Offset:=SDOHandling.OffsetSDOReq, 
                             Length:=sizeof(t_SDOChannels), 
                             RunState:=_BUS_IF_RUN_STATE_SINGLE_RUN,
                             UsageType:=_UsedBySSW) then
                InitSSW := _Wait4MessageCounters;
              end_if;
            else
              // message counters start at 0 provided by OS => no need to read them
              ActInitAccessIndex := 0;

              // if it's the first initialisation => ask the modules if they need special accesses
              if b_IsoDOsCreated = FALSE then
                InitSSW := _InitAccesses;
              else
                // otherwise just check the info block
                InitSSW := _CheckInfoBlock;
              end_if;
            end_if;
          else
#ifdef HWC_LogError
            HWC_LogError(this, "@004F (SdiasManager::CyWork) Couldn't find SDO request channel 1 in info block! Unable to continue with Initialisation!");
#endif
            ClassState := _ComponentNotExists;
            ErrorInitStep := InitSSW;
            InitSSW := _PrepareError;
          end_if;
        else
#ifdef HWC_LogError
          HWC_LogError(this, "@0050 (SdiasManager::CyWork) Couldn't find mapping info in info block of SDIAS Manager! Unable to continue with Initialisation!");
#endif
          ClassState := _ComponentNotExists;
          ErrorInitStep := InitSSW;
          InitSSW := _PrepareError;          
        end_if;
        
//**********************************************************************************************************************************************************
      _Wait4MessageCounters: //only for connection of sdias over varan
        // store the message counters local for the next use of SDOs
        SDOChannels := ASYReadDO.pData^$t_SDOChannels;
        
        //reset usage type of asynchrone read and write because it could be used at next step for AddAccesses() at connected modules (e.g. DC06x, SR01x, ..)
        AsyReadUsage  := _NotUsed;
        AsyWriteUsage := _NotUsed;
        
        for i := 0 to 2 do
          SDOHandling.aChannelData[i].MessageCnt := SDOChannels[i].MessageCounter AND SDIAS_MASK_MESSAGE_COUNTER;
        end_for;

        ActInitAccessIndex := 0;

        // if it's the first initialisation => ask the modules if they need special accesses
        if b_IsoDOsCreated = FALSE then
          InitSSW := _InitAccesses;
        else
          // otherwise just check the info block
          InitSSW := _CheckInfoBlock;
        end_if;
        
//**********************************************************************************************************************************************************
      _InitAccesses:
        
        pModuleInfo := #ModuleObjInfo[ActInitAccessIndex];
        b_ModulInitFinished := TRUE;

        // post init blocks the tasks in cyclic priority (the SDIAS Manager Code is running in lower priority than cyclic and has no time during the postinit) => give it some time
        if (b_PostInitFinished = FALSE) then
          ToMultiTask.TASKDELAY(timeout0:=SDIAS_WAIT_TIME_IN_POST_INIT);
        end_if;
        
        // on VIs all accesse must be created because plug and play, on local SDIAS only for modules which are really there.
        if ConnectionType = SDIAS_CON_VIA_VARAN_uC then
          while ActInitAccessIndex <= MaxPlace do
            // check only the available objects
            if pModuleInfo^.pThis then
            
              // new device info with length parameter to ensure compatibility
              tempCmd.uiCmd := SDIAS_CMD_DEVICE_INFO2;
              tempCmd.aPara[0] := sizeof(HDINT); // length of following parameters
              
              // hardware version: for 1.10 (printed on the module) we have to transform 16#01 major and 16#0100 minor (drop high nibbles of minor) to 16#00000110
              tempCmd.aPara[1] := to_dint((ManagerInfoBlock.ModuleInfos[ActInitAccessIndex].HWVersion SHL 8)            OR 
                                  ((ManagerInfoBlock.ModuleInfos[ActInitAccessIndex].HWVersionMidLow  SHR 4) AND 16#F0) OR
                                  ((ManagerInfoBlock.ModuleInfos[ActInitAccessIndex].HWVersionMidLow       ) AND 16#0F));
              

              // don't check the return code since this command may not be supported
              pModuleInfo^.pThis^.NewInst(pPara:=#tempCmd, pResult:=#_result);

              // send the device info to the module
              tempCmd.uiCmd := SDIAS_CMD_DEVICE_INFO;
              tempCmd.aPara[0] := to_dint(ManagerInfoBlock.ModuleInfos[ActInitAccessIndex].ModuleID);
              tempCmd.aPara[1] := (#ManagerInfoBlock.ModuleInfos[ActInitAccessIndex].SerialNo[0])$DINT;
              
              // additional info which may be needed by the module
              tempCmd.aPara[2] := ud_BusTime_ns$DINT;
              tempCmd.aPara[3] := to_dint(ManagerInfoBlock.ModuleInfos[ActInitAccessIndex].FPGAVersion);
              
              // don't check return code because over varan the hardware does not have to be available yet.
              pModuleInfo^.pThis^.NewInst(pPara:=#tempCmd, pResult:=#_result);
              
              // update default accesses if available
              if ManagerInfoBlock.ModuleInfos[ActInitAccessIndex].ReadAccess.usLength then
                pModuleInfo^.pDefaultAccesses^.ReadAccess.hiOffset := ManagerInfoBlock.ModuleInfos[ActInitAccessIndex].ReadAccess.hiOffset;
                pModuleInfo^.pDefaultAccesses^.ReadAccess.usLength := ManagerInfoBlock.ModuleInfos[ActInitAccessIndex].ReadAccess.usLength;
              end_if;
              
              if ManagerInfoBlock.ModuleInfos[ActInitAccessIndex].WriteAccess.usLength then
                pModuleInfo^.pDefaultAccesses^.WriteAccess.hiOffset := ManagerInfoBlock.ModuleInfos[ActInitAccessIndex].WriteAccess.hiOffset;
                pModuleInfo^.pDefaultAccesses^.WriteAccess.usLength := ManagerInfoBlock.ModuleInfos[ActInitAccessIndex].WriteAccess.usLength;
              end_if;
                
              tempCmd.uiCmd := SDIAS_CMD_INIT_ACCESSES;
              
              RetcodeIPR := pModuleInfo^.pThis^.NewInst(pPara:=#tempCmd, pResult:=#_result);
              if RetcodeIPR = BUSY then
                // if any module needs more runs => continue here next time
                b_ModulInitFinished := FALSE;
                exit;
              elsif RetcodeIPR = ERROR then
#ifdef HWC_LogValue1
                HWC_LogValue1(this, "@0051 (SdiasManager::CyWork) Failed to add accesses on SDIAS Place 0x{0}", ActInitAccessIndex);
#endif
              end_if;
            end_if;  
            pModuleInfo += sizeof(t_ModuleObjectInfo);
            ActInitAccessIndex += 1;
          end_while;
        else 
          //dont call AddAccesses if modul is local and not available or wrong hardware
          while ActInitAccessIndex <= MaxPlace do 
            // check only the available objects
            if pModuleInfo^.pThis
            & IsDeviceBitSet(pDeviceBitMap:=#HardwareConfig.DeviceBitmap[0], Place:=ActInitAccessIndex) then
              // new device info with length parameter to ensure compatibility
              tempCmd.uiCmd := SDIAS_CMD_DEVICE_INFO2;
              tempCmd.aPara[0] := sizeof(HDINT); // length of following parameters
              
              // hardware version: for 1.10 (printed on the module) we have to transform 16#01 major and 16#0100 minor (drop high nibbles of minor) to 16#00000110
              tempCmd.aPara[1] := to_dint((ManagerInfoBlock.ModuleInfos[ActInitAccessIndex].HWVersion SHL 8)            OR 
                                  ((ManagerInfoBlock.ModuleInfos[ActInitAccessIndex].HWVersionMidLow  SHR 4) AND 16#F0) OR
                                  ((ManagerInfoBlock.ModuleInfos[ActInitAccessIndex].HWVersionMidLow       ) AND 16#0F));


              // don't check the return code since this command may not be supported
              pModuleInfo^.pThis^.NewInst(pPara:=#tempCmd, pResult:=#_result);

              // send the device info to the module
              tempCmd.uiCmd := SDIAS_CMD_DEVICE_INFO;
              tempCmd.aPara[0] := to_dint(ManagerInfoBlock.ModuleInfos[ActInitAccessIndex].ModuleID);
              tempCmd.aPara[1] := (#ManagerInfoBlock.ModuleInfos[ActInitAccessIndex].SerialNo[0])$DINT;
              
              // additional info which may be needed by the module
              tempCmd.aPara[2] := ud_BusTime_ns$DINT;
              tempCmd.aPara[3] := to_dint(ManagerInfoBlock.ModuleInfos[ActInitAccessIndex].FPGAVersion);
              
              // check if device ID is ok
              if pModuleInfo^.pThis^.NewInst(pPara:=#tempCmd, pResult:=#_result) = READY then
              
                // update default accesses if available
                if ManagerInfoBlock.ModuleInfos[ActInitAccessIndex].ReadAccess.usLength then
                  pModuleInfo^.pDefaultAccesses^.ReadAccess.hiOffset := ManagerInfoBlock.ModuleInfos[ActInitAccessIndex].ReadAccess.hiOffset;
                  pModuleInfo^.pDefaultAccesses^.ReadAccess.usLength := ManagerInfoBlock.ModuleInfos[ActInitAccessIndex].ReadAccess.usLength;
                end_if;
                
                if ManagerInfoBlock.ModuleInfos[ActInitAccessIndex].WriteAccess.usLength then
                  pModuleInfo^.pDefaultAccesses^.WriteAccess.hiOffset := ManagerInfoBlock.ModuleInfos[ActInitAccessIndex].WriteAccess.hiOffset;
                  pModuleInfo^.pDefaultAccesses^.WriteAccess.usLength := ManagerInfoBlock.ModuleInfos[ActInitAccessIndex].WriteAccess.usLength;
                end_if;
              
                tempCmd.uiCmd := SDIAS_CMD_INIT_ACCESSES;
                RetcodeIPR := pModuleInfo^.pThis^.NewInst(pPara:=#tempCmd, pResult:=#_result);
                if RetcodeIPR = BUSY then
                  // if any module needs more runs => continue here next time
                  b_ModulInitFinished := FALSE;
                  exit;
                elsif RetcodeIPR = ERROR then
#ifdef HWC_LogValue1
                  HWC_LogValue1(this, "@0051 (SdiasManager::CyWork) Failed to add accesses on SDIAS Place 0x{0}", ActInitAccessIndex);
#endif
                end_if;
              end_if;
            end_if;  
            pModuleInfo += sizeof(t_ModuleObjectInfo);
            ActInitAccessIndex += 1;
          end_while;
        end_if;  

        // if we got all accesse => go on
        if b_ModulInitFinished then
          // only if there are entries
          if ManagerInfoBlock.MappingInfo.MappingInfoNo then

            // if the post init is over and the DOs are not created yet => create them in Rt-SSW
            if b_PostInitFinished then
              InitSSW := _StartRtIsoDOCreation;
            else
              CreateAndModifyIsoDOs();
              
              InitSSW := _CheckInfoBlock;
            end_if;
          else
#ifdef HWC_LogError
            HWC_LogError(this, "@0053 (SdiasManager::CyWork) No Mapping Info in Info Block of SDIAS Manager found! Unable to continue Initialisation!");
#endif
            ErrorInitStep := InitSSW;
            InitSSW := _PrepareError;
            ClassState := _ComponentNotExists;
          end_if;
        end_if;
        
//**********************************************************************************************************************************************************
      _StartRtIsoDOCreation:
        // create and modify the iso DOs in realtime priority
        RtSSW := _CreateAndModifyDOs;
        InitSSW := _Wait4RtIsoDOCreation;
        
//**********************************************************************************************************************************************************
      _Wait4RtIsoDOCreation:
        // wait for the DOs to be ready
        if RtSSW = _Wait4DOs then
          InitSSW := _CheckInfoBlock;
        end_if;
        
//**********************************************************************************************************************************************************
      _CheckInfoBlock:
      
        // only if there are entries
        if ManagerInfoBlock.MappingInfo.MappingInfoNo then
          if ISOWriteDO.pData & ISOReadDO.pData then

            // on VIs the info is copied into the payload. on local SDIAS we get the info directly from the OS
            if ConnectionType = SDIAS_CON_VIA_VARAN_uC then        
            
              //Check if the data objects were already created,
              if b_IsoDOsCreated = TRUE then
                
                //No error as default
                bError := FALSE;
                
                //Check if the actusage from the µC is bigger than the DO length we created (read)
                if gcMapping_Informations[IsoRdPayload].ActUsage > sDOLengthsFirstConnect.udISOReadActUsage then
                  bError := TRUE;
                  TempUDINT := TO_UDINT(gcMapping_Informations[IsoRdPayload].ActUsage);
                  HWC_LogPrintf(pThis:=this, format:= "@075F (SdiasManager::CyWork) The actual ISO read usage %u is bigger than the ISO read usage %u from the first connect. Unable to continue Initialisation!", 
                                p0:=#TempUDINT, p1:=#sDOLengthsFirstConnect.udISOReadActUsage);
                end_if;

                //Check if the actusage from the µC is bigger than the DO length we created (write)
                if gcMapping_Informations[IsoWrPayload].ActUsage > sDOLengthsFirstConnect.udISOWriteActUsage then
                  bError := TRUE;                
                  TempUDINT := TO_UDINT(gcMapping_Informations[IsoWrPayload].ActUsage);
                  HWC_LogPrintf(pThis:=this, format:= "@0760 (SdiasManager::CyWork) The actual ISO write usage %u is bigger than the ISO write usage %u from the first connect. Unable to continue Initialisation!", 
                                p0:=#TempUDINT, p1:=#sDOLengthsFirstConnect.udISOWriteActUsage);
                end_if;
                
                //If there is an error, stop the initialisation
                //This can only happen if there was only x modules at the first connect, and at a later connect (now) there are more modules at the VI02x
                //e.g first connect is VI02x + 2 SDIAS modules and at the second connect there is a VI02x + 3 SDIAS modules
                //It is not defined as a usecase, that the amount of connected SDIAS modules gets changed at Plug&Play of the VI02x, just show an error
                if bError then
                  ErrorInitStep := InitSSW;
                  InitSSW := _PrepareError;
                  ClassState := _DataLengthInvalid;
                  return;
                end_if;
              end_if;

              pTaskHelp := TaskInfoDO.pData$^t_TaskInfoReadData;
              WriteTaskInfo.pReadData := #pTaskHelp^.WriteTaskInfo;
              ReadTaskInfo.pReadData  := #pTaskHelp^.ReadTaskInfo;              
            else
              WriteTaskInfo.pReadData := #WrTaskInfo;
              ReadTaskInfo.pReadData  := #RdTaskInfo;
            end_if;

            // tell the modules their DeviceID, Serialnumber and check if it's the correct object at this place. if so, give them the access pointers
            pModuleInfo := #ModuleObjInfo[0];
            for i := 0 to MaxPlace do

              // if we have an object with this place
              if pModuleInfo^.pThis then
                // and the µC detected a module at this place
                if IsDeviceBitSet(pDeviceBitMap:=#HardwareConfig.DeviceBitmap[0], Place:=i) then                  
                  
                  if ManagerInfoBlock.ModuleInfos[i].ModuleID = 16#FFFF then
                    pModuleInfo^.pInitState^ := _SPIError;
                  else
                    // get the init state of the LED of this object
                    TempLEDState := pModuleInfo^.pThis^.LEDControl$USINT;
                    
                    // save the state in the local LED Image
                    
                    // get byte position ouf of place (place 0-3 in byte 0, 4-7 in byte 1,...)
                    ByteNr := i$USINT SHR 2;
                    PosInByte := (i$USINT AND 2#11) SHL 1;
                    AppliLEDStates[ByteNr] := (AppliLEDStates[ByteNr] AND NOT(2#11 SHL PosInByte)) OR (TempLEDState SHL PosInByte);

                    // new device info with length parameter to ensure compatibility
                    tempCmd.uiCmd := SDIAS_CMD_DEVICE_INFO2;
                    tempCmd.aPara[0] := sizeof(HDINT); // length of following parameters
                    
                    // hardware version: for 1.10 (printed on the module) we have to transform 16#01 major and 16#0100 minor (drop high nibbles of minor) to 16#00000110
                    tempCmd.aPara[1] := to_dint((ManagerInfoBlock.ModuleInfos[i].HWVersion SHL 8)            OR 
                                        ((ManagerInfoBlock.ModuleInfos[i].HWVersionMidLow  SHR 4) AND 16#F0) OR
                                        ((ManagerInfoBlock.ModuleInfos[i].HWVersionMidLow       ) AND 16#0F));

                    // don't check the return code since this command may not be supported
                    pModuleInfo^.pThis^.NewInst(pPara:=#tempCmd, pResult:=#_result);

                    // send the device info to the module
                    tempCmd.uiCmd := SDIAS_CMD_DEVICE_INFO;
                    tempCmd.aPara[0] := to_dint(ManagerInfoBlock.ModuleInfos[i].ModuleID);
                    tempCmd.aPara[1] := (#ManagerInfoBlock.ModuleInfos[i].SerialNo[0])$DINT;
                    
                    // additional info which may be needed by the module
                    tempCmd.aPara[2] := ud_BusTime_ns$DINT;
                    tempCmd.aPara[3] := to_dint(ManagerInfoBlock.ModuleInfos[i].FPGAVersion);
                    
                    // check if device ID is ok
                    if pModuleInfo^.pThis^.NewInst(pPara:=#tempCmd, pResult:=#_result) = READY then
                    
                      // the module id matches, now check the accesses
                      
                      // update default accesses if available
                      if ManagerInfoBlock.ModuleInfos[i].ReadAccess.usLength then
                        pModuleInfo^.pDefaultAccesses^.ReadAccess.hiOffset := ManagerInfoBlock.ModuleInfos[i].ReadAccess.hiOffset;
                        pModuleInfo^.pDefaultAccesses^.ReadAccess.usLength := ManagerInfoBlock.ModuleInfos[i].ReadAccess.usLength;

                        // store the pointers to the correct payload data for later usage in the SDIAS Client class
                        pModuleInfo^.pDefaultAccesses^.ReadAccess.pControlByte$^void  := ISOWriteDO.pData + ManagerInfoBlock.ModuleInfos[i].ReadDODataWrOffset - ISOWriteDO.Offset;
                        pModuleInfo^.pDefaultAccesses^.ReadAccess.pStateByte$^void    := ISOReadDO.pData  + ManagerInfoBlock.ModuleInfos[i].ReadDODataRdOffset - ISOReadDO.Offset;
                        pModuleInfo^.pDefaultAccesses^.ReadAccess.pData               := ISOReadDO.pData  + ManagerInfoBlock.ModuleInfos[i].ReadDODataRdOffset - ISOReadDO.Offset + sizeof(t_SDIAS_StateByte);
                        
                        // Disable default read DO (if needed the module class activates it again in the ConnectEvent())
                        pModuleInfo^.pDefaultAccesses^.ReadAccess.pControlByte^ := 0; // RamAnd/ZoePat: This only covers modules placed in the project. Other modules behind might have active read default accesses.
                      end_if;
                     
                      if ManagerInfoBlock.ModuleInfos[i].WriteAccess.usLength then
                        pModuleInfo^.pDefaultAccesses^.WriteAccess.hiOffset := ManagerInfoBlock.ModuleInfos[i].WriteAccess.hiOffset;
                        pModuleInfo^.pDefaultAccesses^.WriteAccess.usLength := ManagerInfoBlock.ModuleInfos[i].WriteAccess.usLength;

                        // store the pointers to the correct payload data for later usage in the SDIAS Client class
                        pModuleInfo^.pDefaultAccesses^.WriteAccess.pControlByte$^void  := ISOWriteDO.pData + ManagerInfoBlock.ModuleInfos[i].WriteDODataWrOffset - ISOWriteDO.Offset;
                        pModuleInfo^.pDefaultAccesses^.WriteAccess.pStateByte$^void    := ISOReadDO.pData + ManagerInfoBlock.ModuleInfos[i].WriteDODataRdOffset - ISOReadDO.Offset;
                        pModuleInfo^.pDefaultAccesses^.WriteAccess.pData               := ISOWriteDO.pData + ManagerInfoBlock.ModuleInfos[i].WriteDODataWrOffset - ISOWriteDO.Offset + sizeof(t_SDIAS_ControlByte);
                      end_if;
                    else
                      // wrong device ID
                      if pModuleInfo^.Required then
                        // first stop blocking the init, otherwise the init freezes when we have a required error
                        if b_PostInitFinished = FALSE then
                          SendPostInitFinished(DisableThisObject:=TRUE);
                        end_if;
                        
#ifdef HWC_LogValue1
                        HWC_LogValue1(this, "@0052 (SdiasManager::CyWork) Wrong device ID at SDIAS Place 0x{0}", i);
#endif
                        
                        SetRequiredError(pTargetThis:=pModuleInfo^.pThis, Place:=i);
                      else
                        pModuleInfo^.pInitState^ := _WrongHardware;
                      end_if;
                    end_if;
                  end_if;
                else
                  // module is not in the device bitmap, but we got an object
                  if pModuleInfo^.Required then
                    // first stop blocking the init, otherwise the init freezes when we have a required error
                    if b_PostInitFinished = FALSE then
                      SendPostInitFinished(DisableThisObject:=TRUE);
                    end_if;

                    SetRequiredError(pTargetThis:=pModuleInfo^.pThis, Place:=i);
                  else
                    pModuleInfo^.pInitState^ := _NoHardware;
                  end_if;
                end_if;
              end_if;

              pModuleInfo += sizeof(t_ModuleObjectInfo);
            end_for;
          end_if;

          if ConnectionType = SDIAS_CON_VIA_VARAN_uC then
            InitSSW := _PrepareResetIsoRdPayload;
          else
            // we don't have to reset the payload => done by OS
            udCurCheckedMod := 0;
            InitSSW := _CheckModule_Valid;
          end_if;

        else
#ifdef HWC_LogError
          HWC_LogError(this, "@0053 (SdiasManager::CyWork) No Mapping Info in Info Block of SDIAS Manager found! Unable to continue Initialisation!");
#endif
          ErrorInitStep := InitSSW;
          InitSSW := _PrepareError;
          ClassState := _ComponentNotExists;
        end_if;

//**********************************************************************************************************************************************************
      _PrepareResetIsoRdPayload:
        // prepare resetting the read payload (toggle bits)
        AccessProgress := 0;
        // reset the write buffer
        _memset(dest:=ASYWriteDO.pData, usByte:=0, cntr:=128);
        NewDataSize := ISOReadDO.Length;
        if NewDataSize > 128 then
          NewDataSize := 128;
        end_if;
        
        if ChangeAsyWr(Offset:=ISOReadDO.Offset, 
                       Length:=NewDataSize$USINT, 
                       RunState:=_BUS_IF_RUN_STATE_CONT_RUN,
                       UsageType:=_UsedBySSW) then

          InitSSW := _ResetIsoRdPayload;
        end_if;

//**********************************************************************************************************************************************************
      _ResetIsoRdPayload:
        AccessProgress += NewDataSize;
        
        if AccessProgress < ISOReadDO.Length then
          if (ISOReadDO.Length - AccessProgress) > 128 then
            // we need more than 128 bytes => write the next 128
            TempNewDataSize := 128;
          else
            // we need to write the rest (last package)
            TempNewDataSize := (ISOReadDO.Length - AccessProgress);
          end_if;
          
          if ChangeAsyWr(Offset:=ISOReadDO.Offset + AccessProgress, 
                         Length:=TempNewDataSize$USINT, 
                         RunState:=_BUS_IF_RUN_STATE_CONT_RUN,
                         UsageType:=_UsedBySSW) then
              NewDataSize := TempNewDataSize;
          else
            NewDataSize := 0;
          end_if;
        else
          // we got the complete info block now => stop the DO
          if ChangeAsyWr(Offset:=0, 
                         Length:=0, 
                         RunState:=_BUS_IF_RUN_STATE_NO_RUN,
                         UsageType:=_UsedBySSW) then
  
            InitSSW := _PrepareResetIsoWrPayload;
          else
            NewDataSize := 0;
          end_if;
        end_if;

//**********************************************************************************************************************************************************
      _PrepareResetIsoWrPayload:
        // prepare resetting the read payload (toggle bits)
        AccessProgress := 0;
        // reset the write buffer
        _memset(dest:=ASYWriteDO.pData, usByte:=0, cntr:=128);
        NewDataSize := ISOWriteDO.Length;
        if NewDataSize > 128 then
          NewDataSize := 128;
        end_if;
        
        if ChangeAsyWr(Offset:=ISOWriteDO.Offset, 
                       Length:=NewDataSize$USINT, 
                       RunState:=_BUS_IF_RUN_STATE_CONT_RUN,
                       UsageType:=_UsedBySSW) then

          InitSSW := _ResetIsoWrPayload;
        end_if;

//**********************************************************************************************************************************************************
      _ResetIsoWrPayload:
        AccessProgress += NewDataSize;
        
        if AccessProgress < ISOWriteDO.Length then
          if (ISOWriteDO.Length - AccessProgress) > 128 then
            // we need more than 128 bytes => write the next 128
            TempNewDataSize := 128;
          else
            // we need to write the rest (last package)
            TempNewDataSize := (ISOWriteDO.Length - AccessProgress);
          end_if;
          
          if ChangeAsyWr(Offset:=ISOWriteDO.Offset + AccessProgress, 
                         Length:=TempNewDataSize$USINT, 
                         RunState:=_BUS_IF_RUN_STATE_CONT_RUN,
                         UsageType:=_UsedBySSW) then
              NewDataSize := TempNewDataSize;
          else
            NewDataSize := 0;
          end_if;
        else
          // we got the complete info block now => stop the DO
          if ChangeAsyWr(Offset:=0, 
                         Length:=0, 
                         RunState:=_BUS_IF_RUN_STATE_NO_RUN,
                         UsageType:=_UsedBySSW) then
  
            udCurCheckedMod := 0;
            InitSSW := _CheckModule_Valid;
          else
            NewDataSize := 0;
          end_if;
        end_if;
        
//**********************************************************************************************************************************************************
      _CheckModule_Valid:
        // tell the modules their DeviceID, Serialnumber and check if it's the correct object at this place. if so, give them the access pointers
        pModuleInfo := #ModuleObjInfo[udCurCheckedMod];

        // if we have an object with this place
        if pModuleInfo^.pThis then
          // and the µC detected a module at this place
          if IsDeviceBitSet(pDeviceBitMap:=#HardwareConfig.DeviceBitmap[0], Place:=udCurCheckedMod) then
            
            if ManagerInfoBlock.ModuleInfos[udCurCheckedMod].ModuleID = 16#FFFF then
              // SPI Error
              if pModuleInfo^.Required then
                // first stop blocking the init, otherwise the init freezes when we have a required error
                if b_PostInitFinished = FALSE then
                  SendPostInitFinished(DisableThisObject:=TRUE);  
                end_if;
                
#ifdef HWC_LogValue1
                HWC_LogValue1(this, "@0052 (SdiasManager::CyWork) Wrong device ID at SDIAS Place 0x{0}", udCurCheckedMod);
#endif
                
                SetRequiredError(pTargetThis:=pModuleInfo^.pThis, Place:=udCurCheckedMod);
              else
                pModuleInfo^.pInitState^ := _SPIError;
                InitSSW := _CheckNextModule;
              end_if;
            else
              // get the init state of the LED of this object
              TempLEDState := pModuleInfo^.pThis^.LEDControl$USINT;
              
              // save the state in the local LED Image
              
              // get byte position ouf of place (place 0-3 in byte 0, 4-7 in byte 1,...)
              ByteNr := udCurCheckedMod$USINT SHR 2;
              PosInByte := (udCurCheckedMod$USINT AND 2#11) SHL 1;
              AppliLEDStates[ByteNr] := (AppliLEDStates[ByteNr] AND NOT(2#11 SHL PosInByte)) OR (TempLEDState SHL PosInByte);

              // new device info with length parameter to ensure compatibility
              tempCmd.uiCmd := SDIAS_CMD_DEVICE_INFO2;
              tempCmd.aPara[0] := sizeof(HDINT); // length of following parameters
              
              // hardware version: for 1.10 (printed on the module) we have to transform 16#01 major and 16#0100 minor (drop high nibbles of minor) to 16#00000110
              tempCmd.aPara[1] := to_dint((ManagerInfoBlock.ModuleInfos[udCurCheckedMod].HWVersion SHL 8)            OR 
                                  ((ManagerInfoBlock.ModuleInfos[udCurCheckedMod].HWVersionMidLow  SHR 4) AND 16#F0) OR
                                  ((ManagerInfoBlock.ModuleInfos[udCurCheckedMod].HWVersionMidLow       ) AND 16#0F));

              // don't check the return code since this command may not be supported
              pModuleInfo^.pThis^.NewInst(pPara:=#tempCmd, pResult:=#_result);

              // send the device info to the module
              tempCmd.uiCmd := SDIAS_CMD_DEVICE_INFO;
              tempCmd.aPara[0] := to_dint(ManagerInfoBlock.ModuleInfos[udCurCheckedMod].ModuleID);
              tempCmd.aPara[1] := (#ManagerInfoBlock.ModuleInfos[udCurCheckedMod].SerialNo[0])$DINT;
              
              // additional info which may be needed by the module
              tempCmd.aPara[2] := ud_BusTime_ns$DINT;
              tempCmd.aPara[3] := to_dint(ManagerInfoBlock.ModuleInfos[udCurCheckedMod].FPGAVersion);
              
              // check if device ID is ok
              if pModuleInfo^.pThis^.NewInst(pPara:=#tempCmd, pResult:=#_result) = READY then

                // the module id matches, continue with access
                pCurCheckModAccPtr := pModuleInfo^.pFirstAccess;
                InitSSW := _SetModAccess;
                                   
              else
                // wrong device ID
                if pModuleInfo^.Required then
                  // first stop blocking the init, otherwise the init freezes when we have a required error
                  if b_PostInitFinished = FALSE then
                    SendPostInitFinished(DisableThisObject:=TRUE); 
                  end_if;
                  
#ifdef HWC_LogValue1
                  HWC_LogValue1(this, "@0052 (SdiasManager::CyWork) Wrong device ID at SDIAS Place 0x{0}", udCurCheckedMod);
#endif
                  
                  SetRequiredError(pTargetThis:=pModuleInfo^.pThis, Place:=udCurCheckedMod);
                else
                  pModuleInfo^.pInitState^ := _WrongHardware;
                  InitSSW := _CheckNextModule;
                end_if;
              end_if;
            end_if;
          else
            // module is not in the device bitmap, but we got an object
            if pModuleInfo^.Required then
              // first stop blocking the init, otherwise the init freezes when we have a required error
              if b_PostInitFinished = FALSE then
                SendPostInitFinished(DisableThisObject:=TRUE);
              end_if;

              SetRequiredError(pTargetThis:=pModuleInfo^.pThis, Place:=udCurCheckedMod);
            else
              pModuleInfo^.pInitState^ := _NoHardware;
              InitSSW := _CheckNextModule;
            end_if;
          end_if;
        else
          InitSSW := _CheckNextModule;      
        end_if;

//**********************************************************************************************************************************************************
      _SetModAccess:
        pModuleInfo := #ModuleObjInfo[udCurCheckedMod];                                  
        if pCurCheckModAccPtr = NIL then
          // no special accesses => call connect event and proceed with next module
          pModuleInfo^.pThis^.ConnectEvent();
          InitSSW := _CheckNextModule;           
        elsif (pCurCheckModAccPtr^.eAccessType = _Read) | (pCurCheckModAccPtr^.eAccessType = _ReadDynamic) then
          
          pWaitAccess := pCurCheckModAccPtr^.pWaitForAccess;
          if pWaitAccess <> NIL then
            if (pWaitAccess^.eAccessType <> pCurCheckModAccPtr^.eAccessType) then
              pWaitAccess := NIL;  
            end_if;
          end_if;

          if(pWaitAccess <> NIL) then
            // address of state byte
            iWaitOffset := ISOReadDO.Offset + (pWaitAccess^.ppStateByte^$HDINT - ISOReadDO.pData$HDINT)$UINT; //pWaitAccess^.hiDOOffsetInDPRAM;
          else
            iWaitOffset := SDIAS_INVALID_VOLATILE_WAIT_HANDLE;
          end_if;
          
          // Create access by new function
          iRetCode := DOL_Handling_Add_DO_TO_List(bIsWriteAcc0:= 0, 
                                                  usModulePlace0:=udCurCheckedMod,
                                                  iModAddr0:= pCurCheckModAccPtr^.hiOffset, 
                                                  iDataLen0:= pCurCheckModAccPtr^.uiLength, 
                                                  bCtrlAcc0:= pCurCheckModAccPtr^.bCtrlAcc0,
                                                  iWaitDOOffset0:= iWaitOffset,
                                                  bIsDynamic0 := (pCurCheckModAccPtr^.eAccessType = _ReadDynamic),
                                                  pActAccess0 := pCurCheckModAccPtr);
                      
          if iRetCode = 0 then
    
            // store the pointers to the correct payload data for later usage in the SDIAS Client class
            if pCurCheckModAccPtr^.ppControlByte then
              pCurCheckModAccPtr^.ppControlByte^$^void := ISOWriteDO.pData + gcWrite_DOL_Desc.iOffFirstData + gcMapping_Informations[IsoWrPayload].StartAddress - ISOWriteDO.Offset;  
              if pCurCheckModAccPtr^.eAccessType = _ReadDynamic then
                if pCurCheckModAccPtr^.bIsFarAcc then
                  pControlStructFar := pCurCheckModAccPtr^.ppControlByte^$^t_SDIAS_ControlStructDynamicFar;
                  pControlStructFar^.ControlByte.EnableFlexRead   := TRUE;
                  pControlStructFar^.ControlByte.EnableFlexWrite  := TRUE;              
                  pControlStructFar^.usLengthRd := pCurCheckModAccPtr^.uiLength$USINT;      
                  pControlStructFar^.usLengthWr := 0;                              
                  pControlStructFar^.hiOffsetRd := (pCurCheckModAccPtr^.hiOffset AND 16#3FF)$HINT + (udCurCheckedMod shl 10); //hiModAddr0;
                  pControlStructFar^.hiOffsetWr := to_uint(pCurCheckModAccPtr^.hiOffset shr 10); //usBlockNo1k;
                  
                else  //bIsFarAcc = false
                  pControlStruct := pCurCheckModAccPtr^.ppControlByte^$^t_SDIAS_ControlStructDynamic;
                  pControlStruct^.ControlByte.EnableFlexRead := TRUE;
                  pControlStruct^.hiOffset := pCurCheckModAccPtr^.hiOffset + (udCurCheckedMod shl 10);
                  pControlStruct^.usLength := pCurCheckModAccPtr^.uiLength$USINT;
                end_if;
              end_if;
            end_if;
            if pCurCheckModAccPtr^.ppStateByte then
              pCurCheckModAccPtr^.ppStateByte^$^void := ISOReadDO.pData + gcRead_DOL_Desc.iOffFirstData + gcMapping_Informations[IsoRdPayload].StartAddress - ISOReadDO.Offset;
            end_if;
            if pCurCheckModAccPtr^.ppData then
              pCurCheckModAccPtr^.ppData^$^void := ISOReadDO.pData + gcRead_DOL_Desc.iOffFirstData + sizeof(t_SDIAS_StateByte) + gcMapping_Informations[IsoRdPayload].StartAddress - ISOReadDO.Offset;
            end_if;       
                          
            InitSSW := _WriteModAccess;
          else
            ErrorInitStep := InitSSW;
            InitSSW := _PrepareError;
            ClassState := _DOCmdInvalid;           
          end_if;
                    
        elsif (pCurCheckModAccPtr^.eAccessType = _Write) | (pCurCheckModAccPtr^.eAccessType = _WriteDynamic) then
          
          pWaitAccess := pCurCheckModAccPtr^.pWaitForAccess;
          if pWaitAccess <> NIL then
            if (pWaitAccess^.eAccessType <> pCurCheckModAccPtr^.eAccessType) then
              pWaitAccess := NIL;  
            end_if;
          end_if;

          if(pWaitAccess <> NIL) then
            // address of state byte
            iWaitOffset := ISOReadDO.Offset + (pWaitAccess^.ppStateByte^$HDINT - ISOReadDO.pData$HDINT)$UINT; //pWaitAccess^.hiDOOffsetInDPRAM;
          else
            iWaitOffset := SDIAS_INVALID_VOLATILE_WAIT_HANDLE;
          end_if;            
                      
          // Create access by new function
          iRetCode := DOL_Handling_Add_DO_TO_List(bIsWriteAcc0:= 1, 
                                                  usModulePlace0:=udCurCheckedMod,
                                                  iModAddr0:= pCurCheckModAccPtr^.hiOffset, 
                                                  iDataLen0:= pCurCheckModAccPtr^.uiLength, 
                                                  bCtrlAcc0:= pCurCheckModAccPtr^.bCtrlAcc0,
                                                  iWaitDOOffset0:= iWaitOffset,
                                                  bIsDynamic0 := (pCurCheckModAccPtr^.eAccessType = _WriteDynamic),
                                                  pActAccess0 := pCurCheckModAccPtr);
                      
          if iRetCode = 0 then
            // store the pointers to the correct payload data for later usage in the SDIAS Client class
            if pCurCheckModAccPtr^.ppControlByte then
              pCurCheckModAccPtr^.ppControlByte^$^void := ISOWriteDO.pData + gcWrite_DOL_Desc.iOffFirstData + gcMapping_Informations[IsoWrPayload].StartAddress - ISOWriteDO.Offset;  
              if pCurCheckModAccPtr^.eAccessType = _WriteDynamic then
                if pCurCheckModAccPtr^.bIsFarAcc then
                  pControlStructFar := pCurCheckModAccPtr^.ppControlByte^$^t_SDIAS_ControlStructDynamicFar;
                  pControlStructFar^.ControlByte.EnableFlexRead   := TRUE;
                  pControlStructFar^.ControlByte.EnableFlexWrite  := TRUE;              
                  pControlStructFar^.usLengthWr := pCurCheckModAccPtr^.uiLength$USINT;      
                  pControlStructFar^.usLengthRd := 0;                              
                  pControlStructFar^.hiOffsetWr := (pCurCheckModAccPtr^.hiOffset AND 16#3FF)$HINT + (udCurCheckedMod shl 10); //hiModAddr0;
                  pControlStructFar^.hiOffsetRd := to_uint(pCurCheckModAccPtr^.hiOffset shr 10); //usBlockNo1k;
                  
                else  //bIsFarAcc = false
                  pControlStruct := pCurCheckModAccPtr^.ppControlByte^$^t_SDIAS_ControlStructDynamic;
                  pControlStruct^.ControlByte.EnableFlexWrite := TRUE;
                  pControlStruct^.hiOffset := pCurCheckModAccPtr^.hiOffset + (udCurCheckedMod shl 10);
                  pControlStruct^.usLength := pCurCheckModAccPtr^.uiLength$USINT;
                end_if;
              end_if;
            end_if;
            if pCurCheckModAccPtr^.ppStateByte then
              pCurCheckModAccPtr^.ppStateByte^$^void := ISOReadDO.pData + gcRead_DOL_Desc.iOffFirstData + gcMapping_Informations[IsoRdPayload].StartAddress - ISOReadDO.Offset; 
            end_if;
            if pCurCheckModAccPtr^.ppData then
              // the data start after the header. at dynamic objects we have more header in write payload => data start after the structure
              if pCurCheckModAccPtr^.eAccessType = _WriteDynamic then
                pCurCheckModAccPtr^.ppData^$^void := ISOWriteDO.pData + gcWrite_DOL_Desc.iOffFirstData + sizeof(t_SDIAS_ControlStructDynamic) + gcMapping_Informations[IsoWrPayload].StartAddress - ISOWriteDO.Offset;
              else
                pCurCheckModAccPtr^.ppData^$^void := ISOWriteDO.pData + gcWrite_DOL_Desc.iOffFirstData + sizeof(t_SDIAS_ControlByte) + gcMapping_Informations[IsoWrPayload].StartAddress - ISOWriteDO.Offset;
              end_if;
            end_if;                  

            InitSSW := _WriteModAccess;
          else
            ErrorInitStep := InitSSW;
            InitSSW := _PrepareError;
            ClassState := _DOCmdInvalid;           
          end_if;                   
        end_if;

//********************************************************************************************************************************************************** 
      _WriteModAccess:
      
          if ConnectionType = SDIAS_CON_VIA_VARAN_uC then
            ASYWriteDO.pData^$t_SDIAS_DOListEntryX2 := cModulAccessCmds;

            // Write data to manager dpram
            if ChangeAsyWr(Offset   := uiWriteCmdAddr, 
                           Length   := sizeof(cModulAccessCmds), 
                           RunState := _BUS_IF_RUN_STATE_SINGLE_RUN,
                           UsageType:= _UsedBySSW) then
          
              InitSSW := _SetNextModAccess;
            end_if;      
          else
            // OS already did this for us
            InitSSW := _SetNextModAccess;
          end_if;
   
//**********************************************************************************************************************************************************
      _SetNextModAccess:
      
        AsyWriteUsage  := _NotUsed;
      
        pModuleInfo := #ModuleObjInfo[udCurCheckedMod];     
        // Reached last access - trigger connect event 
        if(pCurCheckModAccPtr^.pNext = NIL) then
          // call the connect event now (pointers are set now to enable the accesses)
          pModuleInfo^.pThis^.ConnectEvent();
          InitSSW := _CheckNextModule;
        else
          pCurCheckModAccPtr := pCurCheckModAccPtr^.pNext;
          InitSSW := _SetModAccess;
        end_if;
      
//**********************************************************************************************************************************************************
      _CheckNextModule:
      
        // Switch to next module
        udCurCheckedMod += 1;
        
        if(udCurCheckedMod <= MaxPlace) then
          InitSSW := _CheckModule_Valid;
        else
          
          udCurCheckdMngAcc := 0;
          
          if SupportedFeatures.TimeBroadCastSupported then
            InitSSW := _SetBroadCastAccess;
          else
          
            if ConnectionType = SDIAS_CON_VIA_VARAN_uC then
              InitSSW := _WriteDOL_Offsets;
            else
              // we don't have to reset the payload => done by OS                
              InitSSW := _SetStartConfigIsoRd;
            end_if;
          end_if;          
          
          // Check if there are no Clients are connected to local SDIAS Manager
          if ConnectionType = SDIAS_CON_LOCAL_uC then
          
            if MaxPlace = SDIAS_PLACE_NO_MODULE_ADDED_SO_FAR then
            
#ifdef HWC_LogError
              HWC_LogError(this, "@004A (SdiasManager::CyWork) No SDIAS Client objects projected/connected to the SDIAS Manager! Unable to continue with Initialisation!");
#endif
              ErrorInitStep := InitSSW;
              InitSSW := _PrepareError;
              ClassState := _NoHardware;
            end_if;
            
          end_if;
          
        end_if;
        
//**********************************************************************************************************************************************************        
      _SetBroadCastAccess:        
        
          localAccess.eAccessType     := _Write;
          localAccess.usPlace         := 0;
          localAccess.hiOffset        := SDIAS_OFFSET_CLIENT_CTRLTIMESTAMP;
          localAccess.uiLength        := sizeof(UINT);
          localAccess.bCtrlAcc0       := TRUE;
          localAccess.bIsFarAcc       := FALSE;
          localAccess.ppData          := #aBroadCastTime[udCurCheckdMngAcc].pWriteData;
          localAccess.ppStateByte     := #aBroadCastTime[udCurCheckdMngAcc].Access.pStateByte;
          localAccess.ppControlByte   := #aBroadCastTime[udCurCheckdMngAcc].Access.pControlByte;
          localAccess.pWaitForAccess  := NIL;
          localAccess.udOSDOHandle    := 0;
          localAccess.pNext           := NIL;
          
          pCurCheckModAccPtr := #localAccess;
      
          iRetCode := DOL_Handling_Add_DO_TO_List(bIsWriteAcc0  := TRUE
                                                , usModulePlace0:= 0 
                                                , iModAddr0     := SDIAS_OFFSET_CLIENT_CTRLTIMESTAMP
                                                , iDataLen0     := sizeof(UINT)
                                                , bCtrlAcc0     := TRUE
                                                , iWaitDOOffset0:= SDIAS_INVALID_VOLATILE_WAIT_HANDLE
                                                , bIsDynamic0   := FALSE
                                                , pActAccess0   := pCurCheckModAccPtr
                                                , bIsBroadCast  := TRUE);
          if iRetCode = 0 then
          
            // store the pointers to the correct payload data for later usage in the SDIAS Client class
            if pCurCheckModAccPtr^.ppControlByte then              
              pCurCheckModAccPtr^.ppControlByte^$^void := ISOWriteDO.pData + gcWrite_DOL_Desc.iOffFirstData + gcMapping_Informations[IsoWrPayload].StartAddress - ISOWriteDO.Offset;  
              pCurCheckModAccPtr^.ppControlByte^^.EnableDO := 1;
            end_if;
            if pCurCheckModAccPtr^.ppStateByte then              
              pCurCheckModAccPtr^.ppStateByte^$^void := ISOReadDO.pData + gcRead_DOL_Desc.iOffFirstData + gcMapping_Informations[IsoRdPayload].StartAddress - ISOReadDO.Offset;
            end_if;
            if pCurCheckModAccPtr^.ppData then
              // the data start after the header. at dynamic objects we have more header in write payload => data start after the structure                            
              pCurCheckModAccPtr^.ppData^$^void := ISOWriteDO.pData + gcWrite_DOL_Desc.iOffFirstData + sizeof(t_SDIAS_ControlByte) + gcMapping_Informations[IsoWrPayload].StartAddress - ISOWriteDO.Offset;
            end_if;            
            InitSSW := _WriteSetBroadCastAccess;
          else
            ErrorInitStep := InitSSW;
            InitSSW := _PrepareError;
            ClassState := _DOCmdInvalid;           
          end_if;    

//**********************************************************************************************************************************************************        
      _WriteSetBroadCastAccess:
         
          if ConnectionType = SDIAS_CON_VIA_VARAN_uC then
            ASYWriteDO.pData^$t_SDIAS_DOListEntryX2 := cModulAccessCmds;

            // Write data to manager dpram
            if ChangeAsyWr( Offset   := uiWriteCmdAddr, 
                            Length   := sizeof(cModulAccessCmds), 
                            RunState := _BUS_IF_RUN_STATE_SINGLE_RUN,
                            UsageType:= _UsedBySSW) then
              InitSSW := _WaitSetBroadCastAccess;
            end_if;
          else
            InitSSW := _WaitSetBroadCastAccess;
          end_if;         
      
//**********************************************************************************************************************************************************        
      _WaitSetBroadCastAccess:
      
        AsyWriteUsage  := _NotUsed;
        
        udCurCheckdMngAcc += 1;        
        if udCurCheckdMngAcc < SDIAS_NR_TIMEBROADCAST_DOS then
          InitSSW := _SetBroadCastAccess;
        else
          if ConnectionType = SDIAS_CON_VIA_VARAN_uC then
            InitSSW := _WriteDOL_Offsets;
          else
            // we don't have to reset the payload => done by OS                
            InitSSW := _SetStartConfigIsoRd;
          end_if;
        end_if;        
        
//**********************************************************************************************************************************************************
      _WriteDOL_Offsets:             
        
        // Create list informations 
        // Read list offsets
        iDataOffsets[0] := gcRead_DOL_Desc.iOffEndCmd;
        iDataOffsets[1] := gcRead_DOL_Desc.iOffLastData;
        
        // Write list offsets
        iDataOffsets[2] := gcWrite_DOL_Desc.iOffEndCmd;
        iDataOffsets[3] := gcWrite_DOL_Desc.iOffLastData;
        
        bReceivedNewEndRsp := FALSE;
#ifdef HWK_SHOW_PRAGMA_MESSAGES
#pragma message("RamAnd 23.11.2013 19:17 \ ein neues Ende muss nur geschrieben werden, wenn Spezialzugriffe angelegt wurden")
#endif
        if(AddSDOReq(pCmdSvr:= (#ClassState.pMeth)$^SvrChCmd, 
                     Command:= SDIAS_SDO_CMD_SET_NEW_END, 
                     Place:= SDIAS_MANAGER_PLACE, 
                     CmdLength:= 4* sizeof(UDINT), 
                     pReqBuf:= #iDataOffsets[0]$USINT) = READY$DINT) then
                     
           InitSSW := _WaitReq_DOL_Offsets;
        end_if; 
                    
//**********************************************************************************************************************************************************
      _WaitReq_DOL_Offsets:     
        // Wait until receiving request
        if bReceivedNewEndRsp = TRUE then
          bReceivedNewEndRsp := FALSE;

          InitSSW := _GetEventIDs;
        end_if;
      
//**********************************************************************************************************************************************************
      _GetEventIDs:
        if MaxPlace <> SDIAS_PLACE_NO_MODULE_ADDED_SO_FAR then
            // we also start a read access here, so we got the data in the next step
          if ChangeAsyRd(Offset:=SDIAS_OFFSET_TASK_EVENT_IDS, 
                         Length:=sizeof(t_TaskEventIDs), 
                         RunState:=_BUS_IF_RUN_STATE_SINGLE_RUN,
                         UsageType:=_UsedBySSW) then

            udCurCheckedMod := 0;
            InitSSW := _SetStartConfigIsoRd;
          end_if;
        else
#ifdef HWC_LogError
          HWC_LogError(this, "@004A (SdiasManager::CyWork) No SDIAS Client objects projected/connected to the SDIAS Manager! Unable to continue with Initialisation!");
#endif
          ErrorInitStep := InitSSW;
          InitSSW := _PrepareError;
          ClassState := _NoHardware;
        end_if;
      
//**********************************************************************************************************************************************************
      _SetStartConfigIsoRd:
        if ConnectionType = SDIAS_CON_VIA_VARAN_uC then
          TaskEventIDs := ASYReadDO.pData^$t_TaskEventIDs;
        else
          for i := 0 to 7 do
            if SDIAS_iGetNodePropertyIndex(hNodeHandle    := udNodeHandle
                                    , udIndex             := i
                                    , udPropertyId        := SDM_PROP_TASK_START_EVENT_ID,
                                    , pudPropertyValue    := (#TaskEventIDs[i])$^UDINT
                                    ) <> SDIAS_OK then
#ifdef HWC_LogValue1
              HWC_LogValue1(this, "@0054 (SdiasManager::CyWork) Failed to get task event ID 0x{0} via OS interface!", i);
#endif
              ErrorInitStep := InitSSW;
              InitSSW := _PrepareError;
              ClassState := _ManagerError; 
              return;
            end_if;
          end_for;
        end_if;

        AsyReadUsage  := _NotUsed;

        // search for the sync out 0 event id      
        b_FoundIt := FALSE;
        for i := 0 to 7 do
          if ConnectionType = SDIAS_CON_VIA_VARAN_uC then
            if TaskEventIDs[i] = SDIAS_EVENT_MASK_ID_SYNC_OUT0 then
              b_FoundIt := TRUE;
              exit;
            end_if;
          elsif pPLL then          
            if (TaskEventIDs[i] AND 16#F0) = 16#10 then
              // sync out is connected, take lower nibble as syncout index
              if PLL_iGetSyncOutProperty(pPLL, ud_NodeHandlePLL, (TaskEventIDs[i] AND 16#0F), PLL_PROP_SO_SYNC_OUT_ID, #TempUDINT) = PLL_OK then
                if TempUDINT = SDIAS_MANAGER_SYNC_SYNCOUT_ID then
                  b_FoundIt := TRUE;
                  exit;
                end_if;
              end_if;
            end_if;
          else
            // for CPUs without PLL interface
            if TaskEventIDs[i] = SDIAS_EVENT_MASK_ID_SYNC_OUT2 then
              b_FoundIt := TRUE;
              exit;
            end_if;            
          end_if;
        end_for;

        // if we found it, use it for the task start config 0 (which is used by the iso read task)
        if b_FoundIt then
          TaskStartConfig.EventSelection := 1 SHL i$USINT;

          // iso read starts 0µs after the sync
          TaskStartConfig.StartDelay_us  := 0;

          if ConnectionType = SDIAS_CON_VIA_VARAN_uC then
            ASYWriteDO.pData^$t_TaskStartConfig := TaskStartConfig;
            if ChangeAsyWr(Offset:=SDIAS_OFFSET_TASK_START_CFG_0, 
                           Length:=sizeof(t_TaskStartConfig), 
                           RunState:=_BUS_IF_RUN_STATE_SINGLE_RUN,
                           UsageType:=_UsedBySSW) then
                                  
             InitSSW := _SelectTaskStartConfigIsoRd;
            end_if;
          else
            aProperties[0].udPropertyId     := SDM_PROP_TASK_START_CONFIG_WAIT_EVENTS;
            aProperties[0].udPropertyValue  := TaskStartConfig.EventSelection;

            aProperties[1].udPropertyId     := SDM_PROP_TASK_START_CONFIG_DELAY;
            aProperties[1].udPropertyValue  := TaskStartConfig.StartDelay_us;

            if SDIAS_iSetNodePropertiesIndex(hNodeHandle      := udNodeHandle
                                           , udIndex               := 0
                                           , udPropertyCount       := 2
                                           , psPropertyValuePairs  := #aProperties[0]
                                           ) = SDIAS_OK then
              InitSSW := _SelectTaskStartConfigIsoRd;
            else
#ifdef HWC_LogError
              HWC_LogError(this, "@005E (SdiasManager::CyWork) Failed to set the iso read start config via OS interface!");
#endif
              ErrorInitStep := InitSSW;
              InitSSW := _PrepareError;
              ClassState := _ManagerError; 
            end_if;
          end_if;
        else
#ifdef HWC_LogError
          HWC_LogError(this, "@0055 (SdiasManager::CyWork) Couldn't find event mask of sync out 0! Unable to continue with Initialisation!");
#endif
          ClassState := _ComponentNotExists;
          ErrorInitStep := InitSSW;
          InitSSW := _PrepareError;
        end_if;

//**********************************************************************************************************************************************************
      _SelectTaskStartConfigIsoRd:
        // search for the iso read entry in the info block
        b_FoundIt := FALSE;
        for i := 0 to ManagerInfoBlock.MappingInfo.MappingInfoNo-1 do
          if ManagerInfoBlock.MappingInfo.aMappingInfos[i].MappingID = IsoRdList then
            b_FoundIt := TRUE;
            exit;
          end_if;
        end_for;

        // if we found it, use the offset in the task configuration
        if b_FoundIt then
          // set the task duration limit
          TaskConfig.TaskDurationTimeout_us := (ud_BusTime_ns / 1000)$UINT;
#ifdef HWK_SHOW_PRAGMA_MESSAGES
#pragma message("RamAnd 21.10.2013 17:46 \ Timeoutzeit überdenken. hier kann normalerweise kein ganzer Buszyklus verwendet werden (IsoStartpoint miteinbeziehen)")
#endif

          // start address of iso read list
          TaskConfig.Config := ManagerInfoBlock.MappingInfo.aMappingInfos[i].StartAddress;
          
          // now select the start configuration 0 (should already be selected, just check it)
          if TaskConfig.Config AND 2#1111 then
            // in this case the start address of the list is not 16 byte aligned
#ifdef HWC_LogError
            HWC_LogError(this, "@0056 (SdiasManager::CyWork) The start address of the isochronous read DO List is not 16 byte aligned! Unable to continue with Initialisation!");
#endif
            ClassState := _MemoryFault;
            ErrorInitStep := InitSSW;
            InitSSW := _PrepareError;
            return;
          end_if;
          
          // we want to use the start configuration => enable it later in realtime
          TaskConfig.Config.SynchronizedStartEnable := FALSE;

          if ConnectionType = SDIAS_CON_VIA_VARAN_uC then          
            ASYWriteDO.pData^$t_TaskConfig := TaskConfig;
            
            if ChangeAsyWr(Offset:=SDIAS_OFFSET_TASK_CONFIG_1, 
                           Length:=sizeof(t_TaskConfig), 
                           RunState:=_BUS_IF_RUN_STATE_SINGLE_RUN,
                           UsageType:=_UsedBySSW) then

              InitSSW := _SelectTaskStartConfigIsoWr; 
            end_if;
          else
            aProperties[0].udPropertyId     := SDM_PROP_TASK_CONTROL_DURATION_TIMEOUT;
            aProperties[0].udPropertyValue  := TaskConfig.TaskDurationTimeout_us;

            aProperties[1].udPropertyId     := SDM_PROP_TASK_CONTROL_CONFIGURATION;
            aProperties[1].udPropertyValue  := TaskConfig.Config;

            if SDIAS_iSetNodePropertiesIndex(hNodeHandle      := udNodeHandle
                                      , udIndex               := 1
                                      , udPropertyCount       := 2
                                      , psPropertyValuePairs  := #aProperties[0]
                                      ) = SDIAS_OK then
              InitSSW := _SelectTaskStartConfigIsoWr;
            else
#ifdef HWC_LogError
              HWC_LogError(this, "@005E (SdiasManager::CyWork) Failed to set the iso read start config via OS interface!");
#endif
              ErrorInitStep := InitSSW;
              InitSSW := _PrepareError;
              ClassState := _ManagerError; 
            end_if;

          end_if;
        else
#ifdef HWC_LogError
          HWC_LogError(this, "@0057 (SdiasManager::CyWork) Couldn't find iso read entry in info block! Unable to continue with Initialisation!");
#endif
          ClassState := _ComponentNotExists;
          ErrorInitStep := InitSSW;
          InitSSW := _PrepareError;
        end_if;

//**********************************************************************************************************************************************************
      _SelectTaskStartConfigIsoWr:
        // search for the iso write entry in the info block
        b_FoundIt := FALSE;
        for i := 0 to ManagerInfoBlock.MappingInfo.MappingInfoNo-1 do
          if ManagerInfoBlock.MappingInfo.aMappingInfos[i].MappingID = IsoWrList then
            b_FoundIt := TRUE;
            exit;
          end_if;
        end_for;

        // if we found it, use the offset in the task configuration
        if b_FoundIt then
          // set the task duration limit
          TaskConfig.TaskDurationTimeout_us := (ud_BusTime_ns / 1000)$UINT;

          // start address of iso write list
          TaskConfig.Config := ManagerInfoBlock.MappingInfo.aMappingInfos[i].StartAddress;

          if ConnectionType = SDIAS_CON_VIA_VARAN_uC then          
            ASYWriteDO.pData^$t_TaskConfig := TaskConfig;
            
            if ChangeAsyWr(Offset:=SDIAS_OFFSET_TASK_CONFIG_2, 
                           Length:=sizeof(t_TaskConfig), 
                           RunState:=_BUS_IF_RUN_STATE_SINGLE_RUN,
                           UsageType:=_UsedBySSW) then

              InitSSW := _SetTriggerUnits; 
            end_if;
          else
            aProperties[0].udPropertyId     := SDM_PROP_TASK_CONTROL_DURATION_TIMEOUT;
            aProperties[0].udPropertyValue  := TaskConfig.TaskDurationTimeout_us;

            aProperties[1].udPropertyId     := SDM_PROP_TASK_CONTROL_CONFIGURATION;
            aProperties[1].udPropertyValue  := TaskConfig.Config;

            if SDIAS_iSetNodePropertiesIndex(hNodeHandle      := udNodeHandle
                                      , udIndex               := 2
                                      , udPropertyCount       := 2
                                      , psPropertyValuePairs  := #aProperties[0]
                                      ) = SDIAS_OK then
                                      
              InitSSW := _SetTriggerUnits;
            else
#ifdef HWC_LogError
              HWC_LogError(this, "@005E (SdiasManager::CyWork) Failed to set the iso read start config via OS interface!");
#endif
              ErrorInitStep := InitSSW;
              InitSSW := _PrepareError;
              ClassState := _ManagerError; 
            end_if;
          end_if;
        else
#ifdef HWC_LogError
          HWC_LogError(this, "@0058 (SdiasManager::CyWork) Couldn't find iso write entry in info block! Unable to continue with Initialisation!");
#endif
          ClassState := _ComponentNotExists;
          ErrorInitStep := InitSSW;
          InitSSW := _PrepareError;
        end_if;

//**********************************************************************************************************************************************************
      _SetTriggerUnits:
        // configure trigger unit 0 (use it for both iso tasks)
        TriggerUnitSetup[0].TaskSelect := 0;
        TriggerUnitSetup[0].TaskSelect.IsoWrite := TRUE;
        TriggerUnitSetup[0].TaskSelect.IsoRead  := FALSE; // for read task it's set later in realtime

        TriggerUnitSetup[0].StartAddress := ISOWriteDO.Offset; // trigger unit size has already been subtracted before
        TriggerUnitSetup[0].StartAddress.UnitEnable := TRUE;
        
        // configure trigger unit 1 for direct access
        TriggerUnitSetup[1].TaskSelect := 0;
        TriggerUnitSetup[1].TaskSelect.DirectAccess := TRUE;

        // search for the direct access read entry in the info block
        b_FoundIt := FALSE;
        for i := 0 to ManagerInfoBlock.MappingInfo.MappingInfoNo-1 do
          if ManagerInfoBlock.MappingInfo.aMappingInfos[i].MappingID = DAWrPayload then
            b_FoundIt := TRUE;
            exit;
          end_if;
        end_for;

        if b_FoundIt then
          TriggerUnitSetup[1].StartAddress := ManagerInfoBlock.MappingInfo.aMappingInfos[i].StartAddress;
          TriggerUnitSetup[1].StartAddress.UnitEnable := TRUE;
          
          WriteLength := sizeof(t_TriggerUnitSetupX2);
        else
          WriteLength := sizeof(t_TriggerUnitSetup);
#ifdef HWC_LogError
          HWC_LogError(this, "@0059 (SdiasManager::CyWork) Couldn't find the Direct Access Write Payload info in the module mapping");
#endif
        end_if;

        if ConnectionType = SDIAS_CON_VIA_VARAN_uC then

          // if the µC detects the setting on this address, it will stop to start the task in a loop (it starts again if the execution request 
          ASYWriteDO.pData^$t_TriggerUnitSetupX2 := TriggerUnitSetup;
          if ChangeAsyWr(Offset:=SDIAS_OFFSET_TRIGGER_UNIT_SETUP_0, 
                         Length:=WriteLength, 
                         RunState:=_BUS_IF_RUN_STATE_SINGLE_RUN,
                         UsageType:=_UsedBySSW) then

#pragma warning(disable: 74)
            // for local SDIAS we set the enable bit for the watchdog trigger DO (must be enabled always)
            TempControlByte := 0;
            TempControlByte.EnableDO := TRUE;
#pragma warning(default: 74)
            (ISOWriteDO.pData$^t_SDIAS_ControlByte + SDIAS_TRIGGER_UNIT_BYTE_SIZE)^ := TempControlByte;  

            b_WdTriggerActive := TRUE;
            ud_LastWdTime := ops.tAbsolute - SDIAS_WATCHDOG_TRIGGER_TIME - 1; // start with first watchdog now

            InitSSW := _WriteDAList;
          end_if;
        else
          aProperties[0].udPropertyId     := SDM_PROP_TASK_TRIGGER_UNIT_CONTROL;
          aProperties[0].udPropertyValue  := to_udint(TriggerUnitSetup[0].TaskSelect);

          aProperties[1].udPropertyId     := SDM_PROP_TASK_TRIGGER_UNIT_START_ADDR_RANGE;
          aProperties[1].udPropertyValue  := to_udint(TriggerUnitSetup[0].StartAddress);
          
          if SDIAS_iSetNodePropertiesIndex(hNodeHandle          := udNodeHandle
                                          , udIndex             := 0
                                          , udPropertyCount     := 2
                                          , psPropertyValuePairs:= #aProperties[0]
                                          ) = SDIAS_OK then

            aProperties[0].udPropertyId     := SDM_PROP_TASK_TRIGGER_UNIT_CONTROL;
            aProperties[0].udPropertyValue  := to_udint(TriggerUnitSetup[1].TaskSelect);

            aProperties[1].udPropertyId     := SDM_PROP_TASK_TRIGGER_UNIT_START_ADDR_RANGE;
            aProperties[1].udPropertyValue  := to_udint(TriggerUnitSetup[1].StartAddress);
            
            if SDIAS_iSetNodePropertiesIndex(hNodeHandle          := udNodeHandle
                                            , udIndex             := 1
                                            , udPropertyCount     := 2
                                            , psPropertyValuePairs:= #aProperties[0]
                                            ) = SDIAS_OK then

#pragma warning(disable: 74)
              // for local SDIAS we set the enable bit for the watchdog trigger DO (must be enabled always)
              TempControlByte := 0;
              TempControlByte.EnableDO := TRUE;
#pragma warning(default: 74)
              (ISOWriteDO.pData$^t_SDIAS_ControlByte + SDIAS_TRIGGER_UNIT_BYTE_SIZE)^ := TempControlByte;  

              b_WdTriggerActive := TRUE;
              ud_LastWdTime := ops.tAbsolute - SDIAS_WATCHDOG_TRIGGER_TIME - 1; // start with first watchdog now

              InitSSW := _WriteDAList;
            else
#ifdef HWC_LogError
              HWC_LogError(this, "@005A (SdiasManager::CyWork) Failed to make the trigger unit 2 settings via OS interface!");
#endif
              ErrorInitStep := InitSSW;
              InitSSW := _PrepareError;
              ClassState := _ManagerError; 
            end_if;
          else
#ifdef HWC_LogError
            HWC_LogError(this, "@005B (SdiasManager::CyWork) Failed to make the trigger unit 1 settings via OS interface!");
#endif
            ErrorInitStep := InitSSW;
            InitSSW := _PrepareError;
            ClassState := _ManagerError; 
          end_if;
        end_if;
        
//**********************************************************************************************************************************************************
      _WriteDAList:
        // clear the list
        _memset(dest:=#DAListOfDOs, usByte:=0, cntr:=sizeof(DAListOfDOs));

        // initialize the module select array for module initialisation (maybe there are less modules to initialize than SDO channels available)
        NextPlace := 0;
        for i := 0 to SDIAS_SDO_CHANNEL_NO-1 do
          ActModule[i] := SDIAS_PLACE_NO_MODULE_ADDED_SO_FAR;
        end_for;

        // setup the command (memory access with 2 retries)
        DAListOfDOs[0].CmdRetries := 1 OR (2 SHL 5);
        
        // search for the da read payload entry in the info block
        b_FoundIt := FALSE;
        for i := 0 to ManagerInfoBlock.MappingInfo.MappingInfoNo-1 do
          if ManagerInfoBlock.MappingInfo.aMappingInfos[i].MappingID = DARdPayload then
            DAListOfDOs[0].OffsetReadPayload := ManagerInfoBlock.MappingInfo.aMappingInfos[i].StartAddress;
            b_FoundIt := TRUE;
            exit;
          end_if;
        end_for;

        if b_FoundIt = FALSE then
#ifdef HWC_LogError
          HWC_LogError(this, "@005C (SdiasManager::CyWork) Couldn't find the Direct Access Read Payload info in the module mapping");
#endif
          InitSSW := _DeactivateSyncInjection;
          return;
        else
          b_FoundIt := FALSE;
        end_if;

        // search for the da write payload entry in the info block
        b_FoundIt := FALSE;
        for i := 0 to ManagerInfoBlock.MappingInfo.MappingInfoNo-1 do
          if ManagerInfoBlock.MappingInfo.aMappingInfos[i].MappingID = DAWrPayload then
            DAListOfDOs[0].OffsetWritePayload := ManagerInfoBlock.MappingInfo.aMappingInfos[i].StartAddress;
            b_FoundIt := TRUE;
            exit;
          end_if;
        end_for;

        if b_FoundIt = FALSE then
#ifdef HWC_LogError
          HWC_LogError(this, "@0059 (SdiasManager::CyWork) Couldn't find the Direct Access Write Payload info in the module mapping");
#endif
          InitSSW := _DeactivateSyncInjection;
          return;
        else
          b_FoundIt := FALSE;
        end_if;

        // search for the da list entry in the info block
        b_FoundIt := FALSE;
        for i := 0 to ManagerInfoBlock.MappingInfo.MappingInfoNo-1 do
          if ManagerInfoBlock.MappingInfo.aMappingInfos[i].MappingID = DAList then
            DAListOfDOs[0].OffsetWritePayload := ManagerInfoBlock.MappingInfo.aMappingInfos[i].StartAddress;
            b_FoundIt := TRUE;
            exit;
          end_if;
        end_for;

        if b_FoundIt = FALSE then
#ifdef HWC_LogError
          HWC_LogError(this, "@005D (SdiasManager::CyWork) Couldn't find the Direct Access DO list info in the module mapping");
#endif
          InitSSW := _DeactivateSyncInjection;
          return;
        end_if;

        if ConnectionType = SDIAS_CON_VIA_VARAN_uC then          
          // reset direct access read payload (toggle bits, error info)
          if ChangeAsyWr(Offset:=ManagerInfoBlock.MappingInfo.aMappingInfos[i].StartAddress, 
                         Length:=128, 
                         RunState:=_BUS_IF_RUN_STATE_SINGLE_RUN,
                         UsageType:=_UsedBySSW) then

            InitSSW := _ResetDARdPayload; 
          end_if;
        else
          // OS already did this => skip the next step
          InitSSW := _ConfigDATask; 
        end_if;

//**********************************************************************************************************************************************************
      _ResetDARdPayload:

        // reset the write buffer
        _memset(dest:=ASYWriteDO.pData, usByte:=0, cntr:=128);

        // search for the da read payload entry in the info block
        b_FoundIt := FALSE;
        for i := 0 to ManagerInfoBlock.MappingInfo.MappingInfoNo-1 do
          if ManagerInfoBlock.MappingInfo.aMappingInfos[i].MappingID = DARdPayload then
            DAListOfDOs[0].OffsetReadPayload := ManagerInfoBlock.MappingInfo.aMappingInfos[i].StartAddress;
            b_FoundIt := TRUE;
            exit;
          end_if;
        end_for;

        if b_FoundIt = FALSE then
#ifdef HWC_LogError
          HWC_LogError(this, "@005C (SdiasManager::CyWork) Couldn't find the Direct Access Read Payload info in the module mapping");
#endif
          InitSSW := _DeactivateSyncInjection;
          return;
        end_if;

        // reset direct access read payload (toggle bits, error info)
        if ChangeAsyWr(Offset:=ManagerInfoBlock.MappingInfo.aMappingInfos[i].StartAddress, 
                       Length:=128, 
                       RunState:=_BUS_IF_RUN_STATE_SINGLE_RUN,
                       UsageType:=_UsedBySSW) then

          InitSSW := _ConfigDATask; 
        end_if;

//**********************************************************************************************************************************************************
      _ConfigDATask:      
        // search for the da list entry in the info block
        b_FoundIt := FALSE;
        for i := 0 to ManagerInfoBlock.MappingInfo.MappingInfoNo-1 do
          if ManagerInfoBlock.MappingInfo.aMappingInfos[i].MappingID = DAList then
            DAListOfDOs[0].OffsetWritePayload := ManagerInfoBlock.MappingInfo.aMappingInfos[i].StartAddress;
            b_FoundIt := TRUE;
            exit;
          end_if;
        end_for;

        // if we found it, use the offset in the task configuration
        if b_FoundIt then
          // initialize the write buffer for the direct access (the parts which stay the same)
          DaWriteBuffer.ContolByte := 0;
          DaWriteBuffer.ContolByte.EnableDO := TRUE;
          DaWriteBuffer.ContolByte.EnableFlexRead := TRUE;
          DaWriteBuffer.ContolByte.EnableFlexWrite := TRUE;
        
          // set the task duration limit
          TaskConfig.TaskDurationTimeout_us := (ud_BusTime_ns / 1000)$UINT;
        
          // start address of iso read list
          TaskConfig.Config := ManagerInfoBlock.MappingInfo.aMappingInfos[i].StartAddress;

          if ConnectionType = SDIAS_CON_VIA_VARAN_uC then          

            ASYWriteDO.pData^$t_TaskConfig := TaskConfig;
            
            if ChangeAsyWr(Offset:=SDIAS_OFFSET_TASK_CONFIG_0, 
                           Length:=sizeof(t_TaskConfig), 
                           RunState:=_BUS_IF_RUN_STATE_SINGLE_RUN,
                           UsageType:=_UsedBySSW) then

              InitSSW := _DeactivateSyncInjection;
            end_if;
          else
            aProperties[0].udPropertyId     := SDM_PROP_TASK_CONTROL_DURATION_TIMEOUT;
            aProperties[0].udPropertyValue  := TaskConfig.TaskDurationTimeout_us;

            aProperties[1].udPropertyId     := SDM_PROP_TASK_CONTROL_CONFIGURATION;
            aProperties[1].udPropertyValue  := TaskConfig.Config;

            if SDIAS_iSetNodePropertiesIndex(hNodeHandle      := udNodeHandle
                                      , udIndex               := 0
                                      , udPropertyCount       := 2
                                      , psPropertyValuePairs  := #aProperties[0]
                                      ) = SDIAS_OK then
              InitSSW := _DeactivateSyncInjection;
            else
#ifdef HWC_LogError
              HWC_LogError(this, "@005E (SdiasManager::CyWork) Failed to set the iso read start config via OS interface!");
#endif
              ErrorInitStep := InitSSW;
              InitSSW := _PrepareError;
              ClassState := _ManagerError; 
            end_if;
          end_if;
        else
#ifdef HWC_LogError
          HWC_LogError(this, "@005D (SdiasManager::CyWork) Couldn't find the Direct Access DO list info in the module mapping");
#endif
          
          InitSSW := _DeactivateSyncInjection;
        end_if;

//**********************************************************************************************************************************************************
      _DeactivateSyncInjection:
        // we select the read task for sync, there are no sync task trigger losses allowed and we leave the sync disabled
        SyncInjectionCfg := 16#02;
      
        if ConnectionType = SDIAS_CON_VIA_VARAN_uC then          
          ASYWriteDO.pData^$t_SyncInjectionCfg := SyncInjectionCfg;
          
          if ChangeAsyWr(Offset:=SDIAS_OFFSET_SYNC_INJECTION_CFG, 
                         Length:=sizeof(t_SyncInjectionCfg), 
                         RunState:=_BUS_IF_RUN_STATE_SINGLE_RUN,
                         UsageType:=_UsedBySSW) then

            InitSSW := _PrepareModuleInitialisation;
          end_if;
        else
          aProperties[0].udPropertyId     := SDM_PROP_SYNC_INJECTION_CONFIG;
          aProperties[0].udPropertyValue  := SyncInjectionCfg;

          if SDIAS_iSetNodeProperties(hNodeHandle         := udNodeHandle
                                    , udPropertyCount     := 1
                                    , psPropertyValuePairs:= #aProperties[0]
                                    ) = SDIAS_OK then
            InitSSW := _PrepareModuleInitialisation;
          else
#ifdef HWC_LogError
            HWC_LogError(this, "@005F (SdiasManager::CyWork) Failed to deactivate sync injection via OS interface!");
#endif
            ErrorInitStep := InitSSW;
            InitSSW := _PrepareError;
            ClassState := _ManagerError; 
          end_if;
        end_if;

//**********************************************************************************************************************************************************
      _PrepareModuleInitialisation:
        //reset usage type of asynchrone read and write because it could be used at next step (_ModuleInitialisation) for module initialisation
        AsyReadUsage  := _NotUsed;
        AsyWriteUsage := _NotUsed;

        // wait for varan Manager to be ready, otherwise we can't get the module out of reset state
        if (ConnectionType = SDIAS_CON_VIA_VARAN_uC) & (b_PostInitFinished = FALSE) then
          // only if we're still in post init
          if b_PostInitFinished = FALSE then
            // tell the manager we're finished with DO creation
            tempCmd.uiCmd := _BUS_IF_DO_CREATION_FINISHED;
            ToBusInterface.NewInst(pPara:=#tempCmd, pResult:=#_result);
          end_if;

          if _result.aData[0]$t_BusIFRetvalErrorcode <> _BUS_IF_RETVAL_OK then
#ifdef HWC_LogError
            HWC_LogError(this, "@0060 (SdiasManager::CyWork) Failed to tell the manager that the DOs have been created");
#endif
          end_if;

          InitSSW := _Wait4OtherModules;        
        else
          InitSSW := _Wait4HardwareReady;
        end_if;
        
//**********************************************************************************************************************************************************
      _Wait4OtherModules:
        // wait until all sdias managers have created their DOs => needed to create the Mov-DOs which copy safety SPDOs between the modules
        tempCmd.uiCmd := _BUS_IF_DO_MEM_READY;
        ToBusInterface.NewInst(pPara:=#tempCmd, pResult:=#_result);

        if _result.aData[0]$t_BusIFRetvalErrorcode <> _BUS_IF_RETVAL_OK then
#ifdef HWC_LogError
          HWC_LogError(this, "@0060 (SdiasManager::CyWork) Failed to tell the manager that the DOs have been created");
#endif
        else
          // if they are ready => continue
          if _result.aData[4] then      

            // if the ISO DOs were created in this initialisation run => create move DOs
            if b_IsoDOsJustCreated then
              b_IsoDOsJustCreated := FALSE;

              // create move DOs
              tempCmd.uiCmd := SDIAS_CMD_DATA_POINTER_AVAILABLE;
              pModuleInfo := #ModuleObjInfo[0];
              for i := 0 to MaxPlace do
                // check only the available objects
                if pModuleInfo^.pThis then
                  if pModuleInfo^.pThis^.NewInst(pPara:=#tempCmd, pResult:=#_result) <> READY then
#ifdef HWC_LogValue1
                    HWC_LogValue1(this, "@0061 (SdiasManager::CyWork) Initialisation of module at place 0x{0} failed! (Data pointers were available)", i);
#endif
                  end_if;
                end_if;

                pModuleInfo += sizeof(t_ModuleObjectInfo);
              end_for;
            end_if;

            // tell the manager we're finished with DO creation
            tempCmd.uiCmd := _BUS_IF_MOVE_DO_CREATION_FINISHED;
            ToBusInterface.NewInst(pPara:=#tempCmd, pResult:=#_result);

            InitSSW := _Wait4VaranManager;
          end_if;
        end_if;

//**********************************************************************************************************************************************************
      _Wait4VaranManager:
        // wait until all sdias managers have created their move DOs => needed to create the Mov-DOs which copy safety SPDOs between the modules
        tempCmd.uiCmd := _BUS_IF_MOVE_DO_MEM_READY;
        ToBusInterface.NewInst(pPara:=#tempCmd, pResult:=#_result);

        if _result.aData[0]$t_BusIFRetvalErrorcode <> _BUS_IF_RETVAL_OK then
#ifdef HWC_LogError
          HWC_LogError(this, "@0062 (SdiasManager::CyWork) Failed to tell the manager that the Move DOs have been created");
#endif
        else
          // if they are ready => continue
          if _result.aData[4] then
            InitSSW := _Wait4HardwareReady;
          end_if;
        end_if;
        
//**********************************************************************************************************************************************************
      _Wait4HardwareReady:
        // wait until init is finished and the modules are no longer in reset state (takes about 10ms, we wait 15ms)
        if DOStartTime & ((ops.tAbsolute - DOStartTime) >= SDIAS_HARDWARE_STARTUP_TIME) then
        
          // Find the first Module to initialize
          // Search before the loop over SDIAS_SDO_CHANNEL_NO, otherwise 1 channel will be unused.
          if ((ModuleObjInfo[NextPlace].pThis = NIL) | (ModuleObjInfo[NextPlace].pInitState^ <> _NotInitialized)) & MaxPlace then
            repeat
              // skip places, where we don't have to initialize something
              NextPlace += 1;          
            until (ModuleObjInfo[NextPlace].pThis & (ModuleObjInfo[NextPlace].pInitState^ = _NotInitialized)) | (NextPlace = MaxPlace) end_repeat;
          end_if;
          
          // select the first x modules to initialize (x = number of available SDO channels)
          for i := 0 to SDIAS_SDO_CHANNEL_NO-1 do
            if ModuleObjInfo[NextPlace].pThis & (ModuleObjInfo[NextPlace].pInitState^ = _NotInitialized) then
              ActModule[i] := NextPlace;
              LastSelected := NextPlace;
              ModuleInitStartTime[i] := OS_READMICROSEC();
              if NextPlace < MaxPlace then
                repeat
                  // skip places, where we don't have to initialize something
                  NextPlace += 1;          
                until (ModuleObjInfo[NextPlace].pThis & (ModuleObjInfo[NextPlace].pInitState^ = _NotInitialized)) | (NextPlace = MaxPlace) end_repeat;
              else
                exit;
              end_if;
            elsif (NextPlace < MaxPlace) then
              repeat
                // skip places, where we don't have to initialize something
                NextPlace += 1;          
              until (ModuleObjInfo[NextPlace].pThis & (ModuleObjInfo[NextPlace].pInitState^ = _NotInitialized)) | (NextPlace = MaxPlace) end_repeat;
            end_if;
          end_for;
          
          // remember the last selected number to continue there in the next step
          NextPlace := LastSelected;

          InitSSW := _ModuleInitialisation;
        end_if;
        
//**********************************************************************************************************************************************************
      _ModuleInitialisation:
        // we can only initialize the modules if both asynchronous accesses are available
        if (AsyReadUsage = _NotUsed) & (AsyWriteUsage = _NotUsed) then
                
          // preinitialize the complete marker => is resetted if a module has to be initialized
          b_ModulInitComplete := TRUE;

          // post init blocks the tasks in cyclic priority (the SDIAS Manager Code is running in lower priority than cyclic and has no time during the postinit) => give it some time
          if (b_PostInitFinished = FALSE) then
            ToMultiTask.TASKDELAY(timeout0:=SDIAS_WAIT_TIME_IN_POST_INIT);
          end_if;

          // work parallel on all available channels
          for i := 0 to SDIAS_SDO_CHANNEL_NO-1 do
            b_ModulInitFinished := FALSE;
            // if we have selected a module at this position => initialize it
            if ActModule[i] <> SDIAS_PLACE_NO_MODULE_ADDED_SO_FAR then
              b_ModulInitComplete := FALSE;
            
              RetcodeIPR := ModuleObjInfo[ActModule[i]].pThis^.InitModule();
                  
              if RetcodeIPR = ERROR then
#ifdef HWC_LogValue1
                HWC_LogValue1(this, "@0063 (SdiasManager::CyWork) Failed to initialize module on SDIAS Place 0x{0} via InitModule-Interface", ActModule[i]);
#endif
                
                // if it's an required module => error
                if ModuleObjInfo[ActModule[i]].Required then
                  SetRequiredError(pTargetThis:=ModuleObjInfo[ActModule[i]].pThis, Place:=ActModule[i]);
                else
                  //otherwise continue with the next module
                  b_ModulInitFinished := TRUE;
                end_if;
              elsif RetcodeIPR = READY then
                b_ModulInitFinished := TRUE;
              end_if;
              
              if b_ModulInitFinished then
                // save duration for this module
                TempTime := OS_READMICROSEC();
                ModuleObjInfo[ActModule[i]].ModuleInitDuration_us := TempTime - ModuleInitStartTime[i];
                ModuleInitStartTime[i] := TempTime;
                
                if NextPlace < MaxPlace then
                  repeat
                    // skip places, where we don't have to initialize something
                    NextPlace += 1;          
                  until (ModuleObjInfo[NextPlace].pThis & (ModuleObjInfo[NextPlace].pInitState^ = _NotInitialized)) | (NextPlace = MaxPlace) end_repeat;
                  
                  // if we found something to initialize
                  if (ModuleObjInfo[NextPlace].pThis & (ModuleObjInfo[NextPlace].pInitState^ = _NotInitialized)) then
                    // remember it
                    ActModule[i] := NextPlace;
                  else
                    // otherwise we reached max place
                    ActModule[i] := SDIAS_PLACE_NO_MODULE_ADDED_SO_FAR;
                  end_if;
                else
                  // reached max place
                  ActModule[i] := SDIAS_PLACE_NO_MODULE_ADDED_SO_FAR;
                end_if;
              end_if;
            end_if;
          end_for;
          
          if b_ModulInitComplete then
            InitSSW := _SetActualLEDStates;
          end_if;
        end_if;

//**********************************************************************************************************************************************************
      _SetActualLEDStates:        
        // asy write DO can now be used for other purposes (will be used for LEDs)
        AsyWriteUsage := _NotUsed;

        // write the LED States to the Hardware
        b_NewLEDStates := TRUE;

        InitSSW := _FinishInitialisation;
        
//**********************************************************************************************************************************************************
      _FinishInitialisation:
        // tell the manager that we're finished with initializing
        if b_PostInitFinished = FALSE then
          SendPostInitFinished();
        end_if;

        // now that we're finished, we take the Bitmap from the OS:
        // At plug in during runtime it will detect the connect-event later, therefore we take the new and the old value from OS => then we don't detect a disconnect because of this delay
        OldDeviceBitmap := HardwareConfig.DeviceBitmap;
        sd_retval := SDIAS_iGetBitmapOfDevices(uiMaster:=0, pucNode:=pHwPath, udBufferLength:=8, pucData:=(#HardwareConfig.DeviceBitmap)$^USINT);
        
        if sd_retval & (CyclicMsgMarker.AlreadyPosted.GetDeviceBitmap = FALSE) then
#ifdef HWC_LogValue1
          HWC_LogValue1(this, "@0049 (SdiasManager::CyWork) [SL] SDIAS_iGetBitmapOfDevices failed with error code -0x{0}", ABS(sd_retval)$UDINT);
#endif
          CyclicMsgMarker.AlreadyPosted.GetDeviceBitmap := TRUE;
        end_if;

        InitDuration := ops.tAbsolute - InitStartTime;

        InitSSW := _WaitForRtOperational;

        // now we're ready to start the DOs
        RtSSW := _Wait4DOs;
        b_Ready4Rt := TRUE;

//**********************************************************************************************************************************************************
      _WaitForRtOperational:
        // wait to get finished by rt ssw
        
        // this step is to continue calling the cyclic for watchdog triggering but not call the single modules because that could lead to SDO timeouts
          
//**********************************************************************************************************************************************************
      _InitFinished:
        if MaxPlace <> SDIAS_PLACE_NO_MODULE_ADDED_SO_FAR then
          // refresh global SDIAS retry counter
          pModuleInfo := #ModuleObjInfo[0];
          for i := 0 to MaxPlace do
            if pModuleInfo^.pThis & (pModuleInfo^.pThis^.ClassState <> _NoHardware) & (pModuleInfo^.pThis^.ClassState <> _WrongHardware) then
              // update retrycounter
              if (pModuleInfo^.pThis^.RetryCounter > pModuleInfo^.OldRetryCounter) then
                RetryCounter += pModuleInfo^.pThis^.RetryCounter - pModuleInfo^.OldRetryCounter;
                pModuleInfo^.OldRetryCounter := pModuleInfo^.pThis^.RetryCounter;
              end_if;
              
              // call cywork of all objects which are marked for a cyclic call
              if pModuleInfo^.bCyclic then
                pModuleInfo^.pThis^.UpdateCy();
              end_if;
            end_if;
            pModuleInfo += sizeof(t_ModuleObjectInfo);
          end_for;
          
          // check for a change of the hardware configuration (should be plug and play)
          sd_retval := SDIAS_iGetBitmapOfDevices(uiMaster:=0, pucNode:=pHwPath, udBufferLength:=8, pucData:=(#HardwareConfig.DeviceBitmap)$^USINT);
          if sd_retval & (CyclicMsgMarker.AlreadyPosted.GetDeviceBitmap = FALSE) then
#ifdef HWC_LogValue1
            HWC_LogValue1(this, "@0049 (SdiasManager::CyWork) [SL] SDIAS_iGetBitmapOfDevices failed with error code -0x{0}", ABS(sd_retval)$UDINT);
#endif
            CyclicMsgMarker.AlreadyPosted.GetDeviceBitmap := TRUE;
          end_if;
          
          if HardwareConfig.DeviceBitmap <> OldDeviceBitmap then            
            // check for changes from 1 to 0 (module removed) and if the removed module is required
            CompareBitmap[0] := HardwareConfig.DeviceBitmap[0] XOR 16#FFFFFFFF; // we want only the 0s in the new bitmap
            CompareBitmap[1] := HardwareConfig.DeviceBitmap[1] XOR 16#FFFFFFFF; // we want only the 0s in the new bitmap
            
            ResultBitmap[0] := OldDeviceBitmap[0] AND CompareBitmap[0]; // now we check for the 1=>0 switch
            ResultBitmap[1] := OldDeviceBitmap[1] AND CompareBitmap[1]; // now we check for the 1=>0 switch
            
            // if a module has been plugged off
            if ResultBitmap[0] | ResultBitmap[1] then
              
              pModuleInfo := #ModuleObjInfo[0];
              for i := 0 to MaxPlace do
                // check only the available objects
                if pModuleInfo^.pThis then
                  if i < 32 then
                    // in first 32 places
                    if ResultBitmap[0] AND (1 SHL i) then
                      pModuleInfo^.pThis^.DisconnectEvent();
                      if pModuleInfo^.Required then
                        SetRequiredError(pTargetThis:=pModuleInfo^.pThis, Place:=i);
                      else
                        pModuleInfo^.pThis^.ClassState := _NoHardware;
                      end_if;
                    end_if;
                  else
                    // in last 32 places
                    if ResultBitmap[1] AND (1 SHL (i-32)) then
                      pModuleInfo^.pThis^.DisconnectEvent();
                      if pModuleInfo^.Required then
                        SetRequiredError(pTargetThis:=pModuleInfo^.pThis, Place:=i);
                      else
                        pModuleInfo^.pThis^.ClassState := _NoHardware;
                      end_if;
                    end_if;
                  end_if;
                end_if;

                pModuleInfo += sizeof(t_ModuleObjectInfo);
              end_for;
            end_if;
            
            OldDeviceBitmap := HardwareConfig.DeviceBitmap;
          end_if;
        end_if;

//**********************************************************************************************************************************************************
//**                ERROR HANDLING                                           *******************************************************************************
//**********************************************************************************************************************************************************
      _PrepareError: // do error handling and then stay in _ErrorOccured-Step
        // no watchdog triggering in error case
        b_WdTriggerActive := FALSE;
        ToggleReadTaskActive := FALSE;

        if b_MultipleConnectInInit then
#ifdef HWC_LogError
          HWC_LogError(this, "@0064 (SdiasManager::CyWork) Connect has been called twice during initialisation!");
#endif
        end_if;

        // tell the manager that we're finished with initializing
        if b_PostInitFinished = FALSE then
          SendPostInitFinished(DisableThisObject:=TRUE);   
        end_if;
        
        // set required error, if there is a required module
        SetRequiredError();
(*
        // if no required error => set error according to class state
        tempCmd.uiCmd := _BUS_IF_SET_ERROR;
        tempCmd.aPara[0] := ClassState$DINT;

#ifdef HWK_SHOW_PRAGMA_MESSAGES
#pragma message("RamAnd 03.12.2013 18:15 \ Je nach Fehler die entsprechende Meldung ausgeben. tempCmd.aPara[1] soll den Pointer auf den String beinhalten")
#pragma message("RamAnd 03.12.2013 18:15 \ Wenn via VARAN Verbunden noch <exec climsg 45 > an den String vorne hinzufügen")
#pragma message("RamAnd 09.12.2013 17:14 \ Unterscheiden, ob abgestürzt werden soll (je nach Fehler und Required-Einstellung)")
#endif

        tempCmd.aPara[1] := 0;

        // only set an error if there are modules projected
        if (ClassState <> _NoHardware) & (MaxPlace <> SDIAS_PLACE_NO_MODULE_ADDED_SO_FAR) then
          ToBusInterface.NewInst(pPara:=#tempCmd, pResult:=#_result);
        end_if;


        if _result.aData[0]$t_BusIFRetvalErrorcode <> _BUS_IF_RETVAL_OK then
          LogError("@0065 (SdiasManager::CyWork) Failed to set an error to the bus interface!");
        end_if;    
*)
        // if it's still running => stop the asy DOs
        ChangeAsyWr(Offset:=0, 
                    Length:=0, 
                    RunState:=_BUS_IF_RUN_STATE_NO_RUN,
                    UsageType:=AsyWriteUsage);

        ChangeAsyRd(Offset:=0, 
                    Length:=0, 
                    RunState:=_BUS_IF_RUN_STATE_NO_RUN,
                    UsageType:=AsyReadUsage);

        InitSSW := _ErrorOccured;
        
//**********************************************************************************************************************************************************
      _ErrorOccured: // do nothing here
        return;
//**********************************************************************************************************************************************************
    end_case;
    
    // SDO Handling (has to be done also during initialisation)
    CyclicSDOHandling();
    
    // we have to do this after SDO Handling, so we don't block the channel for SDOs with LED Infos
    if InitSSW = _InitFinished then
      // Appli LED State Handling
      if (AsyWriteUsage = _NotUsed) & (b_SendWdTrigger = FALSE) then
        // check if the LED Status has changed on any Module
        if b_NewLEDStates then
          if ConnectionType = SDIAS_CON_VIA_VARAN_uC then
            // write the new LED States to the Hardware
            ASYWriteDO.pData^$t_AppliLEDStates := AppliLEDStates;
            if ChangeAsyWr(Offset:=SDIAS_OFFSET_APPLI_LED_STATES, 
                           Length:=sizeof(t_AppliLEDStates), 
                           RunState:=_BUS_IF_RUN_STATE_SINGLE_RUN,
                           UsageType:=_UsedByLED) = FALSE then
#ifdef HWC_LogError
              HWC_LogError(this, "@0066 (SdiasManager::CyWork) Error occured at setting new Appli LED states");
#endif
            end_if;
          else
            aProperties[0].udPropertyId     := SDM_PROP_BITMAP_APPLICATION_LED_0_15;
            aProperties[0].udPropertyValue  := AppliLEDStates[0]$UDINT;

            aProperties[1].udPropertyId     := SDM_PROP_BITMAP_APPLICATION_LED_16_31;
            aProperties[1].udPropertyValue  := AppliLEDStates[4]$UDINT;

            aProperties[2].udPropertyId     := SDM_PROP_BITMAP_APPLICATION_LED_32_47;
            aProperties[2].udPropertyValue  := AppliLEDStates[8]$UDINT;

            aProperties[3].udPropertyId     := SDM_PROP_BITMAP_APPLICATION_LED_48_63;
            aProperties[3].udPropertyValue  := AppliLEDStates[12]$UDINT;
                        
            if SDIAS_iSetNodeProperties(hNodeHandle         := udNodeHandle
                                      , udPropertyCount     := 4
                                      , psPropertyValuePairs:= #aProperties[0]
                                      ) <> SDIAS_OK then
#ifdef HWC_LogError
              HWC_LogError(this, "@0067 (SdiasManager::CyWork) Failed to set the application LED states via OS interface!");
#endif
              ErrorInitStep := InitSSW;
              InitSSW := _PrepareError;
              ClassState := _ManagerError; 
            else
              b_NewLEDStates := FALSE;
            end_if;
          end_if;
        end_if;
      elsif AsyWriteUsage = _UsedByLED then
        b_NewLEDStates := FALSE;
        AsyWriteUsage := _NotUsed;
      end_if;
    elsif (b_PostInitFinished = FALSE) & InitStartTime & ((ops.tAbsolute - InitStartTime) > (SDIAS_INIT_BLOCK_TIMEOUT + AdditionalPostInitTime)) then
      // timeout for last init if we're stuck in a step for too long (1min). otherwise the plc would not start up, which makes it hard to show the error
#ifdef HWC_LogValue1
      HWC_LogValue1(this, "@0068 (SdiasManager::CyWork) Init has been blocked for too long! Initialisation of SDIAS Manager timed out! Blocked step: 0x{0}",InitSSW$UDINT);
#endif
      ClassState := _TimeoutInInit;
      ErrorInitStep := InitSSW;
      InitSSW := _PrepareError;
    end_if;
    
  elsif b_PostInitFinished = FALSE then
    // if the module is not online => tell the manager that we're finished with initializing
    SendPostInitFinished(DisableThisObject:=TRUE);

    // set required error, if there is a required module
    SetRequiredError();
  end_if;

  PostRtMessages();

	state := READY;

END_FUNCTION


FUNCTION VIRTUAL GLOBAL SdiasManager::RtWork
	VAR_INPUT
		EAX 	: UDINT;
	END_VAR
	VAR_OUTPUT
		state (EAX) 	: UDINT;
	END_VAR
  VAR
  	calloption          : UDINT;
    i                   : UDINT;
    pModuleInfo         : ^t_ModuleObjectInfo;
    dataSETRUNSTATE     : t_SetRunStateCfg;    
    dataResetDO         : t_ResetDOCfg;
    dataSyncData        : t_SyncData;
  	tempCmd             : CmdStruct;
    _result             : results;
    pHelpAccess         : ^t_AccessElement;
    CheckRetryCounters  : BOOL;
    ActFrameCounter     : UDINT;
    TempControlByte     : t_SDIAS_ControlByte;
    dataUPDATEDO        : t_UpdateDOCfg;
    aProperties         : ARRAY [0..4] OF SDM_PROPERTY_VALUE_PAIR;
    SyncInjectionCfg    : t_SyncInjectionCfg;
    CrashThisTime       : USINT;
    aCrashMessage       : ARRAY [0..255] OF CHAR;
    TmpRetryCount       : UDINT;
    TempUDINT           : UDINT;
    ret_code 	          : iprStates;

#ifdef SDIAS_RT_TIME_MEASUREMENT
    Time1           : UDINT;
    Time2           : UDINT;
    TimeTotal1      : UDINT;
    TimeTotal2      : UDINT;
#endif
  END_VAR

  // Called from BusInterface on UpdateRt or UpdateRtPostScan  

  // Save state 
  // This must be the 1. line in this function or EAX may be overwriten by the generated AWL code
  calloption := EAX;

  if Online then    
    pModuleInfo := #ModuleObjInfo[0];
    case RtSSW of
//**********************************************************************************************************************************************************
      _RtIdle: // nothing
      
//**********************************************************************************************************************************************************
      _CreateAndModifyDOs: // create and modify ISO DOs 
        CreateAndModifyIsoDOs();
        
        RtSSW := _Wait4DOs;
        
//**********************************************************************************************************************************************************
      _Wait4DOs:
        if calloption = CALL_OPTION_RT_PRESCAN then    // Called from UpdateRt
          // wait until the DOs can be activated
          if b_Ready4Rt then
          
            // reset data objects is only needed for connection over VARAN
            if ConnectionType = SDIAS_CON_VIA_VARAN_uC then 
              // reset data objects (calculate retry timeout) - must be done every connect because at disconnect the retry time could be set with 0 byte data length
              tempCmd.uiCmd     := _BUS_IF_RESET_DO;
              tempCmd.aPara[0]  := (#dataResetDO)$DINT;              

#ifndef SDIAS_DEACTIVATE_TASK_CHECKS
              dataResetDO.Handle := TaskInfoDO.Handle;

              ToBusInterface.NewInst(pPara:=#tempCmd, pResult:=#_result);
              
              if _result.aData[0]$t_BusIFRetvalErrorcode <> _BUS_IF_RETVAL_OK then
                // remember the log message and write it in cyclic priority to avoid a rt runtime error
                CyclicMsgMarker.PostIt.TaskInfoRunFailed := TRUE;
              end_if;
#endif
              
              dataResetDO.Handle := ISOReadDO.Handle;
              
              ToBusInterface.NewInst(pPara:=#tempCmd, pResult:=#_result);  
              if _result.aData[0]$t_BusIFRetvalErrorcode <> _BUS_IF_RETVAL_OK then
                // remember the log message and write it in cyclic priority to avoid a rt runtime error
                CyclicMsgMarker.PostIt.IsoReadRunFailed := TRUE;
              end_if;  
                  
              dataResetDO.Handle := ISOWriteDO.Handle;

              ToBusInterface.NewInst(pPara:=#tempCmd, pResult:=#_result);
              if _result.aData[0]$t_BusIFRetvalErrorcode <> _BUS_IF_RETVAL_OK then
                // remember the log message and write it in cyclic priority to avoid a rt runtime error
                CyclicMsgMarker.PostIt.IsoWriteRunFailed := TRUE;
              end_if;
            end_if;  
            
            // activate the ISO DOs            
            
            // general settings needed for all DOs
            dataSETRUNSTATE.NewRunState := _BUS_IF_RUN_STATE_CONT_RUN;
            tempCmd.uiCmd         := _BUS_IF_SET_RUN_STATE;  
            tempCmd.aPara[0]      := (#dataSETRUNSTATE)$DINT;             
                        
#ifndef SDIAS_DEACTIVATE_TASK_CHECKS

            if ConnectionType = SDIAS_CON_VIA_VARAN_uC then                      
              // set runstate of taskinfo read
              dataSETRUNSTATE.Handle      := TaskInfoDO.Handle;
             
              ToBusInterface.NewInst(pPara:=#tempCmd, pResult:=#_result); 
              
              if _result.aData[0]$t_BusIFRetvalErrorcode <> _BUS_IF_RETVAL_OK then
                // remember the log message and write it in cyclic priority to avoid a rt runtime error
                CyclicMsgMarker.PostIt.TaskInfoRunFailed := TRUE;
              end_if;  
            end_if;
#endif

            // set runstate of read
            dataSETRUNSTATE.Handle      := ISOReadDO.Handle;
           
            ToBusInterface.NewInst(pPara:=#tempCmd, pResult:=#_result); 
            
            if _result.aData[0]$t_BusIFRetvalErrorcode <> _BUS_IF_RETVAL_OK then
              // remember the log message and write it in cyclic priority to avoid a rt runtime error
              CyclicMsgMarker.PostIt.IsoReadRunFailed := TRUE;
            end_if;  
            
           
            // set runstate of write
            dataSETRUNSTATE.Handle      := ISOWriteDO.Handle;

            ToBusInterface.NewInst(pPara:=#tempCmd, pResult:=#_result); 
            
            if _result.aData[0]$t_BusIFRetvalErrorcode <> _BUS_IF_RETVAL_OK then
              // remember the log message and write it in cyclic priority to avoid a rt runtime error
              CyclicMsgMarker.PostIt.IsoWriteRunFailed := TRUE;
            end_if;
            
            if ConnectionType = SDIAS_CON_VIA_VARAN_uC then
            
              // change config DO => change task config settings for Iso Read Task)
              ISOConfigWrDO.Offset := SDIAS_OFFSET_TASK_CONFIG_1;
              ISOConfigWrDO.Length := sizeof(t_TaskConfig);
              
              dataUPDATEDO.Handle               := ISOConfigWrDO.Handle;
              dataUPDATEDO.ud_addressoff_write  := ISOConfigWrDO.Offset;
              dataUPDATEDO.ud_length_write      := ISOConfigWrDO.Length;

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

              ToBusInterface.NewInst(pPara:=#tempCmd, pResult:=#_result); 
              
              if _result.aData[0]$t_BusIFRetvalErrorcode <> _BUS_IF_RETVAL_OK then
                // remember the log message and write it in cyclic priority to avoid a rt runtime error
                CyclicMsgMarker.PostIt.IsoConfigWrChangeFailed := TRUE;
              else
                // use the task config data
                ISOConfigWrDO.pData^$t_TaskConfig := ISOTaskConfig;
              end_if;

              dataSETRUNSTATE.NewRunState := _BUS_IF_RUN_STATE_SINGLE_RUN;
              dataSETRUNSTATE.Handle      := ISOConfigWrDO.Handle;
              
              tempCmd.uiCmd               := _BUS_IF_SET_RUN_STATE;  
              tempCmd.aPara[0]            := (#dataSETRUNSTATE)$DINT; 

              ToBusInterface.NewInst(pPara:=#tempCmd, pResult:=#_result); 

              if _result.aData[0]$t_BusIFRetvalErrorcode <> _BUS_IF_RETVAL_OK then
                // remember the log message and write it in cyclic priority to avoid a rt runtime error
                CyclicMsgMarker.PostIt.IsoConfigWrTaskConfigFailed := TRUE;
              end_if;  
            
            else
              aProperties[0].udPropertyId     := SDM_PROP_TASK_CONTROL_DURATION_TIMEOUT;
              aProperties[0].udPropertyValue  := ISOTaskConfig.TaskDurationTimeout_us;

              aProperties[1].udPropertyId     := SDM_PROP_TASK_CONTROL_CONFIGURATION;
              aProperties[1].udPropertyValue  := ISOTaskConfig.Config;

              if SDIAS_iSetNodePropertiesIndex(hNodeHandle      := udNodeHandle
                                        , udIndex               := 1
                                        , udPropertyCount       := 2
                                        , psPropertyValuePairs  := #aProperties[0]
                                        ) <> SDIAS_OK then
                CyclicMsgMarker.PostIt.IsoTaskConfigFailed := TRUE;
              end_if;

              // reconfigure PLL to ensure the SDIAS Sync refers to the correct OS tick
            
              // get the actual frame counter
              if SDIAS_iGetNodeProperty(hNodeHandle      :=udNodeHandle
                                      , udPropertyId     :=SDM_PROP_PLL_SYNC_TIME_FRAME_COUNTER
                                      , pudPropertyValue :=#ActFrameCounter
                                      ) = SDIAS_OK then

                tempCmd.uiCmd := _BUS_IF_SET_SYNC;
                
                if pPLL then
                  for i := 0 to 7 do
                    if (TaskEventIDs[i] AND 16#F0) = 16#10 then
                      // sync out is connected, take lower nibble as syncout index
                      if PLL_iGetSyncOutProperty(pPLL, ud_NodeHandlePLL, (TaskEventIDs[i] AND 16#0F), PLL_PROP_SO_SYNC_OUT_ID, #TempUDINT) = PLL_OK then
                        if TempUDINT = SDIAS_MANAGER_SYNC_SYNCOUT_ID then
                          exit;
                        end_if;
                      end_if;
                    end_if;
                  end_for;          
                  dataSyncData.us_sync_nr := TaskEventIDs[i]; // iso read trigger
                else
                  dataSyncData.us_sync_nr := SDIAS_EVENT_MASK_ID_SYNC_OUT2; // iso read trigger
                end_if;
                
                dataSyncData.us_period_multiplier := 0;
                dataSyncData.sd_offset := 0;
                
                // start with the next correct sync
                dataSyncData.us_frame_count_threshold := (ActFrameCounter + 1 + (ud_BusTime_ns / 1000) / ud_SystemPeriodTime)$USINT;
                dataSyncData.us_enable_frame_count := 1;

                tempCmd.aPara[0] := (#dataSyncData)$DINT;
                
                ToBusInterface.NewInst(pPara:=#tempCmd, pResult:=#_result);

                if _result.aData[0]$t_BusIFRetvalErrorcode <> _BUS_IF_RETVAL_OK then
                  CyclicMsgMarker.PostIt.SetSyncFailed := TRUE;
                end_if;
              else
                CyclicMsgMarker.PostIt.GetFrameCounterFailed := TRUE;
              end_if; 
            end_if;

            // stop asynchron watchdog triggering, because the watchdog gets triggered by rt now
            b_WdTriggerActive := FALSE;
            ToggleReadTaskActive := FALSE;
            b_SendWdTrigger := FALSE;

            if AsyWriteUsage = _UsedByWD then
              AsyWriteUsage := _NotUsed;
            end_if;

            PreOpCount := 0;
            RtSSW := _Wait4PllSync;
          end_if;
        end_if;

//**********************************************************************************************************************************************************
      _Wait4PllSync:
        if calloption = CALL_OPTION_RT_PRESCAN then    // Called from UpdateRt
          
          if PreOpCount < SDIAS_CYCLES_WAIT_AFTER_SYNC_ENABLE-1 then
            PreOpCount += 1;
          else
            PreOpCount := 0;
            RtSSW := _Wait2Ticks;
          end_if;
        end_if;

//**********************************************************************************************************************************************************
      _Wait2Ticks:  // SDIAS Manager FPGA measures the sync interval during the first to cycles 
        if calloption = CALL_OPTION_RT_PRESCAN then    // Called from UpdateRt
        
          if PreOpCount < (SDIAS_SYNC_MEASURE_TICKS-1) then
            PreOpCount += 1;

            // we select the read task for sync, there are no sync task trigger losses allowed and we enable the sync injection
            SyncInjectionCfg := 16#03;

            if ConnectionType = SDIAS_CON_VIA_VARAN_uC then          
              // change config DO => change trigger unit settings (also use trigger unit for read task)
              ISOConfigWrDO.Offset := SDIAS_OFFSET_SYNC_INJECTION_CFG;
              ISOConfigWrDO.Length := sizeof(t_SyncInjectionCfg);
              
              dataUPDATEDO.Handle               := ISOConfigWrDO.Handle;
              dataUPDATEDO.ud_addressoff_write  := ISOConfigWrDO.Offset;
              dataUPDATEDO.ud_length_write      := ISOConfigWrDO.Length;

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

              ToBusInterface.NewInst(pPara:=#tempCmd, pResult:=#_result); 
              
              if _result.aData[0]$t_BusIFRetvalErrorcode <> _BUS_IF_RETVAL_OK then
                // remember the log message and write it in cyclic priority to avoid a rt runtime error
                CyclicMsgMarker.PostIt.IsoConfigWrChange2Failed := TRUE;
              else
                // use the sync injection data
                ISOConfigWrDO.pData^$t_SyncInjectionCfg := SyncInjectionCfg;
              end_if;

              dataSETRUNSTATE.NewRunState := _BUS_IF_RUN_STATE_SINGLE_RUN;
              tempCmd.uiCmd               := _BUS_IF_SET_RUN_STATE;  
              tempCmd.aPara[0]            := (#dataSETRUNSTATE)$DINT; 
              
              dataSETRUNSTATE.Handle      := ISOConfigWrDO.Handle;

              ToBusInterface.NewInst(pPara:=#tempCmd, pResult:=#_result); 

              if _result.aData[0]$t_BusIFRetvalErrorcode <> _BUS_IF_RETVAL_OK then
                // remember the log message and write it in cyclic priority to avoid a rt runtime error
                CyclicMsgMarker.PostIt.IsoConfigWrSyncInjFailed := TRUE;
              end_if; 
            else
              aProperties[0].udPropertyId     := SDM_PROP_SYNC_INJECTION_CONFIG;
              aProperties[0].udPropertyValue  := SyncInjectionCfg;

              if SDIAS_iSetNodeProperties(hNodeHandle         := udNodeHandle
                                        , udPropertyCount     := 1
                                        , psPropertyValuePairs:= #aProperties[0]
                                        ) <> SDIAS_OK then
                // remember the log message and write it in cyclic priority to avoid a rt runtime error
                CyclicMsgMarker.PostIt.IsoSyncInjFailed := TRUE;
              end_if;
            end_if;
          else
            if ConnectionType = SDIAS_CON_VIA_VARAN_uC then
              // change config DO => change trigger unit settings (also use trigger unit for read task)
              ISOConfigWrDO.Offset := SDIAS_OFFSET_TRIGGER_UNIT_SETUP_0;
              ISOConfigWrDO.Length := sizeof(t_TriggerUnitSetup);
              
              dataUPDATEDO.Handle               := ISOConfigWrDO.Handle;
              dataUPDATEDO.ud_addressoff_write  := ISOConfigWrDO.Offset;
              dataUPDATEDO.ud_length_write      := ISOConfigWrDO.Length;

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

              ToBusInterface.NewInst(pPara:=#tempCmd, pResult:=#_result); 
              
              if _result.aData[0]$t_BusIFRetvalErrorcode <> _BUS_IF_RETVAL_OK then
                // remember the log message and write it in cyclic priority to avoid a rt runtime error
                CyclicMsgMarker.PostIt.IsoConfigWrChangeFailed := TRUE;
              else
                // use the trigger unit setup data
                ISOConfigWrDO.pData^$t_TriggerUnitSetup := ISOTriggerUnitSetup;
              end_if;

              dataSETRUNSTATE.NewRunState := _BUS_IF_RUN_STATE_SINGLE_RUN;
              tempCmd.uiCmd               := _BUS_IF_SET_RUN_STATE;  
              tempCmd.aPara[0]            := (#dataSETRUNSTATE)$DINT; 
              
              dataSETRUNSTATE.Handle      := ISOConfigWrDO.Handle;

              ToBusInterface.NewInst(pPara:=#tempCmd, pResult:=#_result); 

              if _result.aData[0]$t_BusIFRetvalErrorcode <> _BUS_IF_RETVAL_OK then
                // remember the log message and write it in cyclic priority to avoid a rt runtime error
                CyclicMsgMarker.PostIt.IsoConfigWrTriggerUnitFailed := TRUE;
              end_if;  
            else
              aProperties[0].udPropertyId     := SDM_PROP_TASK_TRIGGER_UNIT_CONTROL;
              aProperties[0].udPropertyValue  := to_udint(ISOTriggerUnitSetup.TaskSelect);

              aProperties[1].udPropertyId     := SDM_PROP_TASK_TRIGGER_UNIT_START_ADDR_RANGE;
              aProperties[1].udPropertyValue  := to_udint(ISOTriggerUnitSetup.StartAddress);
              
              if SDIAS_iSetNodePropertiesIndex(hNodeHandle          := udNodeHandle
                                              , udIndex             := 0
                                              , udPropertyCount     := 2
                                              , psPropertyValuePairs:= #aProperties[0]
                                              ) <> SDIAS_OK then
                CyclicMsgMarker.PostIt.IsoTriggerUnitConfigFailed := TRUE;
              end_if;
            end_if;


            // tell the manager that our sync is running, which triggers the watchdog on the modules from now on
            tempCmd.uiCmd := _BUS_IF_RT_SYNC_READY;
            ToBusInterface.NewInst(pPara:=#tempCmd, pResult:=#_result);
            
            // sync is starting with this RT => deactivate the watchdog trigger (no longer needed)
  #pragma warning(disable: 74)
            TempControlByte := 0;
            TempControlByte.EnableDO := FALSE;
  #pragma warning(default: 74)
            (ISOWriteDO.pData$^t_SDIAS_ControlByte + SDIAS_TRIGGER_UNIT_BYTE_SIZE)^ := TempControlByte;
                        
            PreOpCount := 0;
            RtSSW := _PreOperational;          
            
            if ( SupportedFeatures.TimeBroadCastSupported ) then
              
              uiSyncCountDown := SDIAS_SYNCSTART_COUNTDOWN;
              
              // Ensure that the countdown lasts at least SDIAS_SYNCSTART_COUNTDOWN ms even if the Bus time is faster than 1ms
              if ud_BusTime_ns < 1000000 then
                uiSyncCountDown *= (1000000 / ud_BusTime_ns)$UINT;
              end_if;
              
              //+1 because we always decrement before sending,
              // the return value of SendSyncCntDown() is the value just sent.
              uiSyncCountDown += 1;
              
              // Set MSB
              uiSyncCountDown := uiSyncCountDown OR 16#8000;              
              
              // skip PreOpCount because CntDownSyn takes longer and 
              // calls to UpdateRt must come directly after UpdateRtPreOp              
              PreOpCount  := SDIAS_TASKINFO_READY_TICKS;  
              RtSSW       := _CntDownSyncStart;              
            end_if;                      
                      
          end_if;
        end_if;
        
//**********************************************************************************************************************************************************
      _CntDownSyncStart:
      
        if calloption = CALL_OPTION_RT_PRESCAN then    // Called from UpdateRt 
          
          // Call Modules so they can safe the togle bit prio the first sync
          for i := 0 to MaxPlace do
            if (pModuleInfo^.pThis) & (pModuleInfo^.pInitState) then
              
              if (pModuleInfo^.pInitState^ = _ClassOk) then
                pModuleInfo^.pThis^.UpdateRtPreOp(SDIAS_RTPREOP_CHECKSYNC);
              end_if;
              
            end_if;
            
            pModuleInfo += sizeof(t_ModuleObjectInfo);
          end_for;
          
          // Send Sync countdown
          if SendSyncCntDown() <= 16#8000 then          
            udTimeMark1stSync := ops.tAbsolute;            
            RtSSW := _PreOperationalWait4DataReady;
          end_if;
          
        end_if;

//**********************************************************************************************************************************************************
      _PreOperationalWait4DataReady:
      
        if calloption = CALL_OPTION_RT_PRESCAN then    // Called from UpdateRt 
          SendTimeBroadCast();
          
          ret_code := READY;
          
          // Timeoutueberwachung, 
          if ((ops.tAbsolute - udTimeMark1stSync) < SDIAS_PREOP_DATAVALID_TIMEOUT) then          
          
            // Call Modules to check for dataready                
            for i := 0 to MaxPlace do
              if (pModuleInfo^.pThis) & (pModuleInfo^.pInitState) then
                
                if (pModuleInfo^.pInitState^ = _ClassOk) then
                  if (pModuleInfo^.pThis^.UpdateRtPreOp(SDIAS_RTPREOP_CHECKDATAVALID) = BUSY) then
                    ret_code := BUSY; // Only assign if busy, check later is for any busy
                  end_if;
                end_if;

              end_if;
              
              pModuleInfo += sizeof(t_ModuleObjectInfo);
            end_for;
          
            // All Modules are done
            if (ret_code <> BUSY) then
              RtSSW := _PreOperational;
            end_if;
          
          else // Timeout abgelaufen
          
            // Call Modules to check for dataready                
            for i := 0 to MaxPlace do
              if (pModuleInfo^.pThis) & (pModuleInfo^.pInitState) then
                
                if (pModuleInfo^.pInitState^ = _ClassOk) then
                  if (pModuleInfo^.pThis^.UpdateRtPreOp(SDIAS_RTPREOP_CHECKDATAVALID) <> READY) then
                    // Set Modul to error if it does not return READY on the last attempt.
                    pModuleInfo^.pInitState^ := _TimeoutInInit;
                  end_if;
                end_if;

              end_if;
              
              pModuleInfo += sizeof(t_ModuleObjectInfo);
            end_for;
            
            RtSSW := _PreOperational;
            
          end_if;
        end_if;

//**********************************************************************************************************************************************************
      _PreOperational: // we have to make 1 step between start of DOs and operational => task status bits are not valid the first time
        if calloption = CALL_OPTION_RT_PRESCAN then    // Called from UpdateRt          
          
          SendTimeBroadCast();
          
          if PreOpCount < SDIAS_TASKINFO_READY_TICKS then
            PreOpCount += 1;
          else  
            // finalize cyclic ssw
            if InitSSW = _WaitForRtOperational then
              ClassState  := _ClassOk; 
              InitSSW     := _InitFinished;
              if ConnectionType = SDIAS_CON_VIA_VARAN_uC then
                // data is valid -> set online server to 1
                tempCmd.uiCmd    := _BUS_IF_SET_ONLINE;
                tempCmd.aPara[0] := 1;
                
                ToBusInterface.NewInst(pPara:=#tempCmd, pResult:=#_result);
                
                if _result.aData[0]$t_BusIFRetvalErrorcode <> _BUS_IF_RETVAL_OK then  
                  // remember the log message and write it in cyclic priority to avoid a rt runtime error
                  CyclicMsgMarker.PostIt.SetOnlineStateFailed := TRUE;
                end_if;
              end_if;
            end_if;
            
            RtSSW := _Operational;          
            
            //Set Classstates of the single modules and call the UpdateRt method to ensure valid data on the module servers if we set the state to _ClassOk.
            for i := 0 to MaxPlace do
              if pModuleInfo^.pThis then
                if pModuleInfo^.pInitState then
                
                  //Set ClassState of module, before calls of UpdateRt, since there are some modules which check the classstate in the UpdateRt Method
                  pModuleInfo^.pThis^.ClassState := pModuleInfo^.pInitState^;
                  
                  if pModuleInfo^.bPreScan & (pModuleInfo^.pInitState^ = _ClassOk) then
                    // call all objects which are marked for prescan, to ensure valid data on user if classtate is class ok
                    pModuleInfo^.pThis^.UpdateRt();        
                  end_if;
                else
                 //not possible
                end_if;
              end_if;
              pModuleInfo += sizeof(t_ModuleObjectInfo);
            end_for;
          end_if;
          
        elsif calloption = CALL_OPTION_RT_POSTSCAN then
        
          // dont call the postscan of modules here. It would be to early, so the DOs dont have the right state-bits.
          // The corresponding postscan-call for the UpdateRT call from this step will already be called in the "operational-case", due to the RtSSW already increased.
          
        end_if;
//**********************************************************************************************************************************************************
      _Operational:
        if calloption = CALL_OPTION_RT_PRESCAN then    // Called from UpdateRt
          
#ifdef SDIAS_RT_TIME_MEASUREMENT
          TimeTotal1 := OS_READMICROSEC();
#endif

          CrashThisTime := 0;

#ifndef SDIAS_DEACTIVATE_TASK_CHECKS
                    
          // check if there was a retry
          CheckRetryCounters := WriteTaskInfo.pReadData^.Handshake.AnyRetries | ReadTaskInfo.pReadData^.Handshake.AnyRetries;

          // check toggle bit after first run
          if WriteTaskInfo.MaxDuration then
            if WriteTaskInfo.bOldToggle = WriteTaskInfo.pReadData^.Handshake.Toggle then
              WriteTaskInfo.ToggleErrorCount += 1;
              IsoTaskErrorCount += 1;
              CyclicMsgMarker.PostIt.ToggleErrorWrTask := TRUE;

              ClassState := _TimesliceErrorIRQ;
              Online := 0;

              DisableBus();

              if b_IsRequired then
                CrashThisTime := 1;
                _strcpy(dest:=#aCrashMessage[0], src:="Error in SDIAS write task occured! (Toggle Bit)");            
              end_if;
            end_if;
          end_if;
          WriteTaskInfo.bOldToggle := WriteTaskInfo.pReadData^.Handshake.Toggle;

          // check toggle bit after first run
          if ReadTaskInfo.MaxDuration then
            if ReadTaskInfo.bOldToggle = ReadTaskInfo.pReadData^.Handshake.Toggle then
              ReadTaskInfo.ToggleErrorCount += 1;
              IsoTaskErrorCount += 1;
              CyclicMsgMarker.PostIt.ToggleErrorRdTask := TRUE;
                
              ClassState := _TimesliceError;
              Online := 0;

              DisableBus();

              if b_IsRequired then
                CrashThisTime := 1;
                _strcpy(dest:=#aCrashMessage[0], src:="Error in SDIAS read task occured! (Toggle Bit)");            
              end_if;
            end_if;
          end_if;
          ReadTaskInfo.bOldToggle := ReadTaskInfo.pReadData^.Handshake.Toggle;

          // check executed bit always
          if (WriteTaskInfo.pReadData^.Handshake.Executed = 0) then
            WriteTaskInfo.ErrorCount += 1;
            IsoTaskErrorCount += 1;
            
            CyclicMsgMarker.PostIt.WrTaskNotFinished := TRUE;
            
            ClassState := _TimesliceErrorIRQ;
            Online := 0;

            DisableBus();

            if b_IsRequired then
              CrashThisTime := 1;
              _strcpy(dest:=#aCrashMessage[0], src:="Error in SDIAS write task occured! (Not Executed)");            
            end_if;
          end_if;

          if WriteTaskInfo.pReadData^.Handshake.Error & (WriteTaskInfo.pReadData^.ErrorInfoFlags AND SDIAS_ERROR_INFO_MASK) then
            WriteTaskInfo.ErrorCount += 1;
            IsoTaskErrorCount += 1;
            
            CyclicMsgMarker.PostIt.ErrorWrTask := TRUE;

            ClassState := _TimesliceErrorIRQ;
            Online := 0;

            DisableBus();
            
            if b_IsRequired then
              CrashThisTime := 1;
              _strcpy(dest:=#aCrashMessage[0], src:="Error in SDIAS write task occured! (Error)");            
            end_if;
          end_if;

          // check executed bit always
          if (ReadTaskInfo.pReadData^.Handshake.Executed = 0) & (ReadTaskInfo.pReadData^.Handshake.StatusWait = 0) then
            ReadTaskInfo.ErrorCount += 1;
            IsoTaskErrorCount += 1;
            
            CyclicMsgMarker.PostIt.RdTaskNotFinished := TRUE;

            ClassState := _TimesliceError;
            Online := 0;

            DisableBus();

            if b_IsRequired then
              CrashThisTime := 1;
              _strcpy(dest:=#aCrashMessage[0], src:="Error in SDIAS read task occured! (Not Executed)");            
            end_if;
          end_if;

          if (ReadTaskInfo.pReadData^.Handshake.Executed = 0) & (ReadTaskInfo.pReadData^.Handshake.StatusWait = 1) then
            ReadTaskInfo.ErrorCount += 1;
            IsoTaskErrorCount += 1;
            
            CyclicMsgMarker.PostIt.RdTaskNoEvent := TRUE;

            ClassState := _TimesliceErrorIRQ;
            Online := 0;

            DisableBus();

            if b_IsRequired then
              CrashThisTime := 1;
              _strcpy(dest:=#aCrashMessage[0], src:="Error in SDIAS read task occured! (No Event Occured)");            
            end_if;
          end_if;

          if ReadTaskInfo.pReadData^.Handshake.Error & (ReadTaskInfo.pReadData^.ErrorInfoFlags AND SDIAS_ERROR_INFO_MASK) then
            
            ReadTaskInfo.ErrorCount += 1;
            IsoTaskErrorCount += 1;
            
            CyclicMsgMarker.PostIt.ErrorRdTask := TRUE;

            ClassState := _TimesliceError;
            Online := 0;

            DisableBus();

            if b_IsRequired then
              CrashThisTime := 1;
              _strcpy(dest:=#aCrashMessage[0], src:="Error in SDIAS read task occured! (Error)");            
            end_if;
          end_if;

          //Check if SdiasManager FPGA supports the detection of TimeSliceErrorIRQ
          if FeatureInfo.OptionBits.TaskInterruptionDetectionSupported = TRUE then
            //Check if error info flag bit 0 is set .. SYNC occured while Task was executing
            if WriteTaskInfo.pReadData^.ErrorInfoFlags.AccessCanceled = TRUE then
              WriteTaskInfo.ErrorCount += 1;
              IsoTaskErrorCount += 1;
              
              CyclicMsgMarker.PostIt.WrTaskInterruptedByRdTask := TRUE;
              
              ClassState := _TimesliceErrorIRQ;
              Online := 0;

              DisableBus();

              if b_IsRequired then
                CrashThisTime := 1;
                _strcpy(dest:=#aCrashMessage[0], src:="Error in SDIAS write task occured! (Interrupted by RdTask)");            
              end_if;
            end_if;
          end_if;

          // show the task duration on the servers and remember the max duration
          IsoWrTaskDuration := WriteTaskInfo.pReadData^.DurationTime;
          if IsoWrTaskDuration > WriteTaskInfo.MaxDuration then
            WriteTaskInfo.MaxDuration := IsoWrTaskDuration;
          end_if;
          
          //own if because user can reset the server
          if IsoWrTaskDuration > IsoWrTaskMaxDuration then
            IsoWrTaskMaxDuration := IsoWrTaskDuration;
          end_if;

          // show the task duration on the servers and remember the max duration
          IsoRdTaskDuration := ReadTaskInfo.pReadData^.DurationTime;
          if IsoRdTaskDuration > ReadTaskInfo.MaxDuration then
            ReadTaskInfo.MaxDuration := IsoRdTaskDuration;
          end_if;
          
          //own if because user can reset the server
          if IsoRdTaskDuration > IsoRdTaskMaxDuration then
            IsoRdTaskMaxDuration := IsoRdTaskDuration;
          end_if;
          
#else
#pragma message("ATTENTION: TASK CHECKS FOR SDIAS ARE DEACTIVATED!")

#ifdef SDIAS_CHECK_ALL_RETRIES
          CheckRetryCounters := TRUE;
#else
          CheckRetryCounters := FALSE;
#pragma message("ATTENTION: RETRY CHECKS FOR SDIAS ARE DEACTIVATED!")
#endif
#endif    

          SendTimeBroadCast();
          
          // check accesses for errors
          for i := 0 to MaxPlace do
            // if the state is ok
            if pModuleInfo^.bPreScan & (pModuleInfo^.pThis^.ClassState = _ClassOk) then
              if CheckRetryCounters then
                TmpRetryCount := 0;
                // check default accesses for error
                if pModuleInfo^.pDefaultAccesses^.ReadAccess.pStateByte then
                  // increase retrycounter if retries occured on the access
                  TmpRetryCount += CheckAccess(bsStateByte    := pModuleInfo^.pDefaultAccesses^.ReadAccess.pStateByte^
                                             , sdRequired     := pModuleInfo^.Required
                                             , sdPlace        := i$DINT
                                             , pCrashThisTime := #CrashThisTime
                                             , pCrashMessage  := #aCrashMessage[0]
                                             );             
                end_if;

                if pModuleInfo^.pDefaultAccesses^.WriteAccess.pStateByte then
                  // increase retrycounter if retries occured on the access
                  TmpRetryCount += CheckAccess(bsStateByte    := pModuleInfo^.pDefaultAccesses^.WriteAccess.pStateByte^
                                             , sdRequired     := pModuleInfo^.Required
                                             , sdPlace        := i$DINT
                                             , pCrashThisTime := #CrashThisTime
                                             , pCrashMessage  := #aCrashMessage[0]
                                             );
                end_if;

                // check all special accesses for errors
                pHelpAccess := pModuleInfo^.pFirstAccess;
                while pHelpAccess do                    
                  // increase retrycounter if retries occured on the access
                  TmpRetryCount += CheckAccess(bsStateByte    := pHelpAccess^.ppStateByte^^
                                             , sdRequired     := pModuleInfo^.Required
                                             , sdPlace        := i$DINT
                                             , pCrashThisTime := #CrashThisTime
                                             , pCrashMessage  := #aCrashMessage[0]
                                             );
                  
                  pHelpAccess := pHelpAccess^.pNext;
                end_while;
                
                // update retrycounter
                pModuleInfo^.pThis^.RetryCounter += TmpRetryCount;
                RetryCounter += TmpRetryCount;

              end_if;
#ifdef SDIAS_RT_TIME_MEASUREMENT
              Time1 := OS_READMICROSEC();
#endif

              // call them only if we're not about to crash
              if CrashThisTime = 0 then
                // call all objects which are marked for prescan
                pModuleInfo^.pThis^.UpdateRt();
              end_if;
              
#ifdef SDIAS_RT_TIME_MEASUREMENT
              Time2 := OS_READMICROSEC();
              pModuleInfo^.RtTime_us := Time2 - Time1;
              if pModuleInfo^.RtTime_us > pModuleInfo^.RtTimeMax_us then
                pModuleInfo^.RtTimeMax_us := pModuleInfo^.RtTime_us;
              end_if;
#endif
            end_if;
            pModuleInfo += sizeof(t_ModuleObjectInfo);
          end_for;

          if CrashThisTime then
            // print pending error messages before crash
            PostRtMessages();

            if CrashThisTime = 1 then
              SDIAS_iReportEvent(uiEvent:=SDM_EVENT_ERROR_REQUIRED_MODULE, pucEvntMsg:=#aCrashMessage[0]);
            
            elsif CrashThisTime = 2 then 
              // set required error (don't use SetRequiredError method, because logging in realtime could cause a rt runtime error which will disguise our required error)
              tempCmd.uiCmd     := _BUS_IF_SET_REQUIRED_ERROR;
              
              ToBusInterface.NewInst(pPara:=#tempCmd, pResult:=#_result);
              if _result.aData[0]$t_BusIFRetvalErrorcode <> _BUS_IF_RETVAL_OK then
                CyclicMsgMarker.PostIt.ForwardRequiredErrorFailed := TRUE;
              end_if;    
            end_if;
          end_if;

#ifdef SDIAS_RT_TIME_MEASUREMENT
          TimeTotal2 := OS_READMICROSEC();
          RtPreDuration := TimeTotal2 - TimeTotal1;
#endif

        elsif calloption = CALL_OPTION_RT_POSTSCAN then // Called from UpdateRtPostScan
#ifdef SDIAS_RT_TIME_MEASUREMENT
          TimeTotal1 := OS_READMICROSEC();
#endif

          for i := 0 to MaxPlace do
            if pModuleInfo^.bPostScan & (pModuleInfo^.pThis^.ClassState = _ClassOk) then

#ifdef SDIAS_RT_TIME_MEASUREMENT
              Time1 := OS_READMICROSEC();
#endif

              // call all objects which are marked for postscan
              pModuleInfo^.pThis^.UpdateRtPostScan();

#ifdef SDIAS_RT_TIME_MEASUREMENT
              Time2 := OS_READMICROSEC();
              pModuleInfo^.RtPostTime_us := Time2 - Time1;
              if pModuleInfo^.RtPostTime_us > pModuleInfo^.RtPostTimeMax_us then
                pModuleInfo^.RtPostTimeMax_us := pModuleInfo^.RtPostTime_us;
              end_if;
#endif

            end_if;
            pModuleInfo += sizeof(t_ModuleObjectInfo);
          end_for;
          
#ifdef SDIAS_RT_TIME_MEASUREMENT
          TimeTotal2 := OS_READMICROSEC();
          RtPostDuration := TimeTotal2 - TimeTotal1;
#endif
        end_if;  

//**********************************************************************************************************************************************************
    end_case;
  end_if;

	state := READY;

END_FUNCTION


FUNCTION VIRTUAL GLOBAL SdiasManager::ClassState::NewInst
	VAR_INPUT
		pPara 	: ^CmdStruct;
		pResult 	: ^results;
	END_VAR
	VAR_OUTPUT
		ret_code 	: iprStates;
	END_VAR
  VAR
  	ByteNr      : USINT;
    PosInByte   : USINT;
    pDataADDMove: ^t_AddMoveDOCfg;
    Place       : UDINT;
    pAccessInfo : ^t_AccessInfoRet;
//    DAPara      : t_RDWRDOCfg;
  	tempCmd     : CmdStruct;
    _result     : results;
    sRDDADOCfg  :   t_RDWRDOCfg;
    
    pStr_HWTRequested     : ^CHAR;
    tmpplace      : USINT;
    pStr_HWTreeEntry : ^CHAR;
    usNextPlace   : USINT;
    i             : USINT;
  END_VAR
  
	ret_code := READY;

	CASE pPara^.uiCmd OF
//*****************************************************************************
//** EXTERNAL COMMANDS (FOR DIAGNOSIS)                                       **
//*****************************************************************************

//**********************************************************************************************************************************************************
    SDIAS_CMD_GET_MIB_ADDR :
      // return the address of the ManagerInfoBlock variable
      if ClassState = _ClassOk then
        pResult^.uiLng := 4;
        pResult^.aData[0]$^void := #ManagerInfoBlock$^void;
      else
      
        ret_code := ERROR;
        
        // Read the info block via DAs if we are conncted via Varan and the Classstate is _ModuleFoundButManagerIsOff
        if ConnectionType = SDIAS_CON_VIA_VARAN_uC then

          // Check Class State
          tempCmd.uiCmd := _BUS_IF_GET_CLASS_STATE;              
          ret_code := ToBusInterface.NewInst(pPara:=#tempCmd, pResult:=#_result); 
          
          if ((ret_code = READY) & (_result.aData[0]$t_BusIFRetvalErrorcode = _BUS_IF_RETVAL_OK)) then
            
            if (_result.aData[4]$t_e_VaranErrors = _ModuleFoundButManagerIsOff) then
              // Manager is off so we can read the ManagerInfoBlock with DA without interrupting regular bus transfer
              tempCmd.uiCmd := _BUS_IF_RD_DA;
              
              // prepare fetching the infoblock              
              ModuleSizeNeeded :=sizeof(ManagerInfoBlock.ModuleInfos);
              
              sRDDADOCfg.ud_length    := 128;
              sRDDADOCfg.ud_AddOffset := 0;
              sRDDADOCfg.p_ud_data    := #ManagerInfoBlock + AccessProgress;
              
              tempCmd.aPara[0]$^t_RDWRDOCfg := #sRDDADOCfg;

              while ModuleSizeNeeded >= 128 do
                
                ret_code := ToBusInterface.NewInst(pPara:=#tempCmd, pResult:=#_result); 
                if ((ret_code <> READY) & (_result.aData[0]$t_BusIFRetvalErrorcode <> _BUS_IF_RETVAL_OK)) then                
                  ret_code := ERROR;
                  return;
                end_if;
                
                sRDDADOCfg.ud_AddOffset += 128;                
                sRDDADOCfg.p_ud_data    += 128;
                
                ModuleSizeNeeded  -= 128;
              end_while;
              
              if ModuleSizeNeeded then
              
                sRDDADOCfg.ud_length    := ModuleSizeNeeded;                
                
                ret_code := ToBusInterface.NewInst(pPara:=#tempCmd, pResult:=#_result); 
                if ((ret_code <> READY) & (_result.aData[0]$t_BusIFRetvalErrorcode <> _BUS_IF_RETVAL_OK)) then                
                  ret_code := ERROR;
                  return;
                end_if;
              end_if;
              
              pResult^.uiLng := 4;
              pResult^.aData[0]$^void := #ManagerInfoBlock$^void;
            
            else
              ret_code := ERROR;
            end_if;    
          
          else
            ret_code := ERROR;
          end_if;
        end_if;
      end_if;

//**********************************************************************************************************************************************************
    SDIAS_CMD_GET_MOI_ADDR :
      // return the address of the ModuleObjInfo variable
      pResult^.uiLng := 4;
      pResult^.aData[0]$^void := #ModuleObjInfo$^void;

//**********************************************************************************************************************************************************
    CMD_GET_HARDWARE_DIAGNOSIS:
      //Returns module info
      ret_code := ERROR;
      pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.retcode := _HWC_RETVAL_ERROR;

      pStr_HWTRequested := pPara^.aPara[0]$t_HWCGetHardwareDiagnosisIn.pStr_HardewareTreeEntry;
        
      if pStr_HWTRequested & 
         ( ((pStr_HWTRequested  + pPara^.aPara[0]$t_HWCGetHardwareTreeEntryIn.us_current_index  - 1)^$USINT) = HWT_ESCAPE_SDIAS ) then
        
        tmpplace := (pStr_HWTRequested+pPara^.aPara[0]$t_HWCGetHardwareDiagnosisIn.us_current_index)^$USINT;  
        
        //Check if pointer is valid
        if ModuleObjInfo[tmpplace].pThis then
          ret_code := ModuleObjInfo[tmpplace].pThis^.NewInst(pPara,pResult);
        else
          pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.retcode := _HWC_RETVAL_ERROR_SDIAS_MODULE_NOT_FOUND;
        end_if;
      end_if;

//**********************************************************************************************************************************************************    
    CMD_GET_HARDWARE_TREE_ENTRY:
      //Returns module info
      ret_code := ERROR;
      pResult^.aData[0]$t_HWCGetHardwareTreeEntryOut.retcode := _HWC_RETVAL_ERROR;
      
      pStr_HWTreeEntry := pPara^.aPara[0]$t_HWCGetHardwareTreeEntryIn.pStr_LastHardewareTreeEntry;
      
      //First HWT Path
      if pStr_HWTreeEntry = nil then
        if ModuleObjInfo[0].pThis then
          
          ret_code := ModuleObjInfo[0].pThis^.NewInst(pPara,pResult);
        else
          pResult^.aData[0]$t_HWCGetHardwareTreeEntryOut.retcode := _HWC_RETVAL_ERROR_SDIAS_MODULE_NOT_FOUND;
        end_if;

      //search next module
      elsif ( ((pStr_HWTreeEntry  + pPara^.aPara[0]$t_HWCGetHardwareTreeEntryIn.us_current_index  - 1)^$USINT) = HWT_ESCAPE_SDIAS ) then
      
        // Check last modul again incase it was an extension module        
        usNextPlace := (pStr_HWTreeEntry  + pPara^.aPara[0]$t_HWCGetHardwareTreeEntryIn.us_current_index)^$USINT;    
        
        //Check for valid place to avoid bound exceed error
        if usNextPlace <= SDIAS_MAX_PLACE_NR then
        
          if ModuleObjInfo[usNextPlace].pThis then
          
            ret_code := ModuleObjInfo[usNextPlace].pThis^.NewInst(pPara,pResult);
          else
            ret_code := READY;
            pResult^.aData$t_HWCGetHardwareTreeEntryOut.retcode := _HWC_RETVAL_OK_END_OF_LIST;
            return;
          end_if;
        else
          ret_code := READY;
          pResult^.aData$t_HWCGetHardwareTreeEntryOut.retcode := _HWC_RETVAL_OK_END_OF_LIST;
          return;
        end_if;
        
        // Module was found, return next one
        if ret_code = READY & 
           (pResult^.aData$t_HWCGetHardwareTreeEntryOut.retcode = _HWC_RETVAL_OK_MODULE_FOUND |
            pResult^.aData$t_HWCGetHardwareTreeEntryOut.retcode = _HWC_RETVAL_OK_END_OF_LIST) then
          
          usNextPlace += 1;  
          
          //Check for valid place to avoid bound exceed error          
          if usNextPlace <= SDIAS_MAX_PLACE_NR then
            if ModuleObjInfo[usNextPlace].pThis then
            
              ret_code := ModuleObjInfo[usNextPlace].pThis^.NewInst(pPara,pResult);
            else
              ret_code := READY;
              pResult^.aData$t_HWCGetHardwareTreeEntryOut.retcode := _HWC_RETVAL_OK_END_OF_LIST;
            end_if;
          else
            ret_code := READY;
            pResult^.aData$t_HWCGetHardwareTreeEntryOut.retcode := _HWC_RETVAL_OK_END_OF_LIST;
          end_if;
        end_if;
        
      end_if;      
     
//**********************************************************************************************************************************************************    


//*****************************************************************************
//** COMMANDS FROM SDIAS MODULES                                             **
//*****************************************************************************
    
    // port number is always stored in pPara^.aPara[MAXCMDPARA-1]
//**********************************************************************************************************************************************************
		SDIAS_CMD_ADD_RD_ACCESS:
      if AddAccess(_Read, pPara^.aPara[0]$^SdiasBase, pPara^.aPara[1]$UDINT, pPara^.aPara[2], pPara^.aPara[3]$HINT, pPara^.aPara[4]$UINT, pPara^.aPara[5]$pVoid, pPara^.aPara[6]$pVoid, pPara^.aPara[7]$pVoid, pPara^.aPara[8]$^UDINT, pPara^.aPara[9]$UDINT, pPara^.aPara[10]$BOOL) = FALSE then
        ret_code := ERROR;
      end_if;

//**********************************************************************************************************************************************************
    SDIAS_CMD_ADD_WR_ACCESS:
      if AddAccess(_Write, pPara^.aPara[0]$^SdiasBase, pPara^.aPara[1]$UDINT, pPara^.aPara[2], pPara^.aPara[3]$HINT, pPara^.aPara[4]$UINT, pPara^.aPara[5]$pVoid, pPara^.aPara[6]$pVoid, pPara^.aPara[7]$pVoid, pPara^.aPara[8]$^UDINT, pPara^.aPara[9]$UDINT, pPara^.aPara[10]$BOOL) = FALSE then
        ret_code := ERROR;
      end_if;

//**********************************************************************************************************************************************************
		SDIAS_CMD_ADD_DYN_RD_ACCESS:
      if AddAccess(_ReadDynamic, pPara^.aPara[0]$^SdiasBase, pPara^.aPara[1]$UDINT, pPara^.aPara[2], pPara^.aPara[3]$HINT, pPara^.aPara[4]$UINT, pPara^.aPara[5]$pVoid, pPara^.aPara[6]$pVoid, pPara^.aPara[7]$pVoid, pPara^.aPara[8]$^UDINT, pPara^.aPara[9]$UDINT, pPara^.aPara[10]$BOOL) = FALSE then
        ret_code := ERROR;
      end_if;

//**********************************************************************************************************************************************************
    SDIAS_CMD_ADD_DYN_WR_ACCESS:
      if AddAccess(_WriteDynamic, pPara^.aPara[0]$^SdiasBase, pPara^.aPara[1]$UDINT, pPara^.aPara[2], pPara^.aPara[3]$HINT, pPara^.aPara[4]$UINT, pPara^.aPara[5]$pVoid, pPara^.aPara[6]$pVoid, pPara^.aPara[7]$pVoid, pPara^.aPara[8]$^UDINT, pPara^.aPara[9]$UDINT, pPara^.aPara[10]$BOOL) = FALSE then
        ret_code := ERROR;
      end_if;

//**********************************************************************************************************************************************************
    SDIAS_CMD_CHANGE_DYN_ACCESS:
      if ChangeDynAccess(AccessHandle:=pPara^.aPara[0]$UDINT, NewOffset:=pPara^.aPara[1]$UDINT, NewLength:=pPara^.aPara[2]$UDINT) = FALSE then
        ret_code := ERROR;
      end_if;

//**********************************************************************************************************************************************************
    SDIAS_CMD_SDO_SEND_REQUEST:     
        
      if pPara^.aPara[1]$t_SDIAS_SDO_Cmd = SDIAS_SDO_CMD_SPI_READ & FirmwareVersion < SDIAS_SDO_SPI_FIRMWARE_VERSION_AVAILABLE then
#ifdef HWC_LogError
        HWC_LogError(this, "@0069 (SdiasManager::ClassState::NewInst) SPI Read failed, Update FirmwareVersion of SDIAS Manager");
#endif
        ret_code := ERROR;
        return;
      end_if;      

      if AddSDOReq(pCmdSvr:=pPara^.aPara[0]$^SvrChCmd, Command:=pPara^.aPara[1]$t_SDIAS_SDO_Cmd, Place:=pPara^.aPara[2]$USINT, CmdLength:=pPara^.aPara[3]$USINT, pReqBuf:=pPara^.aPara[4]$^USINT) <> SDIAS_OK then
        ret_code := ERROR;
      end_if;

//**********************************************************************************************************************************************************
    SDIAS_CMD_CHANGE_LED_STATE:
      // get byte position ouf of place (place 0-3 in byte 0, 4-7 in byte 1,...)
      ByteNr := pPara^.aPara[1]$USINT SHR 2;
      PosInByte := (pPara^.aPara[1]$USINT AND 2#11) SHL 1;
      AppliLEDStates[ByteNr] := (AppliLEDStates[ByteNr] AND NOT(2#11 SHL PosInByte)) OR (pPara^.aPara[2]$USINT SHL PosInByte);
      b_NewLEDStates := TRUE;
      
//**********************************************************************************************************************************************************
    SDIAS_CMD_DA_RD_ACCESS:
      // not implemented yet
      ret_code := ERROR;

//      DaWriteBuffer.ReadLength  := pPara^.aPara[1]$USINT;
//      DaWriteBuffer.ReadOffset  := pPara^.aPara[0]$HINT;
//      DaWriteBuffer.WriteLength := 0;
//      DaWriteBuffer.WriteOffset := 0;
//    
//      DaWriteBuffer.TriggerUnit := sizeof(t_DAWrPayloadFrame) - sizeof(t_DAWrPayloadFrame.Data); // no data sent on reading
//    
//      DAPara.ud_AddOffset := DaWriteOffset;
//      DAPara.ud_length    := DaWriteBuffer.TriggerUnit;
//      DAPara.p_ud_data    := (#DaWriteBuffer)$^UDINT;
//      
//      tempCmd.uiCmd := _BUS_IF_WR_DA;
//      tempCmd.aPara[0] := (#DAPara)$DINT;
//      ToBusInterface.NewInst(pPara:=#tempCmd, pResult:=#_result); 
//
//      if _result.aData[4]$t_BusIFRetvalErrorcode <> _BUS_IF_RETVAL_OK then
//        LogError("@006A (SdiasManager::ClassState::NewInst) Direct access write on VARAN failed as part of the SDIAS direct access read!");
//        ret_code := ERROR;
//      else
//        DAPara.ud_AddOffset := DaReadOffset;
//        DAPara.ud_length    := DaWriteBuffer.ReadLength + sizeof(t_SDIAS_StateByte);
//        DAPara.p_ud_data    := (#DaReadBuffer)$^UDINT;
//
//        tempCmd.uiCmd := _BUS_IF_RD_DA;
//        tempCmd.aPara[0] := (#DAPara)$DINT;
//        ToBusInterface.NewInst(pPara:=#tempCmd, pResult:=#_result); 
//
//        if _result.aData[4]$t_BusIFRetvalErrorcode <> _BUS_IF_RETVAL_OK then
//          LogError("@006B (SdiasManager::ClassState::NewInst) Direct access read on VARAN failed as part of the SDIAS direct access read!");
//          ret_code := ERROR;
//        else
//          // copy the read data to the user memory
//          _memcpy(ptr1:=pPara^.aPara[2]$^USINT, ptr2:=#DaReadBuffer.Data, cntr:=DaWriteBuffer.ReadLength);
//        end_if;
//      end_if;
    
//**********************************************************************************************************************************************************
    SDIAS_CMD_DA_WR_ACCESS:
      // not implemented yet
      ret_code := ERROR;
      
//      DaWriteBuffer.ReadLength  := 0;
//      DaWriteBuffer.ReadOffset  := 0;
//      DaWriteBuffer.WriteLength := pPara^.aPara[1]$USINT;
//      DaWriteBuffer.WriteOffset := pPara^.aPara[0]$HINT;
//    
//      DaWriteBuffer.TriggerUnit := sizeof(t_DAWrPayloadFrame) - sizeof(t_DAWrPayloadFrame.Data) + DaWriteBuffer.WriteLength; // no data sent on reading
//    
//      // copy the write data from the user memory
//      _memcpy(ptr1:=#DaWriteBuffer.Data, ptr2:=pPara^.aPara[2]$^USINT, cntr:=DaWriteBuffer.WriteLength);
//
//      DAPara.ud_AddOffset := DaWriteOffset;
//      DAPara.ud_length    := DaWriteBuffer.TriggerUnit;
//      DAPara.p_ud_data    := (#DaWriteBuffer)$^UDINT;
//      
//      tempCmd.uiCmd := _BUS_IF_WR_DA;
//      tempCmd.aPara[0] := (#DAPara)$DINT;
//      ToBusInterface.NewInst(pPara:=#tempCmd, pResult:=#_result); 
//
//      if _result.aData[4]$t_BusIFRetvalErrorcode <> _BUS_IF_RETVAL_OK then
//        LogError("@006C (SdiasManager::ClassState::NewInst) Direct access write on VARAN failed as part of the SDIAS direct access write!");
//        ret_code := ERROR;
//      else
//        DAPara.ud_AddOffset := DaReadOffset;
//        DAPara.ud_length    := sizeof(t_SDIAS_StateByte);
//        DAPara.p_ud_data    := (#DaReadBuffer)$^UDINT;
//
//        tempCmd.uiCmd := _BUS_IF_RD_DA;
//        tempCmd.aPara[0] := (#DAPara)$DINT;
//        ToBusInterface.NewInst(pPara:=#tempCmd, pResult:=#_result); 
//
//        if _result.aData[4]$t_BusIFRetvalErrorcode <> _BUS_IF_RETVAL_OK then
//          LogError("@006D (SdiasManager::ClassState::NewInst) Direct access read on VARAN failed as part of the SDIAS direct access write!");
//          ret_code := ERROR;
//        end_if;
//      end_if;

//**********************************************************************************************************************************************************
    SDIAS_CMD_REQUIRED_ERROR:
      SetRequiredError(pTargetThis:=pPara^.aPara[0]$^SdiasBase, Place:=pPara^.aPara[1]$UDINT);

//**********************************************************************************************************************************************************
    SDIAS_CMD_INIT_STATE_LOGIN:
      Place := pPara^.aPara[1]$UDINT;
      if (Place <= SDIAS_MAX_PLACE_NR) & pPara^.aPara[0] then
        ModuleObjInfo[Place].pInitState       := pPara^.aPara[0]$^t_e_VaranErrors;
        ModuleObjInfo[Place].pThis            := pPara^.aPara[2]$^SdiasBase;

        // get task settings
        ModuleObjInfo[Place].bPreScan         := (pPara^.aPara[3] AND SDIAS_TASK_MASK_RT_PRE ) <> 0;
        ModuleObjInfo[Place].bPostScan        := (pPara^.aPara[3] AND SDIAS_TASK_MASK_RT_POST) <> 0;
        ModuleObjInfo[Place].bCyclic          := (pPara^.aPara[3] AND SDIAS_TASK_MASK_CY     ) <> 0;

        // get access structure
        ModuleObjInfo[Place].pDefaultAccesses := pPara^.aPara[4]$^t_SDIAS_DefaultAccesses;

        // required info
        ModuleObjInfo[Place].Required         := pPara^.aPara[5];

        if ModuleObjInfo[Place].Required & (b_SDIASModulesRequired = FALSE) then
          b_SDIASModulesRequired := TRUE;
          // if any access is required => the businterface is also required
          tempCmd.uiCmd := _BUS_IF_SET_REQUIRED;
          ToBusInterface.NewInst(pPara:=#tempCmd, pResult:=#_result);
          if _result.aData[0]$t_BusIFRetvalErrorcode <> _BUS_IF_RETVAL_OK then  
#ifdef HWC_LogError
            HWC_LogError(this, "@006E (SdiasManager::ClassState::NewInst) Failed to set the BusInterface to required");
#endif
          end_if;
        end_if;

        // remember the highest place to save time in module scanning operations like calling the realtime methods
        if (Place > MaxPlace) | (MaxPlace = SDIAS_PLACE_NO_MODULE_ADDED_SO_FAR) then
          MaxPlace := Place;
        end_if;
      else
        ret_code := ERROR;
      end_if;

//**********************************************************************************************************************************************************
    SDIAS_CMD_GET_HW_PATH:
      // forward it to bus interface
      pPara^.uiCmd := _BUS_IF_GET_HW_PATH;
      ret_code := ToBusInterface.NewInst(pPara, pResult);

//**********************************************************************************************************************************************************
    SDIAS_CMD_INSTALL_CYCLIC_TASK:
      ModuleObjInfo[pPara^.aPara[0]].bCyclic := TRUE;

//**********************************************************************************************************************************************************
    SDIAS_CMD_GET_CONNECTION_TYPE:
      pResult^.uiLng := sizeof(t_SDIAS_ConnectionType);
      pResult^.aData[0]$t_SDIAS_ConnectionType := ConnectionType;

//**********************************************************************************************************************************************************
    SDIAS_CMD_CREATE_MUTEX:
      // forward it to bus interface
      pPara^.uiCmd := _BUS_IF_CREATE_MUTEX;
      ret_code := ToBusInterface.NewInst(pPara, pResult);

//**********************************************************************************************************************************************************
    SDIAS_CMD_IS_VARAN_AVAILABLE:
      // forward it to bus interface
      pPara^.uiCmd := _BUS_IF_IS_VARAN_AVAILABLE;
      ret_code := ToBusInterface.NewInst(pPara, pResult);
    
//**********************************************************************************************************************************************************
    SDIAS_CMD_ADD_DEVICE_ID:
    //add valid ids to list
    for i:= 0 to 9 do
      //Check if no id is stored or if id is already stored in list.
      if aValidDeviceIDs[i] = 0 | aValidDeviceIDs[i] = pPara^.aPara[0]$UDINT then
        aValidDeviceIDs[i] := pPara^.aPara[0]$UDINT;
        exit;
      end_if;
    end_for;
    
//**********************************************************************************************************************************************************
    SDIAS_CMD_GET_SUPPORTED_FEATURES:
      
      //Set length to be flexible for future 
      pResult^.uiLng := 4; 
      pResult^.aData[0]$BDINT := SupportedFeatures;

//**********************************************************************************************************************************************************
    CMD_EXTEND_POST_INIT_TIME:
    
      // use it also for ourself
      AdditionalPostInitTime += pPara^.aPara[0]$UDINT;
    
      // forward it to bus interface
      ret_code := ToBusInterface.NewInst(pPara, pResult);    

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

//*****************************************************************************
//** COMMANDS FORWARDED BY SDIAS BUS INTERFACE                               **
//*****************************************************************************

//**********************************************************************************************************************************************************
    _BUS_IF_ADD_MOVE_DO:
      // correct the parameters, because the calling class doesn't have the information
      pDataADDMove                        := (pPara^.aPara[0])$^t_AddMoveDOCfg;

      pDataADDMove^.ud_handle_source      := ISOReadDO.AccessHandle;
      
      // if the module has no source at this time, don't calculate any addresses with the NIL pointer
      if pDataADDMove^.p_sourcedata then
        pDataADDMove^.ud_addressoff_source  := pDataADDMove^.p_sourcedata$UDINT - ISOReadDO.pData$UDINT;

        // if we have the DPRAM address extra => recalculate the address
        if ISOReadDO.pDataDPRAM then
          pDataADDMove^.p_sourcedata := ISOReadDO.pDataDPRAM + pDataADDMove^.ud_addressoff_source;
        end_if;
      end_if;

      pDataADDMove^.ud_handle_dest        := ISOWriteDO.AccessHandle;
      pDataADDMove^.ud_addressoff_dest    := pDataADDMove^.p_destdata$UDINT - ISOWriteDO.pData$UDINT;

      // if we have the DPRAM address extra => recalculate the address
      if ISOWriteDO.pDataDPRAM then
        pDataADDMove^.p_destdata := ISOWriteDO.pDataDPRAM + pDataADDMove^.ud_addressoff_dest;
      end_if;

      // forward it to bus interface
      ret_code := ToBusInterface.NewInst(pPara, pResult);

//**********************************************************************************************************************************************************
    _BUS_IF_UPDATE_MOVE_DO:
      // forward it to bus interface
      ret_code := ToBusInterface.NewInst(pPara, pResult);

//**********************************************************************************************************************************************************
    _BUS_IF_GET_ACCESS_INFO:
      // return the access info
      pResult^.uiLng := sizeof(t_AccessInfoRet);
      pAccessInfo := (#pResult^.aData[0])$^t_AccessInfoRet;
      
      // check if we got a valid pointer (local memory)
      if pPara^.aPara[0] then
        
        pAccessInfo^.ud_handle     := ISOReadDO.AccessHandle;
        pAccessInfo^.ud_addressoff := pPara^.aPara[0]$UDINT - ISOReadDO.pData$UDINT;

        // if we have the DPRAM address extra => recalculate the address
        if ISOReadDO.pDataDPRAM then
          pAccessInfo^.p_dataDPRAM := ISOReadDO.pDataDPRAM + pAccessInfo^.ud_addressoff;
        end_if;
        
        pAccessInfo^.retcode := _BUS_IF_RETVAL_OK;
      else
        pAccessInfo^.retcode := _BUS_IF_RETVAL_ERROR_INVALID_POINTER;
      end_if;

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

//*****************************************************************************
//** COMMANDS FROM BUS INTERFACE                                             **
//*****************************************************************************

//**********************************************************************************************************************************************************
    _BUS_IF_HWCONNECT :  
      // device has been connected. if there is no bus ready signal or we're in the init (no bus ready in init if module is already connected) => do the connect-stuff here
      ConnectEvent();      
      pResult^.aData[0] := _BUS_IF_RETVAL_OK;

//**********************************************************************************************************************************************************
    _BUS_IF_HWSUB_BUS_READY :
      // we wait for the device bitmap to match => do nothing here
      pResult^.aData[0] := _BUS_IF_RETVAL_OK;

//**********************************************************************************************************************************************************
    _BUS_IF_HWDISCONNECT :
      // device has been disconnected
      DisconnectEvent();
      pResult^.aData[0] := _BUS_IF_RETVAL_OK;

//**********************************************************************************************************************************************************
    _BUS_IF_HWINTERRUPT :
      // error at device which may lead to a disconnect or replace the disconnect callback
      InterruptEvent();
      pResult^.aData[0] := _BUS_IF_RETVAL_OK;

//**********************************************************************************************************************************************************
    _BUS_IF_CHECK_DEVICE_ID :
      // check for correct device id
      
      pResult^.aData[0] := (DeviceID = pPara^.aPara[0]$UDINT);
      if pResult^.aData[0] = false then
        for i:= 0 to 9 do
          //Id found?
          if aValidDeviceIDs[i] = pPara^.aPara[0]$UDINT then
            pResult^.aData[0] := TRUE;
            exit;
          end_if;
        end_for;        
      end_if;

//**********************************************************************************************************************************************************
    _BUS_IF_GET_TASK_INFO:
      // we must fetch the task info before the image with the payload is copied to ensure correct data and correct error detection

      // on local SDIAS we have to fetch it from the OS
      if ConnectionType = SDIAS_CON_LOCAL_uC then
        if SDIAS_iGetNodePropertyIndexLen(hNodeHandle   := udNodeHandle
                                     , udIndex          := 1
                                     , udPropertyId     := SDM_PROP_TASK_INFO
                                     , udBufferLength   := sizeof(t_TaskInfoData) - sizeof(t_TaskInfoData.ErrorInfoFlags) - sizeof(t_TaskInfoData.Reserved)
                                     , pucBuf           := (#RdTaskInfo.Handshake)$^USINT
                                     ) <> SDIAS_OK then
          CyclicMsgMarker.PostIt.GetRdInfoFailed := TRUE;
        end_if;
        if SDIAS_iGetNodePropertyIndex(hNodeHandle      := udNodeHandle
                                     , udIndex          := 1
                                     , udPropertyId     := SDM_PROP_TASK_ERROR_INFO_FLAGS
                                     , pudPropertyValue := (#RdTaskInfo.ErrorInfoFlags)$^UDINT
                                     ) <> SDIAS_OK then
          CyclicMsgMarker.PostIt.GetRdInfoFailed := TRUE;
        end_if;

        if SDIAS_iGetNodePropertyIndexLen(hNodeHandle   := udNodeHandle
                                     , udIndex          := 2
                                     , udPropertyId     := SDM_PROP_TASK_INFO
                                     , udBufferLength   := sizeof(t_TaskInfoData) - sizeof(t_TaskInfoData.ErrorInfoFlags) - sizeof(t_TaskInfoData.Reserved)
                                     , pucBuf           := (#WrTaskInfo.Handshake)$^USINT
                                     ) <> SDIAS_OK then
          CyclicMsgMarker.PostIt.GetWrInfoFailed := TRUE;

        end_if;
        if SDIAS_iGetNodePropertyIndex(hNodeHandle      := udNodeHandle
                                     , udIndex          := 2
                                     , udPropertyId     := SDM_PROP_TASK_ERROR_INFO_FLAGS
                                     , pudPropertyValue := (#WrTaskInfo.ErrorInfoFlags)$^UDINT
                                     ) <> SDIAS_OK then
          CyclicMsgMarker.PostIt.GetWrInfoFailed := TRUE;
        end_if;
      end_if;      

//**********************************************************************************************************************************************************
    _BUS_IF_POST_INIT_RT_READY:
      // if we got an error => return it
      if InitSSW = _ErrorOccured then
        ret_code := ERROR;
        
      // if we're not ready, return busy
      elsif RtSSW <> _Operational then
        ret_code := BUSY;
      end_if;      

//**********************************************************************************************************************************************************      
    CMD_GET_HW_TIMESTAMP:    
      
      if RtSSW = _Operational then
        // SDIASManager gets Time every RtPreScan, no need to pass on the command
        ret_code := READY;
        
        pResult^.uiLng      := sizeof(t_GetHwTimestampResult);
        pResult^.aData[0]$t_GetHwTimestampResult.udVersion   := 1;
        pResult^.aData[0]$t_GetHwTimestampResult.uiTimeStamp := uiHWTimestamp;
      else
        // forward it to bus interface
        ret_code := ToBusInterface.NewInst(pPara, pResult);
      end_if;      
      
//**********************************************************************************************************************************************************
    CMD_HWC_REQ_PLLNS_REGULATION:
      // forward it to bus interface
      ret_code := ToBusInterface.NewInst(pPara, pResult);

//**********************************************************************************************************************************************************
    _BUS_IF_CREATE_MUTEX,
    _BUS_IF_SET_REQUIRED_ERROR,
    _BUS_IF_GET_BUSCYCLE_TIME,
    _BUS_IF_GET_DEACTIVATED_STATE,
    _BUS_IF_GET_HW_PATH,
    _BUS_IF_IS_VARAN_AVAILABLE,
    _BUS_IF_SET_RUN_STATE,
    _BUS_IF_SET_REQUIRED:    
      // forward it to bus interface
      ret_code := ToBusInterface.NewInst(pPara, pResult);
//**********************************************************************************************************************************************************


//*****************************************************************************
//** COMMANDS FROM SDIAS MANAGER ITSELF                                      **
//*****************************************************************************


//**********************************************************************************************************************************************************
		SDIAS_CMD_SDO_RESPONSE:      
      ret_code := ReceiveSDOResponse(Command:=pPara^.aPara[0]$t_SDIAS_SDO_Cmd,
                                     Offset:=pPara^.aPara[1]$HINT,
                                     Length:=pPara^.aPara[2]$USINT, 
                                     Result:=pPara^.aPara[3]$iprStates, 
                                     pResponseBuffer:=pPara^.aPara[4]$^USINT, 
                                     ResponseLength:=pPara^.aPara[5]$USINT
                                     );
      
//**********************************************************************************************************************************************************
  else
    // unknown command
    if bUnknownCmdLogged = FALSE then
      bUnknownCmdLogged := TRUE;
#ifdef HWC_LogValue1
      HWC_LogValue1(this, "@006F (SdiasManager::ClassState::NewInst) [SL] Unknown command: 0x{0}", pPara^.uiCmd);
#endif
    end_if;
    
    ret_code := ERROR;
	END_CASE;

END_FUNCTION


FUNCTION VIRTUAL SdiasManager::AddAccess
	VAR_INPUT
		AccessType 	: t_eAccessType;
		pThis 	: ^SdiasBase;
		Place 	: UDINT;
		Required 	: DINT;
		Offset 	: HINT;
		Length 	: UINT;
		ppData 	: pVoid;
		ppStateByte 	: pVoid;
		ppControlByte 	: pVoid;
		pAccessHandle 	: ^UDINT;
		WaitForAccessHandle 	: UDINT;
		bCtrlAcc0 	: BOOL;
	END_VAR
	VAR_OUTPUT
		Success 	: BOOL;
	END_VAR
      
  // check place
  if Place <= SDIAS_MAX_PLACE_NR then
    // check this pointer
    if pThis then
      // check other pointers as input parameters
      if ppData & ppStateByte & ppControlByte then
        // check offset and length for valid access
        if (Length > 0) & ((Offset + Length) <= SIZE_PER_SDIAS_CLIENT) then

          // remember the highest place to save time in module scanning operations like calling the realtime methods
          if (Place > MaxPlace) | (MaxPlace = SDIAS_PLACE_NO_MODULE_ADDED_SO_FAR) then
            MaxPlace := Place;
          end_if;
          
          // if it's a dynamic access on local SDIAS, check if the OS-Interface is available
          if ConnectionType = SDIAS_CON_LOCAL_uC then
            if ((AccessType = _ReadDynamic) | (AccessType = _WriteDynamic)) & (pSDIAS^.udVersion < SDIAS_CIL_VERSION_SUPPORTS_DYNAMIC_DO) then
#ifdef HWC_LogValue1
              HWC_LogValue1(this, "@0070 (SdiasManager::AddAccess) Newer OS Version needed for dynamic accesses on local SDIAS. Access for module at place 0x{0} can't be created!", Place);
#endif
              ModuleObjInfo[Place].pInitState^ := _UnknownCommand;
              InitError := _UnknownCommand;
              Success := FALSE;
              return;
            end_if;
          end_if;
          
          // remember the access
          Success := AddAccessToList(AccessType           := AccessType,
                                     Place                := Place, 
                                     Offset               := Offset, 
                                     Length               := Length, 
                                     ppData               := ppData, 
                                     ppStateByte          := ppStateByte, 
                                     ppControlByte        := ppControlByte,
                                     pAccessHandle        := pAccessHandle,
                                     WaitForAccessHandle  := WaitForAccessHandle,
                                     bCtrlAcc0            := bCtrlAcc0,
                                     bIsFarAcc            := FALSE
                                     );

          // if adding failed classstate and initerrorstate are already set
          if Success = FALSE then
#ifdef HWC_LogValue1
            HWC_LogValue1(this, "@0071 (SdiasManager::AddAccess) Failed to add Access for Module at Place 0x{0}", Place);
#endif
          end_if;
        else  //add far memory access
          if (Length > 0) & (Length <= SDIAS_MAX_SIZE_FAR_MEM_ACCESS) & ((Offset + Length) > SIZE_PER_SDIAS_CLIENT) & 
             ((Offset + Length) <= (SDIAS_1K_BLOCK_NO*SIZE_PER_SDIAS_CLIENT)) & (bCtrlAcc0 = FALSE) & FarMemoryAccessAvailable() then          
            // remember the access
            Success := AddAccessToList(AccessType           := AccessType,
                                       Place                := Place, 
                                       Offset               := Offset, 
                                       Length               := Length, 
                                       ppData               := ppData, 
                                       ppStateByte          := ppStateByte, 
                                       ppControlByte        := ppControlByte,
                                       pAccessHandle        := pAccessHandle,
                                       WaitForAccessHandle  := WaitForAccessHandle,
                                       bCtrlAcc0            := bCtrlAcc0,
                                       bIsFarAcc            := TRUE
                                       );

            // if adding failed classstate and initerrorstate are already set
            if Success = FALSE then
#ifdef HWC_LogValue1
              HWC_LogValue1(this, "@00DA (SdiasManager::AddAccess) Failed to add far memory access for Module at Place 0x{0}!", Place);
#endif

            end_if;
          else
#ifdef HWC_LogValue3
            HWC_LogValue3(this, "@0072 (SdiasManager::AddAccess) Invalid access for module at place: 0x{0}. Check offset (0x{1}) and length (0x{2})!", Place, Offset, Length);
#endif
            ModuleObjInfo[Place].pInitState^ := _DOLAddressInvalid;
            InitError := _DOLAddressInvalid;
            Success := FALSE;
          end_if;
        end_if;
      else
#ifdef HWC_LogValue1
        HWC_LogValue1(this, "@0073 (SdiasManager::AddAccess) Invalid pointer as input parameter for module at place: 0x{0}", Place);
#endif
        ModuleObjInfo[Place].pInitState^ := _MemoryFault;
        InitError := _MemoryFault;
        Success := FALSE;
      end_if;
    else
#ifdef HWC_LogValue1
      HWC_LogValue1(this, "@0074 (SdiasManager::AddAccess) Invalid this pointer for module at place: 0x{0}", Place);
#endif
      ModuleObjInfo[Place].pInitState^ := _MemoryFault;
      InitError := _MemoryFault;
      Success := FALSE;
    end_if;
  else
#ifdef HWC_LogValue2
    HWC_LogValue2(this, "@0075 (SdiasManager::AddAccess) Invalid Place number: 0x{0}. Maximum is 0x{1}", Place, SDIAS_MAX_PLACE_NR);
#endif
    if pThis then
      pThis^.ClassState := _InvalidDeviceAddress;
    end_if;
    InitError := _InvalidDeviceAddress;
    Success := FALSE;
  end_if;
  
  // if it was an access of a required module => required error
  if Required & (Success = FALSE) then
    SetRequiredError(pThis, Place);
  end_if;

END_FUNCTION


FUNCTION VIRTUAL SdiasManager::ConnectEvent
  VAR
  	tempCmd         : CmdStruct;
    _result         : results;
    dataResetDO     : t_ResetDOCfg;
    Settings        : t_LoginSettings;
  END_VAR
  
  if b_PostInitFinished = FALSE then
    ConnectDuringPostInitCounter += 1;

    // don't reinit in postinit (ignore call from OS)
    if ConnectDuringPostInitCounter >= 2 then
      b_MultipleConnectInInit := TRUE;
      return;
    end_if;
  end_if; 

  // install post init call back only if we're still in init (if we install it in init(), we may get called even the module is not connected)
  if us_Firstscan < 12 then
    tempCmd.uiCmd := _BUS_IF_WAIT_4_POST_INIT;
#pragma warning(disable: 74);
    Settings := 0;
#pragma warning(default: 74);
    Settings.Wait4DOCreation := MaxPlace <> SDIAS_PLACE_NO_MODULE_ADDED_SO_FAR;
    if Settings.Wait4DOCreation & (ConnectionType = SDIAS_CON_VIA_VARAN_uC) then
      Settings.Wait4MoveDOCreation := TRUE;
    end_if;
    Settings.Wait4SyncSend := TRUE;

    tempCmd.aPara[0] := Settings;
    ToBusInterface.NewInst(pPara:=#tempCmd, pResult:=#_result);

    if _result.aData[0]$t_BusIFRetvalErrorcode <> _BUS_IF_RETVAL_OK then
#ifdef HWC_LogError
      HWC_LogError(this, "@0076 (SdiasManager::ConnectEvent) Failed to install post init callback");
#endif
      InitError := _InvalidConfguration;
    end_if;
  else
    b_PostInitFinished := TRUE;    
  end_if;

  if ConnectionType = SDIAS_CON_VIA_VARAN_uC then
  

    // reset data objects (calculate retry timeout)
    tempCmd.uiCmd     := _BUS_IF_RESET_DO;
    tempCmd.aPara[0]  := (#dataResetDO)$DINT;
    
    dataResetDO.Handle := ASYReadDO.Handle;

    ToBusInterface.NewInst(pPara:=#tempCmd, pResult:=#_result);
    if _result.aData[0]$t_BusIFRetvalErrorcode <> _BUS_IF_RETVAL_OK then
#ifdef HWC_LogError
      HWC_LogError(this, "@0077 (SdiasManager::ConnectEvent) Failed reset DO for the asynchronous read data");
#endif
    end_if;

    dataResetDO.Handle := ASYWriteDO.Handle;

    ToBusInterface.NewInst(pPara:=#tempCmd, pResult:=#_result);
    if _result.aData[0]$t_BusIFRetvalErrorcode <> _BUS_IF_RETVAL_OK then
#ifdef HWC_LogError
      HWC_LogError(this, "@0078 (SdiasManager::ConnectEvent) Failed reset DO for the asynchronous write data");
#endif
    end_if;
  end_if;

  if ConnectionType = SDIAS_CON_VIA_VARAN_uC then
    // set online server first on 1 if data is valid
    tempCmd.uiCmd    := _BUS_IF_SET_ONLINE;
    tempCmd.aPara[0] := 0;
    
    ToBusInterface.NewInst(pPara:=#tempCmd, pResult:=#_result);
    
    if _result.aData[0]$t_BusIFRetvalErrorcode <> _BUS_IF_RETVAL_OK then
#ifdef HWC_LogError
      HWC_LogError(this, "@0079 (SdiasManager::ConnectEvent) Failed to set Online server.");
#endif
    end_if;
  end_if;  

  // reset max durations as it marks the first run
  WriteTaskInfo.MaxDuration := 0;
  ReadTaskInfo.MaxDuration := 0;

  InitSSW     := _StartInit;
  b_Ready4Rt  := FALSE;
  RtSSW       := _RtIdle;
  ClassState  := _NotInitialized;
  Online      := 1;

END_FUNCTION


FUNCTION VIRTUAL SdiasManager::DisconnectEvent
  VAR
  	i : UDINT;
  END_VAR
  
  // if there is a required error, we would disguise it, if we call the disconnect interfaces
  if ClassState <> _RequiredError then
  
    // tell all the connected modules
    if MaxPlace <> SDIAS_PLACE_NO_MODULE_ADDED_SO_FAR then
      for i := 0 to MaxPlace do
        if ModuleObjInfo[i].pThis then
          ModuleObjInfo[i].pThis^.DisconnectEvent();
        end_if;
      end_for;
    end_if;
    
    ClassState := _NoHardware;
    
    FirmwareVersion := 0;
  end_if;
  
  Online := 0;

END_FUNCTION


FUNCTION VIRTUAL SdiasManager::InterruptEvent

  // set only the state (we're in the interrupt and have to be fast)
  if b_IsRequired then
    ClassState := _HardwareRequiredIRQ;
  else
    ClassState := _HardwareNotRequiredIRQ;
  end_if;

  Online := 0;

END_FUNCTION


FUNCTION SdiasManager::SdiasManager
	VAR_OUTPUT
		ret_code 	: ConfStates;
	END_VAR

  ClassState := _NotInitialized;

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

  //get pointer for sdias function
	if OS_CILGET( INTERFACE_SDIAS, #pSDIAS ) then
#ifdef HWC_LogError
    HWC_LogError(this, "@007A (SdiasManager::SdiasManager) Failed to get SDIAS OS-Interface. A newer OS is necessary to use SDIAS");
#endif
  end_if;

  if (OS_CILGet("LSL_MULTITASK", #mt_api$void)) THEN
#ifdef HWC_LogError
    HWC_LogError(this, "@007B (SdiasManager::SdiasManager) Failed to get MULTITASK OS-Interface for Mutex usage");
#endif
  end_if;
  
  //Get pointer for pll interface for sync out settings
  OS_CILGet(INTERFACE_PLL, #pPLL$void); //No LogError because not every CPU has an PLL Interface

  MaxPlace := SDIAS_PLACE_NO_MODULE_ADDED_SO_FAR;
  
  //Set Supported Features of the sdias manager class
  SupportedFeatures.DefAcc4InitAcc := TRUE;

	ret_code := C_OK;

END_FUNCTION


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

  if (AsyReadUsage = _NotUsed) | (AsyReadUsage = UsageType) then

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

      dataUPDATEDO.Handle               := ASYReadDO.Handle;
      dataUPDATEDO.ud_addressoff_read   := ASYReadDO.Offset;
      dataUPDATEDO.ud_length_read       := ASYReadDO.Length;

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

      ToBusInterface.NewInst(pPara:=#tempCmd, pResult:=#_result); 
      if _result.aData[0]$t_BusIFRetvalErrorcode <> _BUS_IF_RETVAL_OK then  
#ifdef HWC_LogError
        HWC_LogError(this, "@007C (SdiasManager::ChangeAsyRd) Failed to change asynchron read access");
#endif
      end_if;
    end_if;
    
    // set runstate
    dataSETRUNSTATE.Handle      := ASYReadDO.Handle;
    dataSETRUNSTATE.NewRunState := RunState;
    
    tempCmd.uiCmd         := _BUS_IF_SET_RUN_STATE;  
    tempCmd.aPara[0]      := (#dataSETRUNSTATE)$DINT; 
   
    ToBusInterface.NewInst(pPara:=#tempCmd, pResult:=#_result); 
    
    if _result.aData[0]$t_BusIFRetvalErrorcode <> _BUS_IF_RETVAL_OK then
#ifdef HWC_LogError
      HWC_LogError(this, "@007D (SdiasManager::ChangeAsyRd) Error changing the run state of the asynchron read access!");
#endif
    end_if; 
    
    if RunState = _BUS_IF_RUN_STATE_NO_RUN then
      AsyReadUsage := _NotUsed;
    else
      AsyReadUsage := UsageType;
    end_if;
    
    Success := TRUE;
  else
#ifdef HWC_LogError
    HWC_LogError(this, "@007E (SdiasManager::ChangeAsyRd) Failed to use DO (already in use by another task)");
#endif
    Success := FALSE;
  end_if;

END_FUNCTION


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

  if (AsyWriteUsage = _NotUsed) | (AsyWriteUsage = UsageType) then
    // if a watchdog trigger has to be sent, ignore other requests
    if b_SendWdTrigger & (UsageType <> _UsedByWD) then
      AsyWriteUsage := _UsedByWD;
      Success := FALSE;
      return;
    end_if;
    
    // if length = zero we may just want to stop the DO
    if Length then
      ASYWriteDO.Offset := Offset;
      ASYWriteDO.Length := Length;

      dataUPDATEDO.Handle               := ASYWriteDO.Handle;
      dataUPDATEDO.ud_addressoff_write  := ASYWriteDO.Offset;
      dataUPDATEDO.ud_length_write      := ASYWriteDO.Length;

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

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

    // set runstate
    dataSETRUNSTATE.Handle      := ASYWriteDO.Handle;
    dataSETRUNSTATE.NewRunState := RunState;
    
    tempCmd.uiCmd         := _BUS_IF_SET_RUN_STATE;  
    tempCmd.aPara[0]      := (#dataSETRUNSTATE)$DINT; 
   
    ToBusInterface.NewInst(pPara:=#tempCmd, pResult:=#_result); 
    
    if _result.aData[0]$t_BusIFRetvalErrorcode <> _BUS_IF_RETVAL_OK then
#ifdef HWC_LogError
      HWC_LogError(this, "@0080 (SdiasManager::ChangeAsyWr) Error changing the run state of the asynchron write access!");
#endif
    end_if;  
    
    if RunState = _BUS_IF_RUN_STATE_NO_RUN then
      AsyWriteUsage := _NotUsed;
    else
      AsyWriteUsage := UsageType;
    end_if;
    
    Success := TRUE;
  else
    // only print the message if there is no collision with watchdog (collision with watchdog is very likely)
    if (AsyWriteUsage <> _UsedByWD) & (UsageType <> _UsedByWD) then
#ifdef HWC_LogError
      HWC_LogError(this, "@0081 (SdiasManager::ChangeAsyWr) Failed to use DO (already in use by another task)");
#endif
    end_if;

    Success := FALSE;
  end_if;

END_FUNCTION


FUNCTION VIRTUAL SdiasManager::AddAccessToList
	VAR_INPUT
		AccessType 	: t_eAccessType;
		Place 	: UDINT;
		Offset 	: HINT;
		Length 	: UINT;
		ppData 	: pVoid;
		ppStateByte 	: pVoid;
		ppControlByte 	: pVoid;
		pAccessHandle 	: ^UDINT;
		WaitForAccessHandle 	: UDINT;
		bCtrlAcc0 	: BOOL;
		bIsFarAcc 	: BOOL;
	END_VAR
	VAR_OUTPUT
		Success 	: BOOL;
	END_VAR
  VAR
    pHelpAccess : ^t_AccessElement;
  END_VAR

  if ModuleObjInfo[Place].pFirstAccess = NIL then
    ModuleObjInfo[Place].pFirstAccess$pVoid := ToStdLib.Malloc(size:=sizeof(t_AccessElement));
    pHelpAccess := ModuleObjInfo[Place].pFirstAccess;    
  else
    pHelpAccess := ModuleObjInfo[Place].pFirstAccess;
    while pHelpAccess^.pNext <> NIL do
      pHelpAccess := pHelpAccess^.pNext;
    end_while;
    pHelpAccess^.pNext$pVoid := ToStdLib.Malloc(size:=sizeof(t_AccessElement));
    pHelpAccess := pHelpAccess^.pNext;
  end_if;
  
  if pHelpAccess <> NIL then
    pHelpAccess^.eAccessType                  := AccessType;
    pHelpAccess^.usPlace                      := Place$USINT;
    pHelpAccess^.hiOffset                     := Offset;
    pHelpAccess^.uiLength                     := Length;
    pHelpAccess^.ppData                       := ppData;
    pHelpAccess^.ppStateByte                  := ppStateByte$^t_SDIAS_pStateByte;
    pHelpAccess^.ppControlByte                := ppControlByte$^t_SDIAS_pControlByte;
    pHelpAccess^.pWaitForAccess               := WaitForAccessHandle$^t_AccessElement;
    pHelpAccess^.udOSDOHandle                 := NIL;
    pHelpAccess^.pNext                        := NIL;
    pHelpAccess^.bCtrlAcc0                    := bCtrlAcc0;
    pHelpAccess^.bIsFarAcc                    := bIsFarAcc;
    
    // count the data for the varan payload frames
    case AccessType of
      _Read:
          ISOWriteDO.Length += sizeof(t_SDIAS_ControlByte); // control byte
          ISOReadDO.Length  += sizeof(t_SDIAS_StateByte) + Length; // state byte + data length
          
      _Write:
          ISOWriteDO.Length += sizeof(t_SDIAS_ControlByte) + Length; // control byte + data length
          ISOReadDO.Length  += sizeof(t_SDIAS_StateByte); // state byte;

      _ReadDynamic:
          ISOWriteDO.Length += sizeof(t_SDIAS_ControlStructDynamic); // control byte + length info + offset info
          ISOReadDO.Length  += sizeof(t_SDIAS_StateByte) + Length; // state byte + data length
          
      _WriteDynamic:
          ISOWriteDO.Length += sizeof(t_SDIAS_ControlStructDynamic) + Length; // control byte + length info + offset info + data length
          ISOReadDO.Length  += sizeof(t_SDIAS_StateByte); // state byte;
    end_case;
    
    // only for easier debugging
    ModuleObjInfo[Place].AccessNo += 1;
    
    if pAccessHandle then
      pAccessHandle^ := pHelpAccess$UDINT;
    end_if;
    
    Success := TRUE;
  else
    ClassState := _MemoryFault;
    InitError := _MemoryFault;
#ifdef HWC_LogError
    HWC_LogError(this, "@0082 (SdiasManager::AddAccessToList) Failed to allocate memory for an SDIAS Access");
#endif

    if pAccessHandle then
      pAccessHandle^ := 0;
    end_if;

    Success := FALSE;
  end_if;

END_FUNCTION

FUNCTION VIRTUAL SdiasManager::AddBroadCastAccessesToList
  VAR
    i : USINT;
  END_VAR  

  // Memory for Access data is already held by SDIAS Manager, No need for pHelpAccess  
  
  // count the data for the varan payload frames
  // Access type is control broadcast 2 Byte, Read 0 Byte
  if SupportedFeatures.TimeBroadCastSupported then
    for i := 0 to SDIAS_NR_TIMEBROADCAST_DOS - 1 do
      ISOWriteDO.Length += sizeof(t_SDIAS_ControlByte) + sizeof(UINT);  // control byte + data length
      ISOReadDO.Length  += sizeof(t_SDIAS_StateByte);                   // state byte
    end_for;
  end_if;
  
END_FUNCTION

FUNCTION VIRTUAL SdiasManager::CheckTimeBroadCastSupported
	VAR_OUTPUT
		bTimeBroadCastSupported 	: BOOL;
	END_VAR  
  VAR    
    tempCmd             : CmdStruct;
    _result             : results;
    retval              : iprStates; 
  END_VAR
  
  // Countercheck
  bTimeBroadCastSupported := TRUE;
  
  // Check if broadcast command is supported by OS
  if ConnectionType = SDIAS_CON_LOCAL_uC then
  
    // OS is only needed for local SDIAS
    if (pSDIAS^.udVersion < SDIAS_CILVERSION_BROADCAST) then
      bTimeBroadCastSupported := FALSE;
    end_if;

  end_if;  

  // Check if broadcast command is supported SDIAS Manager  
  if FeatureInfo.ProtocolVersion < SDIAS_PROTOCOLVERSION_BROADCAST then
    bTimeBroadCastSupported := FALSE;
  end_if;  
  
  // Timestamp of HWControl must be valid
  tempCmd.uiCmd := CMD_GET_HW_TIMESTAMP;
  tempCmd.aPara[0]$t_GetHwTimestampCmd.udVersion    := 1;
  tempCmd.aPara[0]$t_GetHwTimestampCmd.udCoreSelect := 0;
  
  _result.aData[0]$t_GetHwTimestampResult.udVersion := 0; // Init return Value incase command is not implemented in HWControl
  
  retval := ToBusInterface.NewInst(#tempCmd, #_result);
  
  if retval <> READY then
    bTimeBroadCastSupported := FALSE;
  elsif _result.aData[0]$t_GetHwTimestampResult.udVersion < 1 then
    bTimeBroadCastSupported := FALSE;
  end_if;
  
END_FUNCTION

FUNCTION VIRTUAL SdiasManager::ReceiveSDOResponse
	VAR_INPUT
		Command 	: t_SDIAS_SDO_Cmd;
		Offset 	: HINT;
		Length 	: USINT;
		Result 	: iprStates;
		pResponseBuffer 	: ^USINT;
		ResponseLength 	: USINT;
	END_VAR
	VAR_OUTPUT
		ret_code 	: iprStates;
	END_VAR
  
  ret_code := READY;

  case Command of
    SDIAS_SDO_CMD_REBUILD_SDIAS:
      // if it succeeded, check if we have something to do
      if Result = READY then
        // everthing is fine
      else
        // an error occured while performing the operation
#ifdef HWC_LogError
        HWC_LogError(this, "@0083 (SdiasManager::ReceiveSDOResponse) Rebuild SDIAS SDO command failed!");
#endif
      end_if;
    SDIAS_SDO_CMD_SET_NEW_END:
      // if it succeeded, check if we have something to do
      if Result = READY then
        // everthing is fine
        bReceivedNewEndRsp := TRUE;
      else
        // an error occured while performing the operation
#ifdef HWC_LogError
        HWC_LogError(this, "@0084 (SdiasManager::ReceiveSDOResponse) Set new DOL end command failed!");
#endif
      end_if;    
    
      
      
  else
    ret_code := ERROR;
#ifdef HWC_LogError
    HWC_LogError(this, "@0085 (SdiasManager::ReceiveSDOResponse) Invalid command in SDO response!");
#endif
  end_case;
  
END_FUNCTION


FUNCTION VIRTUAL SdiasManager::AddSDOReq
	VAR_INPUT
		pCmdSvr 	: ^SvrChCmd;
		Command 	: t_SDIAS_SDO_Cmd;
		Place 	: USINT;
		CmdLength 	: USINT;
		pReqBuf 	: ^USINT;
	END_VAR
	VAR_OUTPUT
		sd_retval 	: DINT;
	END_VAR

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

  // if the buffer is full, or the next element in the buffer is already in use
  if (SDOHandling.pWrite^.Command <> SDIAS_SDO_CMD_INVALID) then
    sd_retval := SDIAS_MAILBOX_FULL;
    OS_MT_SIGNAL(pv_Mutex);
    return;
  end_if;

  // check the pointer first (if needed)
  if CmdLength then
    if pReqBuf then
      _memcpy(ptr1:=#SDOHandling.pWrite^.ReqBufData, ptr2:=pReqBuf, cntr:=CmdLength);
    else
      sd_retval := SDIAS_INVALID_PARAM_DATA_BUFFER;
      OS_MT_SIGNAL(pv_Mutex);
      return;
    end_if;
  end_if;
  
  SDOHandling.pWrite^.pCallBackSvr := pCmdSvr;
  SDOHandling.pWrite^.NMTCommand := 0;
  SDOHandling.pWrite^.SDIASPlace := Place;
  SDOHandling.pWrite^.CmdLength := CmdLength;

  case Command of
    SDIAS_SDO_CMD_MEM_READ,
    SDIAS_SDO_CMD_MEM_WRITE,
    SDIAS_SDO_CMD_CTRL_READ,
    SDIAS_SDO_CMD_CTRL_WRITE:
//    SDIAS_SDO_CMD_SPI_READ,
//    SDIAS_SDO_CMD_SPI_WRITE:
      // store offset and length for read and write accesses
      SDOHandling.pWrite^.RdWrHead := pReqBuf^$t_SDIAS_SDO_RdWr_Head;
    SDIAS_SDO_CMD_SPI_READ,
    SDIAS_SDO_CMD_SPI_WRITE:
      
      // store offset and length for read and write accesses
      SDOHandling.pWrite^.RdWrHead := pReqBuf^$t_SDIAS_SDO_RdWr_Head;
    
  end_case;
  
  // command is the last thing to store, because it indicates a complete entry
  SDOHandling.pWrite^.Command := Command;

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

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

  sd_retval := SDIAS_OK;
  
  OS_MT_SIGNAL(pv_Mutex);
  
END_FUNCTION


FUNCTION VIRTUAL SdiasManager::CyclicSDOHandling
  VAR
  	i,j           : USINT;
    FoundIt       : BOOL;
		Offset 	      : HINT;
		Length 	      : USINT;
    pTempChannel  : ^t_SDOChannel;
    TempChannel   : t_SDOChannel;
    pRingBufEntry : ^t_SDORingBufEntry;
    FirstFound    : USINT;
    LastFound     : USINT;
    Channels2Add  : DINT;
    StartIndex    : USINT;
    EndIndex      : USINT;
    pCmdSvr       : ^SvrChCmd;
  	tempCmd       : CmdStruct;
    _result       : results;
    ReceiveBuffer : ARRAY [0..127] OF USINT;
    ReceiveLength : UDINT;
    sd_retval     : DINT;
    TempUDINT     : UDINT;
    OldChannelNo  : USINT;
  END_VAR

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


  if ConnectionType = SDIAS_CON_VIA_VARAN_uC then

    // check sdo response first. if a channel is ready it can be used for the next request

    // GET SDO RESPONSE
    if (AsyReadUsage = _NotUsed) | (AsyReadUsage = _UsedBySDO) then

      // if the AsyRdDO is used for polling, we check if we got a response
      if AsyReadUsage = _UsedBySDO then      
        StartIndex := ((ASYReadDO.Offset - SDOHandling.OffsetSDOResp) / sizeof(t_SDOChannel))$USINT;
        EndIndex := StartIndex + (ASYReadDO.Length / sizeof(t_SDOChannel))$USINT - 1;
        Offset := 0;
        for i := StartIndex to EndIndex do
          if SDOHandling.aChannelData[i].WaitForResponse then
            // check for the response (copy only header first)
            _memcpy(ptr1:=#TempChannel, ptr2:=ASYReadDO.pData$^t_SDOChannel + Offset, cntr:=sizeof(t_SDOChannel) - sizeof(t_SDOChannel.Data));
            pRingBufEntry := SDOHandling.aChannelData[i].pActElement;
            
            // if the header info is mirrored, the SDO is ready
            if ((TempChannel.MessageCounter AND SDIAS_MASK_MESSAGE_COUNTER) = pRingBufEntry^.MessageCounter) &
               (TempChannel.SDIASPlace = pRingBufEntry^.SDIASPlace) &
               (TempChannel.Command$t_SDIAS_SDO_Cmd = pRingBufEntry^.Command) then
              
              // we got our response
              SDOHandling.aChannelData[i].WaitForResponse := FALSE;
              SDOHandling.EntriesUsed -= 1;
              
              // check for error
              if (TempChannel.MessageCounter AND SDIAS_MASK_GLOBAL_ERROR_FLAG) then
                tempCmd.aPara[3] := ERROR;
                // copy error info
                _memcpy(ptr1:=#TempChannel.Data, ptr2:=ASYReadDO.pData + t_SDOChannel.Data + Offset, cntr:=TempChannel.LengthOfData);
                
                // show error info
                case TempChannel.Data$DINT of              
                  SDIAS_SDO_ERROR_INVALID_MSG_CNT:
#ifdef HWC_LogValue1
                    HWC_LogValue1(this, "@0086 (SdiasManager::CyclicSDOHandling) SDO Error 0x{0}: Invalid message counter", TempChannel.Data$UDINT);
#endif
                    
                  SDIAS_SDO_ERROR_MSG_CNT_NOT_SUCCESSIVE:
#ifdef HWC_LogValue1
                    HWC_LogValue1(this, "@0087 (SdiasManager::CyclicSDOHandling) SDO Error 0x{0}: Message counter not successive", TempChannel.Data$UDINT);
#endif
                    
                  SDIAS_SDO_ERROR_INVALID_CMD:
#ifdef HWC_LogValue1
                    HWC_LogValue1(this, "@0088 (SdiasManager::CyclicSDOHandling) SDO Error 0x{0}: Invalid command", TempChannel.Data$UDINT);
#endif
                    
                  SDIAS_SDO_ERROR_INVALID_SUBCMD:
#ifdef HWC_LogValue1
                    HWC_LogValue1(this, "@0089 (SdiasManager::CyclicSDOHandling) SDO Error 0x{0}: Invalid subcommand", TempChannel.Data$UDINT);
#endif
                    
                  SDIAS_SDO_ERROR_INVALID_PLACE:
#ifdef HWC_LogValue1
                    HWC_LogValue1(this, "@008A (SdiasManager::CyclicSDOHandling) SDO Error 0x{0}: Invalid SDIAS Place", TempChannel.Data$UDINT);
#endif
                    
                  SDIAS_SDO_ERROR_INVALID_CMD_LENGTH:
#ifdef HWC_LogValue1
                    HWC_LogValue1(this, "@008B (SdiasManager::CyclicSDOHandling) SDO Error 0x{0}: Invalid length of data bytes", TempChannel.Data$UDINT);
#endif
                    
                  SDIAS_SDO_ERROR_INVALID_ACCESS_OFFSET:
#ifdef HWC_LogValue1
                    HWC_LogValue1(this, "@008C (SdiasManager::CyclicSDOHandling) SDO Error 0x{0}: Invalid offset for access", TempChannel.Data$UDINT);
#endif
                    
                  SDIAS_SDO_ERROR_INVALID_ACCESS_LENGTH:
#ifdef HWC_LogValue1
                    HWC_LogValue1(this, "@008D (SdiasManager::CyclicSDOHandling) SDO Error 0x{0}: Invalid length for access", TempChannel.Data$UDINT);
#endif
                    
                  SDIAS_SDO_ERROR_INTERNAL_TIMEOUT:
#ifdef HWC_LogValue1
                    HWC_LogValue1(this, "@008E (SdiasManager::CyclicSDOHandling) SDO Error 0x{0}: Internal timeout", TempChannel.Data$UDINT);
#endif
                    
                  SDIAS_SDO_ERROR_GENERAL_ERROR:
#ifdef HWC_LogValue1
                    HWC_LogValue1(this, "@008F (SdiasManager::CyclicSDOHandling) SDO Error 0x{0}: General Error", TempChannel.Data$UDINT);
#endif

                  SDIAS_SDO_ERROR_MSG_CNT_CHANGED:
#ifdef HWC_LogValue1
                    HWC_LogValue1(this, "@0090 (SdiasManager::CyclicSDOHandling) SDO Error 0x{0}: Message counter changed while SDO request was processed", TempChannel.Data$UDINT);
#endif

                  SDIAS_SDO_ERROR_CLIENT_NOT_READY:
#ifdef HWC_LogValue1
                    HWC_LogValue1(this, "@0091 (SdiasManager::CyclicSDOHandling) SDO Error 0x{0}: Communication error between SDIAS Manager and SDIAS Client", TempChannel.Data$UDINT);
#endif
                  
                  SDIAS_SDO_ERROR_MNG_DPRAM_FAILURE:
#ifdef HWC_LogValue1
                    HWC_LogValue1(this, "@0092 (SdiasManager::CyclicSDOHandling) SDO Error 0x{0}: Error accessing the SDIAS Manager DPRAM", TempChannel.Data$UDINT);
#endif

                  SDIAS_SDO_ERROR_ACCESS_NOT_ALLOWED:
#ifdef HWC_LogValue1
                    HWC_LogValue1(this, "@0093 (SdiasManager::CyclicSDOHandling) SDO Error 0x{0}: Access not allowed (e.g. control access to SDIAS Manager)", TempChannel.Data$UDINT);
#endif
                  
                  SDIAS_SDO_ERROR_FLASH_ACCESS_FAILED:
#ifdef HWC_LogValue1
                    HWC_LogValue1(this, "@0094 (SdiasManager::CyclicSDOHandling) SDO Error 0x{0}: Flash access failed", TempChannel.Data$UDINT);
#endif
                  
                  SDIAS_SDO_ERROR_INVALID_PARAMETERS:
#ifdef HWC_LogValue1
                    HWC_LogValue1(this, "@0095 (SdiasManager::CyclicSDOHandling) SDO Error 0x{0}: Invalid parameters in SDO request", TempChannel.Data$UDINT);
#endif

                else
#ifdef HWC_LogValue1
                  HWC_LogValue1(this, "@0096 (SdiasManager::CyclicSDOHandling) SDO Error 0x{0}: Unknown Error", TempChannel.Data$UDINT);
#endif
                end_case;
              else
                tempCmd.aPara[3]$iprStates := READY;
                // copy response data
                if TempChannel.LengthOfData then
                  if TempChannel.LengthOfData <= sizeof(t_SDOChannel.Data) then
                    _memcpy(ptr1:=#TempChannel.Data, ptr2:=ASYReadDO.pData + t_SDOChannel.Data + Offset, cntr:=TempChannel.LengthOfData);
                  else
#ifdef HWC_LogValue2
                    HWC_LogValue2(this, "@0097 (SdiasManager::CyclicSDOHandling) SDO Error: Length in response is too big (0x{0} Byte; Max: 0x{1} Byte)", TempChannel.LengthOfData, sizeof(t_SDOChannel.Data));                
#endif
                  end_if;
                end_if;
              end_if;
              
              // if there is a response, distribute it and set this channel to "available for the next SDO" (set command to SDIAS_SDO_CMD_INVALID and pChannel to NIL)
              tempCmd.uiCmd := SDIAS_CMD_SDO_RESPONSE;
              tempCmd.aPara[0] := TempChannel.Command$t_SDIAS_SDO_Cmd;
              
              // if we got response data
              if TempChannel.LengthOfData then
              
                // if the SDO command was successful
                if tempCmd.aPara[3]$iprStates = READY then
                
                  // check if it's a command with offset and length info
                  case TempChannel.Command$t_SDIAS_SDO_Cmd of
                    SDIAS_SDO_CMD_MEM_READ,
                    SDIAS_SDO_CMD_MEM_WRITE,
                    SDIAS_SDO_CMD_CTRL_READ,
                    SDIAS_SDO_CMD_CTRL_WRITE:
                      // save header info in extra parameters
                      tempCmd.aPara[1] := pRingBufEntry^.RdWrHead.Offset;
                      tempCmd.aPara[2] := pRingBufEntry^.RdWrHead.Length;
                      
                      // remove header info for user from payload
                      TempChannel.LengthOfData -= sizeof(t_SDIAS_SDO_RdWr_Head);
                      
                      // pointer to data
                      tempCmd.aPara[4] := (#TempChannel.Data + sizeof(t_SDIAS_SDO_RdWr_Head))$DINT;
                    
                    
                    SDIAS_SDO_CMD_SPI_READ,
                    SDIAS_SDO_CMD_SPI_WRITE:
                    
                      // no length or offset available
                      tempCmd.aPara[1] := 0;
                      tempCmd.aPara[2] := 0;
                      
                      // pointer to data
                      tempCmd.aPara[4] := (#TempChannel.Data)$DINT;
                    
                  else
                      // no length or offset available
                      tempCmd.aPara[1] := 0;
                      tempCmd.aPara[2] := 0;
                      
                      // pointer to data
                      tempCmd.aPara[4] := (#TempChannel.Data)$DINT;
                  end_case;
                else
                  // check if it's a command with offset and length info
                  case TempChannel.Command$t_SDIAS_SDO_Cmd of
                    SDIAS_SDO_CMD_MEM_READ,
                    SDIAS_SDO_CMD_MEM_WRITE,
                    SDIAS_SDO_CMD_CTRL_READ,
                    SDIAS_SDO_CMD_CTRL_WRITE,
                    SDIAS_SDO_CMD_SPI_READ,
                    SDIAS_SDO_CMD_SPI_WRITE:
                      // save header info in extra parameters
                      tempCmd.aPara[1] := pRingBufEntry^.RdWrHead.Offset;
                      tempCmd.aPara[2] := pRingBufEntry^.RdWrHead.Length;
                  end_case;
                  
                  // pointer to error code
                  tempCmd.aPara[4] := (#TempChannel.Data)$DINT;                
                end_if;
              else
                tempCmd.aPara[4] := 0;
              end_if;
              tempCmd.aPara[5] := TempChannel.LengthOfData;
              
              pCmdSvr := pRingBufEntry^.pCallBackSvr;
              
              if pCmdSvr$pVirtualBase^.NewInst(#tempCmd, #_result) <> READY then               
#ifdef HWC_LogValue1
                HWC_LogValue1(this, "@0099 (SdiasManager::CyclicSDOHandling) SDO Error: Error of module at place 0x{0} while receiving the SDO reponse (which was an ErrorCode)", i);                              
#endif
              end_if;

              // the position in the ringbuffer is free again
              pRingBufEntry^.BusyChannelNo := 0;
              pRingBufEntry^.Command := SDIAS_SDO_CMD_INVALID;
              
              // the SDO channel on the module is free again
              SDOHandling.aChannelData[i].pActElement := NIL;
              
            elsif (ops.tAbsolute - SDOHandling.aChannelData[i].RequestTime) >= SDIAS_SDO_TIMEOUT then
              // the SDO request timed out (should not happen)
#ifdef HWC_LogValue1
              HWC_LogValue1(this, "@0098 (SdiasManager::CyclicSDOHandling) SDO Error: Timeout while waiting for answer of the SDIAS Manager µC (Channel {0} of range 1-3)", i+1);
#endif

              // we got our response
              SDOHandling.aChannelData[i].WaitForResponse := FALSE;
              SDOHandling.EntriesUsed -= 1;
              
              // distribute timeout error and set this channel to "available for the next SDO" (set command to SDIAS_SDO_CMD_INVALID and pChannel to NIL)
              tempCmd.uiCmd := SDIAS_CMD_SDO_RESPONSE;
              tempCmd.aPara[0] := pRingBufEntry^.Command$UINT;
          
              // check if it's a command with offset and length info
              case pRingBufEntry^.Command of
                SDIAS_SDO_CMD_MEM_READ,
                SDIAS_SDO_CMD_MEM_WRITE,
                SDIAS_SDO_CMD_CTRL_READ,
                SDIAS_SDO_CMD_CTRL_WRITE,
                SDIAS_SDO_CMD_SPI_READ,
                SDIAS_SDO_CMD_SPI_WRITE:
                  // save header info in extra parameters
                  tempCmd.aPara[1] := pRingBufEntry^.RdWrHead.Offset;
                  tempCmd.aPara[2] := pRingBufEntry^.RdWrHead.Length;
              else
                  // no length or offset available
                  tempCmd.aPara[1] := 0;
                  tempCmd.aPara[2] := 0;
              end_case;
              
              tempCmd.aPara[3] := ERROR;
              tempCmd.aPara[4] := 0;
              tempCmd.aPara[5] := 0; // no data available
              
              pCmdSvr := pRingBufEntry^.pCallBackSvr;
              if pCmdSvr$pVirtualBase^.NewInst(#tempCmd, #_result) <> READY then
#ifdef HWC_LogValue1
                HWC_LogValue1(this, "@0099 (SdiasManager::CyclicSDOHandling) SDO Error: Error of module at place 0x{0} while receiving the SDO reponse", i);
#endif
              end_if;
              
              // the position in the ringbuffer is free again
              pRingBufEntry^.BusyChannelNo := 0;
              pRingBufEntry^.Command := SDIAS_SDO_CMD_INVALID;
              
              // the SDO channel on the module is free again
              SDOHandling.aChannelData[i].pActElement := NIL;
            end_if;
          end_if;
          
          Offset += sizeof(t_SDOChannel);
        end_for;
      end_if;

      // check for the first (needed for offset) and last (needed for length)
      Length := 0;
      FoundIt := FALSE;
      for i := 0 to (SDIAS_SDO_CHANNEL_NO-1) do
        if SDOHandling.aChannelData[i].pActElement & SDOHandling.aChannelData[i].WaitForResponse then
          if FoundIt = FALSE then
            // found first used channel
            FoundIt := TRUE;
            Offset := SDOHandling.OffsetSDOResp + i * sizeof(t_SDOChannel);
          end_if;
          Length += sizeof(t_SDOChannel);
        end_if;
      end_for;

      if FoundIt then

        // if we have pending SDO requests, start the AsyRdDO for polling
        if ChangeAsyRd(Offset:=Offset, 
                       Length:=Length, 
                       RunState:=_BUS_IF_RUN_STATE_CONT_RUN,
                       UsageType:=_UsedBySDO) = FALSE then
#ifdef HWC_LogError
          HWC_LogError(this, "@009A (SdiasManager::CyclicSDOHandling) Error occured at starting the ReadDO for SDO polling");
#endif
        end_if;
      else
        // if all pending SDOs received stop DO
        if AsyReadUsage = _UsedBySDO then
          if ChangeAsyRd(Offset:=0, 
                         Length:=0, 
                         RunState:=_BUS_IF_RUN_STATE_NO_RUN,
                         UsageType:=_UsedBySDO) = FALSE then
#ifdef HWC_LogError
          HWC_LogError(this, "@009B (SdiasManager::CyclicSDOHandling) Error occured at stopping the ReadDO");
#endif
          end_if;
        end_if;
      end_if;
    end_if;

    
    // SEND SDO REQUEST
    if (AsyWriteUsage = _NotUsed) | (AsyWriteUsage = _UsedBySDO) then
      // if there is a free channel on the module, we have unsent requests and the AsyWrDO is not used => send the Request (or more than 1 if possible)
      
      // first check if we need to increment the msg counter for a previously sent SDO message
      if SDOHandling.IncrementMsgCnt then
        for i := 0 to (SDIAS_SDO_CHANNEL_NO-1) do
          if SDOHandling.IncrementMsgCnt AND 1 then
            // next message counter for this channel
            if SDOHandling.aChannelData[i].MessageCnt = SDIAS_MASK_MESSAGE_COUNTER then
              SDOHandling.aChannelData[i].MessageCnt    := 0;
            else
              SDOHandling.aChannelData[i].MessageCnt    += 1; 
            end_if;
            
            SDOHandling.aChannelData[i].pActElement^.MessageCounter := SDOHandling.aChannelData[i].MessageCnt;
            pTempChannel := #SDOHandling.aChannelData[i].ChannelData;
            pTempChannel^.MessageCounter  := SDOHandling.aChannelData[i].MessageCnt;
            
            // save the new message counter to the Varan DO
            _memcpy(ptr1:=ASYWriteDO.pData$^USINT + i * sizeof(t_SDOChannel) - (ASYWriteDO.Offset - SDOHandling.OffsetSDOReq)$USINT, ptr2:=pTempChannel, cntr:=pTempChannel^.LengthOfData + sizeof(t_SDOChannel) - sizeof(t_SDOChannel.Data));
            SDOHandling.aChannelData[i].WaitForResponse := TRUE;
            TempUDINT := ops.tAbsolute;
            SDOHandling.aChannelData[i].RequestTime     := TempUDINT;
          end_if;
          SDOHandling.IncrementMsgCnt := SDOHandling.IncrementMsgCnt SHR 1;
        end_for;

        // use the same length and offset (it's the same frame just with different message counters)
        Offset := ASYWriteDO.Offset;
        Length := ASYWriteDO.Length$USINT;

        // write the same frame again with higher message counter on the modified SDOs
        if ChangeAsyWr(Offset:=Offset, 
                       Length:=Length, 
                       RunState:=_BUS_IF_RUN_STATE_CONT_RUN,
                       UsageType:=_UsedBySDO) = FALSE then
#ifdef HWC_LogError
          HWC_LogError(this, "@009C (SdiasManager::CyclicSDOHandling) Error occured at starting the WriteDO to write the new message counter");
#endif
        end_if;
      else
        // check for a free channel
        FoundIt := FALSE;
        for i := 0 to (SDIAS_SDO_CHANNEL_NO-1) do
          if SDOHandling.aChannelData[i].pActElement = NIL then
            // found a free channel
            FoundIt := TRUE;
            FirstFound := LastFound := i;
            Offset := SDOHandling.OffsetSDOReq + i * sizeof(t_SDOChannel);
            exit;
          end_if;
        end_for;
        
        // now we fill the buffer in the channels of the hardware (continue as long as there is space in the buffer and we have SDOs to send)
        Channels2Add := 0;
        while FoundIt & (SDOHandling.pRead^.Command <> SDIAS_SDO_CMD_INVALID) & (SDOHandling.pRead^.BusyChannelNo = 0) do
          // i is the index of the free channel => add the data
          pTempChannel := #SDOHandling.aChannelData[i].ChannelData;
          SDOHandling.aChannelData[i].pActElement     := SDOHandling.pRead;
          SDOHandling.pRead^.MessageCounter           := SDOHandling.aChannelData[i].MessageCnt;
          pTempChannel^.MessageCounter                := SDOHandling.pRead^.MessageCounter;
          pTempChannel^.NMT                           := SDOHandling.pRead^.NMTCommand;
          pTempChannel^.SDIASPlace                    := SDOHandling.pRead^.SDIASPlace;
          pTempChannel^.Command$t_SDIAS_SDO_Cmd       := SDOHandling.pRead^.Command;
          pTempChannel^.LengthOfData                  := SDOHandling.pRead^.CmdLength;
          if pTempChannel^.LengthOfData then
            _memcpy(ptr1:=#pTempChannel^.Data, ptr2:=#SDOHandling.pRead^.ReqBufData, cntr:=pTempChannel^.LengthOfData);
          end_if;

          // put the SDO request into the DPRAM on the right channel
          _memcpy(ptr1:=ASYWriteDO.pData$^t_SDOChannel + Channels2Add * sizeof(t_SDOChannel), ptr2:=pTempChannel, cntr:=pTempChannel^.LengthOfData + sizeof(t_SDOChannel) - sizeof(t_SDOChannel.Data));
                    
          // remember this as the last found SDO to work with
          LastFound := i;

          // remember that we have to increment the message counter here
          SDOHandling.IncrementMsgCnt := SDOHandling.IncrementMsgCnt OR (1 SHL i);
          
          // this element is done by channel x
          SDOHandling.pRead^.BusyChannelNo := i+1;
          
          // increase channels to add
          Channels2Add += 1;

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

          OldChannelNo := i;
          
          // check for a free channel
          FoundIt := FALSE;
          for i := 0 to (SDIAS_SDO_CHANNEL_NO-1) do
            if SDOHandling.aChannelData[i].pActElement = NIL then
              // found a free channel
              FoundIt := TRUE;
              
              if i > (OldChannelNo + 1) then
                // refresh the data in the DPRAM for the skipped channels
                for j := (OldChannelNo+1) to (i-1) do
                  // put the SDO request into the DPRAM on the right channel
                  _memcpy(ptr1:=ASYWriteDO.pData$^t_SDOChannel + j * sizeof(t_SDOChannel), ptr2:=#SDOHandling.aChannelData[j].ChannelData, cntr:=SDOHandling.aChannelData[j].ChannelData.LengthOfData + sizeof(t_SDOChannel) - sizeof(t_SDOChannel.Data));

                  // increase channels to add, because we also write the skipped ones
                  Channels2Add += 1;
                end_for;
              end_if;
              
              exit;
            end_if;
          end_for;
        end_while;

        if Channels2Add then
          Length := (LastFound - FirstFound + 1)$USINT * sizeof(t_SDOChannel);
          // if we have something to write => write it
          if ChangeAsyWr(Offset:=Offset, 
                         Length:=Length, 
                         RunState:=_BUS_IF_RUN_STATE_CONT_RUN,
                         UsageType:=_UsedBySDO) = FALSE then
#ifdef HWC_LogError
            HWC_LogError(this, "@009D (SdiasManager::CyclicSDOHandling) Error occured at starting the WriteDO to write the new SDO command");
#endif
          end_if;
        elsif AsyWriteUsage = _UsedBySDO then
          // otherwise release the write buffer to other purposes
          if ChangeAsyWr(Offset:=0, 
                         Length:=0, 
                         RunState:=_BUS_IF_RUN_STATE_NO_RUN,
                         UsageType:=_UsedBySDO) = FALSE then
#ifdef HWC_LogError
            HWC_LogError(this, "@009E (SdiasManager::CyclicSDOHandling) Error occured at stopping the WriteDO");
#endif
          end_if;
        end_if;
      end_if;
    end_if;
  else
    // if connected locally we can use the OS interfaces to access the SDO channels


    // check sdo response first. if a channel is ready it can be used for the next request

    // GET SDO RESPONSE
    if SDOHandling.EntriesUsed then
      // post init blocks the tasks in cyclic priority (the SDIAS Manager Code is running in lower priority than cyclic and has no time during the postinit) => give it some time
      if (b_PostInitFinished = FALSE) then
        ToMultiTask.TASKDELAY(timeout0:=SDIAS_WAIT_TIME_IN_POST_INIT);
      end_if;
      // check if we got a response
      for i := 0 to (SDIAS_SDO_CHANNEL_NO-1) do
        if SDOHandling.aChannelData[i].WaitForResponse then
          
          // get the SDO response
          ReceiveLength := 0;
          sd_retval := SDIAS_iReadSdoResponseChannel(udSdoHandle       := SDOHandling.aChannelData[i].SdoHandle
                                                   , udBufferLength    := sizeof(ReceiveBuffer)
                                                   , pucData           := #ReceiveBuffer[0]
                                                   , pudDataLength     := #ReceiveLength
                                                   );
          
          // check if it's finished => no more busy
          if sd_retval <> SDIAS_SDO_REQUEST_BUSY then
            if ReceiveLength <= sizeof(TempChannel.Data) then
              pRingBufEntry := SDOHandling.aChannelData[i].pActElement;
              
              // copy the info
              _memcpy(ptr1:= #TempChannel.Data, ptr2:= #ReceiveBuffer[0], cntr:= ReceiveLength);
              TempChannel.LengthOfData := ReceiveLength$USINT;
              TempChannel.Command$t_SDIAS_SDO_Cmd := pRingBufEntry^.Command;              
          
              // we got our response
              SDOHandling.aChannelData[i].WaitForResponse := FALSE;
              SDOHandling.EntriesUsed -= 1;
              
              // check for error
              if sd_retval <> SDIAS_OK then
                tempCmd.aPara[3] := ERROR;
                
                LogSDOErrorInfo(sd_retval);
              else
                tempCmd.aPara[3]$iprStates := READY;
              end_if;
              
              // if there is a response, distribute it and set this channel to "available for the next SDO" (set command to SDIAS_SDO_CMD_INVALID and pChannel to NIL)
              tempCmd.uiCmd := SDIAS_CMD_SDO_RESPONSE;
              tempCmd.aPara[0] := pRingBufEntry^.Command$INT;
              
              // if we got response data
              if TempChannel.LengthOfData then
              
                // if the SDO command was successful
                if tempCmd.aPara[3]$iprStates = READY then
                
                  // check if it's a command with offset and length info
                  case TempChannel.Command$t_SDIAS_SDO_Cmd of
                    SDIAS_SDO_CMD_MEM_READ,
                    SDIAS_SDO_CMD_MEM_WRITE,
                    SDIAS_SDO_CMD_CTRL_READ,
                    SDIAS_SDO_CMD_CTRL_WRITE: 
                      // save header info in extra parameters
                      tempCmd.aPara[1] := pRingBufEntry^.RdWrHead.Offset;
                      tempCmd.aPara[2] := pRingBufEntry^.RdWrHead.Length;
                      
                      // remove header info for user from payload
                      TempChannel.LengthOfData -= sizeof(t_SDIAS_SDO_RdWr_Head);
                      
                      // pointer to data
                      tempCmd.aPara[4] := (#TempChannel.Data + sizeof(t_SDIAS_SDO_RdWr_Head))$DINT;

                    
                    SDIAS_SDO_CMD_SPI_READ,
                    SDIAS_SDO_CMD_SPI_WRITE:
                      // no length or offset available
                      tempCmd.aPara[1] := 0;
                      tempCmd.aPara[2] := 0;
                      
                      // pointer to data
                      tempCmd.aPara[4] := (#TempChannel.Data)$DINT;
                    
                  else
                      // no length or offset available
                      tempCmd.aPara[1] := 0;
                      tempCmd.aPara[2] := 0;
                      
                      // pointer to data
                      tempCmd.aPara[4] := (#TempChannel.Data)$DINT;
                  end_case;
                else
                  // check if it's a command with offset and length info
                  case TempChannel.Command$t_SDIAS_SDO_Cmd of
                    SDIAS_SDO_CMD_MEM_READ,
                    SDIAS_SDO_CMD_MEM_WRITE,
                    SDIAS_SDO_CMD_CTRL_READ,
                    SDIAS_SDO_CMD_CTRL_WRITE,
                    SDIAS_SDO_CMD_SPI_READ,
                    SDIAS_SDO_CMD_SPI_WRITE:
                      // save header info in extra parameters
                      tempCmd.aPara[1] := pRingBufEntry^.RdWrHead.Offset;
                      tempCmd.aPara[2] := pRingBufEntry^.RdWrHead.Length;
                  end_case;
                  
                  // pointer to error code
                  tempCmd.aPara[4] := (#sd_retval)$DINT;                
                end_if;
              else
                tempCmd.aPara[4] := 0;
              end_if;
              tempCmd.aPara[5] := TempChannel.LengthOfData;
              
              pCmdSvr := pRingBufEntry^.pCallBackSvr;
              if pCmdSvr$pVirtualBase^.NewInst(#tempCmd, #_result) <> READY then
#ifdef HWC_LogValue1
                HWC_LogValue1(this, "@0099 (SdiasManager::CyclicSDOHandling) SDO Error: Error of module at place 0x{0} while receiving the SDO reponse (which was an ErrorCode)", i);
#endif
              end_if;

              // the position in the ringbuffer is free again
              pRingBufEntry^.BusyChannelNo := 0;
              pRingBufEntry^.Command := SDIAS_SDO_CMD_INVALID;
              
              // the SDO channel on the module is free again
              SDOHandling.aChannelData[i].pActElement := NIL;
            else
#ifdef HWC_LogValue2
              HWC_LogValue2(this, "@009F (SdiasManager::CyclicSDOHandling) SDO Response too big. Received 0x{0} bytes. Maximum is 0x{1} bytes.", ReceiveLength, sizeof(TempChannel.Data));
#endif
            end_if;
          end_if;
        end_if;
      end_for;
    end_if;


    
    // SEND SDO REQUEST
    if SDOHandling.EntriesUsed then
      // if there is a free channel on the module and we have unsent requests => send the Requests
    
      // check for a free channel
      FoundIt := FALSE;
      for i := 0 to (SDIAS_SDO_CHANNEL_NO-1) do
        if SDOHandling.aChannelData[i].pActElement = NIL then
          // found a free channel
          FoundIt := TRUE;
          FirstFound := LastFound := i;
          exit;
        end_if;
      end_for;
      
      // now we fill the buffer in the channels of the hardware (continue as long as there is space in the buffer and we have SDOs to send)
      while FoundIt & (SDOHandling.pRead^.Command <> SDIAS_SDO_CMD_INVALID) & (SDOHandling.pRead^.BusyChannelNo = 0) do
        // i is the index of the free channel => add the data
        SDOHandling.aChannelData[i].pActElement     := SDOHandling.pRead;
        SDOHandling.pRead^.MessageCounter           := SDOHandling.aChannelData[i].MessageCnt;
        TempChannel.MessageCounter                  := SDOHandling.pRead^.MessageCounter;
        TempChannel.NMT                             := SDOHandling.pRead^.NMTCommand;
        TempChannel.SDIASPlace                      := SDOHandling.pRead^.SDIASPlace;
        TempChannel.Command$t_SDIAS_SDO_Cmd         := SDOHandling.pRead^.Command;
        TempChannel.LengthOfData                    := SDOHandling.pRead^.CmdLength;
        if TempChannel.LengthOfData then
          _memcpy(ptr1:=#TempChannel.Data, ptr2:=#SDOHandling.pRead^.ReqBufData, cntr:=TempChannel.LengthOfData);
        end_if;

        // send the SDO to the OS Interface
        sd_retval := SDIAS_iSendSdoRequestChannel(hManagerNodeHandle:= udNodeHandle
                                                , udChannel         := i
                                                , udCommand         := TempChannel.Command$t_SDIAS_SDO_Cmd
                                                , udSdiasAddress    := TempChannel.SDIASPlace
                                                , udDataLength      := TempChannel.LengthOfData
                                                , pucData           := #TempChannel.Data[0]
                                                , pudSdoHandle      := #SDOHandling.aChannelData[i].SdoHandle
                                                );
       
        if sd_retval = SDIAS_OK then
          // this element is done by channel x
          SDOHandling.pRead^.BusyChannelNo := i+1;

          SDOHandling.aChannelData[i].WaitForResponse := TRUE;
          TempUDINT := ops.tAbsolute;
          SDOHandling.aChannelData[i].RequestTime     := TempUDINT;
          
          // after we successfully added this SDO, set the read pointer to the next element
          if SDOHandling.pRead = SDOHandling.pLastEntry then
            SDOHandling.pRead := SDOHandling.pRingBufMemStart;
          else
            SDOHandling.pRead += sizeof(t_SDORingBufEntry);
          end_if;

          // check for a free channel
          FoundIt := FALSE;
          for i := 0 to (SDIAS_SDO_CHANNEL_NO-1) do
            if SDOHandling.aChannelData[i].pActElement = NIL then
              // found a free channel
              FoundIt := TRUE;
              exit;
            end_if;
          end_for;
        else
          LogSDOErrorInfo(sd_retval);
          exit;
        end_if;
      end_while;
    end_if;
  end_if;

    OS_MT_SIGNAL(pv_Mutex);

END_FUNCTION


FUNCTION VIRTUAL SdiasManager::SetRequiredError
	VAR_INPUT
		pTargetThis 	: ^SdiasBase;(* := NIL *)
		Place 	: UDINT;(* := SDIAS_PLACE_NO_MODULE_ADDED_SO_FAR *)
	END_VAR
  VAR
  	tempCmd         : CmdStruct;
    _result         : results;
    i : UDINT;
    FoundIt : BOOL;
  END_VAR

  if pTargetThis & (Place <> SDIAS_PLACE_NO_MODULE_ADDED_SO_FAR) then
    pTargetThis^.ClassState := _RequiredError;
    
#ifdef HWC_LogValue1
    HWC_LogValue1(this, "@00A0 (SdiasManager::SetRequiredError) Required Error on SDIAS Place 0x{0}", Place);
#endif
  else
    // general required error (initialisation failed) => search for the first required module to blame (if there is one)
    FoundIt := FALSE;
    if MaxPlace <> SDIAS_PLACE_NO_MODULE_ADDED_SO_FAR then
      for i := 0 to MaxPlace do
        if ModuleObjInfo[i].pThis & ModuleObjInfo[i].Required then
          FoundIt := TRUE;
        end_if;
      end_for;
    end_if;
    
    // if no required module => don't crash
    if FoundIt = FALSE then
      return;
    end_if;
  end_if;

  ClassState := _RequiredError;
  
  // set required error
  tempCmd.uiCmd     := _BUS_IF_SET_REQUIRED_ERROR;
  
  ToBusInterface.NewInst(pPara:=#tempCmd, pResult:=#_result);
  if _result.aData[0]$t_BusIFRetvalErrorcode <> _BUS_IF_RETVAL_OK then
#ifdef HWC_LogError
    HWC_LogError(this, "@00A1 (SdiasManager::SetRequiredError) Failed to set required error to BusInterface");
#endif
  end_if;    
  
  if InitSSW <> _PrepareError then
    ErrorInitStep := InitSSW;
    InitSSW := _PrepareError;
  end_if;

END_FUNCTION


// New interface - 2013-05-28	
// -----------------------------------------------------------------------
// -	bIsWriteAcc0 : 0 - read access , 1 - write access
// -	iModAddr0 : Module adress at sdias bus (device adr + offset)
// -	iDataLen0 : Data length
// -	bCtrlAcc0 : 0 - access to regular memory, 1 > access to ctrl access
// -    bAccList0 : 0 - access to iso read/write list, 1 - acc to manager admin list, 2 - access to sdo list, 3 - access to periodic manager list


FUNCTION VIRTUAL SdiasManager::DOL_Handling_Add_DO_TO_List
	VAR_INPUT
		bIsWriteAcc0 	: BOOL;
		usModulePlace0 	: USINT;
		iModAddr0 	: HINT;
		iDataLen0 	: UINT;
		bCtrlAcc0 	: BOOL;
		iWaitDOOffset0 	: UINT;
		bIsDynamic0 	: BOOL;
		pActAccess0 	: ^t_AccessElement;
		bIsBroadCast 	: BOOL;(* := FALSE *)
	END_VAR
	VAR_OUTPUT
		iRetCode 	: DINT;
	END_VAR
  VAR
    pReadList       : ^t_SDIAS_DOL_DESC;
    pWriteList      : ^t_SDIAS_DOL_DESC;
    iEndDataPointRd : UINT;
    iEndDOLPointRd  : UDINT;
    iEndDataPointWr : UINT;
    iEndDOLPointWr  : UDINT;   
    udCmdType       : UDINT;
    ReadLen         : UINT;
    ReadAdd         : HDINT;
    WriteLen        : UINT;
    WriteAdd        : HDINT;
    udDOFlags       : UDINT;
    bIsFarAccess    : BOOL;
    usBlockNo1k     : USINT;
    usRetries       : BSINT;
    dolType         : UDINT;
  END_VAR

  iRetCode := -1;

  (* Only ISO DOL	in hardware classes *)
  pReadList := #gcRead_DOL_Desc;
  pWriteList := #gcWrite_DOL_Desc;

  // calculate the module address for far accesses and other
  if pActAccess0^.bIsFarAcc then
    bIsFarAccess  := TRUE;
    usBlockNo1k   := to_usint(iModAddr0 shr 10);
    iModAddr0     := (iModAddr0 AND 16#3FF) + (usModulePlace0 shl 10);
  else
    bIsFarAccess  := FALSE;
    usBlockNo1k   := 0;
    iModAddr0     := iModAddr0 + (usModulePlace0 shl 10);
  end_if;

  if ConnectionType = SDIAS_CON_VIA_VARAN_uC then
    
    (*	Check endpoints of data and DOL	*)
    iEndDataPointRd := pReadList^.iBaseAddrData + pReadList^.iOffLastData + 1;
    iEndDOLPointRd  := pReadList^.iBaseAddr + pReadList^.iOffEndCmd;

    iEndDataPointWr := pWriteList^.iBaseAddrData + pWriteList^.iOffLastData +  1;
    iEndDOLPointWr  := pWriteList^.iBaseAddr + pWriteList^.iOffEndCmd;

    if(bIsWriteAcc0 = 0) then
      (*	Check endpoints of data and DOL	*)
      iEndDataPointRd += iDataLen0;
      iEndDOLPointRd  += sizeof(t_SDIAS_STD_CMD_DO);
    else
      (*	Check endpoints of data and DOL	*)
      iEndDataPointWr += iDataLen0;
      iEndDOLPointWr  += sizeof(t_SDIAS_STD_CMD_DO);
    end_if;

    (* Check available data	in read space *)
    if(iEndDataPointRd > pReadList^.iEndAddrData) then
      iRetCode := -3;
    (* Check space in DOL	*)
    elsif(iEndDOLPointRd > pReadList^.iEndAddr) then
      iRetCode := -4;
    (* Check available data	in write space *)
    elsif(iEndDataPointWr > pWriteList^.iEndAddrData) then
      iRetCode := -5;
    (* Check space in DOL	*)
    elsif(iEndDOLPointWr > pWriteList^.iEndAddr) then
      iRetCode := -6;
    (* Space for all required data	*)
    else

      // Add 1 to switch to first empty byte
      pWriteList^.iOffLastData += sizeof(t_SDIAS_ControlByte);										(* Add do ctrl byte to data		*)
      pReadList^.iOffLastData += sizeof(t_SDIAS_StateByte);	  

      pWriteList^.iOffFirstData := pWriteList^.iOffLastData;			(* Store data start points		*)
      pReadList^.iOffFirstData := pReadList^.iOffLastData;

      // dynamic accesses need more bytes in the write payload
      if bIsDynamic0 then
        // control byte is already considered, so we have to add the difference here
        pWriteList^.iOffLastData += (sizeof(t_SDIAS_ControlStructDynamic) - sizeof(t_SDIAS_ControlByte));
      end_if;

      cModulAccessCmds[0].OffsetWritePayload := pWriteList^.iBaseAddrData + pWriteList^.iOffFirstData;		(* Store data offsets			*)
      cModulAccessCmds[0].OffsetReadPayload := pReadList^.iBaseAddrData + pReadList^.iOffFirstData;

      (* Set wait for DO to inactive	*)
      cModulAccessCmds[0].OffsetVolatileWaitFlag := iWaitDOOffset0;

      (* Init scratchpad info to 0	*)
      cModulAccessCmds[0].ErrorInfo := 0;
      
      usRetries := SDIAS_RETRIES_ALLOWED;
      // No retries with Broadcast 
      if bIsBroadCast then
        usRetries := 0;
      end_if;
      
      (* Ctrl access *)
      if(bCtrlAcc0 <> 0) then
        (* Ctrl access +  retrys	*)
        cModulAccessCmds[0].CmdRetries  := SDIAS_CMD_ACC_CONTROL + (usRetries shl 5);
      elsif bIsFarAccess then
        (* Mem far access +  retrys	*)
        cModulAccessCmds[0].CmdRetries  := SDIAS_CMD_ACC_MEMORY_FAR + (usRetries shl 5);      
      else
        (* Mem access +  retrys	*)
        cModulAccessCmds[0].CmdRetries  := SDIAS_CMD_ACC_MEMORY + (usRetries shl 5);
      end_if;

      (* Init reserved info to 0	*)
      cModulAccessCmds[0].Reserved := 0;
    
      (* Write command to dpram 	*)
      if(bIsWriteAcc0 = 0) then
        if bIsFarAccess then
          cModulAccessCmds[0].ReadLength  := to_usint(iDataLen0);
          cModulAccessCmds[0].ReadOffset  := to_uint(iModAddr0);

          cModulAccessCmds[0].WriteLength := 0;
          cModulAccessCmds[0].WriteOffset := usBlockNo1k;
        else
          cModulAccessCmds[0].ReadLength := to_usint(iDataLen0);
          cModulAccessCmds[0].ReadOffset := to_uint(iModAddr0);

          cModulAccessCmds[0].WriteLength := 0;
          cModulAccessCmds[0].WriteOffset  := 0;
        end_if;

        (* Store write adress of new command  *)
        uiWriteCmdAddr := pReadList^.iBaseAddr + pReadList^.iOffEndCmd;

        (* Increment offset of end command	*)
        pReadList^.iOffEndCmd += sizeof(t_SDIAS_STD_CMD_DO);

        (* End of list	*)
        DOL_Handling_Create_End_Cmd(#cModulAccessCmds[1]);

        (* Add read length to iso read usage	*)
        pReadList^.iOffLastData += iDataLen0;

        (* Set usage vars	*)
        pReadList^.iUsageData := pReadList^.iOffLastData + 1;
        pReadList^.iUsageDOL := pReadList^.iOffEndCmd + sizeof(t_SDIAS_STD_CMD_DO);

        pWriteList^.iUsageData := pWriteList^.iOffLastData + 1;

      else
        if bIsFarAccess then
          cModulAccessCmds[0].ReadLength := 0;
          cModulAccessCmds[0].ReadOffset := usBlockNo1k;

          cModulAccessCmds[0].WriteLength := to_usint(iDataLen0);
          cModulAccessCmds[0].WriteOffset  := to_uint(iModAddr0);
        elsif bIsBroadCast then
          cModulAccessCmds[0]$t_SDIAS_BROADCAST_CMD_DO.iNoOfReadBytes   := 0;
          cModulAccessCmds[0]$t_SDIAS_BROADCAST_CMD_DO.iModAddrRdWrCmd  := to_uint(iModAddr0);
          cModulAccessCmds[0]$t_SDIAS_BROADCAST_CMD_DO.iCmdSubtype      := SDIAS_TIMEBROADCAST_SUBCMD;
          cModulAccessCmds[0]$t_SDIAS_BROADCAST_CMD_DO.iNoOfWriteBytes  := to_usint(iDataLen0);        
        else
          cModulAccessCmds[0].ReadLength := 0;
          cModulAccessCmds[0].ReadOffset := 0;

          cModulAccessCmds[0].WriteLength := to_usint(iDataLen0);
          cModulAccessCmds[0].WriteOffset  := to_uint(iModAddr0);
        end_if;

        (* Store write adress of new command  *)
        uiWriteCmdAddr := pWriteList^.iBaseAddr + pWriteList^.iOffEndCmd;

        (* Increment offset of end command	*)
        pWriteList^.iOffEndCmd += sizeof(t_SDIAS_STD_CMD_DO);

        (* End of list	*)
        DOL_Handling_Create_End_Cmd(#cModulAccessCmds[1]);

        (* Add write length to iso write usage	*)
        pWriteList^.iOffLastData += iDataLen0;

        (* Set usage vars	*)
        pReadList^.iUsageData := pReadList^.iOffLastData + 1;

        pWriteList^.iUsageData := pWriteList^.iOffLastData + 1;
        pWriteList^.iUsageDOL := pWriteList^.iOffEndCmd + sizeof(t_SDIAS_STD_CMD_DO);

        (* Reset write payload	*)
        //SDIAS_Module_CPLD_Com_Write_Data(pWriteList^.iBaseAddrData + pWriteList^.iOffFirstData + 1, iDataLen0 , (void *)&iDOL_ResetData[0]);
      
      end_if;
    
      iRetCode := 0;  
    
    end_if;
    
  else
    // locally we use the OS interface to create the DO

    (* Ctrl access *)
    if(bCtrlAcc0 <> 0) then
      (* Ctrl access +  retrys	*)
      udCmdType         := SDIAS_CMD_ACC_CONTROL;
    elsif  bIsFarAccess then
      // far memory access
      udCmdType         := SDIAS_CMD_ACC_MEMORY_FAR;
    else
      (* Mem access +  retrys	*)
      udCmdType         := SDIAS_CMD_ACC_MEMORY;
    end_if;

    // if the interface for dynamic DOs is not available => use the old interface    
    if (pSDIAS^.udVersion < SDIAS_CIL_VERSION_SUPPORTS_DYNAMIC_DO) then 
      iRetCode := SDIAS_iAddDo(hNodeHandle         := udNodeHandle
                             , udDolType           := SDIAS_DOL_TYPE_ISO
                             , udCmdType           := udCmdType
                             , udRetries           := SDIAS_RETRIES_ALLOWED
                             , udIsWriteAcc        := bIsWriteAcc0
                             , udModuleAddress     := iModAddr0
                             , udDataLen           := iDataLen0
                             , hAddrVolatileWait   := iWaitDOOffset0
                             , phAddrWriteData     := (#cModulAccessCmds[0].OffsetWritePayload)$^pVoid
                             , phAddrReadData      := (#cModulAccessCmds[0].OffsetReadPayload)$^pVoid
                             );
                             
    else
      
        // make read and write settings
      if bIsWriteAcc0 then
        WriteLen := iDataLen0;
        WriteAdd := iModAddr0;
        ReadLen  := 0;
        ReadAdd  := usBlockNo1k;
        
        if bIsBroadCast then
          ReadAdd := iModAddr0; // RdWr Access with rd length 0
        end_if;

      else
        WriteLen := 0;
        WriteAdd := usBlockNo1k;
        ReadLen  := iDataLen0;
        ReadAdd  := iModAddr0;
      end_if;

      dolType   := SDIAS_DOL_TYPE_ISO;
      usRetries := SDIAS_RETRIES_ALLOWED;
      // set DO flags
      udDOFlags := 0;
      if bIsDynamic0 then
        if bIsFarAccess then
          udDOFlags := SDIAS_DO_FLAG_SUPPORT_VARIABLE_READ_BYTE_COUNT_AND_MODULE_ADDR OR SDIAS_DO_FLAG_SUPPORT_VARIABLE_WRITE_BYTE_COUNT_AND_MODULE_ADDR;
        else
          if bIsWriteAcc0 then
            udDOFlags := SDIAS_DO_FLAG_SUPPORT_VARIABLE_READ_BYTE_COUNT_AND_MODULE_ADDR;
          else
            udDOFlags := SDIAS_DO_FLAG_SUPPORT_VARIABLE_WRITE_BYTE_COUNT_AND_MODULE_ADDR;
          end_if;
        end_if;
      elsif bIsBroadCast then
        // Set flag for broadcast write to all SDIAS clients
        udDOFlags := SDIAS_DO_FLAG_ACCESS_TYPE_READBROADCASTWRITE_ALL;        
        // No retries with Broadcast
        usRetries := 0;
        // Force Broadcast into ISO writelist
        dolType   := SDIAS_DOL_TYPE_ISO_WR;
      end_if;

      // use the new interface
      iRetCode := SDIAS_iAddDoDynamic(hNodeHandle         := udNodeHandle
                                    , udDolType           := dolType
                                    , udCmdType           := udCmdType
                                    , udSubCmdType        := SDIAS_DO_SUBCMD_NONE
                                    , udRetries           := usRetries
                                    , udReadAddress       := ReadAdd
                                    , udReadDataLen       := ReadLen
                                    , udWriteAddress      := WriteAdd
                                    , udWriteDataLen      := WriteLen
                                    , udAddrVolatileWait  := iWaitDOOffset0
                                    , hJumpDoHandle       := SDIAS_INVALID_VOLATILE_WAIT_HANDLE
                                    , udDoFlags           := udDOFlags
                                    , phDoHandle          := #pActAccess0^.udOSDOHandle
                                    , phAddrWriteData     := (#cModulAccessCmds[0].OffsetWritePayload)$^pVoid
                                    , phAddrReadData      := (#cModulAccessCmds[0].OffsetReadPayload)$^pVoid
                                    );
    end_if;
    
    if iRetCode = SDIAS_OK then
      (* Store data offsets			*)
      pWriteList^.iOffFirstData := cModulAccessCmds[0].OffsetWritePayload - pWriteList^.iBaseAddrData;
      pReadList^.iOffFirstData  := cModulAccessCmds[0].OffsetReadPayload  - pReadList^.iBaseAddrData;
    else
#ifdef HWC_LogError
      HWC_LogError(this, "@00A2 (SdiasManager::DOL_Handling_Add_DO_TO_List) Failed to add custom SDIAS access via OS interface!");
#endif
    end_if;
  end_if;

END_FUNCTION


FUNCTION VIRTUAL SdiasManager::DOL_Handling_Create_End_Cmd
	VAR_INPUT
		pEndCmdBuffer 	: ^t_SDIAS_DOListEntry;
	END_VAR

 	(* End of list	*)
	pEndCmdBuffer^.OffsetReadPayload := 0xFFFF;
	pEndCmdBuffer^.OffsetWritePayload := 0xFFFF;

	(* Set wait for DO to inactive	*)
	pEndCmdBuffer^.OffsetVolatileWaitFlag := SDIAS_INVALID_VOLATILE_WAIT_HANDLE;

	(* Init scratchpad info to 0	*)
	pEndCmdBuffer^.ErrorInfo := 0;

	pEndCmdBuffer^.CmdRetries := 0x0;

	pEndCmdBuffer^.ReadLength := 0;
	pEndCmdBuffer^.ReadOffset := 0;

	(* Init reserved info to 0	*)
	pEndCmdBuffer^.Reserved := 0;

	pEndCmdBuffer^.WriteLength := 0;
	pEndCmdBuffer^.WriteOffset  := 0;


END_FUNCTION


FUNCTION VIRTUAL SdiasManager::LogSDOErrorInfo
	VAR_INPUT
		OSRetVal 	: DINT;
	END_VAR

 // show error info
  case OSRetVal of              
    SDIAS_MAILBOX_FULL:
#ifdef HWC_LogValue1
      HWC_LogValue1(this, "@00A3 (SdiasManager::LogSDOErrorInfo) SDO Error 0x{0}: Mailbox full", (0-OSRetVal)$UDINT);
#endif
      
    SDIAS_TIMEOUT_TASK:
#ifdef HWC_LogValue1
      HWC_LogValue1(this, "@00A4 (SdiasManager::LogSDOErrorInfo) SDO Error 0x{0}: Timeout of task", (0-OSRetVal)$UDINT);
#endif
      
    SDIAS_RESPONSE_BUFFER_TOO_SMALL:
#ifdef HWC_LogValue1
      HWC_LogValue1(this, "@00A5 (SdiasManager::LogSDOErrorInfo) SDO Error 0x{0}: Response buffer too small", (0-OSRetVal)$UDINT);
#endif
      
    SDIAS_TIMEOUT_SDO_RESPONSE:
#ifdef HWC_LogValue1
      HWC_LogValue1(this, "@00A6 (SdiasManager::LogSDOErrorInfo) SDO Error 0x{0}: Timeout SDO response", (0-OSRetVal)$UDINT);
#endif
      
    SDIAS_OUT_OF_HANDLES:
#ifdef HWC_LogValue1
      HWC_LogValue1(this, "@00A7 (SdiasManager::LogSDOErrorInfo) SDO Error 0x{0}: Out of handles", (0-OSRetVal)$UDINT);
#endif
      
    SDIAS_INVALID_PARAM_DATA_LENGTH:
#ifdef HWC_LogValue1
      HWC_LogValue1(this, "@00A8 (SdiasManager::LogSDOErrorInfo) SDO Error 0x{0}: Invalid length of data bytes", (0-OSRetVal)$UDINT);
#endif
      
    SDIAS_INVALID_PARAM_DATA_BUFFER:
#ifdef HWC_LogValue1
      HWC_LogValue1(this, "@00A9 (SdiasManager::LogSDOErrorInfo) SDO Error 0x{0}: Invalid data buffer", (0-OSRetVal)$UDINT);
#endif
      
    SDIAS_INVALID_PARAM_SDO_HANDLE:
#ifdef HWC_LogValue1
      HWC_LogValue1(this, "@00AA (SdiasManager::LogSDOErrorInfo) SDO Error 0x{0}: Invalid SDO handle", (0-OSRetVal)$UDINT);
#endif
      
    SDIAS_INVALID_PARAM_NODE:
#ifdef HWC_LogValue1
      HWC_LogValue1(this, "@00AB (SdiasManager::LogSDOErrorInfo) SDO Error 0x{0}: Invalid node handle", (0-OSRetVal)$UDINT);
#endif
      
    SDIAS_GLOBAL_ERROR:
#ifdef HWC_LogValue1
      HWC_LogValue1(this, "@00AC (SdiasManager::LogSDOErrorInfo) SDO Error 0x{0}: General Error of SDIAS Manager", (0-OSRetVal)$UDINT);
#endif

    SDIAS_INVALID_MANAGER:
#ifdef HWC_LogValue1
      HWC_LogValue1(this, "@00AD (SdiasManager::LogSDOErrorInfo) SDO Error 0x{0}: SDIAS Manager not found", (0-OSRetVal)$UDINT);
#endif

    SDIAS_SENDING_SDO_REQUEST_FAILED:
#ifdef HWC_LogValue1
      HWC_LogValue1(this, "@00AE (SdiasManager::LogSDOErrorInfo) SDO Error 0x{0}: Sending SDO request failed", (0-OSRetVal)$UDINT);
#endif
    
    SDIAS_RECEIVING_SDO_RESPONSE_FAILED:
#ifdef HWC_LogValue1
      HWC_LogValue1(this, "@00AF (SdiasManager::LogSDOErrorInfo) SDO Error 0x{0}: Receiving SDO response failed", (0-OSRetVal)$UDINT);
#endif

    SDIAS_MANAGER_GLOBAL_ERROR:
#ifdef HWC_LogValue1
      HWC_LogValue1(this, "@00B0 (SdiasManager::LogSDOErrorInfo) SDO Error 0x{0}: General Error of SDIAS Manager (like communication problems to client)", (0-OSRetVal)$UDINT);
#endif
    
    SDIAS_INTERNAL_ERROR:
#ifdef HWC_LogValue1
      HWC_LogValue1(this, "@00B1 (SdiasManager::LogSDOErrorInfo) SDO Error 0x{0}: Internal error", (0-OSRetVal)$UDINT);
#endif

  else
#ifdef HWC_LogValue1
    HWC_LogValue1(this, "@00B2 (SdiasManager::LogSDOErrorInfo) SDO Error 0x{0}: Unknown Error", (0-OSRetVal)$UDINT);
#endif
  end_case;
  
END_FUNCTION


FUNCTION VIRTUAL SdiasManager::CheckAccess
	VAR_INPUT
		bsStateByte 	: t_SDIAS_StateByte;
		sdRequired 	: DINT;
		sdPlace 	: DINT;
		pCrashThisTime 	: ^USINT;
		pCrashMessage 	: ^CHAR;
	END_VAR
	VAR_OUTPUT
		usRetryCounter 	: USINT;
	END_VAR

  // increase retrycounter if retries occured on the access
  usRetryCounter := bsStateByte SHR 5;

  // check if the access failed
  if sdRequired & (bsStateByte.AccessFailed = TRUE) then
    ModuleObjInfo[sdPlace].pThis^.ClassState := _RequiredError;
    RequiredPlace := sdPlace;
    CyclicMsgMarker.PostIt.RequiredError := TRUE;
    ClassState := _RequiredError;
    ErrorInitStep := InitSSW;
    InitSSW := _PrepareError;

    pCrashThisTime^ := 2;

    _strcpy(dest:=pCrashMessage, src:="Access to a required SDIAS Module failed");
  end_if;                  

END_FUNCTION


FUNCTION VIRTUAL SdiasManager::PostRtMessages

  // if there are some messages to post, post them (the methods in the brackets are not the actual, but the methods were the error occured)
  if CyclicMsgMarker.PostIt then
    if CyclicMsgMarker.PostIt.IsoReadRunFailed then
#ifdef HWC_LogError
      HWC_LogError(this, "@00B3 (SdiasManager::RtWork) Error changing the run state of the isochronous read access!");
#endif
    end_if;
    
    if CyclicMsgMarker.PostIt.IsoWriteRunFailed then
#ifdef HWC_LogError
      HWC_LogError(this, "@00B4 (SdiasManager::RtWork) Error changing the run state of the isochronous write access!");
#endif
    end_if;
    
    if CyclicMsgMarker.PostIt.RequiredError then
#ifdef HWC_LogValue1
      HWC_LogValue1(this, "@00B5 (SdiasManager::RtWork) Required Error at SDIAS Place 0x{0}", RequiredPlace$UDINT);
#endif
    end_if;
    
    if CyclicMsgMarker.PostIt.ForwardRequiredErrorFailed then
#ifdef HWC_LogError
      HWC_LogError(this, "@00B6 (SdiasManager::RtWork) Failed to set required error to BusInterface");
#endif
    end_if;
    
    if CyclicMsgMarker.PostIt.ToggleErrorWrTask & (CyclicMsgMarker.AlreadyPosted.ToggleErrorWrTask = FALSE) then
#ifdef HWC_LogError
      HWC_LogError(this, "@00B7 (SdiasManager::RtWork) [SL] Error at toggle bit of iso write task of SDIAS");
#endif
      CyclicMsgMarker.AlreadyPosted.ToggleErrorWrTask := TRUE;
    end_if;
    
    if CyclicMsgMarker.PostIt.ToggleErrorRdTask & (CyclicMsgMarker.AlreadyPosted.ToggleErrorRdTask = FALSE) then
#ifdef HWC_LogError
      HWC_LogError(this, "@00B8 (SdiasManager::RtWork) [SL] Error at toggle bit of iso read task of SDIAS");
#endif
      CyclicMsgMarker.AlreadyPosted.ToggleErrorRdTask := TRUE;
    end_if;

    if CyclicMsgMarker.PostIt.ErrorWrTask & (CyclicMsgMarker.AlreadyPosted.ErrorWrTask = FALSE) then
#ifdef HWC_LogValue1
      HWC_LogValue1(this, "@00B9 (SdiasManager::RtWork) [SL] Error at iso write task of SDIAS 0x{0}", (WriteTaskInfo.pReadData^.ErrorInfoFlags AND SDIAS_ERROR_INFO_MASK));
#endif
      CyclicMsgMarker.AlreadyPosted.ErrorWrTask := TRUE;
    end_if;

    if CyclicMsgMarker.PostIt.ErrorRdTask & (CyclicMsgMarker.AlreadyPosted.ErrorRdTask = FALSE) then
#ifdef HWC_LogValue1
      HWC_LogValue1(this, "@00BA (SdiasManager::RtWork) [SL] Error at iso read task of SDIAS 0x{0}", (ReadTaskInfo.pReadData^.ErrorInfoFlags AND SDIAS_ERROR_INFO_MASK));
#endif
      CyclicMsgMarker.AlreadyPosted.ErrorRdTask := TRUE;
    end_if;

    if CyclicMsgMarker.PostIt.GetRdInfoFailed & (CyclicMsgMarker.AlreadyPosted.GetRdInfoFailed = FALSE) then
#ifdef HWC_LogError
      HWC_LogError(this, "@00BB (SdiasManager::RtWork) [SL] Error fetching iso read task info from OS");
#endif
      CyclicMsgMarker.AlreadyPosted.GetRdInfoFailed := TRUE;
    end_if;

    if CyclicMsgMarker.PostIt.GetWrInfoFailed & (CyclicMsgMarker.AlreadyPosted.GetWrInfoFailed = FALSE) then
#ifdef HWC_LogError
      HWC_LogError(this, "@00BC (SdiasManager::RtWork) [SL] Error fetching iso write task info from OS");
#endif
      CyclicMsgMarker.AlreadyPosted.GetWrInfoFailed := TRUE;
    end_if;

    if CyclicMsgMarker.PostIt.SetSyncFailed & (CyclicMsgMarker.AlreadyPosted.SetSyncFailed = FALSE) then
#ifdef HWC_LogError
      HWC_LogError(this, "@00BD (SdiasManager::RtWork) [SL] Failed to set sync out of pll");
#endif
      CyclicMsgMarker.AlreadyPosted.SetSyncFailed := TRUE;
    end_if;

    if CyclicMsgMarker.PostIt.GetFrameCounterFailed & (CyclicMsgMarker.AlreadyPosted.GetFrameCounterFailed = FALSE) then
#ifdef HWC_LogError
      HWC_LogError(this, "@00BE (SdiasManager::RtWork) [SL] Failed to get the frame counter info via OS interface");
#endif
      CyclicMsgMarker.AlreadyPosted.SetSyncFailed := TRUE;
    end_if;

    if CyclicMsgMarker.PostIt.WrTaskNotFinished & (CyclicMsgMarker.AlreadyPosted.WrTaskNotFinished = FALSE) then
#ifdef HWC_LogError
      HWC_LogError(this, "@00BF (SdiasManager::RtWork) [SL] Iso write task of SDIAS hasn't been completed");
#endif
      CyclicMsgMarker.AlreadyPosted.WrTaskNotFinished := TRUE;
    end_if;
    
    if CyclicMsgMarker.PostIt.WrTaskInterruptedByRdTask & (CyclicMsgMarker.AlreadyPosted.WrTaskInterruptedByRdTask = FALSE) then
#ifdef HWC_LogError
      HWC_LogError(this, "@00C0 (SdiasManager::RtWork) [SL] Iso write task of SDIAS has been interrupted by read task");
#endif
      CyclicMsgMarker.AlreadyPosted.WrTaskInterruptedByRdTask := TRUE;
    end_if;

    if CyclicMsgMarker.PostIt.RdTaskNotFinished & (CyclicMsgMarker.AlreadyPosted.RdTaskNotFinished = FALSE) then
      // this happens on local SDIAS:
      //  - if the iso startpoint is too high and the SDIAS read task can't finish before the next RT
      //
      // on SDIAS via VARAN:
      //  - VARAN iso startpoint too low or SDIAS read task load too high => task is not finished when the data is fetched via VARAN
#ifdef HWC_LogError
      HWC_LogError(this, "@00C1 (SdiasManager::RtWork) [SL] Iso read task of SDIAS hasn't been completed! Check setting of IsoStartPoint and cycle time!");
#endif
      CyclicMsgMarker.AlreadyPosted.RdTaskNotFinished := TRUE;
    end_if;
    if CyclicMsgMarker.PostIt.RdTaskNoEvent & (CyclicMsgMarker.AlreadyPosted.RdTaskNoEvent = FALSE) then
      // this happens on local SDIAS:
      //  - the RT takes too long and the SDIAS read task doesn't even start
      //
      // on SDIAS via VARAN:
      //  - VARAN iso startpoint or VARAN load too high => SDIAS read task doesn't even start
#ifdef HWC_LogError
      HWC_LogError(this, "@00C2 (SdiasManager::RtWork) [SL] Iso read task of SDIAS hasn't been started! Check setting of IsoStartPoint and cycle time!");
#endif
      CyclicMsgMarker.AlreadyPosted.RdTaskNoEvent := TRUE;
    end_if;

    if CyclicMsgMarker.PostIt.TaskInfoRunFailed then
#ifdef HWC_LogError
      HWC_LogError(this, "@00C3 (SdiasManager::RtWork) Error changing the run state of the isochronous read access to get the task info!");
#endif
    end_if;

    if CyclicMsgMarker.PostIt.IsoConfigWrTaskConfigFailed then
#ifdef HWC_LogError
      HWC_LogError(this, "@00C4 (SdiasManager::RtWork) Error starting isochronous configuration write access with single for task config!");
#endif
    end_if;

    if CyclicMsgMarker.PostIt.IsoConfigWrTriggerUnitFailed then
#ifdef HWC_LogError
      HWC_LogError(this, "@00C5 (SdiasManager::RtWork) Error starting isochronous configuration write access with single for trigger unit settings!");
#endif
    end_if;

    if CyclicMsgMarker.PostIt.IsoConfigWrChangeFailed then
#ifdef HWC_LogError
      HWC_LogError(this, "@00C6 (SdiasManager::RtWork) Failed to change the isochronous configuration write access!");
#endif
    end_if;

    if CyclicMsgMarker.PostIt.IsoTaskConfigFailed then
#ifdef HWC_LogError
      HWC_LogError(this, "@00C7 (SdiasManager::RtWork) Failed to set the iso read start config via OS interface!");
#endif
    end_if;

    if CyclicMsgMarker.PostIt.IsoTriggerUnitConfigFailed then
#ifdef HWC_LogError
      HWC_LogError(this, "@00C8 (SdiasManager::RtWork) Failed to set the trigger unit config via OS interface!");
#endif
    end_if;

    if CyclicMsgMarker.PostIt.IsoConfigWrChange2Failed then
#ifdef HWC_LogError
      HWC_LogError(this, "@00C9 (SdiasManager::RtWork) Error changing isochronous configuration write access for sync injection!");
#endif
    end_if;

    if CyclicMsgMarker.PostIt.IsoConfigWrSyncInjFailed then
#ifdef HWC_LogError
      HWC_LogError(this, "@00CA (SdiasManager::RtWork) Error starting isochronous configuration write access with single RUN for sync injection!");
#endif
    end_if;

    if CyclicMsgMarker.PostIt.IsoSyncInjFailed then
#ifdef HWC_LogError
      HWC_LogError(this, "@00CB (SdiasManager::RtWork) Failed to set the sync injection config via OS interface!");
#endif
    end_if;

    if CyclicMsgMarker.PostIt.SetOnlineStateFailed then
#ifdef HWC_LogError
      HWC_LogError(this, "@00CC (SdiasManager::RtWork) Failed to set the Online state!");
#endif
    end_if;
    
    CyclicMsgMarker.PostIt := 0;
  end_if;
  
END_FUNCTION


FUNCTION VIRTUAL SdiasManager::ChangeDynAccess
	VAR_INPUT
		AccessHandle 	: UDINT;
		NewOffset 	: HDINT;
		NewLength 	: UDINT;
	END_VAR
	VAR_OUTPUT
		Success 	: BOOL;
	END_VAR
  VAR
  	pAccess           : ^t_AccessElement;
    pControlStruct    : ^t_SDIAS_ControlStructDynamic;
    pControlStructFar : ^t_SDIAS_ControlStructDynamicFar;
    usBlockNo1k       : USINT;
    hiModAddr0        : HINT;
  END_VAR

  Success := FALSE;
  
  // check if valid handle
  if AccessHandle then
    pAccess := AccessHandle$^t_AccessElement;

    if (pAccess^.eAccessType = _ReadDynamic) | (pAccess^.eAccessType = _WriteDynamic) then
      if pAccess^.bIsFarAcc then
        pControlStructFar := (pAccess^.ppControlByte^)$^t_SDIAS_ControlStructDynamicFar;        
        if pControlStructFar then
          if pAccess^.eAccessType = _ReadDynamic then
            if NewLength <> SDIAS_UNCHANGED_DYNAMIC_PARA then
              if NewLength > SDIAS_MAX_SIZE_FAR_MEM_ACCESS then
                return;
              else
                pControlStructFar^.usLengthRd := NewLength$USINT;
              end_if;
            end_if;
            if NewOffset <> SDIAS_UNCHANGED_DYNAMIC_PARA then            
              usBlockNo1k     := to_usint(NewOffset shr 10);
              hiModAddr0     := (NewOffset AND 16#3FF)$HINT + (pAccess^.usPlace shl 10);              
              pControlStructFar^.hiOffsetRd := hiModAddr0;
              pControlStructFar^.hiOffsetWr := usBlockNo1k;
            end_if;
            Success := TRUE;

          else // _WriteDynamic
            if NewLength <> SDIAS_UNCHANGED_DYNAMIC_PARA then
              if NewLength > SDIAS_MAX_SIZE_FAR_MEM_ACCESS then
                return;
              else
                pControlStructFar^.usLengthWr := NewLength$USINT;
              end_if;
              if NewOffset <> SDIAS_UNCHANGED_DYNAMIC_PARA then            
                usBlockNo1k     := to_usint(NewOffset shr 10);
                hiModAddr0     := (NewOffset AND 16#3FF)$HINT + (pAccess^.usPlace shl 10);                
                pControlStructFar^.hiOffsetWr := hiModAddr0;
                pControlStructFar^.hiOffsetRd := usBlockNo1k;
              end_if;
              Success := TRUE;
              
           end_if;
          end_if;
        end_if;
      else
        pControlStruct := (pAccess^.ppControlByte^)$^t_SDIAS_ControlStructDynamic;
        
        if pControlStruct then
          if NewOffset <> SDIAS_UNCHANGED_DYNAMIC_PARA then
            pControlStruct^.hiOffset := NewOffset$HINT + (pAccess^.usPlace shl 10);         
          end_if;

          if NewLength <> SDIAS_UNCHANGED_DYNAMIC_PARA then
            pControlStruct^.usLength := NewLength$USINT;         
          end_if;
          
          Success := TRUE;
        end_if;
      end_if;
    end_if;
  end_if;

END_FUNCTION


FUNCTION VIRTUAL SdiasManager::CreateAndModifyIsoDOs
  VAR
    dataUPDATEDO          : t_UpdateDOCfg;
    dataADDDO             : t_AddDOCfg;
  	tempCmd               : CmdStruct;
    _result               : results;
  END_VAR

  // initialize the data for the task config in realtime
  
  // set the task duration limit
  ISOTaskConfig.TaskDurationTimeout_us := (ud_BusTime_ns / 1000)$UINT;

  // start address of iso read list
  ISOTaskConfig.Config := gcMapping_Informations[IsoRdList].StartAddress;
           
  // we want to use the start configuration => enable it
  ISOTaskConfig.Config.SynchronizedStartEnable := TRUE; 
  
  // initialize the data for the trigger unit setup for later use
  ISOTriggerUnitSetup.TaskSelect := 0;
  ISOTriggerUnitSetup.TaskSelect.IsoWrite := TRUE;
  ISOTriggerUnitSetup.TaskSelect.IsoRead  := TRUE;
  
  ISOTriggerUnitSetup.StartAddress := gcMapping_Informations[IsoWrPayload].StartAddress - SDIAS_TRIGGER_UNIT_BYTE_SIZE;
  ISOTriggerUnitSetup.StartAddress.UnitEnable := TRUE;

  
  if ConnectionType = SDIAS_CON_VIA_VARAN_uC then

    if b_IsoDOsCreated = FALSE then

#ifndef SDIAS_DEACTIVATE_TASK_CHECKS
      // DO for Task Infos (start at task 1 = read task)
      TaskInfoDO.Offset := SDIAS_OFFSET_TASK_INFO_1;
      TaskInfoDO.Length := sizeof(t_TaskInfoReadData);
      
      dataADDDO.Priority            := _BUS_IF_ISO_MOVE;
      dataADDDO.RdWr                := _BUS_IF_READ;
      dataADDDO.ud_addressoff_read  := TaskInfoDO.Offset;
      dataADDDO.ui_length_read      := TaskInfoDO.Length;
      dataADDDO.b_UseLocalCopy      := TRUE;
      
      tempCmd.uiCmd     := _BUS_IF_ADD_DO;
      tempCmd.aPara[0]  := (#dataADDDO)$DINT;
      
      ToBusInterface.NewInst(pPara:=#tempCmd, pResult:=#_result);
      if _result.aData[0]$t_BusIFRetvalErrorcode = _BUS_IF_RETVAL_OK then
        TaskInfoDO.Handle        := _result.aData$t_AddDORet.Handle;
        TaskInfoDO.pData         := _result.aData$t_AddDORet.pDataRead;
        TaskInfoDO.AccessHandle  := _result.aData$t_AddDORet.AccessHandle;
        
        // the parameter is overwritten with the DPRAM adress if the pData points to local memory
        TaskInfoDO.pDataDPRAM := dataADDDO.ud_addressoff_read$pVoid;
      else
#ifdef HWC_LogError
        HWC_LogError(this, "@00CD (SdiasManager::CreateAndModifyIsoDOs) Failed to add DO for the task info");
#endif
        InitError := _CreateDOFailed;
      end_if;              
#endif

      // DO to enable read task in realtime before going to operational state      
      dataADDDO.Priority            := _BUS_IF_ISO_MOVE;
      dataADDDO.RdWr                := _BUS_IF_WRITE;
      dataADDDO.ud_addressoff_write := SDIAS_OFFSET_TASK_CONFIG_1;
      dataADDDO.ui_length_write     := sizeof(t_TaskConfig);
      dataADDDO.b_UseLocalCopy      := TRUE;
      
      tempCmd.uiCmd     := _BUS_IF_ADD_DO;
      tempCmd.aPara[0]  := (#dataADDDO)$DINT;
      
      ToBusInterface.NewInst(pPara:=#tempCmd, pResult:=#_result);
      if _result.aData[0]$t_BusIFRetvalErrorcode = _BUS_IF_RETVAL_OK then
        ISOConfigWrDO.Handle        := _result.aData$t_AddDORet.Handle;
        ISOConfigWrDO.pData         := _result.aData$t_AddDORet.pDataWrite;
        ISOConfigWrDO.AccessHandle  := _result.aData$t_AddDORet.AccessHandle;
        
        // the parameter is overwritten with the DPRAM adress if the pData points to local memory
        ISOConfigWrDO.pDataDPRAM := dataADDDO.ud_addressoff_write$pVoid;   

        // the first thing we write is the task config
        ISOConfigWrDO.pData^$t_TaskConfig := ISOTaskConfig;
      else
#ifdef HWC_LogError
        HWC_LogError(this, "@00CE (SdiasManager::CreateAndModifyIsoDOs) Failed to add DO for starting the iso read task");
#endif
        InitError := _CreateDOFailed;
      end_if;     
      

      // recalculate payload size for accessing the payload

      AddBroadCastAccessesToList();
      
      // take our special access usage and add the usage according to the µC as well as 2 bytes for the trigger unit activation
      ISOWriteDO.Length += gcMapping_Informations[IsoWrPayload].ActUsage + SDIAS_TRIGGER_UNIT_BYTE_SIZE;
      
      // take our special access usage and add the usage according to the µC
      ISOReadDO.Length  += gcMapping_Informations[IsoRdPayload].ActUsage;

      // since we get the status info extra => skip the status byte of watchdog + status byte of write task info + write task info + status byte of read task info + read task info
      ISOReadDO.Length  -= sizeof(t_SDIAS_StateByte) + sizeof(t_SDIAS_StateByte) + sizeof(t_TaskInfoData.Handshake) + sizeof(t_TaskInfoData.DurationTime) + sizeof(t_TaskInfoData.ExecutionTime)
                                                     + sizeof(t_SDIAS_StateByte) + sizeof(t_TaskInfoData.Handshake) + sizeof(t_TaskInfoData.DurationTime) + sizeof(t_TaskInfoData.ExecutionTime);

      // Long DO for Read Data
      dataADDDO.Priority            := _BUS_IF_ISO_MOVE;
      dataADDDO.RdWr                := _BUS_IF_READ;
      dataADDDO.ud_addressoff_read  := 0;
      dataADDDO.ui_length_read      := ISOReadDO.Length;
      dataADDDO.b_UseLocalCopy      := TRUE;
      
      tempCmd.uiCmd     := _BUS_IF_ADD_DO;
      tempCmd.aPara[0]  := (#dataADDDO)$DINT;
      
      ToBusInterface.NewInst(pPara:=#tempCmd, pResult:=#_result);
      if _result.aData[0]$t_BusIFRetvalErrorcode = _BUS_IF_RETVAL_OK then
        ISOReadDO.Handle        := _result.aData$t_AddDORet.Handle;
        ISOReadDO.pData         := _result.aData$t_AddDORet.pDataRead;
        ISOReadDO.AccessHandle  := _result.aData$t_AddDORet.AccessHandle;
        
        // the parameter is overwritten with the DPRAM adress if the pData points to local memory
        ISOReadDO.pDataDPRAM := dataADDDO.ud_addressoff_read$pVoid;
      else
#ifdef HWC_LogError
        HWC_LogError(this, "@00CF (SdiasManager::CreateAndModifyIsoDOs) Failed to add long DO for the isochronous read data");
#endif
        InitError := _CreateDOFailed;
      end_if;

      // Long DO for Write Data
      dataADDDO.Priority            := _BUS_IF_ISO_MOVE;
      dataADDDO.RdWr                := _BUS_IF_WRITE;
      dataADDDO.ud_addressoff_write := 0;
      dataADDDO.ui_length_write     := ISOWriteDO.Length;
      dataADDDO.b_UseLocalCopy      := TRUE;

      tempCmd.uiCmd     := _BUS_IF_ADD_DO;
      tempCmd.aPara[0]  := (#dataADDDO)$DINT;
      
      ToBusInterface.NewInst(pPara:=#tempCmd, pResult:=#_result);
      if _result.aData[0]$t_BusIFRetvalErrorcode = _BUS_IF_RETVAL_OK then
        ISOWriteDO.Handle       := _result.aData$t_AddDORet.Handle;
        ISOWriteDO.pData        := _result.aData$t_AddDORet.pDataWrite;
        ISOWriteDO.AccessHandle := _result.aData$t_AddDORet.AccessHandle;

        // the parameter is overwritten with the DPRAM adress if the pData points to local memory
        ISOWriteDO.pDataDPRAM := dataADDDO.ud_addressoff_write$pVoid;
      else
#ifdef HWC_LogError
        HWC_LogError(this, "@00D0 (SdiasManager::CreateAndModifyIsoDOs) Failed to add long DO for the isochronous write data");
#endif
        InitError := _CreateDOFailed;
      end_if;
      
      // reset data objects (calculate retry timeout) is done before the runstate is set
      
      //Save length of ISO Read and ISO Write DO, will later be used to check if the length is correct when there is a reconnect
      //It can happen that there is only 1 module at the first connect and at the second connect there are 5 SDIAS module behind the VI02x
      //We save the created length here and check it later if the length is ok
      sDOLengthsFirstConnect.udISOReadLength :=     ISOReadDO.Length;
      sDOLengthsFirstConnect.udISOWriteLength :=    ISOWriteDO.Length;
      sDOLengthsFirstConnect.udISOReadActUsage :=   gcMapping_Informations[IsoRdPayload].ActUsage;
      sDOLengthsFirstConnect.udISOWriteActUsage :=  gcMapping_Informations[IsoWrPayload].ActUsage;

      if InitError <> _CreateDOFailed then
        b_IsoDOsCreated := TRUE;
        b_IsoDOsJustCreated := TRUE;
      end_if;
    end_if;    
  end_if;

  // first we need to check out where our payload is stored and if it got the right size to access the right memory
  if gcMapping_Informations[IsoWrPayload].StartAddress then
    // modify if connected via VARAN
    if ConnectionType = SDIAS_CON_VIA_VARAN_uC then

                                                                                 // trigger unit is not actually part of the usage
      ISOWriteDO.Offset := gcMapping_Informations[IsoWrPayload].StartAddress - SDIAS_TRIGGER_UNIT_BYTE_SIZE; // the trigger unit starts earlier
    
      ISOWriteDO.pData^$UINT := ISOWriteDO.Length - SDIAS_TRIGGER_UNIT_BYTE_SIZE; // trigger unit itself is not part of the payload data size
    
      dataUPDATEDO.Handle               := ISOWriteDO.Handle;
      dataUPDATEDO.ud_addressoff_write  := ISOWriteDO.Offset;
      dataUPDATEDO.ud_length_write      := ISOWriteDO.Length;

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

      ToBusInterface.NewInst(pPara:=#tempCmd, pResult:=#_result); 
      if _result.aData[0]$t_BusIFRetvalErrorcode <> _BUS_IF_RETVAL_OK then  
#ifdef HWC_LogError
        HWC_LogError(this, "@00D3 (SdiasManager::CreateAndModifyIsoDOs) Failed to change isochronous write access! Unable to continue with Initialisation!");
#endif
        ClassState := _ManagerError;
        ErrorInitStep := InitSSW;
        InitSSW := _PrepareError;
        return;
      end_if;
    else
      // create if connected locally

      // Long DO for Write Data
      
      AddBroadCastAccessesToList();

      // take our special access usage and add the usage according to the µC as well as 2 bytes for the trigger unit activation
      ISOWriteDO.Length += gcMapping_Informations[IsoWrPayload].ActUsage + SDIAS_TRIGGER_UNIT_BYTE_SIZE;              

      ISOWriteDO.Offset := gcMapping_Informations[IsoWrPayload].StartAddress - SDIAS_TRIGGER_UNIT_BYTE_SIZE; // the trigger unit starts earlier

      dataADDDO.Priority            := _BUS_IF_ISO_MOVE;
      dataADDDO.RdWr                := _BUS_IF_WRITE;
      dataADDDO.ud_addressoff_write := ISOWriteDO.Offset;
      dataADDDO.ui_length_write     := ISOWriteDO.Length;
      dataADDDO.ud_addressoff_read  := 0;
      dataADDDO.ui_length_read      := 0;
      dataADDDO.b_UseLocalCopy      := TRUE;

      tempCmd.uiCmd     := _BUS_IF_ADD_DO;
      tempCmd.aPara[0]  := (#dataADDDO)$DINT;
      
      ToBusInterface.NewInst(pPara:=#tempCmd, pResult:=#_result);
      if _result.aData[0]$t_BusIFRetvalErrorcode = _BUS_IF_RETVAL_OK then
        ISOWriteDO.Handle       := _result.aData$t_AddDORet.Handle;
        ISOWriteDO.pData        := _result.aData$t_AddDORet.pDataWrite;
        ISOWriteDO.AccessHandle := _result.aData$t_AddDORet.AccessHandle;

        // initialize the trigger unit
        ISOWriteDO.pData^$UINT := ISOWriteDO.Length - SDIAS_TRIGGER_UNIT_BYTE_SIZE;

        // the parameter is overwritten with the DPRAM adress if the pData points to local memory
        ISOWriteDO.pDataDPRAM := dataADDDO.ud_addressoff_write$pVoid;
      else
#ifdef HWC_LogError
        HWC_LogError(this, "@00D0 (SdiasManager::CreateAndModifyIsoDOs) Failed to add long DO for the isochronous write data");
#endif
        InitError := _CreateDOFailed;
      end_if;
    end_if;
  end_if;

  if gcMapping_Informations[IsoRdPayload].StartAddress then
    // modify if connected via VARAN
    if ConnectionType = SDIAS_CON_VIA_VARAN_uC then
      ISOReadDO.Offset := gcMapping_Informations[IsoRdPayload].StartAddress;
      
      // since we get the status info extra => skip the status byte of watchdog + status byte of write task info + write task info + status byte of read task info + read task info
      ISOReadDO.Offset += sizeof(t_SDIAS_StateByte) + sizeof(t_SDIAS_StateByte) + sizeof(t_TaskInfoData.Handshake) + sizeof(t_TaskInfoData.DurationTime) + sizeof(t_TaskInfoData.ExecutionTime)
                                                    + sizeof(t_SDIAS_StateByte) + sizeof(t_TaskInfoData.Handshake) + sizeof(t_TaskInfoData.DurationTime) + sizeof(t_TaskInfoData.ExecutionTime);

      dataUPDATEDO.Handle               := ISOReadDO.Handle;
      dataUPDATEDO.ud_addressoff_read   := ISOReadDO.Offset;
      dataUPDATEDO.ud_length_read       := ISOReadDO.Length;

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

      ToBusInterface.NewInst(pPara:=#tempCmd, pResult:=#_result); 
      if _result.aData[0]$t_BusIFRetvalErrorcode <> _BUS_IF_RETVAL_OK then  
#ifdef HWC_LogError
        HWC_LogError(this, "@00D4 (SdiasManager::CreateAndModifyIsoDOs) Failed to change isochronous read access! Unable to continue with Initialisation!");
#endif
        ClassState := _ManagerError;
        ErrorInitStep := InitSSW;
        InitSSW := _PrepareError;
        return;
      end_if;
    else
      // create if connected locally

      // Long DO for Read Data

      // take our special access usage and add the usage according to the µC
      ISOReadDO.Length  += gcMapping_Informations[IsoRdPayload].ActUsage;

      ISOReadDO.Offset := gcMapping_Informations[IsoRdPayload].StartAddress;

      dataADDDO.Priority            := _BUS_IF_ISO_MOVE;
      dataADDDO.RdWr                := _BUS_IF_READ;
      dataADDDO.ud_addressoff_read  := ISOReadDO.Offset;
      dataADDDO.ui_length_read      := ISOReadDO.Length;
      dataADDDO.ud_addressoff_write := 0;
      dataADDDO.ui_length_write     := 0;
      dataADDDO.b_UseLocalCopy      := TRUE;
      
      tempCmd.uiCmd     := _BUS_IF_ADD_DO;
      tempCmd.aPara[0]  := (#dataADDDO)$DINT;
      
      ToBusInterface.NewInst(pPara:=#tempCmd, pResult:=#_result);
      if _result.aData[0]$t_BusIFRetvalErrorcode = _BUS_IF_RETVAL_OK then
        ISOReadDO.Handle        := _result.aData$t_AddDORet.Handle;
        ISOReadDO.pData         := _result.aData$t_AddDORet.pDataRead;
        ISOReadDO.AccessHandle  := _result.aData$t_AddDORet.AccessHandle;
        
        // the parameter is overwritten with the DPRAM adress if the pData points to local memory
        ISOReadDO.pDataDPRAM := dataADDDO.ud_addressoff_read$pVoid;
      else
#ifdef HWC_LogError
        HWC_LogError(this, "@00CF (SdiasManager::CreateAndModifyIsoDOs) Failed to add long DO for the isochronous read data");
#endif
        InitError := _CreateDOFailed;
      end_if;
    end_if;
  end_if;

END_FUNCTION


FUNCTION VIRTUAL SdiasManager::IsDeviceBitSet
	VAR_INPUT
		pDeviceBitMap 	: ^BDINT;
		Place 	: UDINT;
	END_VAR
	VAR_OUTPUT
		bIsSet 	: BOOL;
	END_VAR

  if Place >= 32 then
    Place -= 32;
    pDeviceBitmap += 4;
  end_if;  
  bIsSet := ((pDeviceBitmap^ SHR Place) AND 1)$BOOL;

END_FUNCTION


FUNCTION VIRTUAL SdiasManager::DisableBus
  VAR
    dataSETRUNSTATE     : t_SetRunStateCfg;
  	tempCmd             : CmdStruct;
    _result             : results;
    dataUPDATEDO        : t_UpdateDOCfg;
    aProperties         : ARRAY [0..4] OF SDM_PROPERTY_VALUE_PAIR;
    SyncInjectionCfg    : t_SyncInjectionCfg;
  END_VAR

  // we select the read task for sync, there are no sync task trigger losses allowed and we disable the sync injection
  SyncInjectionCfg := 16#02;

  if ConnectionType = SDIAS_CON_VIA_VARAN_uC then          
    // change config DO => change trigger unit settings (also use trigger unit for read task)
    ISOConfigWrDO.Offset := SDIAS_OFFSET_SYNC_INJECTION_CFG;
    ISOConfigWrDO.Length := sizeof(t_SyncInjectionCfg);
    
    dataUPDATEDO.Handle               := ISOConfigWrDO.Handle;
    dataUPDATEDO.ud_addressoff_write  := ISOConfigWrDO.Offset;
    dataUPDATEDO.ud_length_write      := ISOConfigWrDO.Length;

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

    ToBusInterface.NewInst(pPara:=#tempCmd, pResult:=#_result); 
    
    if _result.aData[0]$t_BusIFRetvalErrorcode <> _BUS_IF_RETVAL_OK then
      // remember the log message and write it in cyclic priority to avoid a rt runtime error
      CyclicMsgMarker.PostIt.IsoConfigWrChange2Failed := TRUE;
    else
      // use the sync injection data
      ISOConfigWrDO.pData^$t_SyncInjectionCfg := SyncInjectionCfg;
    end_if;

    dataSETRUNSTATE.NewRunState := _BUS_IF_RUN_STATE_SINGLE_RUN;
    tempCmd.uiCmd               := _BUS_IF_SET_RUN_STATE;  
    tempCmd.aPara[0]            := (#dataSETRUNSTATE)$DINT; 
    
    dataSETRUNSTATE.Handle      := ISOConfigWrDO.Handle;

    ToBusInterface.NewInst(pPara:=#tempCmd, pResult:=#_result); 

    if _result.aData[0]$t_BusIFRetvalErrorcode <> _BUS_IF_RETVAL_OK then
      // remember the log message and write it in cyclic priority to avoid a rt runtime error
      CyclicMsgMarker.PostIt.IsoConfigWrSyncInjFailed := TRUE;
    end_if; 
  else
    aProperties[0].udPropertyId     := SDM_PROP_SYNC_INJECTION_CONFIG;
    aProperties[0].udPropertyValue  := SyncInjectionCfg;

    if SDIAS_iSetNodeProperties(hNodeHandle         := udNodeHandle
                              , udPropertyCount     := 1
                              , psPropertyValuePairs:= #aProperties[0]
                              ) <> SDIAS_OK then
      // remember the log message and write it in cyclic priority to avoid a rt runtime error
      CyclicMsgMarker.PostIt.IsoSyncInjFailed := TRUE;
    end_if;
  end_if;            
            
  
  // general settings needed for all DOs
  dataSETRUNSTATE.NewRunState := _BUS_IF_RUN_STATE_NO_RUN;
  tempCmd.uiCmd         := _BUS_IF_SET_RUN_STATE;  
  tempCmd.aPara[0]      := (#dataSETRUNSTATE)$DINT; 
  
#ifndef SDIAS_DEACTIVATE_TASK_CHECKS
  if ConnectionType = SDIAS_CON_VIA_VARAN_uC then
    // set runstate of taskinfo read
    dataSETRUNSTATE.Handle      := TaskInfoDO.Handle;
   
    ToBusInterface.NewInst(pPara:=#tempCmd, pResult:=#_result); 
    
    if _result.aData[0]$t_BusIFRetvalErrorcode <> _BUS_IF_RETVAL_OK then
      // remember the log message and write it in cyclic priority to avoid a rt runtime error
      CyclicMsgMarker.PostIt.TaskInfoRunFailed := TRUE;
    end_if;  
  end_if;
#endif

  // set runstate of read
  dataSETRUNSTATE.Handle      := ISOReadDO.Handle;
 
  ToBusInterface.NewInst(pPara:=#tempCmd, pResult:=#_result); 
  
  if _result.aData[0]$t_BusIFRetvalErrorcode <> _BUS_IF_RETVAL_OK then
    // remember the log message and write it in cyclic priority to avoid a rt runtime error
    CyclicMsgMarker.PostIt.IsoReadRunFailed := TRUE;
  end_if;  


  // set runstate of write
  dataSETRUNSTATE.Handle      := ISOWriteDO.Handle;

  ToBusInterface.NewInst(pPara:=#tempCmd, pResult:=#_result); 
  
  if _result.aData[0]$t_BusIFRetvalErrorcode <> _BUS_IF_RETVAL_OK then
    // remember the log message and write it in cyclic priority to avoid a rt runtime error
    CyclicMsgMarker.PostIt.IsoWriteRunFailed := TRUE;
  end_if;

END_FUNCTION


FUNCTION VIRTUAL GLOBAL SdiasManager::BusIFLogIn
  VAR
  	tempCmd         : CmdStruct;
    _result         : results;
    dataADDCallback : t_BusIFAddCallback;
  END_VAR

  // first check if the module may be deactivated
  tempCmd.uiCmd     := _BUS_IF_GET_DEACTIVATED_STATE;
  ToBusInterface.NewInst(pPara:=#tempCmd, pResult:=#_result);
  if _result.aData[0]$t_BusIFRetvalErrorcode = _BUS_IF_RETVAL_OK then
    b_Deactivated := _result.aData[4]$BOOL;
    if b_Deactivated then
#ifdef HWC_LogError
      HWC_LogError(this, "@00D5 (SdiasManager::BusIFLogIn) SDIAS Manager object inactive");
#endif
      return;
    end_if;
  else
#ifdef HWC_LogError
    HWC_LogError(this, "@00D6 (SdiasManager::BusIFLogIn) Failed to get deactivation state via BusInterface");
#endif
  end_if;

  // Set this class as the operator class of the BusInterface
  dataADDCallback.pthis := this$pVirtualBase;
  
  tempCmd.uiCmd     := _BUS_IF_ADD_CALLBACK;
  tempCmd.aPara[0]  := (#dataADDCallback)$DINT;      
  ToBusInterface.NewInst(pPara:=#tempCmd, pResult:=#_result);
  if _result.aData[0]$t_BusIFRetvalErrorcode <> _BUS_IF_RETVAL_OK then
#ifdef HWC_LogError
    HWC_LogError(this, "@00D7 (SdiasManager::BusIFLogIn) Failed to install callback at bus interface");
#endif
  else
    b_CallbackAdded := TRUE;
  end_if;
  
END_FUNCTION


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

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

  if _result.aData[0]$t_BusIFRetvalErrorcode <> _BUS_IF_RETVAL_OK then
#ifdef HWC_LogError
    HWC_LogError(this, "@00D8 (SdiasManager::CyWork) Failed to set the post init to finished via bus interface!");
#endif
  end_if;    

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

END_FUNCTION


FUNCTION VIRTUAL SdiasManager::FarMemoryAccessAvailable
	VAR_OUTPUT
		IsAvailable 	: BOOL;
	END_VAR
  
  if FarMemoryAccessInfo.IsAvailableIsValid = FALSE then
    // get it when entering the first time 
    FarMemoryAccessInfo.IsAvailable := FeatureInfo.OptionBits.FarMemoryAccessSupported;
    if (ConnectionType = SDIAS_CON_LOCAL_uC) & (pSDIAS^.udVersion < SDIAS_CIL_VERSION_SUPPORTS_DYNAMIC_DO) then
      // far memory access needs the new CIL
      FarMemoryAccessInfo.IsAvailable := FALSE;
    end_if;    
    FarMemoryAccessInfo.IsAvailableIsValid := TRUE;
    if FarMemoryAccessInfo.IsAvailable = FALSE then      
#ifdef HWC_LogError
      HWC_LogError(this, "@00DB (SdiasManager::FarMemoryAccessAvailable) Failed to add far memory access! Update OS and/or fpga.");
#endif
    end_if;
  end_if;
  
  IsAvailable := FarMemoryAccessInfo.IsAvailable;

END_FUNCTION

FUNCTION VIRTUAL SdiasManager::SendTimeBroadCast
  VAR
  	tempCmd             : CmdStruct;
    _result             : results;
    uiBroadCastTime     : UINT;
  END_VAR

  if SupportedFeatures.TimeBroadCastSupported then
    // Get Timestamp from HWControl
    tempCmd.uiCmd := CMD_GET_HW_TIMESTAMP;
    tempCmd.aPara[0]$t_GetHwTimestampCmd.udVersion    := 1;
    tempCmd.aPara[0]$t_GetHwTimestampCmd.udCoreSelect := 0;
    
    ToBusInterface.NewInst(#tempCmd, #_result);
    
    // Update Timestamp, do not inkrement here because application accesses this variable!
    uiHWTimestamp := _result.aData[0]$t_GetHwTimestampResult.uiTimeStamp;
    
    uiBroadCastTime := (uiHWTimestamp + uiSDIASSyncoffset_us) AND 16#7FFF;
    
    // Inkrement and Boadcast Timestamp
    if aBroadCastTime[0].pWriteData then
      aBroadCastTime[0].pWriteData^ := uiBroadCastTime;
    end_if;
    if aBroadCastTime[1].pWriteData then
      aBroadCastTime[1].pWriteData^ := uiBroadCastTime;
    end_if;
  end_if;
  
END_FUNCTION

FUNCTION VIRTUAL SdiasManager::SendSyncCntDown
	VAR_OUTPUT
		SyncCountDown 	: UINT;
	END_VAR
  
  if SupportedFeatures.TimeBroadCastSupported then
    
    // Decrement before sending, return value is the sent value
    uiSyncCountDown -= 1;
          
    // Send Sync countdown
    if aBroadCastTime[0].pWriteData then
      aBroadCastTime[0].pWriteData^ := uiSyncCountDown;
    end_if;
    if aBroadCastTime[1].pWriteData then
      aBroadCastTime[1].pWriteData^ := uiSyncCountDown;
    end_if;
  
  end_if;
  
  SyncCountDown := uiSyncCountDown;
          
END_FUNCTION