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

(*!
<Class
	Name               = "RamFile"
	Revision           = "1.9"
	GUID               = "{D5F246E6-EA0F-4431-9134-C50A66E56711}"
	RealtimeTask       = "false"
	CyclicTask         = "false"
	BackgroundTask     = "false"
	Sigmatek           = "true"
	OSInterface        = "false"
	HighPriority       = "false"
	Automatic          = "false"
	UpdateMode         = "Prescan"
	IconPath           = ".\Class\RamFile\Ram.ICO"
	SharedCommandTable = "true"
	Objectsize         = "(450,240)">
	<Channels>
		<Server Name="FileNameHex" GUID="{0941D254-6150-4D02-BCD0-5C3DE24E87AD}" Visualized="true" Initialize="false" WriteProtected="true" Retentive="false" Comment="Shows the Filename in an Hexadecimal value"/>
		<Server Name="m_udLength" GUID="{59B171D4-E9AA-4206-A049-717953C3466E}" Visualized="true" Initialize="false" WriteProtected="true" Retentive="false" Comment="Server shows the size of File without header"/>
		<Server Name="SizeError" GUID="{B708A640-1A0C-476E-AE9E-F44A5B69576A}" Visualized="true" Initialize="false" WriteProtected="true" Retentive="false" Comment="is set if error was in function SetSize"/>
		<Client Name="Alarm" Required="false" Internal="false" Comment="if Checksum is wrong"/>
		<Client Name="MultiTask" Required="false" Internal="false" Comment="is automatically connected "/>
		<Client Name="Setup" Required="true" Internal="false" Comment="Bit0 must be &quot;1&quot; to work, Bit1: 0=Work with File, Bit2 = Checksum On/Off, Bit3 = Encrypt On/Off | Encrypt and EnableChecksum increased the write accesses on the CF card"/>
	</Channels>
	<RevDoku>
		<Owner Company="Sigmatek" Author="HubChr"/>
		<Dokumentation Revision="1.9" Date="2015-09-22" Author="HubChr" Company="Sigmatek" Description="Class has been moved into &quot;_old&quot; folder. Instead of this class, RAMex shall be used (set Client UseFile to 1)."/>
		<Dokumentation Revision="1.8" Date="2013-04-08" Author="kolott" Company="Sigmatek" Description="ARM-Ready"/>
		<Dokumentation Revision="1.7" Date="2012-03-22" Author="HlaWol" Company="Sigmatek" Description="- bug: if encryption active, the memory with encrypted data is freed before saved to file/sram -&gt; can cause loss of data!&#13;&#10;"/>
	</RevDoku>
</Class>
*)
RamFile : CLASS
	TYPE
	  fDataFG : STRUCT
	    FilenameHexFG : HDINT;
	    FileSizeFG : UDINT;
	    SetupFG : FeSetup;
	    OperationState : BOOL;
	    m_udlengthFG : UDINT;
	  END_STRUCT;
	  fHeader : STRUCT
	    Version : UINT;  //! <Type Comment="internal Version of System (for Read only)" Name="fHeader.Version"/>
	    UserVersion : UINT;  //! <Type Comment="Version for user can be read/write" Name="fHeader.UserVersion"/>
	    CRC : UDINT;
	    Setup : FeSetup;
	    resarray : ARRAY [0..499] OF USINT;
	  END_STRUCT;
	  pData : ^RamFp;
	END_TYPE
  //Servers:
	m_udLength 	: SvrChCmd_UDINT;
	FileNameHex 	: SvrCh_HDINT;
	SizeError 	: SvrCh_DINT;
  //Clients:
	Setup 	: CltCh_FeSetup;
	Alarm 	: CltCh_UDINT;
	MultiTask 	: CltChCmd__MultiTask;
  //Variables:
		Header 	: fHeader;
		us_Filename : ARRAY [0..29] OF CHAR;
			//! <Variable Comment="Filename one the Disk" Name="us_Filename"/>
		us_FilenameBak : ARRAY [0..29] OF CHAR;

		us_Init 	: USINT;			//! <Variable Comment="1= we are already initialized" Name="us_Init"/>
		p_us_DataI 	: ^USINT;
		us_Encbyte 	: USINT;
		ud_Filesize 	: UDINT;
		b_FileAccessControl 	: BOOL;
		ud_DataOffset 	: UDINT;
		ud_DataSize 	: UDINT;
		p_us_DataFG 	: ^USINT;
		ui_UserVer 	: UINT;
		b_Reload 	: BOOL;
		b_check_ok 	: BOOL;
  //Functions:
	
	FUNCTION VIRTUAL GLOBAL Init;
				//! <Function Comment="[Server]  m_udLength   :W  :Server shows the size of File without header&#13;&#10;    FileNameHex   :W  :Shows the Filename in an Hexadecimal value&#13;&#10;[Clients]  Setup    :R  :Client contains the adjustments of the class &#13;&#10;    Alarm    :W  :Client is 1 if checksum is wrong&#13;&#10;[members]  us_Init    :R/W :variable is set if class is initialized&#13;&#10;    us_Filename   :W  :array containing the Path and Filename of File &#13;&#10;    us_FilenameBak  :W  :array containing the Path and Filename of .bak File&#13;&#10;    b_FileAccessControl :W  :variable marks if the file operation is finished or runs&#13;&#10;    us_Encbyte   :W  :variable to encrypt data&#13;&#10;    Header    :R/W :structure contains the inforamtions of the Header of File&#13;&#10;    p_us_DataI   :W/R :pointer for our working buffer&#13;&#10;    ui_UserVer   :W  :variable for user Version&#13;&#10;[locals]  p_obj    :W  :Pointer to Data of object&#13;&#10;    ud_length   :W/R :variable for length to copy string&#13;&#10;    p_us_eof   :W  :Pointer to FilenameBak&#13;&#10;    b_check_ok   :W/R :Flag for loading the correct File ( if checksum is rigth ) &#13;&#10;    sd_handle   :W/R :variable for File handling&#13;&#10;    ud_length_total  :W  :total length of File&#13;&#10;    ud_data_length  :W/R :length of Data in File (without Header)&#13;&#10;    ud_ctr    :W/R :counter for working with filedata&#13;&#10;    ud_Checksum   :R/W :variable for checksum calculation&#13;&#10;" Name="InitMe"/>
	FUNCTION InitMe;
				//! <Function Comment="Function to create the Filename&#13;&#10;" Name="CreateFileName"/>
	FUNCTION CreateFileName
		VAR_INPUT
			ud_crc 	: UDINT;			//! <Variable Comment="Hex value of Filename" Name="CreateFileName.ud_crc"/>
			p_us_name 	: ^CHAR;			//! <Variable Comment="Pointer to Array for Filename" Name="CreateFileName.p_us_name"/>
		END_VAR;
				//! <Function Comment="Path of the Directory where the RamFiles were saved&#13;&#10;" Name="Direktory"/>
	FUNCTION TAB Direktory;
				//! <Function Comment="Function copies the Direktory path in the array for the Filename&#13;&#10;" Name="CopyDir"/>
	FUNCTION CopyDir
		VAR_INPUT
			p_us_name 	: ^CHAR;
		END_VAR
		VAR_OUTPUT
			p_us_end_of_dir 	: ^CHAR;			//! <Variable Comment="Pointer to last Array entry of Filename" Name="CopyDir.p_us_end_of_dir"/>
		END_VAR;
				//! <Function Comment="function to get the user version of file&#13;&#10;[Clients]  Setup    :R  :Client contains the adjustments of the class &#13;&#10;[members]  us_Init    :R  :variable is set if class is initialized&#13;&#10;    p_us_DataI   :R  :pointer for our working buffer&#13;&#10;    Header    :R  :structure contains the inforamtions of the Header of File&#13;&#10;" Name="GetUserVersion"/>
	FUNCTION VIRTUAL GLOBAL GetUserVersion
		VAR_OUTPUT
			ui_version 	: UINT;			//! <Variable Comment="Version of file" Name="GetUserVersion.ui_version"/>
		END_VAR;
				//! <Function Comment="Function to set user version of file&#13;&#10;[Clients]  Setup    :R  :Client contains the adjustments of the class &#13;&#10;[members]  us_Init    :R  :variable is set if class is initialized&#13;&#10;    p_us_DataI   :R  :pointer for our working buffer&#13;&#10;    Header    :W  :structure contains the inforamtions of the Header of File&#13;&#10;    us_Filename   :R  :array containing the Path and Filename of File &#13;&#10;[locals]  sd_handle   :R  :variable for file handling&#13;&#10;" Name="SetUserVersion"/>
	FUNCTION VIRTUAL GLOBAL SetUserVersion
		VAR_INPUT
			ui_version 	: HINT;			//! <Variable Comment="Version shich is set to file" Name="SetUserVersion.ui_version"/>
		END_VAR;
				//! <Function Comment="[#ENGLISH]&#13;&#10;This Function returns the State of the File operation. If it returns&#13;&#10;1 the last File operation does not finished. The User must wait&#13;&#10;with the next File operation until this function returns 0!!&#13;&#10;[member]  b_FileAccessControl :W  :variable marks if the file operation is finished or runs&#13;&#10;" Name="GetFileState"/>
	FUNCTION VIRTUAL GLOBAL GetFileState
		VAR_OUTPUT
			State 	: BOOL;			//! <Variable Comment="State of File operations" Name="GetFileState.State"/>
		END_VAR;
				//! <Function Comment="[#ENGLISH]&#13;&#10;Function assure that all file operations are finished.&#13;&#10;The CF - card can be removed safley.&#13;&#10;" Name="RemoveHWSafley"/>
	FUNCTION VIRTUAL GLOBAL RemoveHWSafley
		VAR_OUTPUT
			ret_code 	: ConfStates;
		END_VAR;
				//! <Function Comment="[#ENGLISH]&#13;&#10;Use this function to change the size of the data buffer&#13;&#10;Size should be set once to the maximum bytes you will need in the&#13;&#10;file (so no cyclic growing files !!)&#13;&#10;&#13;&#10;SetSize should not be called cyclic you may destroy the CF card.&#13;&#10;2.000.000 write accesses to each sector. FAT and directory&#13;&#10;must be updated periodically if you change the size cyclic.&#13;&#10;[Server]  m_udLength   :R  :Server shows the size of File without header&#13;&#10;[members]  us_Init    :R  :variable is set if class is initialized&#13;&#10;    ud_Filesize   :W  :size of File&#13;&#10;    b_FileAccessControl :R/W :variable marks if the file operation is finished or runs&#13;&#10;    p_us_DataI   :R  :pointer for our working buffer&#13;&#10;" Name="SetSize"/>
	FUNCTION VIRTUAL GLOBAL SetSize
		VAR_INPUT
			ud_size 	: UDINT;			//! <Variable Comment="size of data" Name="SetSize.ud_size"/>
		END_VAR
		VAR_OUTPUT
			ret_code 	: ConfStates;
		END_VAR;
				//! <Function Comment="[#ENGLISH]&#13;&#10;Use this function to change the size of the data buffer in the background&#13;&#10;(for bigger files, because it can require a long time)&#13;&#10;Size should be set once to the maximum bytes you will need in the&#13;&#10;file (so no cyclic growing files !!)&#13;&#10;&#13;&#10;SetSize should not be called cyclic you may destroy the CF card.&#13;&#10;2.000.000 write accesses to each sector. FAT and directory&#13;&#10;must be updated periodically if you change the size cyclic.&#13;&#10;[Server]  m_udLength   :R  :Server shows the size of File without header&#13;&#10;[members]  us_Init    :R  :variable is set if class is initialized&#13;&#10;    ud_Filesize   :W  :size of File&#13;&#10;    b_FileAccessControl :R/W :variable marks if the file operation is finished or runs&#13;&#10;    p_us_DataI   :R  :pointer for our working buffer&#13;&#10;[locals]  p_us_fg    :W/R :pointer to forground function&#13;&#10;" Name="SetSizeBackground"/>
	FUNCTION VIRTUAL GLOBAL SetSizeBackground
		VAR_INPUT
			ud_size 	: UDINT;
		END_VAR
		VAR_OUTPUT
			ret_code 	: ConfStates;
		END_VAR;
				//! <Function Comment="[#ENGLISH]&#13;&#10;Call this function, to get back a certain part from the stored Data&#13;&#10;If udAt is bigger than &quot;Buffer&quot; no Data are copied&#13;&#10;If udSize is bigger than &quot;Buffer&quot; no Data are copied&#13;&#10;[Server]  m_udLength   :R  :Server shows the size of File without header&#13;&#10;[members]  us_Init    :R  :variable is set if class is initialized&#13;&#10;    b_FileAccessControl :R/W :variable marks if the file operation is finished or runs&#13;&#10;    p_us_DataI   :R  :pointer for our working buffer&#13;&#10;    p_us_DataFG   :W  :pointer to data which should be read&#13;&#10;    ud_DataSize   :W  :size of data which should be read&#13;&#10;    ud_DataOffset   :W  :offset of data which should be read&#13;&#10;" Name="GetDataAt"/>
	FUNCTION VIRTUAL GLOBAL GetDataAt
		VAR_INPUT
			p_us_data 	: ^USINT;			//! <Variable Comment="pointer to a buffer with sufficient size" Name="GetDataAt.p_us_data"/>
			ud_size 	: UDINT;
			ud_at 	: UDINT;			//! <Variable Comment="offset of the first byte to change" Name="GetDataAt.ud_at"/>
		END_VAR
		VAR_OUTPUT
			ret_code 	: ConfStates;
		END_VAR;
				//! <Function Comment="[#ENGLISH]&#13;&#10;Call this function, to get back a certain part from&#13;&#10;the stored Data in Background for bigger files or a huge part of data.&#13;&#10;If udAt is bigger than &quot;Buffer&quot; no Data are copied&#13;&#10;If udSize is bigger than &quot;Buffer&quot; no Data are copied&#13;&#10;[Server]  m_udLength   :R  :Server shows the size of File without header&#13;&#10;[members]  us_Init    :R  :variable is set if class is initialized&#13;&#10;    b_FileAccessControl :R/W :variable marks if the file operation is finished or runs&#13;&#10;    p_us_DataI   :R  :pointer for our working buffer&#13;&#10;    p_us_DataFG   :W  :pointer to data which shouldbe read&#13;&#10;    ud_DataSize   :W  :size of data which should be read&#13;&#10;    ud_DataOffset   :W  :offset of data which should be read&#13;&#10;[locals]  p_us_fg    :W/R :pointer to foreground function&#13;&#10;" Name="GetDataAtBackground"/>
	FUNCTION VIRTUAL GLOBAL GetDataAtBackground
		VAR_INPUT
			p_us_data 	: ^USINT;
			ud_size 	: UDINT;
			ud_at 	: UDINT;
		END_VAR
		VAR_OUTPUT
			ret_code 	: ConfStates;
		END_VAR;
				//! <Function Comment="[#ENGLISH]&#13;&#10;Use this function to change a part of the data buffer.&#13;&#10;If buffer is not big enough no data are written.&#13;&#10;Call SetSize before, to make sure, the internal data buffer is&#13;&#10;sufficiently big.&#13;&#10;To write on the CF Card you should work in 512 Byte boundarys&#13;&#10;because the card internally have 512 Byte sektors and you can write&#13;&#10;on each sektor 2.000.000. So a lifetime of writing to each sektor&#13;&#10;every 2 minutes of 5 years.&#13;&#10;[Server]  m_udLength   :R  :Server shows the size of File without header&#13;&#10;[members]  us_Init    :R  :variable is set if class is initialized&#13;&#10;    b_FileAccessControl :R/W :variable marks if the file operation is finished or runs&#13;&#10;    p_us_DataI   :R  :pointer for our working buffer&#13;&#10;    p_us_DataFG   :W  :pointer to data which shouldbe read&#13;&#10;    ud_DataSize   :W  :size of data which should be read&#13;&#10;    ud_DataOffset   :W  :offset of data which should be read&#13;&#10;" Name="SetDataAt"/>
	FUNCTION VIRTUAL GLOBAL SetDataAt
		VAR_INPUT
			p_us_data 	: ^USINT;
			ud_size 	: UDINT;
			ud_at 	: UDINT;
		END_VAR
		VAR_OUTPUT
			ret_code 	: ConfStates;
		END_VAR;
				//! <Function Comment="[#ENGLISH]&#13;&#10;Use this function to change a part of the data buffer in Background&#13;&#10;for bigger Files or a huge part of Data.&#13;&#10;If buffer is not big enough no data are written.&#13;&#10;Call SetSize before, to make sure, the internal data buffer is&#13;&#10;sufficiently big.&#13;&#10;To write on the CF Card you should work in 512 Byte boundarys&#13;&#10;because the card internally have 512 Byte sektors and you can write&#13;&#10;on each sektor 2.000.000. So a lifetime of writing to each sektor&#13;&#10;every 2 minutes of 5 years.&#13;&#10;[Server]  m_udLength   :R  :Server shows the size of File without header&#13;&#10;[members]  us_Init    :R  :variable is set if class is initialized&#13;&#10;    b_FileAccessControl :R/W :variable marks if the file operation is finished or runs&#13;&#10;    p_us_DataI   :R  :pointer for our working buffer&#13;&#10;    p_us_DataFG   :W  :pointer to data which shouldbe read&#13;&#10;    ud_DataSize   :W  :size of data which should be read&#13;&#10;    ud_DataOffset   :W  :offset of data which should be read&#13;&#10;[locals]  p_us_fg    :W/R :pointer for foreground function&#13;&#10;" Name="SetDataAtBackground"/>
	FUNCTION VIRTUAL GLOBAL SetDataAtBackground
		VAR_INPUT
			p_us_data 	: ^USINT;
			ud_size 	: UDINT;
			ud_at 	: UDINT;
		END_VAR
		VAR_OUTPUT
			ret_code 	: ConfStates;
		END_VAR;
				//! <Function Comment="Function creates the checksum of the File&#13;&#10;[Clients]  Setup    :R  :Client contains the adjustments of the class &#13;&#10;[members]  us_Filename   :R  :array containing the Path and Filename of File &#13;&#10;    Header    :W  :structure contains the inforamtions of the Header of File&#13;&#10;[locals]  sd_handle   :W/R :variable for file handling&#13;&#10;" Name="CreateChecksum"/>
	FUNCTION CreateChecksum;
				//! <Function Comment="Function calculates checksum from delivered file&#13;&#10;[members]  Header    :R  :structure contains the inforamtions of the Header of File&#13;&#10;[locals]  sd_checksum_length :W/R :length of file to calculate checksum&#13;&#10;    ud_checksum_calc :W/R :calculated checksum&#13;&#10;    p_us_data_checksum :W/R :pointer to data to calculate checksum&#13;&#10;" Name="CalculateChecksum"/>
	FUNCTION CalculateChecksum
		VAR_INPUT
			sd_handle 	: DINT;			//! <Variable Comment="Handle variable from file" Name="CalculateChecksum.sd_handle"/>
		END_VAR
		VAR_OUTPUT
			ud_retval 	: UDINT;			//! <Variable Comment="return value of function" Name="CalculateChecksum.ud_retval"/>
		END_VAR;
				//! <Function Comment="Function encrypts the data&#13;&#10;" Name="EncryptData"/>
	FUNCTION AWL EncryptData
		VAR_INPUT
			p_us_data_enc 	: ^USINT;			//! <Variable Comment="pointer to data which should be encrypt" Name="EncryptData.p_us_data_enc"/>
			ud_size 	: UDINT;
		END_VAR;
				//! <Function Comment="Function to create a new File (AWL because foreground)&#13;&#10;[Server]  m_udLength   :W  :Server shows the size of File without header&#13;&#10;[Clients]  Alarm    :W  :Client is 1 if checksum is wrong&#13;&#10;[members]  Header    :W  :structure contains the inforamtions of the Header of File&#13;&#10;    ud_Filesize   :R  :size of File&#13;&#10;    b_FileAccessControl :W  :variable marks if the file operation is finished or runs&#13;&#10;" Name="CreateNewFile_FG_AWL"/>
	FUNCTION AWL CreateNewFile_FG_AWL
		VAR_INPUT
			p_param 	: ^RamFile;			//! <Variable Comment="Pointer to Object (this)" Name="CreateNewFile_FG_AWL.p_param"/>
		END_VAR;
				//! <Function Comment="Function to create a new File&#13;&#10;[Clients]  Setup   :R  :Client contains the adjustments of the class &#13;&#10;[members]  Header   :W  :structure contains the inforamtions of the Header of File&#13;&#10;    us_Filename  :R  :array containing the Path and Filename of File &#13;&#10;    ud_Filesize  :R  :size of File&#13;&#10;    p_us_DataI  :W/R :pointer for our working buffer&#13;&#10;[locals]  sd_handle  :W/R :variable for File handling&#13;&#10;    i    :W/R :counter value and help value&#13;&#10;" Name="CreateNewFile_FG"/>
	FUNCTION CreateNewFile_FG;
				//! <Function Comment="Function to extend an available File (AWL because foreground)&#13;&#10;[Server]  m_udLength   :W  :Server shows the size of File without header&#13;&#10;[members]  ud_Filesize   :R  :size of File&#13;&#10;    b_FileAccessControl :W  :variable marks if the file operation is finished or runs&#13;&#10;" Name="ExtendFile_FG_AWL"/>
	FUNCTION AWL ExtendFile_FG_AWL
		VAR_INPUT
			p_param 	: ^RamFile;
		END_VAR;
				//! <Function Comment="Function to extend an available File &#13;&#10;[Server]  m_udLength  :R  :Server shows the size of File without header&#13;&#10;[Clients]  Setup   :R  :Client contains the adjustments of the class &#13;&#10;[members]  us_Filename  :R  :array containing the Path and Filename of File &#13;&#10;    ud_Filesize  :R  :size of File&#13;&#10;    p_us_DataI  :W/R :pointer for our working buffer&#13;&#10;[locals]  sd_handle  :W/R :variable for File handling&#13;&#10;    i    :W/R :counter value and help value&#13;&#10;" Name="ExtendFile_FG"/>
	FUNCTION ExtendFile_FG;
				//! <Function Comment="Function to extend an available File (AWL because foreground)&#13;&#10;[Server]  m_udLength   :W  :Server shows the size of File without header&#13;&#10;[members]  ud_Filesize   :R  :size of File&#13;&#10;    b_FileAccessControl :W  :variable marks if the file operation is finished or runs&#13;&#10;" Name="ReduceFile_FG_AWL"/>
	FUNCTION AWL ReduceFile_FG_AWL
		VAR_INPUT
			p_param 	: ^RamFile;
		END_VAR;
				//! <Function Comment="Function to extend an available File &#13;&#10;[members] us_Filename  :R  :array containing the Path and Filename of File &#13;&#10;   us_FilenameBak :R  :array containing the Path and Filename of .bak File&#13;&#10;   ud_Filesize  :R  :size of File&#13;&#10;   p_us_DataI  :W/R :pointer for our working buffer&#13;&#10;   Header   :R  :structure contains the inforamtions of the Header of File&#13;&#10;[locals] sd_handle  :W/R :variable for File handling&#13;&#10;   sd_handle2  :W/R :variable for file handling with bak file&#13;&#10;   i    :W/R :counter value and help value&#13;&#10;   p_us_data_cpy :W/R :Pointer for copy data&#13;&#10;" Name="ReduceFile_FG"/>
	FUNCTION ReduceFile_FG;
				//! <Function Comment="Function to read the File (AWL because foreground)&#13;&#10;[members]  b_FileAccessControl  :W  :variable marks if the file operation is finished or runs&#13;&#10;" Name="ReadFile_FG_AWL"/>
	FUNCTION AWL ReadFile_FG_AWL
		VAR_INPUT
			p_param 	: ^RamFile;
		END_VAR;
				//! <Function Comment="Function to read the File&#13;&#10;[Server]  m_udLength  :R  :Server shows the size of File without header&#13;&#10;[Clients]  Setup   :R  :Client contains the adjustments of the class &#13;&#10;[members]  p_us_DataI  :R  :pointer for our working buffer&#13;&#10;    us_Filename  :R  :array containing the Path and Filename of File &#13;&#10;    p_us_DataFG  :R  :pointer to data which shouldbe read&#13;&#10;    ud_DataSize  :R  :size of data which should be read&#13;&#10;    ud_DataOffset  :R  :offset of data which should be read&#13;&#10;[locals]  sd_handle  :W/R :variable for file handling&#13;&#10;" Name="ReadFile_FG"/>
	FUNCTION ReadFile_FG;
				//! <Function Comment="Function to write the File (AWL because foreground)&#13;&#10;[members]  b_FileAccessControl  :W  :variable marks if the file operation is finished or runs&#13;&#10;" Name="WriteFile_FG_AWL"/>
	FUNCTION AWL WriteFile_FG_AWL
		VAR_INPUT
			p_param 	: ^RamFile;
		END_VAR;
				//! <Function Comment="Function to write the File&#13;&#10;[Clients]  Setup   :R  :Client contains the adjustments of the class &#13;&#10;[members]  p_us_DataI  :R  :pointer for our working buffer&#13;&#10;    us_Filename  :R  :array containing the Path and Filename of File &#13;&#10;    p_us_DataFG  :R/W :pointer to data which shouldbe read&#13;&#10;    ud_DataSize  :R  :size of data which should be read&#13;&#10;    ud_DataOffset  :R  :offset of data which should be read&#13;&#10;[locals]  sd_handle  :W/R :variable for file handling&#13;&#10;    p_us_data_help :W/R :pointer to written data&#13;&#10;" Name="WriteFile_FG"/>
	FUNCTION WriteFile_FG;
				//! <Function Comment="[&gt;p_ud_Data]pointer to data&#13;&#10;" Name="CalcChk"/>
	FUNCTION AWL CalcChk
		VAR_INPUT
			p_us_data 	: ^USINT;
			ud_length 	: UDINT;			//! <Variable Comment="length of data" Name="CalcChk.ud_length"/>
		END_VAR
		VAR_OUTPUT
			ud_sum 	: UDINT;			//! <Variable Comment="sum of data" Name="CalcChk.ud_sum"/>
		END_VAR;
				//! <Function Comment="[#ENGLISH]&#13;&#10;" Name="ReloadFile2Ram"/>
	FUNCTION VIRTUAL GLOBAL ReloadFile2Ram
		VAR_OUTPUT
			ret_code 	: ConfStates;
		END_VAR;
	
	FUNCTION AWL ReloadFile2Ram_FG_AWL
		VAR_INPUT
			p_param 	: ^RamFile;
		END_VAR;
				//! <Function Comment="[#ENGLISH]&#13;&#10;" Name="ReloadFile2RamBackground"/>
	FUNCTION VIRTUAL GLOBAL ReloadFile2RamBackground
		VAR_OUTPUT
			ret_code 	: ConfStates;
		END_VAR;
	
	FUNCTION GetFileSize;
	
	FUNCTION DeleteFile;
  //Tables:
	FUNCTION @STD
		VAR_OUTPUT
			ret_code	: CONFSTATES;
		END_VAR;
	FUNCTION GLOBAL TAB @CT_;
