#include-once

;wrapped by funkey

#cs
LIBNODAVE provides a way to exchange data with Siemens PLCs of S7-200, 300 and 400 families.
It has also been successfully tested with a VIPA Speed7 CPU. It should also be useable with S7-compatible PLCs from SAIA.
Data exchange comprises all memory areas and variables you canaccess in your PLC programs, e.g. flags, data blocks,
input and output image memory, timers and counters.
Additionally, LIBNODAVE provides access to functions that are in the scope of programming software, e.g. reading diagnostic information,
read program blocks from a PLC and write them to a PLC, start and stop a PLC.

LIBNODAVE is free software under GPL and LGPL. 

http://libnodave.sf.net/

#ce

Global Const $DLE = 0x10
Global Const $ETX = 0x03
Global Const $STX = 0x02
Global Const $SYN = 0x16
Global Const $NAK = 0x15
Global Const $EOT = 0x04	;  for S5
Global Const $ACK = 0x06	;  for S5

Global Const $daveProtoMPI	= 0	; MPI for S7 300/400
Global Const $daveProtoMPI2	= 1	; MPI for S7 300/400, "Andrew's version" without STX 
Global Const $daveProtoMPI3	= 2	; MPI for S7 300/400, Step 7 Version, not yet implemented 
Global Const $daveProtoMPI4	= 3	; MPI for S7 300/400, "Andrew's version" with STX 

Global Const $daveProtoPPI	= 10	; PPI for S7 200 

Global Const $daveProtoAS511	= 20	; S5 programming port protocol 

Global Const $daveProtoS7online = 50	; use s7onlinx.dll for transport 

Global Const $daveProtoISOTCP	= 122	; ISO over TCP 
Global Const $daveProtoISOTCP243 = 123	; ISO over TCP with CP243 
Global Const $daveProtoISOTCPR = 124	; ISO over TCP with Routing 

Global Const $daveProtoMPI_IBH = 223	; MPI with IBH NetLink MPI to ethernet gateway 
Global Const $daveProtoPPI_IBH = 224	; PPI with IBH NetLink PPI to ethernet gateway 

Global Const $daveProtoNLpro = 230	; MPI with NetLink Pro MPI to ethernet gateway 

Global Const $daveProtoUserTransport = 255	; Libnodave will pass the PDUs of S7 Communication to user 
					; defined call back functions. 

;   ProfiBus speed constants:

Global Const $daveSpeed9k     = 0
Global Const $daveSpeed19k    = 1
Global Const $daveSpeed187k   = 2
Global Const $daveSpeed500k   = 3
Global Const $daveSpeed1500k  = 4
Global Const $daveSpeed45k    = 5
Global Const $daveSpeed93k    = 6

;    Some MPI function codes (yet unused ones may be incorrect).

Global Const $daveFuncOpenS7Connection	= 0xF0
Global Const $daveFuncRead			= 0x04
Global Const $daveFuncWrite			= 0x05
Global Const $daveFuncRequestDownload		= 0x1A
Global Const $daveFuncDownloadBlock		= 0x1B
Global Const $daveFuncDownloadEnded		= 0x1C
Global Const $daveFuncStartUpload		= 0x1D
Global Const $daveFuncUpload			= 0x1E
Global Const $daveFuncEndUpload		= 0x1F
Global Const $daveFuncInsertBlock		= 0x28

;    S7 specific constants:

Global Const $daveBlockType_OB  = 56	; '8'
Global Const $daveBlockType_DB  = 65	; 'A'
Global Const $daveBlockType_SDB = 66	; 'B'
Global Const $daveBlockType_FC  = 67	; 'C'
Global Const $daveBlockType_SFC = 68	; 'D'
Global Const $daveBlockType_FB  = 69	; 'E'
Global Const $daveBlockType_SFB = 70	; 'F'

Global Const $daveS5BlockType_DB  = 0x01
Global Const $daveS5BlockType_SB  = 0x02
Global Const $daveS5BlockType_PB  = 0x04
Global Const $daveS5BlockType_FX  = 0x05
Global Const $daveS5BlockType_FB  = 0x08
Global Const $daveS5BlockType_DX  = 0x0C
Global Const $daveS5BlockType_OB  = 0x10

;    Use these constants for parameter "area" in daveReadBytes and daveWriteBytes
    
Global Const $daveSysInfo = 0x3		; System info of 200 family 
Global Const $daveSysFlags  = 0x5	; System flags of 200 family 
Global Const $daveAnaIn  = 0x6		; analog inputs of 200 family 
Global Const $daveAnaOut  = 0x7		; analog outputs of 200 family 

Global Const $daveP = 0x80    		; direct peripheral access 
Global Const $daveInputs = 0x81    
Global Const $daveOutputs = 0x82    
Global Const $daveFlags = 0x83
Global Const $daveDB = 0x84			; data blocks 
Global Const $daveDI = 0x85			; instance data blocks 
Global Const $daveLocal = 0x86 		; not tested 
Global Const $daveV = 0x87			; don't know what it is 
Global Const $daveCounter = 28		; S7 counters 
Global Const $daveTimer = 29		; S7 timers 
Global Const $daveCounter200 = 30	; IEC counters (200 family) 
Global Const $daveTimer200 = 31		; IEC timers (200 family) 
Global Const $daveSysDataS5 = 0x86	; system data area ? 
Global Const $daveRawMemoryS5 = 0	; just the raw memory 

;    Library specific:
#cs
    Result codes. Genarally, 0 means ok, 
    >0 are results (also errors) reported by the PLC
    <0 means error reported by library code.
#ce

Global Const $daveResOK = 0				; means all ok 
Global Const $daveResNoPeripheralAtAddress = 1		; CPU tells there is no peripheral at address 
Global Const $daveResMultipleBitsNotSupported = 6 	; CPU tells it does not support to read a bit block with a 
						; length other than 1 bit. 
Global Const $daveResItemNotAvailable200 = 3		; means a a piece of data is not available in the CPU, e.g. 
						; when trying to read a non existing DB or bit bloc of length<>1 
						; This code seems to be specific to 200 family. 
					    
Global Const $daveResItemNotAvailable = 10		; means a a piece of data is not available in the CPU, e.g. 
						; when trying to read a non existing DB 

Global Const $daveAddressOutOfRange = 5			; means the data address is beyond the CPUs address range 
Global Const $daveWriteDataSizeMismatch = 7		; means the write data size doesn't fit item size 
Global Const $daveResCannotEvaluatePDU = -123    	; PDU is not understood by libnodave 
Global Const $daveResCPUNoData = -124 
Global Const $daveUnknownError = -125 
Global Const $daveEmptyResultError = -126 
Global Const $daveEmptyResultSetError = -127 
Global Const $daveResUnexpectedFunc = -128 
Global Const $daveResUnknownDataUnitSize = -129
Global Const $daveResNoBuffer = -130
Global Const $daveNotAvailableInS5 = -131
Global Const $daveResInvalidLength = -132
Global Const $daveResInvalidParam = -133
Global Const $daveResNotYetImplemented = -134

