/*
"Glue" to allow the Velleman P8055 pcb to be used from Gamemaker.
Wrappers are provided for all functions so all parameters are of type "double".
Note that currently ReadAllAnalog combines the two bytes as two 16 bit values,
Channel1 is high word and Channel2 is low word before returning them in "double"
(floating point) form. 16 bits are returned to allow for future versions with 10
or 12 bit analog.
Also note that the Version function will "block" if called from GM and that the old OpenDevice
method of initialisation and the newer SearchDevices/SetCurrentDevice methods are incompatible.
Attempting to call SetCurrentDevice after OpenDevice has been used will fail and vice-versa.
SearchDevices,SetCurrentDevice and Version are not implemented in early versions
of the K8055D DLL. To avoid dependancy issues this DLL soft-links those functions
so they can be used if available but a program can still function if they are missing.
They return -1 if unimplemented, except for SetCurrentDevice which is converted to OpenDevice
if unavailable. This means that if you don't bother to test for -1
your program will detect all cards present on an old K8055D.DLL version
*/
#include <stdio.h>
#include <windows.h>
#ifdef __cplusplus
extern "C" {
#endif
#define FUNCTION __declspec(dllimport)
FUNCTION long __syscall OpenDevice(long CardAddress);
FUNCTION void __syscall CloseDevice(void);
FUNCTION long __syscall ReadAnalogChannel(long Channel);
FUNCTION void __syscall ReadAllAnalog(long *Data1, long *Data2);
FUNCTION void __syscall OutputAnalogChannel(long Channel, long Data);
FUNCTION void __syscall OutputAllAnalog(long Data1, long Data2);
FUNCTION void __syscall ClearAnalogChannel(long Channel);
FUNCTION void __syscall ClearAllAnalog();
FUNCTION void __syscall SetAnalogChannel(long Channel);
FUNCTION void __syscall SetAllAnalog();
FUNCTION void __syscall WriteAllDigital(long Data);
FUNCTION void __syscall ClearDigitalChannel(long Channel);
FUNCTION void __syscall ClearAllDigital();
FUNCTION void __syscall SetDigitalChannel(long Channel);
FUNCTION void __syscall SetAllDigital();
FUNCTION int __syscall ReadDigitalChannel(long Channel);
FUNCTION long __syscall ReadAllDigital();
FUNCTION long __syscall ReadCounter(long CounterNr);
FUNCTION void __syscall ResetCounter(long CounterNr);
FUNCTION void __syscall SetCounterDebounceTime(long CounterNr, long DebounceTime);
#ifdef __cplusplus
}
#endif
#if defined(__cplusplus)
#define EXTERNC extern "C"
#else
#define EXTERNC
#endif
DWORD TlsIndex; /* Global Thread Local Storage index */
HINSTANCE K8055DLib = NULL;
long (__stdcall *SearchDevices)(void) = NULL;
long (__stdcall *SetCurrentDevice)(long Address) = NULL;
void (__stdcall *Version)(void) = NULL;
/* Error checking should be performed in following code */
BOOL APIENTRY LibMain( HANDLE hinstDLL,
DWORD fdwReason,
LPVOID lpvReserved )
{
switch( fdwReason ) {
case DLL_PROCESS_ATTACH:
/* do process initialization */
/* create soft links */
K8055DLib = LoadLibrary("K8055D.dll");
if (K8055DLib)
{
SearchDevices = (long (__stdcall *) (void))GetProcAddress(K8055DLib, "SearchDevices");
SetCurrentDevice = (long (__stdcall *) (long))GetProcAddress(K8055DLib, "SetCurrentDevice");
Version = (void (__stdcall *) (void))GetProcAddress(K8055DLib, "Version");
}
/* create TLS index */
TlsIndex = TlsAlloc();
break;
case DLL_THREAD_ATTACH:
/* do thread initialization */
/* allocate private storage for thread */
/* and save pointer to it */
TlsSetValue( TlsIndex, malloc(200) );
break;
case DLL_THREAD_DETACH:
/* do thread cleanup */
/* get the TLS value and free associated memory */
free( TlsGetValue( TlsIndex ) );
break;
case DLL_PROCESS_DETACH:
/* do process cleanup */
if (K8055DLib)
FreeLibrary(K8055DLib);
/* free TLS index */
TlsFree( TlsIndex );
break;
}
return( 1 ); /* indicate success */
/* returning 0 indicates initialization failure */
}
EXTERNC double __syscall GM_OpenDevice(double CardAddress)
{
return OpenDevice(CardAddress);
}
EXTERNC double __syscall GM_CloseDevice()
{
CloseDevice();
return 0;
}
EXTERNC double __syscall GM_ReadAnalogChannel(double Channel)
{
return ReadAnalogChannel(Channel);
}
EXTERNC double __syscall GM_ReadAllAnalog()
{
long iData1,iData2;
ReadAllAnalog(&iData1,&iData2);
return ((iData1 & 0xFFFF) << 16 )|( iData2 & 0xFFFF);
}
EXTERNC double __syscall GM_OutputAnalogChannel(double Channel, double Data)
{
OutputAnalogChannel(Channel, Data);
return 0;
}
EXTERNC double __syscall GM_OutputAllAnalog(double Data1, double Data2)
{
OutputAllAnalog(Data1, Data2);
return 0;
}
EXTERNC double __syscall GM_ClearAnalogChannel(double Channel)
{
ClearAnalogChannel(Channel);
return 0;
}
EXTERNC double __syscall GM_ClearAllAnalog()
{
ClearAllAnalog();
return 0;
}
EXTERNC double __syscall GM_SetAnalogChannel(double Channel)
{
SetAnalogChannel(Channel);
return 0;
}
EXTERNC double __syscall GM_SetAllAnalog()
{
SetAllAnalog();
return 0;
}
EXTERNC double __syscall GM_WriteAllDigital(double Data)
{
WriteAllDigital(Data);
return 0;
}
EXTERNC double __syscall GM_ClearDigitalChannel(double Channel)
{
ClearDigitalChannel(Channel);
return 0;
}
EXTERNC double __syscall GM_ClearAllDigital()
{
ClearAllDigital();
return 0;
}
EXTERNC double __syscall GM_SetDigitalChannel(double Channel)
{
SetDigitalChannel(Channel);
return 0;
}
EXTERNC double __syscall GM_SetAllDigital()
{
SetAllDigital();
return 0;
}
EXTERNC double __syscall GM_ReadDigitalChannel(double Channel)
{
return ReadDigitalChannel(Channel);
}
EXTERNC double __syscall GM_ReadAllDigital()
{
return ReadAllDigital();
}
EXTERNC double __syscall GM_ReadCounter(double CounterNr)
{
return ReadCounter(CounterNr);
}
EXTERNC double __syscall GM_ResetCounter(double CounterNr)
{
ResetCounter(CounterNr);
return 0;
}
EXTERNC double __syscall GM_SetCounterDebounceTime(double CounterNr, double DebounceTime)
{
SetCounterDebounceTime(CounterNr,DebounceTime);
return 0;
}
EXTERNC double __syscall GM_SearchDevices()
{
if (SearchDevices != NULL)
{
return (*SearchDevices) ();
};
return -1;
}
EXTERNC double __syscall GM_SetCurrentDevice(double Address)
{
if (SetCurrentDevice != NULL)
{
return (*SetCurrentDevice) (Address);
};
return OpenDevice(Address);
}
EXTERNC double __syscall GM_Version()
{
if (Version != NULL)
{
(*Version) ();
return 0;
};
return -1;
}
|