END_CLASS;

#pragma usingLtd _MultiTask


//}}LSL_DECLARATION


FUNCTION GLOBAL TAB RamFile::@CT_
0$UINT,
2#0100000000000000$UINT, //TY_RAMFILE
1$UINT, 9$UINT, (SIZEOF(::RamFile))$UINT, 
3$UINT, 3$UINT, 0$UINT, 
TO_UDINT(3591333481), "RamFile", //Class
TO_UDINT(0), 0, 0$UINT, 0$UINT, //Baseclass
//Servers:
(::RamFile.m_udLength.pMeth)$UINT, _CH_CMD$UINT, 2#0000000000000000$UINT, TO_UDINT(3370139294), "m_udLength", 
(::RamFile.FileNameHex.pMeth)$UINT, _CH_SVR$UINT, 2#0000000000000000$UINT, TO_UDINT(614477652), "FileNameHex", 
(::RamFile.SizeError.pMeth)$UINT, _CH_SVR$UINT, 2#0000000000000000$UINT, TO_UDINT(798954529), "SizeError", 
//Clients:
(::RamFile.Setup.pCh)$UINT, _CH_CLT_DATA$UINT, 2#0000000000000010$UINT, TO_UDINT(3528037504), "Setup", 
(::RamFile.Alarm.pCh)$UINT, _CH_CLT_DATA$UINT, 2#0000000000000000$UINT, TO_UDINT(2211153005), "Alarm", 
(::RamFile.MultiTask.pCh)$UINT, _CH_CLT_OBJ$UINT, 2#0000000000000000$UINT, TO_UDINT(3505031941), "MultiTask", TO_UDINT(2641766936), "_MultiTask", 1$UINT, 1$UINT, 
END_FUNCTION