Global Const $daveResShortPacket = -1024 
Global Const $daveResTimeout = -1025 

#cs
	Max number of bytes in a single message. 
    An upper limit for MPI over serial is:
    8		transport header
    +2*240	max PDU len *2 if every character were a DLE
    +3		DLE,ETX and BCC
    = 491
    
    Later I saw some programs offering up to 960 bytes in PDU size negotiation    
    
    Max number of bytes in a single message. 
    An upper limit for MPI over serial is:
    8		transport header
    +2*960	max PDU len *2 if every character were a DLE
    +3		DLE,ETX and BCC
    = 1931
    
    For now, we take the rounded max of all this to determine our buffer size. This is ok
    for PC systems, where one k less or more doesn't matter.
#ce

Global Const $daveMaxRawLen = 2048

;    Some definitions for debugging:

Global Const $daveDebugRawRead  	= 0x01	; Show the single bytes received 
Global Const $daveDebugSpecialChars  	= 0x02	; Show when special chars are read 
Global Const $daveDebugRawWrite	= 0x04	; Show the single bytes written 
Global Const $daveDebugListReachables = 0x08	; Show the steps when determine devices in MPI net 
Global Const $daveDebugInitAdapter 	= 0x10	; Show the steps when Initilizing the MPI adapter 
Global Const $daveDebugConnect 	= 0x20	; Show the steps when connecting a PLC 
Global Const $daveDebugPacket 	= 0x40
Global Const $daveDebugByte 		= 0x80
Global Const $daveDebugCompare 	= 0x100
Global Const $daveDebugExchange 	= 0x200
Global Const $daveDebugPDU 		= 0x400	; debug PDU handling 
Global Const $daveDebugUpload		= 0x800	; debug PDU loading program blocks from PLC 
Global Const $daveDebugMPI 		= 0x1000
Global Const $daveDebugPrintErrors	= 0x2000	; Print error messages 
Global Const $daveDebugPassive 	= 0x4000

Global Const $daveDebugErrorReporting	= 0x8000
Global Const $daveDebugOpen		= 0x10000  ; print messages in openSocket and setPort 

Global Const $daveDebugAll = 0x1ffff

;  IBH-NetLink packet types:

Global Const $_davePtEmpty = -2
Global Const $_davePtMPIAck = -3
Global Const $_davePtUnknownMPIFunc = -4
Global Const $_davePtUnknownPDUFunc = -5
Global Const $_davePtReadResponse = 1
Global Const $_davePtWriteResponse = 2

;    set and read debug level:

;~ EXPORTSPEC void DECL2 daveSetDebug(int nDebug);
;~ EXPORTSPEC int DECL2 daveGetDebug(void);

;    Some data types:

Global Const $uc = "byte"	;unsigned char
Global Const $us = "ushort"
Global Const $u32 = "uint"


Global Const $_PDU = "ptr header;ptr param;ptr data;ptr udata;int hlen;int plen;int dlen;int udlen"

Global Const $_daveOSserialType = "HANDLE rfd; HANDLE wfd"

Global Const $_daveInterface = "long timeout;" & $_daveOSserialType & ";INT localMPI;int users;char name[20];INT protocol;INT speed;INT ackPos;INT nextConnection;" & _
								"INT_PTR initAdapter;INT_PTR connectPLC;INT_PTR disconnectPLC;INT_PTR disconnectAdapter;INT_PTR exchange;INT_PTR sendMessage;" & _
								"INT_PTR getResponse;INT_PTR listReachablePartners;char realName[20];INT_PTR ifread;INT_PTR ifwrite;INT seqNumber" 

Global Const $_daveS5reaInfo = "int area;int DBnumber;int address;int len;ptr next"

Global Const $_daveS5cache = "int PAE;int PAA;int flags;int timers;int counters;int systemData;ptr first"

Global Const $_daveConnection = "int AnswLen;ptr resultPointer;int maxPDUlength;int MPIAdr;ptr iface;int needAckNumber;int PDUnumber;int ibhSrcConn;" & _
								"int ibhDstConn;byte msgIn["& $daveMaxRawLen & "];byte msgOut["& $daveMaxRawLen & "];ptr _resultPointer;int PDUstartO;int PDUstartI;" & _
								"int rack;int slot;int connectionNumber;int connectionNumber2;byte messageNumber; byte packetNumber;ptr hook;ptr cache"

Global Const $_daveBlockTypeEntry = "byte type[2];ushort count"
Global Const $_daveBlockEntry = "ushort number;byte type[2]"
Global Const $_daveBlockInfo = "byte type[2];byte x1[2];byte w1[2];char pp[2];byte x2[4];ushort number; byte x3[26];ushort length;byte x4[16];byte name[8];byte x5[12]"

Global Const $_devaResult = "int error;int length;ptr bytes"

Global Const $_devaResultSet = "int numResults;ptr results"

Global $hDLL_LibNoDave = 0

;#############################################################################
; fertige und funktionierende Funktionen

Func _DaveInit($DLL = "libnodave.dll")
	$hDLL_LibNoDave = DllOpen($DLL)
	If $hDLL_LibNoDave = -1 Then Return SetError(1)
EndFunc

Func _DaveDeInit()
	If $hDLL_LibNoDave Then DllClose($hDLL_LibNoDave)
EndFunc

Func _daveTCPConnect($sIP, ByRef $hSocket, ByRef $di, ByRef $dc, $CPURack = 0, $CPUSlot = 2, $sName = "SPS")
	If $hDLL_LibNoDave = 0 Then _DaveInit()
	If @error Then Return SetError(1)
	$hSocket = _openSocket($sIP)
	If @error Then Return SetError(2)
	Local $fds = DllStructCreate($_daveOSserialType)
	DllStructSetData($fds, "rfd", $hSocket)
	DllStructSetData($fds, "wfd", $hSocket)
	$di = _daveNewInterface($fds, $sName, 0, $daveProtoISOTCP)
	If @error Then
		_daveTCPDisconnect($hSocket, $di, $dc)
		Return SetError(3)
	EndIf
	_daveInitAdapter($di)
	$dc = _daveNewConnection($di, $CPUSlot, $CPURack)
	If @error Then
		_daveTCPDisconnect($hSocket, $di, $dc)
		Return SetError(4)
	EndIf
	Return _daveConnectPLC($dc)
EndFunc

Func _daveTCPDisconnect(ByRef $hSocket, ByRef $di, ByRef $dc)
	If $dc Then
		_daveDisconnectPLC($dc)
		_daveFree($dc)
	EndIf
	If $di Then
		_daveDisconnectAdapter($di)
		_daveFree($di)
	EndIf
	If $hSocket Then _closeSocket($hSocket)
EndFunc

