//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 IsLasalEepromIdOk_IS_AVAILABLE

#define DIAS_EEPROM_OFFSET      16#00

#define DIAS_EEPROM_OFFSET_HWVERSION      16#06
#define DIAS_EEPROM_OFFSET_DEVICE_NAME    16#10

// Kennung of DIAS Modules with standardized EEPROM. The actual Kennung may be read from the EEPROM From offset 16#08
// s. "DIAS_LASAL EEPROM.DOC" and "DIAS Kennungen.doc"
#define DIAS_STANDARD_EEPROM_AVAILABLE_1  16#13
#define DIAS_STANDARD_EEPROM_AVAILABLE_2  16#73
#define DIAS_STANDARD_EEPROM_AVAILABLE_3  16#17
#define DIAS_STANDARD_EEPROM_AVAILABLE_4  16#77
//}}LSL_DEFINES

//{{LSL_DECLARATION
#include "..\..\Class\HwControl\HwControl.h"

(*!
<Class
	Name               = "HwBase"
	Revision           = "2.36"
	GUID               = "{97E357E5-4B1A-11D6-AB3C-00106092052D}"
	RealtimeTask       = "false"
	CyclicTask         = "false"
	BackgroundTask     = "false"
	Sigmatek           = "true"
	OSInterface        = "false"
	HighPriority       = "true"
	Automatic          = "false"
	UpdateMode         = "Postscan"
	IconPath           = ".\Class\Tool.ico"
	SharedCommandTable = "true"
	Objectsize         = "(452,120)"
	Comment            = "The Base hardware class for DIAS">
	<Channels>
		<Server Name="RetryCounter" GUID="{A8CD0E40-5926-48E9-8718-88B6A05EE517}" Visualized="true" Initialize="false" WriteProtected="false" Retentive="false" Comment="counts up if retries occur on the DIAS Bus, while trying to access this module&#13;&#10;&#13;&#10;-1..Retrycounter not active. &#13;&#10;&#13;&#10;Possible reasons for an inactive Retrycounter:&#13;&#10; - device isn&apos;t connected with an intelligent master&#13;&#10; - if connected over CIV/DIV, the FPGA of the CIV/DIV doesn&apos;t support the Retrycounter (newer version of the FPGA required)"/>
		<Server Name="State" GUID="{97E357E6-4B1A-11D6-AB3C-00106092052D}" Visualized="true" Initialize="false" WriteProtected="true" Retentive="false" Comment="This Server indicates the state of the hardware class. If the value is greater then 0, an error occured (may be wrong settings at the client &quot;Place&quot;).&#13;&#10;A perfect function of this hardware class is indicated on this erver by 0.&#13;&#10;&#13;&#10;&#13;&#10;&#13;&#10;"/>
		<Client Name="MasterConnect" Required="true" Internal="false" Comment="connect to DiasMasterC or DIAS-Client of DIV or CIV"/>
		<Client Name="Place" Required="false" Internal="false" Comment="write the adress of the hardware modul (DIAS Bus- ID) as init value to this client&#13;&#10;"/>
		<Client Name="Required" Required="false" Internal="false" DefValue="1" Comment="0 = module is not required&#13;&#10;1 = module is required (CPU will crash if module is missing)"/>
		<Client Name="To_StdLib" Required="false" Internal="false"/>
	</Channels>
	<Dependencies>
		<Files>
			<File Path=".\Class\DiasMaster\DIASMaster.h" Include="false"/>
			<File Path=".\Source\interfaces\lsl_st_varan.h" Include="false"/>
			<File Path=".\Class\HwControl\HwControl.h" Include="true"/>
		</Files>
	</Dependencies>
	<RevDoku>
		<Owner Company="Sigmatek" Author="SilBer"/>
		<Dokumentation Revision="2.36" Date="18.12.2020" Author="RamAnd" Company="Sigmatek" Description="Removed CLI/STI occurances in internal time measurements"/>
		<Dokumentation Revision="2.35" Date="06.03.2018" Author="EisMic" Company="Sigmatek" Description="Attached header files no longer point to the installation directory of LASAL but instead now point to the the source/interfaces folder."/>
		<Dokumentation Revision="2.34" Date="23.01.2018" Author="RamAnd" Company="Sigmatek" Description="Log messages have been standardized for easier maintenance, easier use in any class and to allow spam filtering. Code for the logging functions is now only located in HwControl."/>
		<Dokumentation Revision="2.33" Date="23.05.2017" Author="RamAnd" Company="Sigmatek" Description="A pointer for dynamic parameters has been added to the hardware diagnosis. Added initialisation of the pointer with NIL."/>
		<Dokumentation Revision="2.32" Date="10.05.2016" Author="RamAnd" Company="Sigmatek" Description="Suppressed warning that would occur with target ARM on compiler version 30 or higher."/>
		<Dokumentation Revision="2.31" Date="24.06.2014" Author="LanSte" Company="Sigmatek" Description="Added support for reading hardware diagnosis."/>
		<Dokumentation Revision="2.30" Date="06.12.2013" Author="Fucher" Company="Sigmatek" Description="New methods CreateMutex(), MutexStart() and MutexStop()."/>
		<Dokumentation Revision="2.20" Date="07.03.2013" Author="BeiWol" Company="Sigmatek" Description="Added functionality to use module optional via define DEACTIVATED_LSL as Place value."/>
		<Dokumentation Revision="2.10" Date="18.07.2012" Author="ObeChr" Company="Sigmatek" Description="Implemented time measurement for internal tests in methods UpdateRt, UpdateRtPostScan and UpdateCy"/>
		<Dokumentation Revision="2.9" Date="19.01.2012" Author="ZoePat" Company="Sigmatek" Description="Corrected handling of RequiredError (In some cases it could have happened, that an error has been generated even if the module has been connected)"/>
		<Dokumentation Revision="2.8" Date="22.09.2011" Author="RamAnd" Company="Sigmatek" Description="Parameter of Server Read/Write-Methods have been changed to the type of the server."/>
		<Dokumentation Revision="2.7" Date="27.01.2011" Author="RamAnd" Company="Sigmatek" Description="Corrected comment of server RetryCounter"/>
		<Dokumentation Revision="2.6" Date="11.01.2011" Author="RamAnd" Company="Sigmatek" Description="Added method IsLasalEepromIdOk for an easier check of DIAS module IDs."/>
		<Dokumentation Revision="2.5" Date="17.11.2010" Author="WocPet" Company="Sigmatek" Description="Retrycounter now possible over varan"/>
		<Dokumentation Revision="2.4" Date="02.09.2010" Author="BleErn" Company="Sigmatek" Description="improved comment for client MasterConnect"/>
		<Dokumentation Revision="2.3" Date="23.06.2010" Author="WocPet" Company="Sigmatek" Description="new server &quot;RetryCounter&quot; added"/>
		<Dokumentation Revision="2.2" Date="04.03.2010" Author="BleErn" Company="Sigmatek" Description="Changed order of methods"/>
		<Dokumentation Revision="2.1" Date="08.02.2010" Author="BleErn" Company="Sigmatek" Description="New virtual method UpdateRtPostScan&#13;&#10;New method SetUpdateRtPostScan"/>
	</RevDoku>
</Class>
*)
HwBase : CLASS
	TYPE
	  MasterType : DINT;  //! <Type Comment="Type of Master (standard or IMaster)" Name="MasterType"/>
	END_TYPE
  //Servers:
	State 	: SvrChCmd_IO_State;
	RetryCounter 	: SvrCh_DINT;
  //Clients:
	MasterConnect 	: CltChCmd_DiasMasterC;
	Place 	: CltCh_UDINT;
	Required 	: CltCh_DINT;
	To_StdLib 	: CltChCmd__StdLib;
  //Variables:
		Kennung 	: UDINT;
		MasterType 	: UDINT;
		ScanMode 	: DINT;
		IOSegmentByte 	: ^USINT;
		IOSegmentWord 	: ^UINT;
		b_VaranAvailable 	: BOOL;
		b_initialized 	: BOOL;
		us_EEOk 	: USINT;
		ProfilerCy 	: s_PROFILER_Time;
		ProfilerRt 	: s_PROFILER_Time;
		ProfilerRtPostScan 	: s_PROFILER_Time;
		mt_api 	: ^LSL_MT_TYPE;
		p_ObjectPath 	: ^USINT;
  //Functions:
	
	FUNCTION HwBase
		VAR_OUTPUT
			ret_code 	: ConfStates;
		END_VAR;
	
	FUNCTION VIRTUAL GLOBAL Init;
				//! <Function Comment=" *****************************************************************************&#13;&#10;   this is the base of updating a channel should be overwiten by each class&#13;&#10; *****************************************************************************&#13;&#10;" Name="UpDateCY"/>
	FUNCTION VIRTUAL GLOBAL UpDateCY
		VAR_INPUT
			Handle 	: UDINT;
		END_VAR;
	
	FUNCTION VIRTUAL GLOBAL UpDateRT
		VAR_INPUT
			handle 	: UDINT;
		END_VAR;
	
	FUNCTION VIRTUAL GLOBAL UpDateRTPostScan
		VAR_INPUT
			Handle 	: UDINT := 0;
		END_VAR;
	
	FUNCTION VIRTUAL GLOBAL CheckSync
		VAR_OUTPUT
			Sync (AL) 	: USINT;
		END_VAR;
	
	FUNCTION VIRTUAL GLOBAL GetEEState
		VAR_OUTPUT
			state 	: DINT;
		END_VAR;
				//! <Function Comment="[#ENGLISH]&#13;&#10;&#13;&#10;" Name="GetEEData"/>
	FUNCTION VIRTUAL GLOBAL GetEEData
		VAR_INPUT
			channel 	: DINT;
			Typ 	: DINT;
			pData 	: ^DINT;
		END_VAR;
	
	FUNCTION VIRTUAL GLOBAL AddOneChannel
		VAR_INPUT
			thisp 	: ^void;
			RTCY 	: DINT;
			channel 	: DINT;
		END_VAR
		VAR_OUTPUT
			Handle 	: DINT;
		END_VAR;
	
	FUNCTION VIRTUAL GLOBAL GetCallHandle
		VAR_INPUT
			channel 	: DINT;
		END_VAR
		VAR_OUTPUT
			Handle 	: DINT;
		END_VAR;
	
	FUNCTION GLOBAL IsLasalEepromIdOk
		VAR_INPUT
			pModuleName 	: ^CHAR;
		END_VAR
		VAR_OUTPUT
			IsOK 	: BOOL;
		END_VAR;
				//! <Function Comment="Function to intialize TimeMeassurement" Name="InitTimeMeasurement"/>
	FUNCTION InitTimeMeasurement
		VAR_INPUT
			usMode (EAX) 	: DINT;			//! <Variable Comment="Indicates the type of the Profiler:&#13;&#10;&#13;&#10;DMTIME_RT (0) .......... Profiler for UpdateRt-Task&#13;&#10;DMTIME_CY (1) .......... Profiler for UpdateCy-Task&#13;&#10;DMTIME_RTPOSTSCAN (2) .. Profiler for UpdateRtPostScan-Task" Name="InitTimeMeasurement.usMode"/>
		END_VAR;
				//! <Function Comment="Function to start TimeMeassurement" Name="StartTimeMeasurement"/>
	FUNCTION StartTimeMeasurement
		VAR_INPUT
			usMode (EAX) 	: DINT;			//! <Variable Comment="Indicates the type of the Profiler:&#13;&#10;&#13;&#10;DMTIME_RT (0) .......... Profiler for UpdateRt-Task&#13;&#10;DMTIME_CY (1) .......... Profiler for UpdateCy-Task&#13;&#10;DMTIME_RTPOSTSCAN (2) .. Profiler for UpdateRtPostScan-Task" Name="StartTimeMeasurement.usMode"/>
		END_VAR;
				//! <Function Comment="Function to stop TimeMeassurement" Name="StopTimeMeasurement"/>
	FUNCTION StopTimeMeasurement
		VAR_INPUT
			usMode (EAX) 	: DINT;			//! <Variable Comment="Indicates the type of the Profiler:&#13;&#10;&#13;&#10;DMTIME_RT (0) .......... Profiler for UpdateRt-Task&#13;&#10;DMTIME_CY (1) .......... Profiler for UpdateCy-Task&#13;&#10;DMTIME_RTPOSTSCAN (2) .. Profiler for UpdateRtPostScan-Task" Name="StopTimeMeasurement.usMode"/>
		END_VAR;
	
	FUNCTION CreateMutex
		VAR_INPUT
			MutexName 	: ^CHAR;
			pThis 	: ^VirtualBase;
		END_VAR
		VAR_OUTPUT
			pv_RetMutex 	: pVoid;
		END_VAR;
	
	FUNCTION MutexStart
		VAR_INPUT
			pMutex 	: pVoid;
		END_VAR;
	
	FUNCTION MutexStop
		VAR_INPUT
			pMutex 	: pVoid;
		END_VAR;
	
	FUNCTION GetOwnObjectPath;
	
	FUNCTION SetObjectThisp
		VAR_OUTPUT
			sd_retval 	: DINT;
		END_VAR;
				//! <Function Comment="This method returns the device id of the module.&#13;&#10;Has to be overwritten in every module." Name="GetDeviceID"/>
	FUNCTION VIRTUAL GetDeviceID
		VAR_OUTPUT
			output 	: UDINT;
		END_VAR;
				//! <Function Comment="This method returns the kennung/variante of the module.&#13;&#10;Has to be overwritten in every module." Name="GetVariante"/>
	FUNCTION VIRTUAL GetVariante
		VAR_OUTPUT
			output 	: UDINT;
		END_VAR;
				//! <Function Comment="This method returns the firmware version of the module.&#13;&#10;Has to be overwritten in every module with firmware." Name="GetFWVersion"/>
	FUNCTION VIRTUAL GetFWVersion
		VAR_INPUT
			pData 	: ^CHAR;
			length 	: DINT;
		END_VAR;
	
	FUNCTION VIRTUAL LogError
		VAR_INPUT
			e_msg 	: ^CHAR;
		END_VAR;
	
	FUNCTION VIRTUAL LogValue
		VAR_INPUT
			pString 	: ^CHAR;
			Value 	: UDINT;
			Value2 	: UDINT := 16#FFFFFFFF;
			Value3 	: UDINT := 16#FFFFFFFF;
		END_VAR;
	
	FUNCTION VIRTUAL GLOBAL State::NewInst
		VAR_INPUT
			pPara 	: ^CmdStruct;
			pResult 	: ^results;
		END_VAR
		VAR_OUTPUT
			ret_code 	: iprStates;
		END_VAR;
  //Tables:
	FUNCTION @STD
		VAR_OUTPUT
			ret_code	: CONFSTATES;
		END_VAR;
	FUNCTION GLOBAL TAB @CT_;