#define USER_CNT_RamFile 12

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

END_FUNCTION

//{{LSL_IMPLEMENTATION
(******************************************************************************
*
*	Class to save data 
*	Created: Sigmatek  / 2004
*	Changes:
*		1.5 => 1.6	/	02.01.2006	/	Mark:	//#SR003
*			now Error is generated if function SetSize failed
*		1.4 => 1.5	/	07.06.2006	/	Mark:	//#SR002
*			Now we make a realloc instead of alloc in function ReloadFile2Ram
*		1.3 => 1.4	/	23.02.2006	/	Mark:	//#SR001
*			use CreatThread instead of AddForgroundFunction
*		1.2 => 1.3	/	08.07.2005	/	Mark:	//#SR000
*			Add function to reload a file to ram
*		1.0 => 1.2	/ 03.09.2004 / Mark: no Mark
*			reworking and addition the available programm (Encrypt, Checksum, Background work)
*
******************************************************************************)

#include <lsl_st_osfile.h>   // Damit ich beim laden alter active.dat zugreifen kann

#define LASAL2_OBJ			//activate for Lasal2 Library
#define fVERSION 		16#0102
#define WORKING_BUFFER 	10*1024		// 10 kByte of working buffer


// =========================================================================================
// Functions for memory allocation                     
// =========================================================================================
FUNCTION GLOBAL _alloc_resize
VAR_INPUT
	udSize          : UDINT;
END_VAR
VAR_OUTPUT
	pMem            : ^VOID;
END_VAR;

FUNCTION GLOBAL _realloc
VAR_INPUT
	pOld			: ^void;
	udSize          : UDINT;
END_VAR
VAR_OUTPUT
	pMem            : ^void;
END_VAR;

FUNCTION GLOBAL _free
VAR_INPUT
	pMem            : ^VOID;
END_VAR;



FUNCTION VIRTUAL GLOBAL RamFile::Init
  
   b_Reload := 0;		//#SR000
   InitMe();

END_FUNCTION //VIRTUAL GLOBAL RamFile::Init
//[Server]		m_udLength			:W		:Server shows the size of File without header
//				FileNameHex			:W		:Shows the Filename in an Hexadecimal value

//[Clients]		Setup				:R		:Client contains the adjustments of the class 
//				Alarm				:W		:Client is 1 if checksum is wrong

//[members]		us_Init				:R/W	:variable is set if class is initialized
//				us_Filename			:W		:array containing the Path and Filename of File 
//				us_FilenameBak		:W		:array containing the Path and Filename of .bak File
//				b_FileAccessControl	:W		:variable marks if the file operation is finished or runs
//				us_Encbyte			:W		:variable to encrypt data
//				Header				:R/W	:structure contains the inforamtions of the Header of File
//				p_us_DataI			:W/R	:pointer for our working buffer
//				ui_UserVer			:W		:variable for user Version

//[locals]		p_obj				:W		:Pointer to Data of object
//				ud_length			:W/R	:variable for length to copy string
//				p_us_eof			:W		:Pointer to FilenameBak
//				b_check_ok			:W/R	:Flag for loading the correct File ( if checksum is rigth )	
//				sd_handle			:W/R	:variable for File handling
//				ud_length_total		:W		:total length of File
//				ud_data_length		:W/R	:length of Data in File (without Header)
//				ud_ctr				:W/R	:counter for working with filedata
//				ud_Checksum			:R/W	:variable for checksum calculation

FUNCTION  RamFile::InitMe
VAR
 	p_obj    		: ^obj;
 	ud_length	 	: UDINT;
 	p_us_eof 		: ^USINT;
 	sd_handle  		: DINT;
	ud_length_total	: UDINT;
 	ud_data_length	: UDINT;
	ud_ctr 			: UDINT;
	ud_Checksum		: UDINT;
	i				: USINT;