Func _daveMPIConnect($sPort, $sBaud, ByRef $hPort, ByRef $di, ByRef $dc, $CPURack = 0, $CPUSlot = 2, $sName = "SPS")
	If Not $hDLL_LibNoDave Then _DaveInit()
	$hPort = _setPort($sPort, $sBaud,  "o")
	If @error Then Return SetError(1)
	Local $fds = DllStructCreate($_daveOSserialType)
	DllStructSetData($fds, "rfd", $hPort)
	DllStructSetData($fds, "wfd", $hPort)
	$di = _daveNewInterface($fds, $sName, 0, $daveProtoMPI)
	If @error Then
		_daveMPIDisconnect($hPort, $di, $dc)
		Return SetError(2)
	EndIf
	_daveInitAdapter($di)
	$dc = _daveNewConnection($di, $CPUSlot, $CPURack)
	If @error Then
		_daveMPIDisconnect($hPort, $di, $dc)
		Return SetError(3)
	EndIf
	Return _daveConnectPLC($dc)
EndFunc

Func _daveMPIDisconnect(ByRef $hPort, ByRef $di, ByRef $dc)
	If $dc Then
		_daveDisconnectPLC($dc)
		_daveFree($dc)
	EndIf
	If $di Then
		_daveDisconnectAdapter($di)
		_daveFree($di)
	EndIf
	If $hPort Then _closePort($hPort)
EndFunc

Func _daveS5Connect($sPort, ByRef $hPort, ByRef $di, ByRef $dc, $sName = "SPS")
	If Not $hDLL_LibNoDave Then _DaveInit()
	$hPort = _setPort($sPort, 9600,  "e")
	If @error Then Return SetError(1)
	Local $fds = DllStructCreate($_daveOSserialType)
	DllStructSetData($fds, "rfd", $hPort)
	DllStructSetData($fds, "wfd", $hPort)
	$di = _daveNewInterface($fds, $sName, 0, $daveProtoAS511)
	If @error Then
		_daveS5Disconnect($hPort, $di, $dc)
		Return SetError(2)
	EndIf
	_daveSetTimeout($di, 100000)
	_daveInitAdapter($di)
	$dc = _daveNewConnection($di, 2, 0, 0)
	If @error Then
		_daveS5Disconnect($hPort, $di, $dc)
		Return SetError(3)
	EndIf
	Local $res = _daveConnectPLC($dc)
	If $res <> 0 Then
		_daveS5Disconnect($hPort, $di, $dc)
		Return SetError(4, $res)
	EndIf	
	Return $res
EndFunc

Func _daveS5Disconnect(ByRef $hPort, ByRef $di, ByRef $dc)
	If $dc Then
		_daveDisconnectPLC($dc)
		_daveFree($dc)
	EndIf
	If $di Then
		_daveDisconnectAdapter($di)
		_daveFree($di)
	EndIf
	If $hPort Then _closePort($hPort)
EndFunc

Func _openSocket($sIP, $iPort = 102)
	Local $aRet = DllCall($hDLL_LibNoDave, "int", "openSocket", "int", $iPort, "str", $sIP)
	If $aRet[0] <= 0 Then SetError(1)
	Return $aRet[0]
EndFunc

Func _closeSocket($hSocket)
	Local $aRet = DllCall($hDLL_LibNoDave, "int", "closeSocket", "int", $hSocket)
	If $aRet[0] < 0 Then SetError(1)
	Return $aRet[0]
EndFunc

Func _openS7online($sAccessPoint= "S7online", $hWnd = "")
	If  $hWnd = "" Then $hWnd = _GetHwndFromPID()
	Local $aRet = DllCall($hDLL_LibNoDave, "handle", "openS7online", "str", $sAccessPoint, "hwnd", $hWnd)
	If $aRet[0] <= 0 Then SetError(1)
	Return $aRet[0]
EndFunc

Func _closeS7online($hWnd)
	Local $aRet = DllCall($hDLL_LibNoDave, "handle", "closeS7online", "int", $hWnd)
	If $aRet[0] <= 0 Then SetError(1)
	Return $aRet[0]
EndFunc

Func _setPort($sPort, $sBaud, $sParity)
	Local $struct_Parity = DllStructCreate("wchar parity")
	DllStructSetData($struct_Parity, "parity", AscW($sParity))
	Local $aRet = DllCall($hDLL_LibNoDave, "int", "setPort", "str", $sPort, "str", $sBaud, "ptr", DllStructGetPtr($struct_Parity))
	If $aRet[0] < 0 Then SetError(1)
	Return $aRet[0]
EndFunc	

Func _closePort($hPort)
	Local $aRet = DllCall($hDLL_LibNoDave, "int", "closePort", "handle", $hPort)
	If $aRet[0] < 0 Then SetError(1)
	Return $aRet[0]
EndFunc

Func _daveStrerror($iError)
	$aRet = DllCall($hDLL_LibNoDave, "str", "daveStrerror", "int", $iError)
	Return $aRet[0]
EndFunc

Func _daveFree($dc)
	DllCall($hDLL_LibNoDave, "none", "daveFree", "ptr", $dc)
EndFunc

Func _daveSetTimeout(ByRef $di, $tmo)
	DllCall($hDLL_LibNoDave, "none", "daveSetTimeout", "ptr", $di, "int", $tmo)	
EndFunc

Func _daveGetTimeout(ByRef $di)
	Local $aRet = DllCall($hDLL_LibNoDave, "int", "daveGetTimeout", "ptr", $di)
	Return $aRet[0]
EndFunc

Func _daveSetDebug($iDebug)
	DllCall($hDLL_LibNoDave, "none", "daveSetDebug", "int", $iDebug)
EndFunc

Func _daveGetDebug()
	Local $aRet = DllCall($hDLL_LibNoDave, "int", "daveGetDebug")
	Return $aRet[0]
EndFunc

Func _daveGetOrderCode(ByRef $dc)
	Local $Buffer = DLLStructCreate("char buffer[21]")
	$aRet = DllCall($hDLL_LibNoDave, "int", "daveGetOrderCode", "ptr", $dc, "ptr", DllStructGetPtr($Buffer, 'buffer'))
	Return DllStructGetData($Buffer, "buffer")
EndFunc

Func _daveNewInterface($fds, $nname = "IF1", $localMPI = 0, $protocol = $daveProtoISOTCP, $speed = $daveSpeed187k)
    If IsPtr($fds) Then 
        Local $i_fds = $fds
    Else
        Local $i_fds = DllStructGetPtr($fds)
    EndIf
    Local $di = DllCall($hDLL_LibNoDave, "HANDLE", "davePascalNewInterface", "ptr", $i_fds, "str", $nname, "int", $localMPI, "int", $protocol, "int", $speed)
    If @error Then Return SetError(1,@error,0)
    Return $di[0]
EndFunc

Func _daveInitAdapter($di)
    Local $ret = DllCall($hDLL_LibNoDave, "int", "daveInitAdapter", "ptr", $di)
	Return $ret[0]
EndFunc

Func _daveNewConnection($di, $iSlot = 2, $iMPI_Address = 2, $iRack = 0)
    Local $ret = DllCall($hDLL_LibNoDave, "ptr", "daveNewConnection", "ptr", $di, "int", $iMPI_Address, "int", $iRack, "int", $iSlot)
	Return $ret[0]	