END_CLASS;

#pragma usingLtd _StdLib
#pragma usingLtd DiasMasterC


//}}LSL_DECLARATION


FUNCTION GLOBAL TAB HwBase::@CT_
0$UINT,
2#0010000000000000$UINT, //TY_HWBASE
2$UINT, 36$UINT, (SIZEOF(::HwBase))$UINT, 
2$UINT, 4$UINT, 0$UINT, 
TO_UDINT(262141616), "HwBase", //Class
TO_UDINT(0), 0, 0$UINT, 0$UINT, //Baseclass
//Servers:
(::HwBase.State.pMeth)$UINT, _CH_CMD$UINT, 2#0000000000000000$UINT, TO_UDINT(1422331979), "State", 
(::HwBase.RetryCounter.pMeth)$UINT, _CH_SVR$UINT, 2#0000000000000000$UINT, TO_UDINT(3383993698), "RetryCounter", 
//Clients:
(::HwBase.MasterConnect.pCh)$UINT, _CH_CLT_OBJ$UINT, 2#0000000000000010$UINT, TO_UDINT(1515240279), "MasterConnect", TO_UDINT(3069482179), "DiasMasterC", 1$UINT, 83$UINT, 
(::HwBase.Place.pCh)$UINT, _CH_CLT_DATA$UINT, 2#0000000000000000$UINT, TO_UDINT(2202636669), "Place", 
(::HwBase.Required.pCh)$UINT, _CH_CLT_DATA$UINT, 2#0000000000000000$UINT, TO_UDINT(648558917), "Required", 
(::HwBase.To_StdLib.pCh)$UINT, _CH_CLT_OBJ$UINT, 2#0000000000000000$UINT, TO_UDINT(2139173287), "To_StdLib", TO_UDINT(3689364044), "_StdLib", 2$UINT, 0$UINT, 
END_FUNCTION