END_VAR;
 
 	// check if init is already made 
	if us_init = 0 then

		b_FileAccessControl := 1;				//#SR000
  		Setup:= Setup.read();											// read setup data

  		if Setup.Valid then												// check if valid
   		
			us_Init := 1;												// we are valid so make init

			if b_Reload = 0 then				//#SR000
	   			p_obj := LSL_GetHdr( this );

				#ifdef LASAL2_OBJ
			        #pragma warning (disable:137)
						FileNameHex := p_obj^.pObjDsc^.Symname.udCRC;
					#pragma warning (default:137)
				#else
	   				FileNameHex :=	p_obj^.pObjDsc^.udCRC;
				#endif   			

				//Create Filename and Path and store it in Filename
				CreateFileName( FileNameHex, CopyDir( #us_Filename[0] ) );	

	   			//Create Filename and Path for Bak File and steore it in us_FilenameBak
				_memcpy( #us_FilenameBak[0], #us_Filename[0], sizeof( us_Filename ) ); 	
	   			ud_length 	:= _strlen( #us_FilenameBak[0] );	
	   			p_us_eof 	:= #us_FilenameBak[0] + ud_length;
	   			p_us_eof^	:= '.';
	   			( p_us_eof + 1 )^ := 'B';
	   			( p_us_eof + 2 )^ := 'A';
	   			( p_us_eof + 3 )^ := 'K';
	   			( p_us_eof + 4 )^ := 0;

				b_FileAccessControl := 0;				//Bit which marks if the file operation is finished
				b_check_ok := 1;	
				ud_ctr := 0;
			
				//create encrypt byte from filename						
				for i := 0 to 3 do					
					us_Encbyte += ( FileNameHex SHR ( i * 8 ) )$USINT; 
				end_for;
			end_if;							//#SR000
   	
   			// check if we are working in RamEX or in a File	
   			if Setup.FileorRam = 0 then
			
				// open File 
				sd_handle := OS_FILE_OPEN( #us_Filename[0], 2, ATT_READ_WRITE ); 	 
				  
				if sd_handle >= 0 then
	 		
					// file is available, check length
	 				ud_length_total$DINT := OS_FILE_LENGTH( sd_handle );

	 				if ud_length_total < sizeof (fHeader) then
	  		
						//there stands trash
	  					ud_length_total := 0;
	  					m_udLength  	:= 0;
	  					OS_FILE_CLOSE( sd_handle );
						TRACE( "File is destroyed (smaller than the Header)!" );
	 			
					else
	  					m_udLength := ud_length_total - sizeof( fHeader ); 
						//read Header informations 	     
	  					OS_FILE_READ( sd_handle, #Header, sizeof( fHeader ) );

						//-------------------------------------------------------------------------------------------
						//user want to encrypt file, but file isn't encrypt -> we must encrypt it
						//or user want no encryption, but File is encrypt -> we must decrypt file
						if Setup.Encrypt & Header.Setup.Encrypt = 0 | Setup.Encrypt = 0 & Header.Setup.Encrypt then							
			
							//encrypt or decrypt Header
							EncryptData( ( #Header )$^USINT, sizeof( fHeader ) );		
							Header.Setup := Setup;			//Setup must not encyrpt because we need the status of the file
							Header.CRC := 0;				//because checksum isn't valid after encryption
														
							ud_data_length := m_udLength;								//data length (without Header)
							if p_us_DataI = NIL then		//#SR002
								p_us_DataI := ( _alloc_resize( WORKING_BUFFER ) )$^USINT;		//load working buffer
							//#SR002 start
							else
								p_us_DataI := ( _realloc( p_us_DataI, WORKING_BUFFER ) )$^USINT;
							end_if;
							//#SR002 end
							
							if p_us_DataI = NIL then
	    						TRACE("No Memory left for Class RamFile (Init)");
								return;
							end_if;		
							
							//encrypt or decrypt Data in File
							while 1 do										
								if ud_data_length < WORKING_BUFFER then
								
									OS_FILE_READ( sd_handle, p_us_DataI, ud_data_length );
									OS_FILE_SEEK( sd_handle, sizeof( fHeader ) + WORKING_BUFFER * ud_ctr, FILE_BEGIN );
									EncryptData( p_us_DataI, ud_data_length );
									OS_FILE_WRITE( sd_handle, p_us_DataI, ud_data_length);					
									exit;
								end_if;	

								OS_FILE_READ( sd_handle, p_us_DataI, WORKING_BUFFER );
								OS_FILE_SEEK( sd_handle, sizeof( fHeader ) + WORKING_BUFFER * ud_ctr, FILE_BEGIN );
								EncryptData( p_us_DataI, WORKING_BUFFER );
								OS_FILE_WRITE( sd_handle, p_us_DataI, WORKING_BUFFER );					

								ud_data_length -= WORKING_BUFFER;
								ud_ctr += 1;
							end_while;
							_free( p_us_DataI );
							p_us_DataI := NIL;

							//calculate new checksum if user want it
							if Setup.EnableChecksum then						
								Header.CRC := CalculateChecksum( sd_handle );
							
							else
								OS_FILE_SEEK( sd_handle, 0, FILE_BEGIN );
							end_if;

							//write new Header
							OS_FILE_WRITE( sd_handle, #header, sizeof( fHeader ) );		
	
						else
							//we must look if user want a checksum  
							if Setup.EnableChecksum then							//if user want a checksum
								ud_Checksum := CalculateChecksum( sd_handle );		//calculate checksum of file

								if Header.Setup.EnableChecksum & b_Reload = 0 then	//if checksumfunction already used		//#SR000

									if ud_Checksum <> Header.CRC then					//compare calculated checksum with checksum read from file
								
										b_check_ok := 0;							//Flag for not loading the destroyed File
										OS_FILE_CLOSE( sd_handle );
										TRACE( "Checksum Error! Create a new File with setsize" );
										Alarm := 1;									//Set Alram Client
										m_udLength := 0;							
										return;
									end_if;

								else												//write checksum to file
									if b_Reload = 0 then					//#SR000
										Header.CRC := ud_Checksum + 4;						//+4 because size of Setup changed because EnableChecksum bit is set!
										Header.Setup.EnableChecksum := 1;				//Mark that we have now a checksum
									else									//#SR000
										Header.CRC := ud_Checksum;			//#SR000
									end_if;									//#SR000
									OS_FILE_WRITE( sd_handle, #Header, sizeof( fheader ) );	//write Header with checksum
								end_if;

							else
								if Header.Setup.EnableChecksum then					//if checksum is already available, but user won't it
									Header.CRC := 0;								//clear checksum	
									Header.Setup.EnableChecksum := 0;				//Mark that we have now no checksum
									OS_FILE_SEEK( sd_handle, 0, FILE_BEGIN );
									OS_FILE_WRITE( sd_handle, #Header, sizeof( fHeader ) );	//write Header without checksum
								end_if;
							end_if;
						end_if;
						//-------------------------------------------------------------------------------------------
						ui_UserVer := 0;

						b_Reload := 0;							//#SR000
						if b_check_ok = 1 then
		  					// if size is smaller 64 k we load into memory 
		  					// else we work with file directly (out of memory reason)
		  					if m_udLength < 64 * 1024 then
		   						if p_us_DataI = NIL then			//#SR002
									p_us_DataI := ( _alloc_resize( m_udLength ) )$^USINT;			//Load data in program store for faster read access
								//#SR002 start
								else
									p_us_DataI := ( _realloc( p_us_DataI, m_udLength ) )$^USINT;
								end_if;
								//#SR002 end
		   						
								if p_us_DataI <> NIL then
									//to show to beginning of data
									OS_FILE_SEEK( sd_handle, sizeof( fHeader ), FILE_BEGIN );
									OS_FILE_READ( sd_handle, p_us_DataI, m_udLength );
		   						
								else
		    						TRACE( "No Memory left for Class RamFile (Init)" );
	       						end_if;
		  					
							else
		  						// the file is bigger than 64k so we alloc a 10kByte working buffer
		   						p_us_DataI := ( _alloc_resize( Working_buffer ) )$^USINT;
								if p_us_DataI = NIL then
		    						TRACE( "No Memory left for Class RamFile (Init)" );
								end_if;
		  					end_if; 
						end_if;
	 				end_if;	//if ud_length_total < sizeof (fHeader)	
					OS_FILE_CLOSE( sd_handle );
				end_if;	//if sd_handle >= 0
   			
			else
				Trace( "Ramex in Ramfile not supported" );   
   			end_if;	//if Setup.FileorRam = 0
		end_if;	//if Setup.Valid
		b_FileAccessControl := 0;									//#SR000
 	end_if;	//if us_init = 0 then

END_FUNCTION // RamFile::InitMe
//Function to create the Filename

//[>ud_crc]Hex value of Filename
//[>p_us_name]Pointer to Array for Filename
FUNCTION RamFile::CreateFileName
  VAR_INPUT  
    ud_crc			: UDINT;
    p_us_name		: ^CHAR;
  END_VAR
  VAR
  	nox : udint;
    ptab : ^char;
  END_VAR

  nox  := 8;
  ptab := "0123456789ABCDEF";
  while(nox) do
    ud_crc     := ud_crc rol 4;
    p_us_name^ := (ptab + (ud_crc and 16#0F))^;
    p_us_name  += 1;
    nox        -= 1;
  end_while;
  p_us_name^ := 0;

END_FUNCTION

//Path of the Directory where the RamFiles were saved
FUNCTION TAB  RamFile::Direktory
 "C:\FDATA\"
END_FUNCTION //TAB  RamFile::Direktory
//Function copies the Direktory path in the array for the Filename

//[>p_us_name]Pointer to Array for Filename
//[<p_us_end_of_dir]Pointer to last Array entry of Filename

FUNCTION RamFile::CopyDir
  VAR_INPUT 
    p_us_name			: ^CHAR;
  END_VAR
  VAR_OUTPUT
    p_us_end_of_dir		: ^CHAR;
  END_VAR
  VAR
  	ph : ^udint;
  END_VAR

  ph := #Direktory();
  _memcpy(p_us_name, ph+4, ph^);
  p_us_end_of_dir := p_us_name + ph^;
  
END_FUNCTION

//[#ENGLISH]
//Use this function to change the size of the data buffer
//Size should be set once to the maximum bytes you will need in the
//file (so no cyclic growing files !!)
//
//SetSize should not be called cyclic you may destroy the CF card.
//2.000.000 write accesses to each sector. FAT and directory
//must be updated periodically if you change the size cyclic.

//[Server]		m_udLength			:R		:Server shows the size of File without header

//[members]		us_Init				:R		:variable is set if class is initialized
//				ud_Filesize			:W		:size of File
//				b_FileAccessControl	:R/W	:variable marks if the file operation is finished or runs
//				p_us_DataI			:R		:pointer for our working buffer

//[>ud_size]new size of File
//[<ret_code]return code of function

FUNCTION VIRTUAL GLOBAL RamFile::SetSize
VAR_INPUT
	ud_size		: UDINT;
END_VAR
VAR_OUTPUT
	ret_code	: ConfStates;
END_VAR

	ret_code := C_OK;

  	// test if we must init	
  	if us_Init = 0 then
   		InitMe();	
  	end_if;
  	
 	// test if we have a size
	if ud_size = 0 then
  		ret_code := C_SYNTAX_ERROR;
  		return; 
 	end_if;

	//test if there is a fault in init or if last File operation does not finish
  	if us_Init <> 0 & b_FileAccessControl = 0 then	
   	
		ud_Filesize := ud_size;								

		//look if there is a change of size
		if m_udLength <> ud_size then					
			b_FileAccessControl := 1;					//Flag to mark new File operation
  
    		// we got a new size now we have to do something in the file
    		if m_udLength < ud_size then 				// the file is growing
	 
				if p_us_DataI = NIL then  				//File not availaible, we must create it
					CreateNewFile_FG_AWL( this );
				
				else					 	 			// file already exists, make it bigger
					ExtendFile_FG_AWL( this );
				end_if;

    		else  						   				// File is getting smaller	
				ReduceFile_FG_AWL( this );
    		end_if;
   		end_if;   										// no change of size  
  	
	else												
   		// there is no init possible ( bit0 = Server Setup !!! must be 1 for valid )
   		ret_code := C_INIT;
   		TRACE("Init not possible or last File-operation not finished (SetSize)");
  	end_if;												

	//#SR003 start
	if ( SizeError = TRUE ) then
		ret_code := C_OUTOF_NEAR;
	end_if;
	//#SR003 end

END_FUNCTION //VIRTUAL GLOBAL RamFile::SetSize
//[#ENGLISH]
//Use this function to change the size of the data buffer in the background
//(for bigger files, because it can require a long time)
//Size should be set once to the maximum bytes you will need in the
//file (so no cyclic growing files !!)
//
//SetSize should not be called cyclic you may destroy the CF card.
//2.000.000 write accesses to each sector. FAT and directory
//must be updated periodically if you change the size cyclic.

//[Server]		m_udLength			:R		:Server shows the size of File without header

//[members]		us_Init				:R		:variable is set if class is initialized
//				ud_Filesize			:W		:size of File
//				b_FileAccessControl	:R/W	:variable marks if the file operation is finished or runs
//				p_us_DataI			:R		:pointer for our working buffer

//[locals]		p_us_fg				:W/R	:pointer to forground function

//[>ud_size]new size of File
//[<ret_code]return code of function

FUNCTION VIRTUAL GLOBAL RamFile::SetSizeBackground
VAR_INPUT
	ud_size		: UDINT;
END_VAR
VAR_OUTPUT
	ret_code		: ConfStates;
END_VAR
VAR
	p_us_fg			: MT_TASKHANDLE;
END_VAR

	ret_code := C_OK;

  	// test if we must init	
  	if us_Init = 0 then
   		InitMe();	
  	end_if;
  	
 	// test if we have a size
 	if ud_size = 0 then
  		ret_code := C_SYNTAX_ERROR;
  		return; 
 	end_if;

	//test if there is a fault in init or if last File operation does not finish
  	if us_Init <> 0 & b_FileAccessControl = 0 then		
   	
		ud_Filesize := ud_size;	
	
		if m_udLength <> ud_size then						//look if there is a change of size
			b_FileAccessControl := 1;						//Flag to mark new File ooperation
  
    		// we got a new size now we have to do something in the file
    		if m_udLength < ud_size then		     		// the file is growing
	 			
				if p_us_DataI = NIL then  						//File not availaibel, we must create it
 	  				//to create bigger File takes a long time -> we do it in a ForeGround operation otherwise you get a Runtime error
					p_us_fg := MultiTask.CREATETHREAD( taskfunction0 := #CreateNewFile_FG_AWL(), priority0 := 8, stackSize0 := 16#1000, flags0 := 0, parameter0 := this, name0 := #us_Filename[ 0 ] );		//#SR001
//#SR001					p_us_fg := ( TaskObjectControl.AddForegroundFunction( #CreateNewFile_FG_AWL(), this, 0x1000 ) )$^USINT;		//Install Foreground Task
					if p_us_fg = NIL then
						TRACE( "Error creating File, because fault in installing ForeGround function (SetSizeBackground)" );
						b_FileAccessControl := 0;
						ret_code := C_OUTOF_NEAR;
					end_if;
				
				else						 	 			// file already exists, make it bigger
					p_us_fg := MultiTask.CREATETHREAD( taskfunction0 := #ExtendFile_FG_AWL(), priority0 := 8, stackSize0 := 16#1000, flags0 := 0, parameter0 := this, name0 := #us_Filename[ 0 ] );		//#SR001
//#SR001					p_us_fg := ( TaskObjectControl.AddForegroundFunction( #ExtendFile_FG_AWL(), this, 0x1000 ) )$^USINT;		//Install Foreground Task
					if p_us_fg = NIL then
						TRACE( "Error creating File, because fault in installing ForeGround function (SetSizeBackground)" );
						b_FileAccessControl := 0;
						ret_code := C_OUTOF_NEAR;
					end_if;
	 			end_if;

    		else  							   				// File is getting smaller	
				p_us_fg := MultiTask.CREATETHREAD( taskfunction0 := #ReduceFile_FG_AWL(), priority0 := 8, stackSize0 := 16#1000, flags0 := 0, parameter0 := this, name0 := #us_Filename[ 0 ] );		//#SR001
//#SR001				p_us_fg := ( TaskObjectControl.AddForegroundFunction( #ReduceFile_FG_AWL(), this, 0x1000 ) )$^USINT;			//Install Foreground Task
				if p_us_fg = NIL then
					TRACE( "Error creating File, because fault in installing ForeGround function (SetSizeBackground)" );
					b_FileAccessControl := 0;
					ret_code := C_OUTOF_NEAR;
				end_if;
    		end_if;
   		end_if;  											// no change of size  
  	
	else
   		// there is no init possible (bit0 = Server Setup !!! must be 1 for valid)
   		ret_code := C_INIT;
   		TRACE("Init not possible or last File-operation not finished (SetSizeBackground)");
  	end_if;	  

END_FUNCTION //VIRTUAL GLOBAL RamFile::SetSizeBackground
//Function to create a new File (AWL because foreground)

//[Server]		m_udLength			:W		:Server shows the size of File without header

//[Clients]		Alarm				:W		:Client is 1 if checksum is wrong

//[members]		Header				:W		:structure contains the inforamtions of the Header of File
//				ud_Filesize			:R		:size of File
//				b_FileAccessControl	:W		:variable marks if the file operation is finished or runs

//[>p_param]Pointer to Object (this)

 // RamFile::CreateNewFile_FG_AWL

#ifdef _LSL_TARGETARCH_X86
FUNCTION  AWL RamFile::CreateNewFile_FG_AWL		
VAR_INPUT
	p_param		: ^RamFile;
END_VAR

	l.esi	p_param									//load pointer to object (for Forground important)
	l.w		Header.Version,fVERSION					//Set Version
	
	call	CreateNewFile_FG						//create new file	
	call	CreateChecksum							//calculate checksum

	//#SR003 start
	cmp.d	SizeError, TRUE
	jne		LABEL_NoError
	call	GetFileSize
	jmp		LABEL_Fault

LABEL_NoError
	//#SR003 end

	l.eax	ud_Filesize								
	s.eax	m_udLength								//write new Filesize to Server
	l.d		Alarm,0									//clear Alarm client

LABEL_Fault											//#SR003
	l.b		b_FileAccessControl,0					//end of File access

END_FUNCTION // RamFile::CreateNewFile_FG_AWL
#else
FUNCTION  RamFile::CreateNewFile_FG_AWL		
VAR_INPUT
	p_param		: ^RamFile;
END_VAR
  
  this := p_param;
	Header.Version := fVERSION;					//Set Version
	
	CreateNewFile_FG();						//create new file	
	CreateChecksum();							//calculate checksum

  if(SizeError = true) then
    GetFileSize();
  else
    m_udLength := ud_Filesize;
    Alarm      := 0;
  end_if;
  
  b_FileAccessControl := false;

END_FUNCTION
#endif
//Function to create a new File

//[Clients]		Setup			:R		:Client contains the adjustments of the class 

//[members]		Header			:W		:structure contains the inforamtions of the Header of File
//				us_Filename		:R		:array containing the Path and Filename of File 
//				ud_Filesize		:R		:size of File
//				p_us_DataI		:W/R	:pointer for our working buffer

//[locals]		sd_handle		:W/R	:variable for File handling
//				i				:W/R	:counter value and help value

FUNCTION  RamFile::CreateNewFile_FG		
VAR 
	sd_handle 	:	DINT;
	i			:	UDINT;
	ud_retval	: 	UDINT;			//#SR003
END_VAR

    // Create a new header
    Header.CRC 		:= 0;
    Header.Setup 	:= Setup;
	Header.UserVersion := ui_UserVer;
	
	for i := 0 to sizeof( Header.resarray ) - 1 do
		Header.resarray[i] := 0;
	end_for;

	//Create new File
	sd_handle := OS_FILE_OPEN( #us_Filename[0], 2, ATT_READ_WRITE or ATT_CREATE_ALWAYS );	
   	if sd_handle < 0 then
    	TRACE( "open file fault Class RamFile (CreateFile)" );
		return;
   	end_if;

	//if file smaller 64k we can work with the program storage for faster read access
	if ud_Filesize < 64 * 1024 then		

		p_us_DataI:=( _alloc_resize( ud_Filesize ) )$^USINT;
		if p_us_DataI = NIL then 
			TRACE( "no memory left for Class RamFile (CreateFile)" );
			return;
	    end_if;
		_memset( p_us_DataI, 0, ud_Filesize); 						//set Data in Programm storage

		if Setup.Encrypt then										//if option is set, encrypt Data
			EncryptData( ( #Header )$^USINT, sizeof( fHeader ) );	
			Header.Setup := Setup;									//must not encrypt 
			EncryptData( p_us_DataI$^USINT, ud_Filesize );
		end_if;
    
	    ud_retval := OS_FILE_WRITE( sd_handle, #Header, sizeof( fHeader ) );	//write Header to File

		//#SR003 start
		//look if header is written
		if ( ud_retval < sizeof( fHeader ) ) then
			SizeError := TRUE;
			OS_FILE_CLOSE( sd_handle );	
			return;
		end_if;
		//#SR003 end

		ud_retval := OS_FILE_WRITE( sd_handle, p_us_DataI, ud_Filesize );		//write Data to File

		//#SR003 start
		//look if header is written
		if ( ud_retval < ud_Filesize ) then
			SizeError := TRUE;
			OS_FILE_CLOSE( sd_handle );	
			return;
		end_if;
		//#SR003 end

	// File is bigger than 64 kByte, we work with a working buffer
	else													    	
	    p_us_DataI:=( _alloc_resize( WORKING_BUFFER ) )$^USINT;
	    if p_us_DataI = NIL then 
	     	TRACE( "no memory left for Class RamFile (CreateFile)" );
		 	return;
        
		end_if;
	    _memset( p_us_DataI, 0, WORKING_BUFFER ); 

		if Setup.Encrypt then										//if option is set, encrypt Data
			EncryptData( ( #Header )$^USINT, sizeof( fHeader ) );
			Header.Setup := Setup;									//must not encrypt 
			EncryptData( p_us_DataI$^USINT, WORKING_BUFFER );
		
		end_if;

	    ud_retval := OS_FILE_WRITE( sd_handle, #Header,sizeof( fHeader ) );		//write Header to File

		//#SR003 start
		//look if header is written
		if ( ud_retval < sizeof( fHeader ) ) then
			SizeError := TRUE;
			OS_FILE_CLOSE( sd_handle );	
			return;
		end_if;
		//#SR003 end

		i := ud_Filesize;
		while 1 do 													//write Data to File
		 	ud_retval := OS_FILE_WRITE( sd_handle, p_us_DataI, WORKING_BUFFER );

			//#SR003 start
			//look if header is written
			if ( ud_retval < WORKING_BUFFER ) then
				SizeError := TRUE;
				OS_FILE_CLOSE( sd_handle );	
				return;
			end_if;
			//#SR003 end

		 	i -= WORKING_BUFFER;
		 	if i < WORKING_BUFFER then
		  		ud_retval := OS_FILE_WRITE( sd_handle, p_us_DataI, i );

				//#SR003 start
				//look if header is written
				if ( ud_retval < i ) then
					SizeError := TRUE;
					OS_FILE_CLOSE( sd_handle );	
					return;
				end_if;
				//#SR003 end

		  		EXIT;
		 	end_if; 
			  			
		end_while;

	end_if;

	OS_FILE_CLOSE( sd_handle );
	SizeError := FALSE;					//#SR003
	
END_FUNCTION // RamFile::SetSize_FG
//Function to extend an available File (AWL because foreground)

//[Server]		m_udLength			:W		:Server shows the size of File without header

//[members]		ud_Filesize			:R		:size of File
//				b_FileAccessControl	:W		:variable marks if the file operation is finished or runs

//[>p_param]Pointer to Object (this)


 // RamFile::ExtendFile_FG_AWL

#ifdef _LSL_TARGETARCH_X86
FUNCTION AWL RamFile::ExtendFile_FG_AWL							
VAR_INPUT
	p_param		: ^RamFile;
END_VAR

	l.esi	p_param								//load pointer to object (for Forground important)
	
	call	ExtendFile_FG						//extend new file
	call	CreateChecksum						//calculate new checksum

	//#SR003 start
	cmp.d	SizeError, TRUE
	jne		LABEL_NoError
	call	GetFileSize
	jmp		LABEL_Fault

LABEL_NoError
	//#SR003 end
	
	l.eax	ud_Filesize
	s.eax	m_udLength							//write new size to server

LABEL_Fault										//#SR003
	l.b		b_FileAccessControl,0				//end of File access

END_FUNCTION // RamFile::ExtendFile_FG_AWL
#else
FUNCTION RamFile::ExtendFile_FG_AWL							
VAR_INPUT
	p_param		: ^RamFile;
END_VAR

  this := p_param;
  ExtendFile_FG();  //extend new file
	CreateChecksum(); //calculate new checksum

  if(SizeError = true) then
    GetFileSize();
  else
    m_udLength := ud_Filesize;
  end_if;
  
  b_FileAccessControl := false;

END_FUNCTION
#endif
//Function to extend an available File 

//[Server]		m_udLength		:R		:Server shows the size of File without header

//[Clients]		Setup			:R		:Client contains the adjustments of the class 

//[members]		us_Filename		:R		:array containing the Path and Filename of File 
//				ud_Filesize		:R		:size of File
//				p_us_DataI		:W/R	:pointer for our working buffer

//[locals]		sd_handle		:W/R	:variable for File handling
//				i				:W/R	:counter value and help value

FUNCTION  RamFile::ExtendFile_FG		
VAR 
	sd_handle 	: DINT;
	i			: UDINT;
	ud_retval	: UDINT;			//#SR003
END_VAR

	//open File
	sd_handle := OS_FILE_OPEN( #us_Filename[0], 2, ATT_READ_WRITE or ATT_CREATE );
	if sd_handle < 0 then
		TRACE( "open file fault Class RamFile (ExtendFile)" );
		return;
	end_if;

	//if file smaller 64k we can work with the program storage for faster read access		
	if ud_Filesize < 64 * 1024 then									
		
		p_us_DataI:=( _realloc( p_us_DataI, ud_Filesize ) )$^USINT;
		if p_us_DataI = NIL then
	   		TRACE( "extend fileSize fault Class RamFile (ExtendFile)" );
			return;
		end_if;
		_memset( p_us_DataI + m_udLength, 0, ( ud_Filesize - m_udLength ) );		//set Data in Programm storage

   		if Setup.Encrypt then														//if option is set, encrypt Data
			EncryptData( ( p_us_DataI + m_udLength )$^USINT, ( ud_Filesize - m_udLength ) );
		end_if;

	  	OS_FILE_SEEK( sd_handle, 0, FILE_END );        								// mov filepointer to the end
	  	ud_retval := OS_FILE_WRITE( sd_handle, p_us_DataI + m_udlength, ( ud_Filesize - m_udlength ) );	//write new Data to File

		//#SR003 start
		//look if header is written
		if ( ud_retval < ( ud_Filesize - m_udlength ) ) then
			SizeError := TRUE;
			OS_FILE_CLOSE( sd_handle );	
			return;
		end_if;
		//#SR003 end

	// File is bigger than 64 kByte so we work with a working buffer
	else																			

		p_us_DataI := ( _realloc( p_us_DataI, WORKING_BUFFER ) )$^USINT;
		if p_us_DataI = NIL then
			TRACE( "extend fileSize fault Class RamFile (ExtendFile)" );
		   	return;
		end_if;
		_memset( p_us_DataI, 0, WORKING_BUFFER );

		if Setup.Encrypt then									//if option is set, encrypt Data
			EncryptData( p_us_DataI$^USINT, WORKING_BUFFER );
		end_if;

		OS_FILE_SEEK( sd_handle, 0, FILE_END );	              	// mov filepointer to the end
		i := ud_Filesize - m_udlength;
		
		while 1 do												//write new Data to File
			if i < WORKING_BUFFER then
				ud_retval := OS_FILE_WRITE( sd_handle, p_us_DataI, i);

				//#SR003 start
				//look if header is written
				if ( ud_retval < i ) then
					SizeError := TRUE;
					OS_FILE_CLOSE( sd_handle );	
					return;
				end_if;
				//#SR003 end

				exit;
			end_if;

			ud_retval := OS_FILE_WRITE( sd_handle, p_us_DataI, WORKING_BUFFER );

			//#SR003 start
			//look if header is written
			if ( ud_retval < WORKING_BUFFER ) then
				SizeError := TRUE;
				OS_FILE_CLOSE( sd_handle );	
				return;
			end_if;
			//#SR003 end

			i -= WORKING_BUFFER;
		end_while;
	end_if;

	OS_FILE_CLOSE( sd_handle );
	SizeError := FALSE;					//#SR003

END_FUNCTION // RamFile::ExtendFile_FG
//Function to extend an available File (AWL because foreground)

//[Server]		m_udLength			:W		:Server shows the size of File without header

//[members]		ud_Filesize			:R		:size of File
//				b_FileAccessControl	:W		:variable marks if the file operation is finished or runs

//[>p_param]Pointer to Object (this)



#ifdef _LSL_TARGETARCH_X86
FUNCTION  AWL RamFile::ReduceFile_FG_AWL	
VAR_INPUT
	p_param		: ^RamFile;
END_VAR

	l.esi	p_param								//load pointer to object (for Forground important)
	
	call	ReduceFile_FG						//reduce File
	call	CreateChecksum						//calculate new checksum

	//#SR003 start
	cmp.d	SizeError, TRUE
	jne		LABEL_NoError
	call	GetFileSize
	jmp		LABEL_Fault

LABEL_NoError
	//#SR003 end
	
	l.eax	ud_Filesize
	s.eax	m_udLength							//write new size to server

LABEL_Fault										//#SR003
	l.b		b_FileAccessControl,0				//end of File access

END_FUNCTION // RamFile::ReduceFile_FG_AWL
#else
FUNCTION RamFile::ReduceFile_FG_AWL
VAR_INPUT
	p_param		: ^RamFile;
END_VAR
  
  this := p_param;
  ReduceFile_FG();						//reduce File
  CreateChecksum();						//calculate new checksum

  if(SizeError = true) then
    GetFileSize();
  else
    m_udLength := ud_Filesize;
  end_if;

  b_FileAccessControl := false;
  
END_FUNCTION
#endif
//Function to extend an available File 

//[members]	us_Filename		:R		:array containing the Path and Filename of File 
//			us_FilenameBak	:R		:array containing the Path and Filename of .bak File
//			ud_Filesize		:R		:size of File
//			p_us_DataI		:W/R	:pointer for our working buffer
//			Header			:R		:structure contains the inforamtions of the Header of File

//[locals]	sd_handle		:W/R	:variable for File handling
//			sd_handle2		:W/R	:variable for file handling with bak file
//			i				:W/R	:counter value and help value
//			p_us_data_cpy	:W/R	:Pointer for copy data

FUNCTION  RamFile::ReduceFile_FG		
VAR
    sd_handle 		: DINT;
	sd_handle2		: DINT;
	i				: UDINT;
	p_us_data_cpy	: ^USINT;
	ud_retval		: UDINT;			//#SR003
END_VAR
	
	//Rename Data File
	OS_FILE_RENAME( #us_Filename[0], #us_FilenameBak[0] );									
	sd_handle  := OS_FILE_OPEN( #us_Filename[0], 2, ATT_READ_WRITE or ATT_CREATE_ALWAYS );
	sd_handle2 := OS_FILE_OPEN( #us_FilenameBak[0], 2, ATT_READ_WRITE );
 	
	if ( sd_handle < 0 ) | ( sd_handle2 < 0 ) then
	   OS_FILE_CLOSE( sd_handle );	   	
	   OS_FILE_CLOSE( sd_handle2 );	   	
	   TRACE( "open file fault Class RamFile (ReduceFile)" );
	   return;
	end_if;

	// copy the header 	
	OS_FILE_READ( sd_handle2, #Header, sizeof( fHeader ) );	
	ud_retval := OS_FILE_WRITE( sd_handle, #Header, sizeof( fHeader ) );	

	//#SR003 start
	//look if header is written
	if ( ud_retval < sizeof( fHeader ) ) then
		SizeError := TRUE;
		OS_FILE_CLOSE( sd_handle );	
		OS_FILE_CLOSE( sd_handle2 );
  		OS_FILE_DELETE( #us_Filename[0] );
		OS_FILE_RENAME( #us_FilenameBak[0], #us_Filename[0] );
		return;
	end_if;
	//#SR003 end

	
	//if file smaller 64k we can work with the program storage for faster read access
	if ud_Filesize < 64 * 1024 then										
	
		p_us_DataI := ( _realloc( p_us_DataI, ud_Filesize ) )$^USINT;
		if p_us_DataI = NIL then
			TRACE( "No Memory left for Class RamFile (ReduceFile)" );
			return;
		end_if;
			
		OS_FILE_READ( sd_handle2, p_us_DataI, ud_Filesize );			//read Data from bak File for working in the program store
		OS_FILE_SEEK( sd_handle2, sizeof( fHeader ), FILE_BEGIN );	
	end_if;

	p_us_data_cpy := ( _alloc_resize( WORKING_BUFFER ) )$^USINT;	
	if p_us_data_cpy = NIL then
		TRACE( "No Memory left for Class RamFile (ReduceFile)" );
		return;
	end_if;

	//copy Data from bak file
	i := ud_Filesize;
	while 1 do 
		if i < WORKING_BUFFER then
	    	OS_FILE_READ( sd_handle2, p_us_data_cpy, i );	
			ud_retval := OS_FILE_WRITE( sd_handle, p_us_data_cpy, i );

			//#SR003 start
			//look if header is written
			if ( ud_retval < i ) then
				SizeError := TRUE;
				OS_FILE_CLOSE( sd_handle );	
				OS_FILE_CLOSE( sd_handle2 );
		  		OS_FILE_DELETE( #us_Filename[0] );
				OS_FILE_RENAME( #us_FilenameBak[0], #us_Filename[0] );
				_free( p_us_data_cpy );
				return;
			end_if;
			//#SR003 end

			EXIT;
		end_if;   			
		OS_FILE_READ( sd_handle2, p_us_data_cpy, WORKING_BUFFER );	
		ud_retval := OS_FILE_WRITE( sd_handle, p_us_data_cpy, WORKING_BUFFER );

		//#SR003 start
		//look if header is written
		if ( ud_retval < WORKING_BUFFER ) then
			SizeError := TRUE;
			OS_FILE_CLOSE( sd_handle );	
			OS_FILE_CLOSE( sd_handle2 );
	  		OS_FILE_DELETE( #us_Filename[0] );
			OS_FILE_RENAME( #us_FilenameBak[0], #us_Filename[0] );
			_free( p_us_data_cpy );
			return;
		end_if;
		//#SR003 end

		i -= WORKING_BUFFER;
	end_while;

	OS_FILE_CLOSE( sd_handle );
	OS_FILE_CLOSE( sd_handle2 );
  	OS_FILE_DELETE( #us_FilenameBak[0] );
	_free( p_us_data_cpy );
	SizeError := FALSE;					//#SR003

END_FUNCTION // RamFile::ReduceFile_FG
//[#ENGLISH]
//Call this function, to get back a certain part from the stored Data
//If udAt is bigger than "Buffer" no Data are copied
//If udSize is bigger than "Buffer" no Data are copied

//[Server]		m_udLength			:R		:Server shows the size of File without header

//[members]		us_Init				:R		:variable is set if class is initialized
//				b_FileAccessControl	:R/W	:variable marks if the file operation is finished or runs
//				p_us_DataI			:R		:pointer for our working buffer
//				p_us_DataFG 		:W		:pointer to data which should be read
//				ud_DataSize 		:W		:size of data which should be read
//				ud_DataOffset 		:W		:offset of data which should be read

//[>p_us_data]pointer to a buffer with sufficient size
//[>ud_size]this amount of bytes will be copied
//[>ud_at]start copy at this offset in the internal buffer
//[<ret_code]return code of function

FUNCTION VIRTUAL GLOBAL RamFile::GetDataAt
VAR_INPUT
	p_us_data	: ^USINT;
	ud_size		: UDINT;
	ud_at		: UDINT;
END_VAR
VAR_OUTPUT
	ret_code	: ConfStates;
END_VAR

	ret_code := C_OK;

 	// test if size = 0 --> error no copy
 	if ud_size = 0 then
  		ret_code := C_SYNTAX_ERROR;
  		return; 
 	end_if;

 	// if somebody calles me befor my init was called
 	if us_Init = 0 then
  		// test if we must init	
  		InitMe();
 	end_if;
	  	
	//Look if File exist (if user call SetDataAt before SetSize)
	if p_us_DataI = NIL then
		TRACE( "File does not exist, create one with SetSize (GetDataAt)" );
		ret_code := C_SYNTAX_ERROR;
		return;
	end_if;	

 	// test if size is big enough --> error no copy	
 	if ( ud_size + ud_at  ) > m_udLength then
  		ret_code := C_SYNTAX_ERROR;
  		return; 
 	end_if;

	//if a File access does not finish
	if b_FileAccessControl = 1 then							
		ret_code := C_SYNTAX_ERROR;
		TRACE("Last File operation does not finished (GetDataAt)");
		return;
	end_if;
	b_FileAccessControl := 1;									//mark new File access

	p_us_DataFG := p_us_Data;
	ud_DataSize := ud_size;
	ud_DataOffset := ud_at;
	
	ReadFile_FG_AWL( this );

END_FUNCTION //VIRTUAL GLOBAL RamFile::GetDataAt
//[#ENGLISH]
//Call this function, to get back a certain part from
//the stored Data in Background for bigger files or a huge part of data.
//If udAt is bigger than "Buffer" no Data are copied
//If udSize is bigger than "Buffer" no Data are copied

//[Server]		m_udLength			:R		:Server shows the size of File without header

//[members]		us_Init				:R		:variable is set if class is initialized
//				b_FileAccessControl	:R/W	:variable marks if the file operation is finished or runs
//				p_us_DataI			:R		:pointer for our working buffer
//				p_us_DataFG 		:W		:pointer to data which shouldbe read
//				ud_DataSize 		:W		:size of data which should be read
//				ud_DataOffset 		:W		:offset of data which should be read

//[locals]		p_us_fg				:W/R	:pointer to foreground function

//[>p_us_data]pointer to a buffer with sufficient size
//[>ud_size]this amount of bytes will be copied
//[>ud_at]start copy at this offset in the internal buffer
//[<ret_code]return code of function

FUNCTION VIRTUAL GLOBAL RamFile::GetDataAtBackground
VAR_INPUT
	p_us_data	: ^USINT;
	ud_size		: UDINT;
	ud_at		: UDINT;
END_VAR
VAR_OUTPUT
	ret_code		: ConfStates;
END_VAR
VAR
	p_us_fg			: MT_TASKHANDLE;
END_VAR

	ret_code := C_OK;

 	// test if size = 0 --> error no copy
 	if ud_size = 0 then
  		ret_code := C_SYNTAX_ERROR;
  		return; 
 	end_if;

 	// if somebody calles me befor my init was called
 	if us_Init = 0 then
  		// test if we must init	
  		InitMe();
 	end_if; 

	//Look if File exist (if user call SetDataAt before SetSize)
	if p_us_DataI = NIL then
		TRACE( "File does not exist, create one with SetSize (GetDataAtBackground)" );
		ret_code := C_SYNTAX_ERROR;
		return;
	end_if;	

 	// test if size is big enough --> error no copy	
 	if ( ud_size + ud_at ) > m_udLength then
  		ret_code := C_SYNTAX_ERROR;
  		return; 
 	end_if;

	//if a ForeGround Function does not finished
	if b_FileAccessControl = 1 then							
		ret_code := C_SYNTAX_ERROR;
		TRACE( "Last File operation does not finished (GetDataAtBackground)" );
		return;
	end_if;
	b_FileAccessControl := 1;						//mark new File access

	p_us_DataFG := p_us_Data;
	ud_DataSize := ud_size;
	ud_DataOffset := ud_at;
	
	//Install Foreground Task
	p_us_fg := MultiTask.CREATETHREAD( taskfunction0 := #ReadFile_FG_AWL(), priority0 := 8, stackSize0 := 16#1000, flags0 := 0, parameter0 := this, name0 := #us_Filename[ 0 ] );		//#SR001
//#SR001	p_us_fg := ( TaskObjectControl.AddForegroundFunction( #ReadFile_FG_AWL(), this, 0x1000 ) )$^USINT;					
	if p_us_fg = NIL then
		TRACE( "Error creating File, because fault in installing ForeGround function (GetDataAtBackground)" );	
		b_FileAccessControl := 0;
		ret_code := C_OUTOF_NEAR;
	end_if;	

END_FUNCTION //VIRTUAL GLOBAL RamFile::GetDataAtBackground
//Function to read the File (AWL because foreground)

//[members]		b_FileAccessControl		:W		:variable marks if the file operation is finished or runs

//[>p_param]Pointer to Object (this)

#ifdef _LSL_TARGETARCH_X86
FUNCTION AWL RamFile::ReadFile_FG_AWL
VAR_INPUT
	p_param		: ^RamFile;
END_VAR

	l.esi	p_param							//load pointer to object (for Forground important)

	call	ReadFile_FG						//read file

	l.b		b_FileAccessControl,0			//end of File access

END_FUNCTION // RamFile::ReadFile_FG_AWL
#else
FUNCTION RamFile::ReadFile_FG_AWL
VAR_INPUT
	p_param		: ^RamFile;
END_VAR

  this := p_param;
  ReadFile_FG();                //read file
  b_FileAccessControl := false; //end of File access

END_FUNCTION
#endif
//Function to read the File

//[Server]		m_udLength		:R		:Server shows the size of File without header

//[Clients]		Setup			:R		:Client contains the adjustments of the class 

//[members]		p_us_DataI		:R		:pointer for our working buffer
//				us_Filename		:R		:array containing the Path and Filename of File 
//				p_us_DataFG 	:R		:pointer to data which shouldbe read
//				ud_DataSize 	:R		:size of data which should be read
//				ud_DataOffset 	:R		:offset of data which should be read

//[locals]		sd_handle		:W/R	:variable for file handling

FUNCTION  RamFile::ReadFile_FG
VAR
	sd_handle	: DINT;
END_VAR

 	//if File smaller than 64k we can read the data from program store
	if m_udLength < 64*1024 then			
	
	 	_memcpy( p_us_DataFG, p_us_DataI + ud_DataOffset, ud_DataSize);

 	else									//else we need a file access	
   		sd_handle := OS_FILE_OPEN( #us_Filename[0], 2, ATT_READ_WRITE );
   		if sd_handle < 0  then
   	   		TRACE( "open file fault Class RamFile (ReadFile)" );
     		return;
   		end_if;   	 
   		OS_FILE_SEEK( sd_handle, ud_DataOffset + sizeof( fheader ), 0 );
   		OS_FILE_READ( sd_handle, p_us_DataFG, ud_DataSize );
   		OS_FILE_CLOSE( sd_handle );	
 	end_if;	

	//if data is encrypt, decrypt it
	if Setup.Encrypt then												
		EncryptData( p_us_DataFG, ud_DataSize );
  	end_if;

END_FUNCTION // RamFile::ReadFile_FG
//[#ENGLISH]
//Use this function to change a part of the data buffer.
//If buffer is not big enough no data are written.
//Call SetSize before, to make sure, the internal data buffer is
//sufficiently big.
//To write on the CF Card you should work in 512 Byte boundarys
//because the card internally have 512 Byte sektors and you can write
//on each sektor 2.000.000. So a lifetime of writing to each sektor
//every 2 minutes of 5 years.

//[Server]		m_udLength			:R		:Server shows the size of File without header

//[members]		us_Init				:R		:variable is set if class is initialized
//				b_FileAccessControl	:R/W	:variable marks if the file operation is finished or runs
//				p_us_DataI			:R		:pointer for our working buffer
//				p_us_DataFG 		:W		:pointer to data which shouldbe read
//				ud_DataSize 		:W		:size of data which should be read
//				ud_DataOffset 		:W		:offset of data which should be read

//[>p_us_data]pointer to a data buffer with udSize elements
//[>ud_size]number of bytes that should be copied
//[>ud_at]offset of the first byte to change
//[<ret_code]return code of function

FUNCTION VIRTUAL GLOBAL RamFile::SetDataAt
VAR_INPUT
	p_us_data		: ^USINT;
	ud_size		: UDINT;
	ud_at		: UDINT;
END_VAR
VAR_OUTPUT
	ret_code		: ConfStates;
END_VAR

	ret_code := C_OK;

 	// test if size = 0 --> error no copy
 	if ud_size = 0 then
  		ret_code := C_SYNTAX_ERROR;
  		return; 
 	end_if;

 	// if somebody calls me befor my init was called
 	if us_Init = 0 then
  		// test if we must init	
	  	InitMe();
 	end_if;  

	//Look if File exist (if user call SetDataAt before SetSize)
	if p_us_DataI = NIL then
		TRACE( "File does not exist, create one with SetSize (SetDataAt)" );
		ret_code := C_SYNTAX_ERROR;
		return;
	end_if;	

 	// test if size is big enough --> error no copy	
 	if ( ud_size + ud_at ) > m_udLength then
  		TRACE( "Datalength with this offset is bigger than the Filesize (SetDataAt)" );
		ret_code := C_SYNTAX_ERROR;
  		return; 
 	end_if;

	//if a File access does not finish
	if b_FileAccessControl = 1 then								
		ret_code := C_SYNTAX_ERROR;
		TRACE( "Last File operation does not finished (SetDataAt)" );
		return;
	end_if;
	b_FileAccessControl := 1;					//mark new File access

	p_us_DataFG := p_us_data;
	ud_DataSize := ud_size;
	ud_DataOffset := ud_at;
	
	WriteFile_FG_AWL( this );
	
END_FUNCTION //VIRTUAL GLOBAL RamFile::SetDataAt
//[#ENGLISH]
//Use this function to change a part of the data buffer in Background
//for bigger Files or a huge part of Data.
//If buffer is not big enough no data are written.
//Call SetSize before, to make sure, the internal data buffer is
//sufficiently big.
//To write on the CF Card you should work in 512 Byte boundarys
//because the card internally have 512 Byte sektors and you can write
//on each sektor 2.000.000. So a lifetime of writing to each sektor
//every 2 minutes of 5 years.

//[Server]		m_udLength			:R		:Server shows the size of File without header

//[members]		us_Init				:R		:variable is set if class is initialized
//				b_FileAccessControl	:R/W	:variable marks if the file operation is finished or runs
//				p_us_DataI			:R		:pointer for our working buffer
//				p_us_DataFG 		:W		:pointer to data which shouldbe read
//				ud_DataSize 		:W		:size of data which should be read
//				ud_DataOffset 		:W		:offset of data which should be read

//[locals]		p_us_fg				:W/R	:pointer for foreground function

//[>p_us_data]pointer to a buffer with sufficient size
//[>ud_size]number of bytes that should be copied
//[>ud_at]offset of the first byte to change
//[<ret_code]return code of function

FUNCTION VIRTUAL GLOBAL RamFile::SetDataAtBackground
VAR_INPUT
	p_us_data	: ^USINT;
	ud_size		: UDINT;
	ud_at		: UDINT;
END_VAR
VAR_OUTPUT
	ret_code		: ConfStates;
END_VAR
VAR
	p_us_fg			: MT_TASKHANDLE;
END_VAR
	ret_code := C_OK;

 	// test if size = 0 --> error no copy
 	if ud_size = 0 then
  		ret_code := C_SYNTAX_ERROR;
  		return; 
 	end_if;

 	// if somebody calls me befor my init was called
 	if us_Init = 0 then
  		// test if we must init	
	  	InitMe();
 	end_if;  

	//Look if File exist (if user call SetDataAt before SetSize)
	if p_us_DataI = NIL then
		TRACE( "File does not exist, create one with SetSize (SetDataAtBackground)" );
		ret_code := C_SYNTAX_ERROR;
		return;
	end_if;	
	
 	// test if size is big enough --> error no copy	
 	if ( ud_size + ud_at ) > m_udLength then
  		TRACE( "Datalength with this offset is bigger than the Filesize (SetDataAtBackground)" );
  		ret_code := C_SYNTAX_ERROR;
  		return; 
 	end_if;

	//if a File access does not finish
	if b_FileAccessControl = 1 then								
		ret_code := C_SYNTAX_ERROR;
		TRACE( "Last File operation does not finished (SetDataAtBackground)" );
		return;
	end_if;
	b_FileAccessControl := 1;					//mark new File access

	p_us_DataFG := p_us_data;
	ud_DataSize := ud_size;
	ud_DataOffset := ud_at;
	
	//Install Forfround Task
	p_us_fg := MultiTask.CREATETHREAD( taskfunction0 := #WriteFile_FG_AWL(), priority0 := 8, stackSize0 := 16#1000, flags0 := 0, parameter0 := this, name0 := #us_Filename[ 0 ] );		//#SR001
//#SR001	p_us_fg := ( TaskObjectControl.AddForegroundFunction( #WriteFile_FG_AWL(), this, 0x1000 ) )$^USINT;			
	if p_us_fg = NIL then
		TRACE( "Error creating File, because fault in installing ForeGround function (SetDataAtBackground)" );
		b_FileAccessControl := 0;
		ret_code := C_OUTOF_NEAR;
	end_if;	

END_FUNCTION //VIRTUAL GLOBAL RamFile::SetDataAtBackground
//Function to write the File (AWL because foreground)

//[members]		b_FileAccessControl		:W		:variable marks if the file operation is finished or runs

//[>p_param]Pointer to Object (this)

 // RamFile::WriteFile_FG_AWL
#ifdef _LSL_TARGETARCH_X86
FUNCTION AWL RamFile::WriteFile_FG_AWL
VAR_INPUT
	p_param		: ^RamFile;
END_VAR

	l.esi	p_param								//load pointer to object (for Forground important)
	
	call	WriteFile_FG						//Write File	
	call	CreateChecksum						//calculate new checksum
	
	l.b		b_FileAccessControl,0				//end of File access

END_FUNCTION // RamFile::WriteFile_FG_AWL
#else
FUNCTION RamFile::WriteFile_FG_AWL
VAR_INPUT
	p_param		: ^RamFile;
END_VAR

  this := p_param;
  WriteFile_FG();						//Write File	
  CreateChecksum();						//calculate new checksum
	
  b_FileAccessControl := false;				//end of File access

END_FUNCTION
#endif
//Function to write the File

//[Clients]		Setup			:R		:Client contains the adjustments of the class 

//[members]		p_us_DataI		:R		:pointer for our working buffer
//				us_Filename		:R		:array containing the Path and Filename of File 
//				p_us_DataFG 	:R/W	:pointer to data which shouldbe read
//				ud_DataSize 	:R		:size of data which should be read
//				ud_DataOffset 	:R		:offset of data which should be read

//[locals]		sd_handle		:W/R	:variable for file handling
//				p_us_data_help	:W/R	:pointer to written data

FUNCTION  RamFile::WriteFile_FG
VAR
	sd_handle 		: DINT;
	p_us_data_help	: ^USINT;
END_VAR

  p_us_data_help := nil;
  
	if Setup.Encrypt then										//user want to enccrypt data 	
		
		p_us_data_help := ( _alloc_resize( ud_DataSize ) )$^USINT;	
		if p_us_data_help = NIL then
			TRACE( "extend fileSize fault Class RamFile for encryption (WriteFile)" );
			return;
		end_if;	
		_memcpy( p_us_data_help, p_us_DataFG, ud_DataSize );	//we must copy the data to change it
		
		p_us_DataFG := p_us_data_help;
		EncryptData( p_us_DataFG, ud_DataSize );
//		_free( p_us_data_help );
	end_if;

 	if m_udLength < 64*1024 then								//if File smaller than 64k we must load the data also in the program store
  	
		_memcpy( p_us_DataI + ud_DataOffset, p_us_DataFG, ud_DataSize );			//write data do the program store
  		sd_handle := OS_FILE_OPEN( #us_Filename[0], 2, ATT_READ_WRITE or ATT_CREATE );
   		if sd_handle < 0 then
   	   		TRACE("open file fault Class RamFile (WriteFile)");
     		return;
   		end_if;   	 
  	
		OS_FILE_SEEK( sd_handle, ud_DataOffset + sizeof( fheader ), 0 );
  		OS_FILE_WRITE( sd_handle, p_us_DataFG, ud_DataSize);					//write Data to File
  		OS_FILE_SEEK( sd_handle, 0, FILE_END );
 	
	else															//File bigger than 64k
   		sd_handle:= OS_FILE_OPEN( #us_Filename[0], 2, ATT_READ_WRITE );
   		if sd_handle < 0 then
   	   		TRACE( "open file fault Class RamFile (WriteFile)" );
     		return;
   		end_if;   	 
   	
		OS_FILE_SEEK( sd_handle, ud_DataOffset + sizeof( fheader ), 0 );
   		OS_FILE_write( sd_handle, p_us_DataFG, ud_DataSize );					//write Data to File
 	end_if;

  if p_us_data_help <> nil then
		_free( p_us_data_help );
  end_if;

   	OS_FILE_CLOSE( sd_handle );

END_FUNCTION // RamFile::WriteFile_FG
//function to get the user version of file

//[Clients]		Setup				:R		:Client contains the adjustments of the class 

//[members]		us_Init				:R		:variable is set if class is initialized
//				p_us_DataI			:R		:pointer for our working buffer
//				Header				:R		:structure contains the inforamtions of the Header of File

//[<ui_version]Version of file
FUNCTION VIRTUAL GLOBAL RamFile::GetUserVersion
VAR_OUTPUT
	ui_version		: UINT;
END_VAR

 	// if somebody calls me befor my init was called
 	if us_Init = 0 then
  		// test if we must init	
  		InitMe();
 	end_if;  	

	//Look if File exist (if user call SetDataAt before SetSize)
	if p_us_DataI = NIL then
		TRACE( "File does not exist, create one with SetSize (SetDataAtBackground)" );
		ui_version := 0xFFFF;
		return;
	end_if;	

 	if Setup.Encrypt then								//if Data is encrypted
		EncryptData( ( #Header )$^USINT, sizeof( fHeader ) );
		ui_version := Header.UserVersion;
		EncryptData( ( #Header )$^USINT, sizeof( fHeader ) );
	else
		ui_version := Header.UserVersion;
	end_if;
	
END_FUNCTION //VIRTUAL GLOBAL RamFile::GetUserVersion
//Function to set user version of file

//[Clients]		Setup				:R		:Client contains the adjustments of the class 

//[members]		us_Init				:R		:variable is set if class is initialized
//				p_us_DataI			:R		:pointer for our working buffer
//				Header				:W		:structure contains the inforamtions of the Header of File
//				us_Filename			:R		:array containing the Path and Filename of File 

//[locals]		sd_handle			:R		:variable for file handling

//[>ui_version]Version shich is set to file

FUNCTION VIRTUAL GLOBAL RamFile::SetUserVersion
VAR_INPUT
	ui_Version		: HINT;
END_VAR
VAR
    sd_handle 		: DINT;
END_VAR

 	// if somebody calls me befor my init was called
 	if us_Init = 0 then
  		// test if we must init	
  		InitMe();
 	end_if;  	

	//Look if File exist (if user call SetDataAt before SetSize)
	if p_us_DataI = NIL then
		TRACE( "File does not exist, create one with SetSize (SetDataAtBackground)" );
		return;
	end_if;	

	if Setup.Encrypt then								//if Data is encrypted
		EncryptData( ( #Header )$^USINT, sizeof( fHeader ) );
		Header.UserVersion := ui_Version;
		EncryptData( ( #Header )$^USINT, sizeof( fHeader ) );
	else
		Header.UserVersion := ui_Version;
	end_if;

 	sd_handle := OS_FILE_OPEN( #us_Filename[0], 2, ATT_READ_WRITE );
 	if sd_handle < 0 then
  		TRACE( "open file fault Class RamFile (SetUserVersion)" );
  		return;
 	end_if;   	 
 	OS_FILE_WRITE( sd_handle, #Header, sizeof( fHeader ) );		//write new Header
 	OS_FILE_CLOSE( sd_handle );
	
	//calculate new checksum
	CreateChecksum();		   							

END_FUNCTION //VIRTUAL GLOBAL RamFile::SetUserVersion
//[#ENGLISH]
//This Function returns the State of the File operation. If it returns
//1 the last File operation does not finished. The User must wait
//with the next File operation until this function returns 0!!

//[member]		b_FileAccessControl	:W		:variable marks if the file operation is finished or runs

//[<State]State of File operations
FUNCTION VIRTUAL GLOBAL RamFile::GetFileState
VAR_OUTPUT
	State		: BOOL;
END_VAR

	State := b_FileAccessControl;

END_FUNCTION //VIRTUAL GLOBAL RamFile::GetFileState
//Function creates the checksum of the File

//[Clients]		Setup				:R		:Client contains the adjustments of the class 

//[members]		us_Filename			:R		:array containing the Path and Filename of File 
//				Header				:W		:structure contains the inforamtions of the Header of File

//[locals]		sd_handle			:W/R	:variable for file handling

FUNCTION  RamFile::CreateChecksum
VAR
	sd_handle	:	DINT;
END_VAR

	if Setup.EnableChecksum then									//if Checksum option is enable
		sd_handle := OS_FILE_OPEN( #us_Filename[0], 2, ATT_READ_WRITE );
		if sd_handle < 0 then
	   		TRACE( "open file fault Class RamFile (CreateChecksum)" );
	    	return;
	   	
		end_if;   
	
		Header.CRC := CalculateChecksum( sd_handle );
		OS_FILE_WRITE( sd_handle, #Header, sizeof( fHeader ) );				//write new Header
		OS_FILE_CLOSE( sd_handle );	 
	end_if;

END_FUNCTION // RamFile::CreateChecksum
//Function calculates checksum from delivered file

//[members]		Header				:R		:structure contains the inforamtions of the Header of File

//[locals]		sd_checksum_length	:W/R	:length of file to calculate checksum
//				ud_checksum_calc	:W/R	:calculated checksum
//				p_us_data_checksum	:W/R	:pointer to data to calculate checksum

//[>sd_handle]Handle variable from file
//[<ud_retval]return value of function

FUNCTION  RamFile::CalculateChecksum		
VAR_INPUT	
	sd_handle		: DINT;
END_VAR
VAR_OUTPUT
	ud_retval		: UDINT;
END_VAR
VAR
	sd_checksum_length	:	DINT;
	ud_checksum_calc	:	UDINT;
	i					:	UDINT;
	p_us_data_checksum	:	^USINT;
END_VAR;

	sd_checksum_length := OS_FILE_LENGTH( sd_handle );					//Get length of File
	if sd_checksum_length = 0 then
		TRACE( "Filelength is 0 (Calculate Checksum)" );
		ud_retval := C_OUTOF_NEAR;
		return;
	end_if;
	
	p_us_data_checksum := ( _alloc_resize( WORKING_BUFFER ) )$^USINT;
	if p_us_data_checksum = NIL then 
		TRACE( "no memory left for Class RamFile (Calculate Checksum)" );
        ud_retval := C_OUTOF_NEAR;
		return;
  	end_if;
	
	ud_checksum_calc := Header.Version + Header.UserVersion + Header.Setup; 
	for i:=0 to ( sizeof( Header.resarray ) - 1 ) do
		ud_checksum_calc += Header.resarray[i];
	end_for;
	
	OS_FILE_SEEK( sd_handle, sizeof( fHeader ), FILE_BEGIN );
	sd_checksum_length -= sizeof( fHeader );

	//summarize the data bytes of the file
	while 1 do			
		if sd_checksum_length = 0 then
			exit;
		end_if;

		if sd_checksum_length < WORKING_BUFFER then
			OS_FILE_READ( sd_handle, p_us_data_checksum, sd_checksum_length$UDINT );
			ud_checksum_calc += CalcChk( p_us_data_checksum, sd_checksum_length$UDINT );
			exit;
		end_if;

		OS_FILE_READ( sd_handle, p_us_data_checksum, WORKING_BUFFER );	
		ud_checksum_calc += CalcChk( p_us_data_checksum, WORKING_BUFFER );
		sd_checksum_length -= WORKING_BUFFER;
	end_while;
	OS_FILE_SEEK( sd_handle, 0, FILE_BEGIN );
	_free( p_us_data_checksum );
	ud_retval := ud_checksum_calc;

END_FUNCTION // RamFile::CalculateChecksum
//[>p_ud_Data]pointer to data
//[>ud_length]length of data
//[<ud_sum]sum of data

#ifdef _LSL_TARGETARCH_X86
FUNCTION AWL RamFile::CalcChk
VAR_INPUT
	p_us_data	: ^USINT;
	ud_length	: UDINT;
END_VAR
VAR_OUTPUT
	ud_sum		: UDINT;
END_VAR

	l.ecx		ud_length
	l.edi		p_us_data
	x.eax		eax

LABEL_Chk
	lzxb.ebx	( edi )
	add.eax		ebx
	inc			edi
	loop		LABEL_Chk
	s.eax		ud_sum

END_FUNCTION
#else
FUNCTION RamFile::CalcChk
VAR_INPUT
	p_us_data	: ^USINT;
	ud_length	: UDINT;
END_VAR
VAR_OUTPUT
	ud_sum		: UDINT;
END_VAR

  ud_sum := 0;
  while ud_length do
    ud_sum    += p_us_data^;
    p_us_data += 1;
    ud_length -= 1;
  end_while;
  
END_FUNCTION
#endif
//Function encrypts the data

//[>p_us_data_enc]pointer to data which should be encrypt
//[>ud_size]size of data

#ifdef _LSL_TARGETARCH_X86
FUNCTION AWL RamFile::EncryptData			
VAR_INPUT
	p_us_data_enc	: ^USINT;
	ud_size			: UDINT;
END_VAR

	l.ebx		p_us_data_enc
	l.ecx		ud_size

LABEL_Enc
	l.al		( ebx )
	x.al		us_Encbyte
	s.al		( ebx )
	inc			ebx
	loop		LABEL_Enc

END_FUNCTION // RamFile::EncryptData
#else
FUNCTION RamFile::EncryptData			
  VAR_INPUT  
    p_us_data_enc	: ^USINT;
    ud_size			: UDINT;
  END_VAR
  VAR
  	tmp : usint;
  END_VAR

  tmp := us_Encbyte$usint;
  while(ud_size) do
    p_us_data_enc^ := p_us_data_enc^ xor tmp;
    p_us_data_enc += 1;
    ud_size -= 1;
  end_while;

END_FUNCTION
#endif
//[#ENGLISH]
//Function assure that all file operations are finished.
//The CF - card can be removed safley.

FUNCTION VIRTUAL GLOBAL RamFile::RemoveHWSafley					
VAR_OUTPUT
	ret_code		: ConfStates;
END_VAR

	if b_FileAccessControl = 0 then
		ret_code := C_OK;
	else
		TRACE("File operation not finished!");
		ret_code := C_SYNTAX_ERROR;
	end_if;

END_FUNCTION //VIRTUAL GLOBAL RamFile::RemoveHWSafley
//[#ENGLISH]
//[<ret_code]return code of function
FUNCTION VIRTUAL GLOBAL RamFile::ReloadFile2Ram				//#SR000
VAR_OUTPUT
	ret_code		: ConfStates;
END_VAR

	ret_code := C_OK;
	if b_FileAccessControl = 1 then							
		ret_code := C_SYNTAX_ERROR;
		TRACE("Last File operation does not finished ( ReloadFile2Ram )");
		return;
	end_if;
	b_FileAccessControl := 1;
	ReloadFile2Ram_FG_AWL( this );
		
END_FUNCTION //VIRTUAL GLOBAL RamFile::ReloadFile2Ram

#ifdef _LSL_TARGETARCH_X86
FUNCTION AWL RamFile::ReloadFile2Ram_FG_AWL					//#SR000
VAR_INPUT
	p_param		: ^RamFile;
END_VAR

	l.esi	p_param							//load pointer to object (for Forground important)
	l.b		b_Reload,1
	l.b		us_init,0

	call	InitMe							//reload file

END_FUNCTION // RamFile::ReloadFile2Ram_FG_AWL
#else
FUNCTION RamFile::ReloadFile2Ram_FG_AWL					//#SR000
VAR_INPUT
	p_param		: ^RamFile;
END_VAR

  this := p_param;
  b_Reload := true;
  us_Init  := 0;
  InitMe();

END_FUNCTION
#endif
//[#ENGLISH]
//[<ret_code]return code of function
FUNCTION VIRTUAL GLOBAL RamFile::ReloadFile2RamBackground		//#SR000
VAR_OUTPUT
	ret_code		: ConfStates;
END_VAR
VAR
	p_us_fg			: MT_TASKHANDLE;
END_VAR

	ret_code := C_OK;
	if b_FileAccessControl = 1 then							
		ret_code := C_SYNTAX_ERROR;
		TRACE("Last File operation does not finished (ReloadFile2RamBackground)");
		return;
	end_if;
	b_FileAccessControl := 1;

	//Install Foreground Task
	p_us_fg := MultiTask.CREATETHREAD( taskfunction0 := #ReloadFile2Ram_FG_AWL(), priority0 := 8, stackSize0 := 16#1000, flags0 := 0, parameter0 := this, name0 := #us_Filename[ 0 ] );		//#SR001
//#SR001	p_us_fg := ( TaskObjectControl.AddForegroundFunction( #ReloadFile2Ram_FG_AWL(), this, 0x1000 ) )$^USINT;					
	if p_us_fg = NIL then
		TRACE( "Error creating File, because fault in installing ForeGround function (ReloadFile2RamBackground)" );	
		b_FileAccessControl := 0;
		ret_code := C_OUTOF_NEAR;
	end_if;	

END_FUNCTION //VIRTUAL GLOBAL RamFile::ReloadFile2RamBackground

FUNCTION  RamFile::GetFileSize			//#SR003
VAR
	sd_handle		: DINT;
	ud_length_total	: UDINT;
END_VAR

	//Create new File
	sd_handle := OS_FILE_OPEN( #us_Filename[0], 2, ATT_READ_ONLY );	
   	if ( sd_handle < 0 ) then
    	TRACE( "open file fault Class RamFile (CreateFile)" );
		return;
   	end_if;

	// file is available, check length
	ud_length_total$DINT := OS_FILE_LENGTH( sd_handle );

	if ( ud_length_total < sizeof (fHeader) ) then
	  		
		//there stands trash
		ud_length_total := 0;
		m_udLength  	:= 0;
		TRACE( "File is destroyed (smaller than the Header)!" );
	 			
	else
	  	m_udLength := ud_length_total - sizeof( fHeader ); 
	end_if;

	OS_FILE_CLOSE( sd_handle );

END_FUNCTION // RamFile::GetFileSize

FUNCTION  RamFile::DeleteFile				//#SR003

	OS_FILE_DELETE( #us_Filename[ 0 ] );
	_free( p_us_DataI );
	p_us_DataI := NIL;

END_FUNCTION // RamFile::DeleteFile