EndFunc

Func _daveConnectPLC($dc)
    Local $ret = DllCall($hDLL_LibNoDave, "int", "daveConnectPLC", "ptr", $dc)
	Return $ret[0]	
EndFunc

Func _daveDisconnectPLC($dc)
    Local $ret = DllCall($hDLL_LibNoDave, "int", "daveDisconnectPLC", "ptr", $dc)
	Return $ret[0]	
EndFunc

Func _daveDisconnectAdapter($di)
    Local $ret = DllCall($hDLL_LibNoDave, "int", "daveDisconnectAdapter", "ptr", $di)
	Return $ret[0]
EndFunc

Func _setTimeOut($di, $iTime)
    DllCall($hDLL_LibNoDave, "none", "setTimeOut", "ptr", $di, "int", $iTime)
EndFunc

Func _daveReadSZL(ByRef $dc, $iID = 0, $iIndex = 0, $iAnzahl = 1000)
	Local $Buffer = DLLStructCreate("byte buffer["&$iAnzahl&"]"), $Werte[$iAnzahl]
	$aRet = DllCall($hDLL_LibNoDave, "int", "daveReadSZL", "ptr", $dc, "int", $iID, "int", $iIndex, "ptr", DllStructGetPtr($Buffer, 'buffer'), "int", $iAnzahl)
	For $i = 1 To $iAnzahl
		$Werte[$i-1] = DllStructGetData($Buffer, 'buffer', $i)
	Next
	Return $Werte
EndFunc

Func _daveGetCycleTimeMin(ByRef $dc)
	Local $aInfo = _daveReadSZL($dc, 0x222, 1, 20)
	Return BitShift($aInfo[16], -8) +  $aInfo[17]
EndFunc

Func _daveGetCycleTimeMax(ByRef $dc)
	Local $aInfo = _daveReadSZL($dc, 0x222, 1, 20)
	Return BitShift($aInfo[18], -8) +  $aInfo[19]
EndFunc

Func _daveGetCycleTime(ByRef $dc)
	Local $aInfo = _daveReadSZL($dc, 0x222, 1, 20)
	Return BitShift($aInfo[14], -8) +  $aInfo[15]
EndFunc

Func _daveGetCycleTimeLimit(ByRef $dc)
	Local $aInfo = _daveReadSZL($dc, 0x222, 80, 20)
	Return BitShift($aInfo[18], -8) +  $aInfo[19]
EndFunc

Func _daveGetBlockInfo(ByRef $dc, $type, $iNumber)
	Local $db_info = DllStructCreate($_daveBlockInfo)
	Local $p_dbi = DllStructGetPtr($db_info)
	$aRet = DllCall($hDLL_LibNoDave, "int", "daveGetBlockInfo", "ptr", $dc, "ptr", $p_dbi, "byte", $type, "int", $iNumber)
	Return SetError(@error, $aRet[0], DllStructGetData($db_info, "length"))
EndFunc

Func _daveReadBytes(ByRef $dc, $iArea, $iDB, $iStart, $iLen)
	;reads max. 224 Bytes!!	<-- PDU from CPU 315 = 240 Bytes
	Local $LenCT = 1
	If $iArea = $daveCounter Or $iArea = $daveTimer Then $LenCT = 2
	Local $Buffer = DLLStructCreate("byte buffer["&$iLen * $LenCT&"]")
	$aRet = DllCall($hDLL_LibNoDave, "int", "daveReadBytes", "ptr", $dc, "int", $iArea, "int", $iDB, "int", $iStart, "int", $iLen, "ptr", DllStructGetPtr($Buffer, 'buffer'))
	Return $aRet[0]
EndFunc

Func _daveReadManyBytes(ByRef $dc, $iArea, $iDB, $iStart, $iLen)
	Local $LenCT = 1
	If $iArea = $daveCounter Or $iArea = $daveTimer Then $LenCT = 2
	Local $Buffer = DLLStructCreate("byte buffer["&$iLen * $LenCT&"]")
	$aRet = DllCall($hDLL_LibNoDave, "int", "daveReadManyBytes", "ptr", $dc, "int", $iArea, "int", $iDB, "int", $iStart, "int", $iLen, "ptr", DllStructGetPtr($Buffer, 'buffer'))
	Return $aRet[0]
EndFunc

Func _daveReadPEW(ByRef $dc, $iStart, $iCount)
	Local $aPEW[$iCount]
	Local $Res = _daveReadBytes($dc, $daveP, 0, $iStart, $iCount * 2)
	If $Res Then Return SetError(1)
	For $i = 0 To $iCount - 1
		$aPEW[$i] = _daveGetS16($dc)
	Next
	Return $aPEW
EndFunc

Func _daveReadBits(ByRef $dc, $iArea, $iDB, $iStart, $iLen)
	Local $Buffer = DLLStructCreate("BYTE buffer["&$iLen&"]")
	Local $aBits[$iLen]
	$aRet = DllCall($hDLL_LibNoDave, "int", "daveReadBits", "ptr", $dc, "int", $iArea, "int", $iDB, "int", $iStart, "int", $iLen, "ptr", DllStructGetPtr($Buffer, 'buffer'))
	For $i = 1 To $iLen
		$aBits[$i - 1] = DllStructGetData($Buffer, 1, $i)
	Next
	Return SetError($aRet[0], 0, $aBits)
EndFunc

Func _daveReadBit(ByRef $dc, $iArea, $iDB, $iByte, $iBit)
	Local $Buffer = DLLStructCreate("BYTE buffer[1]")
	$aRet = DllCall($hDLL_LibNoDave, "int", "daveReadBits", "ptr", $dc, "int", $iArea, "int", $iDB, "int", $iStart, "int", $iByte * 8 + 1, "ptr", DllStructGetPtr($Buffer, 'buffer'))
	Return DllStructGetData($Buffer, 1, 1)
EndFunc

Func _daveReadReal($dc, $iArea, $iDB, $iStart, $iLen)
	;reads max. 56 floats! --> 224 Bytes!!	<-- PDU from CPU 315 = 240 Bytes
	Local $Werte[$iLen]
	$aRet = DllCall($hDLL_LibNoDave, "int", "daveReadBytes", "ptr", $dc, "int", $iArea, "int", $iDB, "int", $iStart, "int", $iLen * 4, "ptr", 0)
	For $i = 1 To $iLen
		$Werte[$i-1] = _daveGetFloat($dc)
	Next
	Return SetError($aRet[0], 0, $Werte)
EndFunc

Func _daveReadManyReal($dc, $iArea, $iDB, $iStart, $iLen)
	Local $Werte[$iLen]
	$aRet = DllCall($hDLL_LibNoDave, "int", "daveReadManyBytes", "ptr", $dc, "int", $iArea, "int", $iDB, "int", $iStart, "int", $iLen * 4, "ptr", 0)
	For $i = 1 To $iLen
		$Werte[$i-1] = _daveGetFloat($dc)
	Next
	Return SetError($aRet[0], 0, $Werte)