#define USER_CNT_HwBase 13

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	IF State.pMeth THEN
		ret_code	:= C_OK;
	ELSE
		ret_code	:= C_OUTOF_NEAR;
		RETURN;
	END_IF;
	RetryCounter.pMeth			:= StoreMethod( #M_RD_DIRECT(), #M_WR_DIRECT() );
	IF RetryCounter.pMeth THEN
		ret_code	:= C_OK;
	ELSE
		ret_code	:= C_OUTOF_NEAR;
		RETURN;
	END_IF;
	ret_code	:= HwBase();

END_FUNCTION

//{{LSL_IMPLEMENTATION
#pragma using DiasMasterC

(**************************************************************************************
* 
*	Baseclass for all Dias Hardwaremoduls
* 	Created : Sigmatek / 2003
*	Changes : 
*		1.1 => 2.0	/	30.11.2007	/	Mark:	//#SR000
*			- [DB 713]: make compatible to CIV/DIV DataMover
*		0.1 => 1.1 / 23.12.2004 / no Mark / ws
*			compatibility with Lasal Class 2
*			removed visible flags from internal servers
*		0.0 => 0.1 / 01.06.2004 / Mark: // #BS000
*			Added Function CheckSync()
*
**************************************************************************************)

#PRAGMA warning (disable:73)   

VAR_PRIVATE
  p_this            : ^void;
	a_EEHEADER        : ARRAY[0..31] of UINT; // 64 Byte Standard EEPROM Header
  a_DeviceName			: ARRAY[0..43] OF CHAR;
  a_FWVersion       : ARRAY[0..43] OF CHAR;
    
  a_HWTEntryStr     : ARRAY[0.. VARAN_MAX_DEPTH+1] OF CHAR;  // VaranMaxDepth +1 because length is 2 byte long

END_VAR


FUNCTION VIRTUAL GLOBAL HwBase::Init

  MasterType := MasterConnect.GetMasterType();	
  Place := Place.Read();
  IOSegmentByte := MasterConnect.GetDiasIosegment()+(Place*16#100);		 
  IOSegmentWord := MasterConnect.GetDiasIosegment()+16#4000+(Place*16#100);		 

	b_VaranAvailable := MasterConnect.IsVaranAvailable() <> 0;		//#SR000
  
  if Place <= 63 then 
    Kennung := MasterConnect.GetKennung(Place);
  else
    Kennung :=16#FF;
  end_if;

  if ((Kennung <> 16#FF) & (MasterType = 2)) | (b_VaranAvailable = true) then //WOPE
  
    //if a hardware was found direct on dias with intelligent master or over varan, mark modul in diasmaster for retry counter
    MasterConnect.SetRetryCounterAvailability(Port:=Place$USINT, p_State:=#State, p_RetryCounter:=#RetryCounter);
  
    //mark counter as ok
    RetryCounter := 0;
    
  end_if;
    
  //only in our first init
  if b_initialized = false then
    Required := Required.Read();
    if Required then
      Required := 1;
      MasterConnect.AddRequiredObject(thisp:=this);
    end_if;  
    
  end_if;
  
  //get position in object network
  GetOwnObjectPath(); 
  
  //save this-pointer of object in reference to the object path
  SetObjectThisp();
  
  b_initialized := true;  

END_FUNCTION //VIRTUAL GLOBAL HwBase::Init
// *****************************************************************************
//   this is the base of updating a channel should be overwiten by each class
// *****************************************************************************

FUNCTION GLOBAL HwBase::UpDateCY
  VAR_INPUT
    Handle		:  Udint;
  END_VAR

END_FUNCTION //GLOBAL HwBase::UpDate


FUNCTION VIRTUAL GLOBAL HwBase::UpDateRT
  VAR_INPUT
    handle		: UDINT;
  END_VAR

END_FUNCTION //VIRTUAL GLOBAL HwBase::UdDateRT


FUNCTION VIRTUAL GLOBAL HwBase::GetEEState
  VAR_OUTPUT
    state		: DINT;
  END_VAR
  
	state := 1;  // no EEprom in BASE
  
END_FUNCTION //VIRTUAL GLOBAL HwBase::GetEEState

//[#ENGLISH]
//

FUNCTION VIRTUAL GLOBAL HwBase::GetEEData
  VAR_INPUT
    channel		: DINT;
    Typ		: DINT;
    pData		: ^DINT;
  END_VAR

END_FUNCTION //VIRTUAL GLOBAL HwBase::GetEEData


FUNCTION VIRTUAL GLOBAL HwBase::AddOneChannel
  VAR_INPUT
    thisp		: ^void;
    RTCY		: DINT;
    channel		: DINT;
  END_VAR
  VAR_OUTPUT
    Handle		: DINT;
  END_VAR
  
	handle :=-1;
  
END_FUNCTION //VIRTUAL GLOBAL HwBase::AddOneChannel


FUNCTION VIRTUAL GLOBAL HwBase::GetCallHandle
  VAR_INPUT
    channel		: DINT;
  END_VAR
  VAR_OUTPUT
    Handle		: DINT;
  END_VAR
  
  if channel then
  end_if;
  
  Handle := -1;
    
END_FUNCTION //VIRTUAL GLOBAL HwBase::GetCallHandle

FUNCTION  HwBase::HwBase
  VAR_OUTPUT
    ret_code		: CONFSTATES;
  END_VAR

#ifdef HWC_LogInit
  HWC_LogInit();
#endif

	state.uiIO_Flags :=16#ffff;
  RetryCounter     := -1;
	ret_code	       := C_OK;

END_FUNCTION //  HwBase::HwBase


FUNCTION VIRTUAL GLOBAL HwBase::CheckSync // #BS000
  VAR_OUTPUT
    Sync(AL)		: USINT;
  END_VAR

	Sync := 0;

END_FUNCTION //VIRTUAL GLOBAL HwBase::CheckSync

//BLEERN001 start
FUNCTION VIRTUAL GLOBAL HwBase::UpDateRTPostScan
	VAR_INPUT
		Handle 	: UDINT;
	END_VAR

END_FUNCTION
#pragma warning(default: 73 )
//BLEERN001 end

FUNCTION GLOBAL HwBase::IsLasalEepromIdOk
	VAR_INPUT
		pModuleName : ^CHAR;
	END_VAR
	VAR_OUTPUT
		IsOK 	      : BOOL;
	END_VAR
  VAR
  	i           : UINT;
    Temp        : UINT;
    TempEEProm  : ARRAY [0..31] OF UINT;
  END_VAR

  IsOK := FALSE;
  
  // init and read eeprom
  MasterConnect.EEProm.InitEE(udPortAddr:=0, uiStationNo:=Place$uint, uiReadType:=3);

  for i := 0 to 31 do
    Temp := MasterConnect.EEProm.EE_Rd(i);
    if Temp <> 16#FFFF then
      TempEEProm[i]                     := Temp;
    else
      State.uiIO_Flags					        := 0;
      State.uiIO_Flags.NoCalibration		:= 1;
      State.uiIO_Flags.PhysicAccessOff	:= 1;
      return;            
    end_if;
  end_for;

  // check if it's the right module
  if (MasterConnect.EEProm.EE_CHK(pEEData:=(#TempEEProm[0])$^UINT, TYP:=1) <> 0) | _memcmp(ptr1:=#TempEEProm[16], ptr2:=pModuleName, cntr:=_strlen(pModuleName)) then
    State.uiIO_Flags					        := 0;
    State.uiIO_Flags.NoCalibration		:= 1;
    State.uiIO_Flags.PhysicAccessOff	:= 1;
    return;
  end_if;

  IsOK := TRUE;

END_FUNCTION


FUNCTION VIRTUAL GLOBAL HwBase::State::NewInst
	VAR_INPUT
		pPara 	            : ^CmdStruct;
		pResult 	          : ^Results;
	END_VAR
	VAR_OUTPUT
		ret_code 	          : IprStates;
	END_VAR
  VAR
    ptmpStr             : ^CHAR;
    i                   : USINT;
    
    ui_OffsetDeviceName : UINT;
  END_VAR
  
  ptmpStr := NIL;
  i       := 0;
  
  ui_OffsetDeviceName := 0;

	ret_code := READY;

	CASE pPara^.uiCmd OF
//*****************************************************************************************************************************      
		DM_CHECK_REQUIRED_ERROR :
      // if it's not optional (mandatory) and the module could not be found and the eeprom data are invalid (module is actually not connected if used via VARAN; always zero if used on CDIAS)
      if (Place <> DEACTIVATED_LSL) & ((State$BINT and 2#1100000000000011) <> 0) & (us_EEOk = 0) then
        ret_code := ERROR;
        if pResult <> NIL then
          pResult^.aData[0] := Place$USINT;
          pResult^.aData[1] := DIAS_MODULE;
        end_if;
      end_if;
//*****************************************************************************************************************************      
    CMD_GET_HARDWARE_TREE_ENTRY :
      
      //Set Errors
      ret_code := ERROR;
      pResult^.aData$t_HWCGetHardwareTreeEntryOut.retcode := _HWC_RETVAL_ERROR;
      pResult^.aData[0]$t_HWCGetHardwareTreeEntryOut.pStr_NextHardewareTreeEntry := NIL;
      
      // Don't check for State = _ClassOk, method will be used to compare Real HWT with placed classes        
      
      if p_ObjectPath then
  
        //Copy Length of p_objectpath (is on 1st byte) on first byte of our array, length is 2 byte so set the 2nd byte manual
        a_HWTEntryStr[0] := p_ObjectPath^$USINT;
        a_HWTEntryStr[1] := 0;
        
        //a_HWTEntryStr + 2 because first 2 bytes are lenght, ObjectPath 1st byte is length, copy as long as the object path is
        _memcpy(ptr1:=#a_HWTEntryStr+2, ptr2:=p_ObjectPath+1, cntr:=a_HWTEntryStr[0]);   
        
        //Return Hardware Tree Entry and set return codes
        pResult^.aData[0]$t_HWCGetHardwareTreeEntryOut.pStr_NextHardewareTreeEntry := #a_HWTEntryStr[0];
        ret_code := READY;
        pResult^.aData[0]$t_HWCGetHardwareTreeEntryOut.retcode := _HWC_RETVAL_OK_HWTSTR_RETURNED;
        
        // Compare Module string with passed string
        if pPara^.aPara[0]$t_HWCGetHardwareDiagnosisIn.pStr_HardewareTreeEntry then 
        
          if pPara^.aPara[0]$t_HWCGetHardwareDiagnosisIn.pStr_HardewareTreeEntry$^USINT^ =
             pResult^.aData[0]$t_HWCGetHardwareTreeEntryOut.pStr_NextHardewareTreeEntry$^USINT^ then // Compare Length
             
            if _memcmp( ptr1:= pPara^.aPara[0]$t_HWCGetHardwareDiagnosisIn.pStr_HardewareTreeEntry // Compare Data
                      , ptr2:= pResult^.aData[0]$t_HWCGetHardwareTreeEntryOut.pStr_NextHardewareTreeEntry
                      , cntr:= pResult^.aData[0]$t_HWCGetHardwareTreeEntryOut.pStr_NextHardewareTreeEntry$^USINT^ + 2) = 0 then   // + 2 for 2 Byte Length
                      
              pResult^.aData$t_HWCGetHardwareTreeEntryOut.retcode :=  _HWC_RETVAL_OK_MODULE_FOUND; 
            end_if;
          end_if;
        end_if;
        
      end_if;     
    
//*****************************************************************************************************************************      
    CMD_GET_HARDWARE_DIAGNOSIS :
      ret_code := ERROR;
      pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.retcode           := _HWC_RETVAL_ERROR_CLASS_NOT_ONLINE;
      
      //Return State and Device ID and Kennung of placed module --------------------------------
      if State.uiIO_Flags.WrongHW = 1 then
        pResult^.aData$t_HWCGetHardwareDiagnosisOut.ClassState := _WrongHardware;
        pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.retcode := _HWC_RETVAL_ERROR_WRONG_HARDWARE;
      elsif State.uiIO_Flags.NoHW = 1 then
        pResult^.aData$t_HWCGetHardwareDiagnosisOut.ClassState := _NoHardware;
        pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.retcode := _HWC_RETVAL_ERROR_NO_HARDWARE;
      elsif State.uiIO_Flags.NoCalibration = 1 then
        pResult^.aData$t_HWCGetHardwareDiagnosisOut.ClassState := _NoCalibDataFound;
        pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.retcode := _HWC_RETVAL_ERROR_NO_CALIB_DATA_FOUND;        
      end_if;

      pResult^.aData$t_HWCGetHardwareDiagnosisOut.ud_DeviceID := GetDeviceID();
      pResult^.aData$t_HWCGetHardwareDiagnosisOut.ud_Variante := GetVariante();
      //-----------------------------------------------------------------------------------------
      
      // Only respond if the class is online
      if State.uiIO_Flags = 0 then
        pResult^.aData$t_HWCGetHardwareDiagnosisOut.ClassState := _ClassOk;
        ptmpStr := pPara^.aPara[0]$t_HWCGetHardwareDiagnosisIn.pStr_HardewareTreeEntry;
      
        // Check if position pointers strings are valid
        if ptmpStr & p_ObjectPath then       
        
          if ( _memcmp(ptr1:=ptmpStr+2, ptr2:=p_ObjectPath+1, cntr:= (ptmpStr)$^UINT^) = 0 ) then  // Compare strings , 2 bytes length for ptmpStr, 1 byte length for p_ObjectPath
                        
            ret_code := READY;
            pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.retcode           := _HWC_RETVAL_OK;
            pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.ud_DeviceID       := Kennung;
            pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.pStr_VendorName   := NIL;
            pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.ud_VendorID       := 0;             
            pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.pStr_OrderingNo   := NIL;
            pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.ud_LicenseNo      := 0;
            
            
            // Will be overwritten with data from EEPROM
            pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.pStr_DeviceName := NIL;
            pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.hd_HWVersion    := 0;
            
            // Check if Module uses standard EEPROM
            if  ( Kennung = DIAS_STANDARD_EEPROM_AVAILABLE_1) | 
                ( Kennung = DIAS_STANDARD_EEPROM_AVAILABLE_2) | 
                ( Kennung = DIAS_STANDARD_EEPROM_AVAILABLE_3) | 
                ( Kennung = DIAS_STANDARD_EEPROM_AVAILABLE_4) then
            
              // init and read EEprom -------------------------------------------------------------------------------------
              MasterConnect.eeprom.InitEE(udPortAddr:=0, uiStationNo:=Place$uint, uiReadType:=3);            
              
              a_EEHEADER[0] := MasterConnect.eeprom.EE_Rd(0); // Checksumme
              a_EEHEADER[1] := MasterConnect.eeprom.EE_Rd(1); // 

              // Check i first 2 enries are valid              
              if a_EEHEADER[0] & a_EEHEADER[1] & a_EEHEADER[1] <> 16#ffff then
                
                for i := 0 to ( (sizeof(a_EEHEADER)/2) - 1) do
                  a_EEHEADER[i] := MasterConnect.eeprom.EE_Rd(i);
                end_for;   
                
                // Overwrite Kennung with Data from EEPROM
                pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.ud_DeviceID := a_EEHEADER[4];
                
                // Get Device Name ------------------------------------------------------------------------------------------
                ui_OffsetDeviceName := a_EEHEADER[8];
                
                if ui_OffsetDeviceName < sizeof(a_EEHEADER) then
                
                  _strcpy(dest:=#a_DeviceName[0], src:= (#a_EEHEADER[0] + ui_OffsetDeviceName)$^Char );
                  pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.pStr_DeviceName := #a_DeviceName[0];
                  
                end_if;
                
                // Get Hardwareversion --------------------------------------------------------------------------------------

                pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.hd_HWVersion := a_EEHEADER[3];
              
              end_if;
            end_if;
            
            // -----------------------------------------------------------------------------------------------------------
            pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.pStr_SerialNo     := NIL;            
            
            // FW Version --------------------------------------------------------------------------------------------        
            GetFWVersion(pData:=#a_FWVersion[0],sizeof(a_FWVersion));
            pResult^.aData$t_HWCGetHardwareDiagnosisOut.pStr_FWVersion := #a_FWVersion[0];
            
            // -----------------------------------------------------------------------------------------------------------
            pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.ud_Place          := Place;
            pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.ud_reserved_size  := 0;
            pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.pud_reserved      := NIL;
            pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.ud_user_size      := 0;
            pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.pud_user          := NIL;
            pResult^.aData[0]$t_HWCGetHardwareDiagnosisOut.p_DynExtList      := NIL;
          end_if;
        end_if;
      end_if;
//*****************************************************************************************************************************      

	END_CASE;

END_FUNCTION


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

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

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

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

  end_if;    
  
END_FUNCTION


FUNCTION HwBase::MutexStart
  VAR_INPUT
    pMutex  : pVoid;
  END_VAR

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

END_FUNCTION


FUNCTION HwBase::MutexStop
  VAR_INPUT
    pMutex  : pVoid;
  END_VAR

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

END_FUNCTION


#pragma warning(disable:74)
#pragma warning(disable:73)
FUNCTION HwBase::InitTimeMeasurement
	VAR_INPUT
		usMode (EAX) 	: DINT;
	END_VAR
  
#ifdef DM_Profiler
  VAR
  	tmpProfiler : ^s_PROFILER_Time;
  END_VAR

  case usMode of
 
    //-----------------------------------------------------------
    
    DMTIME_RT:
      tmpProfiler := #ProfilerRt;
      
    //-----------------------------------------------------------
    
    DMTIME_CY:
      tmpProfiler := #ProfilerCy;
      
    //-----------------------------------------------------------
    
    DMTIME_RTPOSTSCAN:
      tmpProfiler := #ProfilerRtPostScan;
      
    //-----------------------------------------------------------
    
  end_case;

	tmpProfiler^.sum 	:= 0;
	tmpProfiler^.run 	:= 0;
	tmpProfiler^._max := 0;
	tmpProfiler^._min := 16#ffffffff;
	tmpProfiler^.init := OS_readmicrosec();
  
#endif

END_FUNCTION


FUNCTION HwBase::StartTimeMeasurement
	VAR_INPUT
		usMode (EAX) 	: DINT;
	END_VAR
  
#ifdef DM_Profiler
  VAR
  	tmpProfiler : ^s_PROFILER_Time;
  END_VAR

  case usMode of
 
    //-----------------------------------------------------------
    
    DMTIME_RT:
      tmpProfiler := #ProfilerRt;
      
    //-----------------------------------------------------------
    
    DMTIME_CY:
      tmpProfiler := #ProfilerCy;
      
    //-----------------------------------------------------------
    
    DMTIME_RTPOSTSCAN:
      tmpProfiler := #ProfilerRtPostScan;
      
    //-----------------------------------------------------------
    
  end_case;
	
	tmpProfiler^.start := OS_ReadMicroSec();
	if ( ( tmpProfiler^.start - tmpProfiler^.init ) > DM_ProfilerDelay ) then
		tmpProfiler^.initfl := 0;
	else
		tmpProfiler^.initfl := 1;
	end_if;
#endif

END_FUNCTION


FUNCTION HwBase::StopTimeMeasurement
	VAR_INPUT
		usMode (EAX) 	: DINT;
	END_VAR
  
#ifdef DM_Profiler
  VAR
  	tmpProfiler : ^s_PROFILER_Time;
  END_VAR

  case usMode of
 
    //-----------------------------------------------------------
    
    DMTIME_RT:
      tmpProfiler := #ProfilerRt;
      
    //-----------------------------------------------------------
    
    DMTIME_CY:
      tmpProfiler := #ProfilerCy;
      
    //-----------------------------------------------------------
    
    DMTIME_RTPOSTSCAN:
      tmpProfiler := #ProfilerRtPostScan;
      
    //-----------------------------------------------------------
    
  end_case;

	if ( tmpProfiler^.initfl = 0 ) then

		tmpProfiler^.stop := OS_ReadMicroSec();
		tmpProfiler^.diff := tmpProfiler^.stop - tmpProfiler^.start - DM_CPUconstant;
		tmpProfiler^.sum += tmpProfiler^.diff;
		tmpProfiler^.run += 1;

		if ( tmpProfiler^.diff < tmpProfiler^._min ) then
			tmpProfiler^._min := tmpProfiler^.diff;
		end_if;

		if ( tmpProfiler^.diff > tmpProfiler^._max ) then
			tmpProfiler^._max := tmpProfiler^.diff;
		end_if;

		tmpProfiler^.avg := tmpProfiler^.sum * 100 / tmpProfiler^.run;

	end_if;
#endif

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


FUNCTION HwBase::GetOwnObjectPath
  VAR
    sd_retval : DINT;
  END_VAR

  //get position of connected class
  if ( p_ObjectPath = NIL ) then

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

		//look if an error occurs
		if ( p_ObjectPath = NIL ) then
      return;
    end_if;

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

    //get position
    sd_retval := MasterConnect.GetObjectPath( p_us_ObjectPath := p_ObjectPath );
	
    //look if an error occurs and check length
    if ( ( sd_retval <> 0 ) | ( p_ObjectPath^ >= VARAN_MAX_DEPTH ) ) then
      p_ObjectPath :=	( To_StdLib.ReAlloc	( mptr		:= p_ObjectPath
                                          , newsize	:= 1
                                          ) 
                      )$^USINT;
      return;
    end_if;

    //class is connected to DiasMasterC
    if ( p_ObjectPath^ = 1 ) then
      p_ObjectPath^ := 2;
      ( p_ObjectPath + 2 )^ := HWT_ESCAPE_DIAS;
    end_if;
    
    //alloc memory for position pointer and add one byte for place
    p_ObjectPath :=	( To_StdLib.ReAlloc	( mptr		:= p_ObjectPath
                                        , newsize	:= p_ObjectPath^ + 2
                                        ) 
                    )$^USINT;

    //look if an error occurs
    if ( p_ObjectPath = NIL ) then
      return;
    end_if;

    //increase length
    p_ObjectPath^ += 1;
    
    //add place
    ( p_ObjectPath + p_ObjectPath^ )^ := TO_USINT( Place );
    
  end_if;

END_FUNCTION


FUNCTION HwBase::SetObjectThisp
	VAR_OUTPUT
		sd_retval 	: DINT;
	END_VAR

  sd_retval := MasterConnect.SetObjectThisp( p_us_ObjectPath := p_ObjectPath
                                           , ud_thisp        := this$UDINT
                                           );

END_FUNCTION


FUNCTION VIRTUAL HwBase::GetDeviceID
	VAR_OUTPUT
		output 	: UDINT;
	END_VAR
  
  //Overwrite this method in derived class
  output := HWC_INVALID_DEVICE_ID;
  
END_FUNCTION


FUNCTION VIRTUAL HwBase::GetVariante
	VAR_OUTPUT
		output 	: UDINT;
	END_VAR
  
  //Overwrite this method in derived class
  output := HWC_INVALID_DEVICE_ID;
  
END_FUNCTION


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

END_FUNCTION

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

END_FUNCTION


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

END_FUNCTION
#pragma warning(default: 73);