EndFunc

Func _daveGetS8(ByRef $dc)
	$aRet = DllCall($hDLL_LibNoDave, "int", "daveGetS8", "ptr", $dc)
	Return $aRet[0]
EndFunc

Func _daveGetU8(ByRef $dc)
	$aRet = DllCall($hDLL_LibNoDave, "int", "daveGetU8", "ptr", $dc)
	Return $aRet[0]
EndFunc

Func _daveGetS16(ByRef $dc)
	$aRet = DllCall($hDLL_LibNoDave, "int", "daveGetS16", "ptr", $dc)
	Return $aRet[0]
EndFunc

Func _daveGetU16(ByRef $dc)
	$aRet = DllCall($hDLL_LibNoDave, "int", "daveGetU16", "ptr", $dc)
	Return $aRet[0]
EndFunc

Func _daveGetS32(ByRef $dc)
	$aRet = DllCall($hDLL_LibNoDave, "int", "daveGetS32", "ptr", $dc)
	Return $aRet[0]
EndFunc

Func _daveGetU32(ByRef $dc)
	$aRet = DllCall($hDLL_LibNoDave, "uint", "daveGetU32", "ptr", $dc)
	Return $aRet[0]
EndFunc

Func _daveGetFloat(ByRef $dc)
	$aRet = DllCall($hDLL_LibNoDave, "float", "daveGetFloat", "ptr", $dc)
	Return $aRet[0]
EndFunc

Func _daveGetS8from(ByRef $b)
	$aRet = DllCall($hDLL_LibNoDave, "int", "daveGetS8from", "ptr", $b)
	Return $aRet[0]
EndFunc

Func _daveGetU8from(ByRef $b)
	$aRet = DllCall($hDLL_LibNoDave, "int", "daveGetU8from", "ptr", $b)
	Return $aRet[0]
EndFunc

Func _daveGetS16from(ByRef $b)
	$aRet = DllCall($hDLL_LibNoDave, "int", "daveGetS16from", "ptr", $b)
	Return $aRet[0]
EndFunc

Func _daveGetU16from(ByRef $b)
	$aRet = DllCall($hDLL_LibNoDave, "int", "daveGetU16from", "ptr", $b)
	Return $aRet[0]
EndFunc

Func _daveGetS32from(ByRef $b)
	$aRet = DllCall($hDLL_LibNoDave, "int", "daveGetS32from", "ptr", $b)
	Return $aRet[0]
EndFunc

Func _daveGetU32from(ByRef $b)
	$aRet = DllCall($hDLL_LibNoDave, "uint", "daveGetU32from", "ptr", $b)
	Return $aRet[0]
EndFunc

Func _daveGetFloatfrom(ByRef $b)
	$aRet = DllCall($hDLL_LibNoDave, "float", "daveGetFloatfrom", "ptr", $b)
	Return $aRet[0]
EndFunc

Func _daveGetS8At(ByRef $dc, $iPos)
	$aRet = DllCall($hDLL_LibNoDave, "int", "daveGetS8At", "ptr", $dc, "int", $iPos)
	Return $aRet[0]
EndFunc

Func _daveGetU8At(ByRef $dc, $iPos)
	$aRet = DllCall($hDLL_LibNoDave, "int", "daveGetU8At", "ptr", $dc, "int", $iPos)
	Return $aRet[0]
EndFunc

Func _daveGetS16At(ByRef $dc, $iPos)
	$aRet = DllCall($hDLL_LibNoDave, "int", "daveGetS16At", "ptr", $dc, "int", $iPos)
	Return $aRet[0]
EndFunc

Func _daveGetU16At(ByRef $dc, $iPos)
	$aRet = DllCall($hDLL_LibNoDave, "int", "daveGetU16At", "ptr", $dc, "int", $iPos)
	Return $aRet[0]
EndFunc

Func _daveGetS32At(ByRef $dc, $iPos)
	Local $aRet = DllCall($hDLL_LibNoDave, "int", "daveGetS32At", "ptr", $dc, "int", $iPos)
	Return $aRet[0]
EndFunc

Func _daveGetU32At(ByRef $dc, $iPos)
	Local $aRet = DllCall($hDLL_LibNoDave, "uint", "daveGetU32At", "ptr", $dc, "int", $iPos)
	Return $aRet[0]
EndFunc

Func _daveGetFloatAt(ByRef $dc, $iPos)
	Local $aRet = DllCall($hDLL_LibNoDave, "float", "daveGetFloatAt", "ptr", $dc, "int", $iPos)
	Return $aRet[0]
EndFunc

Func _daveGetSeconds(ByRef $dc)
	Local $aRet = DllCall($hDLL_LibNoDave, "float", "daveGetSeconds", "ptr", $dc)
	Return $aRet[0]
EndFunc

Func _daveGetSecondsAt(ByRef $dc, $iPos)
	Local $aRet = DllCall($hDLL_LibNoDave, "float", "daveGetSecondsAt", "ptr", $dc, "int", $iPos)
	Return $aRet[0]
EndFunc

Func _daveGetCounterValue(ByRef $dc)
	Local $aRet = DllCall($hDLL_LibNoDave, "int", "daveGetCounterValue", "ptr", $dc)
	Return $aRet[0]
EndFunc

Func _daveGetCounterValueAt(ByRef $dc, $iPos)
	Local $aRet = DllCall($hDLL_LibNoDave, "int", "daveGetCounterValueAt", "ptr", $dc, "int", $iPos)
	Return $aRet[0]
EndFunc

Func _davePut8(ByRef $p, $Byte)
	Local $aRet = DllCall($hDLL_LibNoDave, "ptr", "davePut8", "ptr", $p, "int", $Byte)
	$p = $aRet[0]
EndFunc

Func _davePut16(ByRef $p, $Word)
	Local $aRet = DllCall($hDLL_LibNoDave, "ptr", "davePut16", "ptr", $p, "int", $Word)
	$p = $aRet[0]
EndFunc

Func _davePut32(ByRef $p, $DWord)
	Local $aRet = DllCall($hDLL_LibNoDave, "ptr", "davePut32", "ptr", $p, "int", $DWord)
	Return $aRet[0]
EndFunc

Func _davePutFloat(ByRef $p, $Float)
	Local $aRet = DllCall($hDLL_LibNoDave, "ptr", "davePutFloat", "ptr", $p, "float", $Float)
	$p = $aRet[0]
EndFunc

Func _davePutKG(ByRef $p, $KG)
	Local $aRet = DllCall($hDLL_LibNoDave, "ptr", "davePutKG", "ptr", $p, "float", $KG)
	Return $aRet[0]
EndFunc

Func _davePut8At(ByRef $p, $iPos, $Byte)
	Local $aRet = DllCall($hDLL_LibNoDave, "none", "davePut8At", "ptr", $p, "int", $iPos, "int", $Byte)
	Return $aRet[0]
EndFunc

Func _davePut16At(ByRef $p, $iPos, $Word)
	Local $aRet = DllCall($hDLL_LibNoDave, "none", "davePut16At", "ptr", $p, "int", $iPos, "int", $Word)
	Return $aRet[0]
EndFunc

Func _davePut32At(ByRef $p, $iPos, $DWord)
	Local $aRet = DllCall($hDLL_LibNoDave, "none", "davePut32At", "ptr", $p, "int", $iPos, "int", $DWord)
	Return $aRet[0]
EndFunc

Func _davePutFloatAt(ByRef $p, $iPos, $Float)
	Local $aRet = DllCall($hDLL_LibNoDave, "none", "davePutFloatAt", "ptr", $p, "int", $iPos, "float", $Float)
	Return $aRet[0]
EndFunc

Func _davePutKGAt(ByRef $p, $iPos, $KG)
	Local $aRet = DllCall($hDLL_LibNoDave, "none", "davePutKGAt", "ptr", $p, "int", $iPos, "float", $KG)
	Return $aRet[0]
EndFunc

Func _daveWriteBytes(ByRef $dc, $iArea, $iDB, $iStart, $iLen, $buf)
	DllCall($hDLL_LibNoDave, "int", "daveWriteBytes", "ptr", $dc, "int", $iArea, "int", $iDB, "int", $iStart, "int", $iLen, "ptr", DllStructGetPtr($buf))
EndFunc

Func _daveWriteBits(ByRef $dc, $iArea, $iDB, $iByte, $iBit, $Value)
	Local $Buf = DllStructCreate("byte")
	DllStructSetData($Buf, 1, $Value)
	DllCall($hDLL_LibNoDave, "int", "daveWriteBits", "ptr", $dc, "int", $iArea, "int", $iDB, "int", $iByte*8+$iBit, "int", 1, "ptr", DllStructGetPtr($Buf))
EndFunc

Func _daveSetBit(ByRef $dc, $iArea, $iDB, $iByte, $iBit)
	DllCall($hDLL_LibNoDave, "int", "daveSetBit", "ptr", $dc, "int", $iArea, "int", $iDB, "int", $iByte, "int", $iBit)
EndFunc

Func _daveClrBit(ByRef $dc, $iArea, $iDB, $iByte, $iBit)
	DllCall($hDLL_LibNoDave, "int", "daveClrBit", "ptr", $dc, "int", $iArea, "int", $iDB, "int", $iByte, "int", $iBit)
EndFunc

Func _daveGetMPIAdr(ByRef $dc)
	Local $aRet = DllCall($hDLL_LibNoDave, "int", "daveGetMPIAdr", "ptr", $dc)
	Return $aRet[0]
EndFunc

Func _daveGetAnswLen(ByRef $dc)
	Local $aRet = DllCall($hDLL_LibNoDave, "int", "daveGetAnswLen", "ptr", $dc)
	Return $aRet[0]
EndFunc

Func _daveGetMaxPDULen(ByRef $dc)
	Local $aRet = DllCall($hDLL_LibNoDave, "int", "daveGetMaxPDULen", "ptr", $dc)
	Return $aRet[0]
EndFunc

Func _daveStart(ByRef $dc)
	Local $aRet = DllCall($hDLL_LibNoDave, "int", "daveStart", "ptr", $dc)
	Return $aRet[0]
EndFunc

Func _daveStop(ByRef $dc)
	Local $aRet = DllCall($hDLL_LibNoDave, "int", "daveStop", "ptr", $dc)
	Return $aRet[0]
EndFunc

Func _daveCopyRAMtoROM(ByRef $dc)
	Local $aRet = DllCall($hDLL_LibNoDave, "int", "daveCopyRAMtoROM", "ptr", $dc)
	Return $aRet[0]
EndFunc

Func _daveFromBCD($int)
	Local $aRet = DllCall($hDLL_LibNoDave, "byte", "daveFromBCD", "byte", $int)
	Return $aRet[0]
EndFunc

Func _daveToBCD($int)
	Local $aRet = DllCall($hDLL_LibNoDave, "byte", "daveToBCD", "byte", $int)
	Return $aRet[0]
EndFunc

Func _daveSetPLCTimeToSystime(ByRef $dc)
	Local $aRet = DllCall($hDLL_LibNoDave, "int", "daveSetPLCTimeToSystime", "ptr", $dc)
	Return $aRet[0]
EndFunc

Func _daveGetResponse(ByRef $dc)
	Local $aRet = DllCall($hDLL_LibNoDave, "int", "daveGetResponse", "ptr", $dc)
	Return $aRet[0]
EndFunc

Func _davePrepareReadRequest(ByRef $dc, ByRef $p)
	DllCall($hDLL_LibNoDave, "none", "davePrepareReadRequest", "ptr", $dc, "ptr", $p)
EndFunc

Func _daveAddVarToReadRequest(ByRef $p, $iArea, $iDB, $iStart, $iLen)
	DllCall($hDLL_LibNoDave, "none", "daveAddVarToReadRequest", "ptr", $p, "int", $iArea, "int", $iDB, "int", $iStart, "int", $iLen)
EndFunc

Func _daveExecReadRequest(ByRef $dc, ByRef $p, ByRef $res)
	Local $aRet = DllCall($hDLL_LibNoDave, "int", "daveExecReadRequest", "ptr", $dc, "ptr", $p, "ptr", $res)
	Return $aRet[0]
EndFunc

Func _daveUseResult(ByRef $dc, ByRef $rs, $n)
	Local $aRet = DllCall($hDLL_LibNoDave, "int", "daveUseResult", "ptr", $dc, "ptr", $rs, "int", $n)
	Return $aRet[0]
EndFunc

Func _daveFreeResults(ByRef $rs)
	DllCall($hDLL_LibNoDave, "none", "daveFreeResults", "ptr", $rs)
EndFunc

Func _daveAddBitVarToReadRequest(ByRef $p, $iArea, $iDB, $iStart, $iLen)
	DllCall($hDLL_LibNoDave, "none", "daveAddBitVarToReadRequest", "ptr", $p, "int", $iArea, "int", $iDB, "int", $iStart, "int", $iLen)
EndFunc

Func _davePrepareMultipleRead(ByRef $dc, ByRef $a_p, $aResList)
	_davePrepareReadRequest($dc, $a_p[0])
	For $i = 0 To UBound($aResList, 1) -1
		_daveAddVarToReadRequest($a_p[0], $aResList[$i][0], $aResList[$i][1], $aResList[$i][2], $aResList[$i][3])	
	Next
EndFunc

Func _daveMultipleRead(ByRef $dc, ByRef $a_p, $aResList)
	Local $iUbound = _daveGetResultSum($aResList)
	Local $iRes = @extended
	Local $ByteArray[$iUbound], $n = 0
	Local $err = _daveExecReadRequest($dc, $a_p[0], $a_p[1])
	If $err Then
		ConsoleWrite("daveExecReadRequest: - " & _daveStrerror($err) & @cr)
		Return SetError(1)
	EndIf
	For $i = 0 To UBound($aResList, 1) -1
		$err = _daveUseResult($dc, $a_p[1], $i)
		For $j = 0 To ($aResList[$i][3] - 1) / $aResList[$i][5]
			$ByteArray[$n] = Call("_daveGet" & $aResList[$i][4], $dc)
			$n += 1
		Next
	Next
	 _daveFreeResults($a_p[1])
	 Return $ByteArray
EndFunc

Func _daveReadMultiple(ByRef $dc, $aResList)
	Local $pdu1 = DllStructCreate($_PDU)
	Local $rs1 = DllStructCreate($_devaResultSet)
	Local $a_p[2] = [DllStructGetPtr($pdu1), DllStructGetPtr($rs1)]
	_davePrepareReadRequest($dc, $a_p[0])
	For $i = 0 To UBound($aResList, 1) -1
		_daveAddVarToReadRequest($a_p[0], $aResList[$i][0], $aResList[$i][1], $aResList[$i][2], $aResList[$i][3])
	Next
	Local $iUbound = _daveGetResultSum($aResList)
	Local $iRes = @extended
	Local $ByteArray[$iUbound], $n = 0
	Local $err = _daveExecReadRequest($dc, $a_p[0], $a_p[1])
	If $err Then
		ConsoleWrite("daveExecReadRequest: - " & _daveStrerror($err) & @cr)
		Return SetError(1)
	EndIf
	For $i = 0 To UBound($aResList, 1) -1
		$err = _daveUseResult($dc, $a_p[1], $i)
		For $j = 0 To ($aResList[$i][3] - 1) / $aResList[$i][5]
			$ByteArray[$n] = Call("_daveGet" & $aResList[$i][4], $dc)
			$n += 1
		Next
	Next
	 _daveFreeResults($a_p[1])
	 Return $ByteArray
EndFunc

Func _daveGetResultSum($a)
	Local $Sum = 0, $SumExt = 0
	For $i = 0 To UBound($a) - 1
			$Sum += $a[$i][3] / $a[$i][5]
			$SumExt += $a[$i][3]
	Next
	Return SetExtended($SumExt, $Sum)
EndFunc

Func _daveReadPLCTime(ByRef $dc)
	Local $aRet = DllCall($hDLL_LibNoDave, "int", "daveReadPLCTime", "ptr", $dc)
	If $aRet[0] <> 0 Then Return SetError(1)
	Local $aTime[10]
	For $i = 0 To 9
		$aTime[$i] = _daveFromBCD(_daveGetU8($dc))
	Next
	Return $aTime
EndFunc

#cs
Byte 0: ist wohl Reserve
Byte 1: ist wohl immer &h19
Byte 1, Jahreszahl von 90 ...89, d.h. die Jahre von 1990 bis 2089
Byte 3: Monat
Byte 4: Tag
Byte 5: Stunde
Byte 6: Minute
Byte 7: Sekunde
Byte 8: Hunderter und Zehner der Millisekunden
Byte 9: oberes Nibbel: Einer der Millisekunden
unteres Nibbel: Wochentag 1 ... 7 (1=Sonntag)
#ce

Func _daveGetPLCTimeString(ByRef $dc)
	Local $aTime = _daveReadPLCTime($dc)
	Local $sTime, $Year, $WDay
	If $aTime[2] > 89 Then
		$Year = "19" & $aTime[2]
	Else
		$Year = "20" & $aTime[2]
	EndIf
	Local $iHelper = $aTime[8] * 100 + $aTime[9]
	$WDay = _Locale_DayName(Mod($iHelper, 10) - 1)
	Return StringFormat("%s, %02s.%02s.%04s %02s:%02s:%02s.%03s", $WDay, $aTime[4], $aTime[3], $Year, $aTime[5], $aTime[6], $aTime[7], Floor($iHelper / 10))
EndFunc

Func _daveListBlocks(ByRef $dc)
	Local $tStruct = "byte[2];ushort;byte[2];ushort;byte[2];ushort;byte[2];ushort;byte[2];ushort;byte[2];ushort;byte[2];ushort"
	Local $dbte = DllStructCreate($tStruct)
	Local $p_dbte = DllStructGetPtr($dbte)
	
	DllCall($hDLL_LibNoDave, "int", "daveListBlocks", "ptr", $dc, "ptr", $p_dbte)
	
	Local $aRes[7][2]
	For $i = 0 To 6
		$aRes[$i][0] = DllStructGetData($dbte, 2*$i + 1, 2)
		$aRes[$i][1] = DllStructGetData($dbte, 2*$i + 2)
	Next
	Return $aRes
EndFunc

#cs
Das zweite Byte ist die Sprache des Bausteins:

0x00, "Not defined"
0x01, "AWL"
0x02, "KOP"
0x03, "FUP"
0x04, "SCL"
0x05, "DB"
0x06, "GRAPH" 
#ce

Func _daveListBlocksOfType(ByRef $dc, $type)
	Local $MaxBlockNumber = _daveGetMaxBlockNumber($dc, $type)
	Local $aStruct = "byte type["&4*$MaxBlockNumber&"]"
	Local $dbe = DllStructCreate($aStruct)
	;Es wird ein Array des Structs erwartet!
	Local $p_dbe = DllStructGetPtr($dbe)
	Local $aRet = DllCall($hDLL_LibNoDave, "int", "daveListBlocksOfType", "ptr", $dc, "byte", $type, "ptr", $p_dbe)

	Local $aRes[$MaxBlockNumber][2]
	For $i = 0 To $MaxBlockNumber - 1
		$aRes[$i][0] = BitShift(DllStructGetData($dbe, "type", 4*$i+2), -8) +  DllStructGetData($dbe, "type", 4*$i+1)
;~ 		$aRes[$i][1] = DllStructGetData($dbe, "type", 4*$i+3)
		$aRes[$i][1] = DllStructGetData($dbe, "type", 4*$i+4)
	Next
	Return $aRes
EndFunc

Func _daveGetMaxBlockNumber(ByRef $dc, $type)
	Local $aList = _daveListBlocks($dc)
	For $i = 0 To UBound($aList, 1)
		If $aList[$i][0] = $type Then Return $aList[$i][1]
	Next
	Return SetError(1)
EndFunc

Func _daveBlockName($bn)
	Local $aRet = DllCall($hDLL_LibNoDave, "str", "daveBlockName", "byte", $bn)
	Return $aRet[0]
EndFunc

Func _daveAreaName($n)
	Local $aRet = DllCall($hDLL_LibNoDave, "str", "daveAreaName", "byte", $n)
	Return $aRet[0]
EndFunc

;#############################################################################
; internal functions
Func _GetHwndFromPID($PID = @AutoItPID)
    Local $hWnd = 0, $stPID = DllStructCreate("int")
	Local $winlist = WinList()
	For $i = 1 To $winlist[0][0]
		If $winlist[$i][0] <> "" Then
			DllCall("user32.dll", "int", "GetWindowThreadProcessId", "hwnd", $winlist[$i][1], "ptr", DllStructGetPtr($stPID))
			If DllStructGetData($stPID, 1) = $PID Then
				$hWnd = $winlist[$i][1]
				ExitLoop
			EndIf
		EndIf
	Next
    Return $hWnd
EndFunc ;==>_GetHwndFromPID

Func _Locale_DayName($WDay, $Abbrev = False)
    Local Const $LOCALE_USER_DEFAULT = 0x0400
    Local Const $LOCALE_SDAYNAME = 0x29
    Local Const $LOCALE_SABBREVDAYNAME = 0x30
    Local $LCType = $LOCALE_SDAYNAME
    If $Abbrev Then $LCType = $LOCALE_SABBREVDAYNAME
    If Not StringIsInt($WDay) Or $WDay < 1 Or $WDay > 7 Then Return False
    Local $aResult = DllCall("Kernel32.dll", "Int", "GetLocaleInfoA", _
                            "UInt", $LOCALE_USER_DEFAULT, _
                            "UInt", $LCType + $WDay, _
                            "Str", "", _
                            "Int", 80)
    If @error Or $aResult[0] = 0 Then Return False
    Return $aResult[3]
EndFunc

Func _StructArrayToArray($tStruct, $Teiler = 4, $MaxLen = 0)
	Local $Len = $MaxLen
	If $MaxLen = 0 Then $Len = DllStructGetSize($tStruct) / $Teiler
	Local $array[$Len]
	For $i = 1 To $Len
		$array[$i - 1] = DllStructGetData($tStruct, 1, $i)
	Next
	Return $array
EndFunc

;#############################################################################
; noch nicht fertige und nicht richtig funktionierende Funktionen

Func _initUpload($dc, $BlockType, $BlockNumber)
	Local $UploadID = DllStructCreate("int"), $p_UploadID = DllStructGetPtr($UploadID)
	Local $aRet = DllCall($hDLL_LibNoDave, "int", "initUpload", "ptr", $dc, "byte", $BlockType, "int", $BlockNumber, "ptr", $p_UploadID)
	Return SetError($aRet[0], 0, DllStructGetData($UploadID, 1))
EndFunc

Func _doUpload($dc, ByRef $p_Buffer, $UploadID)
	Local $More = DllStructCreate("int"), $p_More = DllStructGetPtr($More)
	Local $Len = DllStructCreate("int"), $p_Len = DllStructGetPtr($Len)
	
	Local $aRet = DllCall($hDLL_LibNoDave, "int", "doUpload", "ptr", $dc, "ptr", $p_More, "ptr", $p_Buffer, "ptr", $p_Len, "int", $UploadID)
	Return SetError($aRet[0], DllStructGetData($More, 1), DllStructGetData($Len, 1))
EndFunc

Func _endUpload($dc, $UploadID)
	Local $aRet = DllCall($hDLL_LibNoDave, "int", "endUpload", "ptr", $dc, "int", $UploadID)
	Return SetError($aRet[0], 0, $aRet[0])
EndFunc

Func _readProgramBlockDummy(ByRef $dc, $BlockType, $BlockNumber)
	Local $bb = DllStructCreate("byte[20000]"), $p_bb = DllStructGetPtr($bb)
	$ID = _initUpload($dc, $BlockType, $BlockNumber)
	Local $Size = 0
	Do
		$Size += _doUpload($dc, $p_bb, $ID)
	Until @extended = 0
	_endUpload($dc, $ID)
	Local $aBlock = _daveGetProgramBlock($dc, $BlockType, $BlockNumber, $Size)
	Return $aBlock
EndFunc


Func _readProgramBlock(ByRef $dc, $BlockType, $BlockNumber)
	Local $bb = DllStructCreate("byte[20000]"), $p_bb = DllStructGetPtr($bb)
	$ID = _initUpload($dc, $BlockType, $BlockNumber)
	Local $Buffer = DllStructCreate("byte[20000]"), $p_Buffer = DllStructGetPtr($Buffer)
	Local $Size = 0, $Size_now = 0, $aBuffer[1], $extended_save
	Do
		$Size_now = _doUpload($dc, $p_bb, $ID)
		$extended_save = @extended
		$Size += $Size_now
		ReDim $aBuffer[$Size]
		ConsoleWrite($Size & " / " & $Size_now & @cr)
		For $i = 1 To $Size_now
;~ 			$aBuffer[$Size - $Size_now + $i - 1] = Hex(DllStructGetData($Buffer, 1, $i), 2)
			$aBuffer[$Size - $Size_now + $i - 1] = DllStructGetData($bb, 1, $i)
		Next
		
;~ 		ConsoleWrite($Count & @cr)
;~ 		$Count += 1
		
	Until $extended_save = 0
	
	_endUpload($dc, $ID)
	
	ConsoleWrite($Size & @cr)

;~ 	Local $aBuffer[$Size], $sBuffer
;~ 	For $i = 1 To $Size
;~ 		$aBuffer[$i - 1] = Hex(DllStructGetData($Buffer, 1, $i), 2)
;~ 		$sBuffer &= $aBuffer[$i - 1]
;~ 	Next
	Return $aBuffer
EndFunc


Func _daveGetProgramBlock(ByRef $dc, $BlockType, $BlockNumber, $Len)
	Local $Buffer = DllStructCreate("byte["&$Len&"]"), $Length = DllStructCreate("int")
	Local $p_Buffer = DllStructGetPtr($Buffer), $p_Length = DllStructGetPtr($Length)
	Local $aRet = DllCall($hDLL_LibNoDave, "int", "daveGetProgramBlock", "ptr", $dc, "int", $BlockType, "int", $BlockNumber, "ptr", $p_Buffer, "ptr", $p_Length)
;~ 	ConsoleWrite($aRet[0] & @cr)
;~ Local $Size = DllStructGetData($Length, 1)
	Local $aBuffer[$Len], $sBuffer
	For $i = 1 To $Len
		$aBuffer[$i - 1] = BinaryToString("0x" & Hex(DllStructGetData($Buffer, 1, $i), 2))
		$sBuffer &= $aBuffer[$i - 1]
	Next
	Return $aBuffer
EndFunc


#cs

;    PLC program read functions:

EXPORTSPEC int DECL2 initUpload(daveConnection * dc, char blockType, int blockNr, int * uploadID); // char or uc,to decide
EXPORTSPEC int DECL2 doUpload(daveConnection*dc, int * more, uc**buffer, int*len, int uploadID);
EXPORTSPEC int DECL2 endUpload(daveConnection*dc, int uploadID);


;    Functions to load blocks from PLC:

EXPORTSPEC void DECL2 _daveConstructUpload(PDU *p, char blockType, int blockNr); // char or uc,to decide
EXPORTSPEC void DECL2 _daveConstructDoUpload(PDU * p, int uploadID);
EXPORTSPEC void DECL2 _daveConstructEndUpload(PDU * p, int uploadID);

;	Program Block from PLC:

EXPORTSPEC int DECL2 daveGetProgramBlock(daveConnection * dc, int blockType, int number, char* buffer, int * length);

#ce

;#############################################################################


