Gamestudio Links
Zorro Links
Newest Posts
Blobsculptor tools and objects download here
by NeoDumont. 03/28/24 03:01
Issue with Multi-Core WFO Training
by aliswee. 03/24/24 20:20
Why Zorro supports up to 72 cores?
by Edgar_Herrera. 03/23/24 21:41
Zorro Trader GPT
by TipmyPip. 03/06/24 09:27
VSCode instead of SED
by 3run. 03/01/24 19:06
AUM Magazine
Latest Screens
The Bible Game
A psychological thriller game
SHADOW (2014)
DEAD TASTE
Who's Online Now
3 registered members (VoroneTZ, monk12, Quad), 829 guests, and 4 spiders.
Key: Admin, Global Mod, Mod
Newest Members
sakolin, rajesh7827, juergen_wue, NITRO_FOREVER, jack0roses
19043 Registered Users
Previous Thread
Next Thread
Print Thread
Rating: 5
Page 1 of 7 1 2 3 4 5 6 7
Serial Communications Header #280484
07/22/09 20:32
07/22/09 20:32
Joined: Feb 2008
Posts: 3,232
Australia
EvilSOB Offline OP
Expert
EvilSOB  Offline OP
Expert

Joined: Feb 2008
Posts: 3,232
Australia
Hi again.
Due to inspiration by The_Mehmaster, Ive decided to write a Serial Communications Suite.
It enables 3DGS to communicate via the SERIAL port (COMx) of the computer, like port_in & port_out does with the parallel port.
But Serial devices are easier to design (in my mind), much more common on "specialised" hardware than parallel, and more flexible.
Also, my code contains buffering of data on both READ and WRITE data-flow, so it needs less effort by your code than port_in/port_out.

Another thing to remember, this being a work in progress and all, THEORETICALLY, my code can be utilised to use many types of ports
at the same time, with the same code, the only difference being the parameters you call the port_open_xxxx with.
I am still investigating this, but theoretically, my code will be able to handle TCP ports, parallel ports, serial ports and possibly more.
But this investigation is on hold till this code is "finished" exclusivly for Serial-Ports.


Its still under development, but Im brain-fried for the night. So I'm putting this work-in-progress up for everyones scrutiny.

All the serial READing functions are fully functional, as are the WRITEing functions. (I'll be starting the the bi-directional port handling tomorrow)
[EDIT] The bi-directional communications appears to be working but still needs quality testing. (Ive updated the code-block below)

But both all three types are in need of further testing. Im hoping for you guys to help.
Im also looking for suggestions as to improvements/additions to make this header a more complete communications suite.
I know this tool is a bit of a "niche" product, but Im hoping it will get some interest.
The usage is modeled on 3DGS's way of handling files. There is plenty of included documentation so there shouldnt be a problem
for you to get it going. If the documentation is lacking, please let me know.

[EDIT]Thanks to the newbie "druid" spotting it, but there was a bug when trying to access serial ports with a number higher than 9.
This has now been fixed and the code in this post has been corrected.
No changes in usage are required, and only the "port_open_???" functions have been changed.


[EDIT] ALSO, if you have any code/implementation problems, let me know here, so all can see what is going on.
BUT, If you are connecting to external hardware (that ISNT a PC), please let me know of any Success/Fail/Wish stories via PM. Im VERY interested to hear about it.


Port_IO.H
Code:
#ifndef	port_io_h
#define	port_io_h
////
//
//////////////////////////////////////////////////////////////////////////////////////////
//																						//
//	File :	Port_IO.h																	//
//	Author:	EvilSOB 																	//
//	Date:	23/July/2009																//
//	Updated:23/May /2010	(Failing Com ports > 9 bug fixed)							//
//																						//
//	Requirements:	None	(except acknex.h or litec.h of course)						//
//																						//
//																						//
//======================================================================================//
//	USAGE Descriptions																	//
//======================================================================================//
//																						//
//	var port_open_read(char* portname, char* config);									//
//																						//
//--------------------------------------------------------------------------------------//
//																						//
//		Opens a communications port for reading.										//
//																						//
//--------------------------------------------------------------------------------------//
//																						//
//		Parameters:																		//
//			char*	portname = The windows name for the port. eg COM1. 	  (see NOTES#1)	//
//			char*	config	 = The serial port settings. eg "9600,n,8,1"  (see NOTES#2)	//
//																						//
//--------------------------------------------------------------------------------------//
//		Returns:																		//
//					NULL = Port could not be opened.									//
//					else = A VAR handle for the open port.								//
//																						//
//																						//
//																						//
//																						//
//======================================================================================//
//																						//
//	var port_open_write(char* portname, char* config);									//
//																						//
//--------------------------------------------------------------------------------------//
//																						//
//		Opens a communications port for writing.										//
//																						//
//--------------------------------------------------------------------------------------//
//																						//
//		Parameters:																		//
//			char*	portname = The windows name for the port. eg COM1. 	  (see NOTES#1)	//
//			char*	config	 = The serial port settings. eg "9600,n,8,1"  (see NOTES#2)	//
//																						//
//--------------------------------------------------------------------------------------//
//		Returns:																		//
//					NULL = Port could not be opened.									//
//					else = A VAR handle for the open port.								//
//																						//
//																						//
//																						//
//																						//
//======================================================================================//
//																						//
//	var port_open_readwrite(char* portname, char* config);								//
//																						//
//--------------------------------------------------------------------------------------//
//																						//
//		Opens a communications port for both reading and writing.						//
//																						//
//--------------------------------------------------------------------------------------//
//																						//
//		Parameters:																		//
//			char*	portname = The windows name for the port. eg COM1. 	  (see NOTES#1)	//
//			char*	config	 = The serial port settings. eg "9600,n,8,1"  (see NOTES#2)	//
//																						//
//--------------------------------------------------------------------------------------//
//		Returns:																		//
//					NULL = Port could not be opened.									//
//					else = A VAR handle for the open port.								//
//																						//
//																						//
//																						//
//																						//
//======================================================================================//
//																						//
//	void port_close(var port);															//
//																						//
//--------------------------------------------------------------------------------------//
//																						//
//		Closes a communications port that was previously opened for reading or writing.	//
//																						//
//--------------------------------------------------------------------------------------//
//																						//
//		Parameters:																		//
//			char*	port 	= The VAR handle of a previously opened communications port.//
//																						//
//--------------------------------------------------------------------------------------//
//		Returns:	NONE																//
//																						//
//																						//
//																						//
//																						//
//======================================================================================//
//																						//
//	var port_read_status(var port);														//
//																						//
//--------------------------------------------------------------------------------------//
//																						//
//		Checks the "IDLE" status of an open communications port.						//
//																						//
//--------------------------------------------------------------------------------------//
//																						//
//		Parameters:																		//
//			char*	port 	= The VAR handle of a previously opened communications port.//
//																						//
//--------------------------------------------------------------------------------------//
//		Returns:	TRUE   = Port is IDLE. Ready for read/write. (writing untested)		//
//					FALSE  = Port is BUSY. Waiting to Send, or Still Receiving.			//
//																						//
//																						//
//																						//
//																						//
//======================================================================================//
//																						//
//	var port_read_buffer_size(var port);												//
//																						//
//--------------------------------------------------------------------------------------//
//																						//
//		Checks how full the READ buffer is in bytes.									//
//																						//
//--------------------------------------------------------------------------------------//
//																						//
//		Parameters:																		//
//			char*	port 	= The VAR handle of a previously opened communications port.//
//																						//
//--------------------------------------------------------------------------------------//
//		Returns:	-1   = Port was opened for WRITE-ONLY.								//
//					else = Number of bytes in use.										//
//																						//
//																						//
//																						//
//																						//
//======================================================================================//
//	PORT READING FUNCTIONS																//
//======================================================================================//
//																						//
//	var port_read_bytes(var port, void* outdata, long bytes);							//
//																						//
//--------------------------------------------------------------------------------------//
//																						//
//		Reads a "block" of data into a buffer, to a maximum length of 'bytes'.			//
//																						//
//--------------------------------------------------------------------------------------//
//																						//
//		Parameters:																		//
//			char*	port 	= The VAR handle of a previously opened communications port.//
//			void*	outdata = A pointer to an output-buffer to store the data in.		//
//			long	bytes	= The maximum length of the output-buffer.					//
//																						//
//--------------------------------------------------------------------------------------//
//		Returns:	-1   = The port handle was invalid or the Port is WRITE-ONLY.		//
//					 0	 = There was NO data in the READ-buffer to retrieve.			//
//					else = The number of bytes retieved from the READ-buffer.			//
//																						//
//																						//
//																						//
//======================================================================================//
//																						//
//	var port_read_string(var port, STRING* outdata);									//
//																						//
//--------------------------------------------------------------------------------------//
//																						//
//		Reads a null-terminated string and overwrites the contents of 'outdata'.		//
//																						//
//--------------------------------------------------------------------------------------//
//																						//
//		Parameters:																		//
//			char*	port 	= The VAR handle of a previously opened communications port.//
//			void*	outdata = A pointer to valid STRING object to store the data in.	//
//																						//
//--------------------------------------------------------------------------------------//
//		Returns:	-1   = The port handle was invalid or the Port is WRITE-ONLY.		//
//					 0	 = There was NO data in the READ-buffer to retrieve.			//
//					else = The length of the retrieved string.							//
//																						//
//																						//
//																						//
//======================================================================================//
//																						//
//	var port_read_number(var port, DWORD* outdata);										//
//																						//
//--------------------------------------------------------------------------------------//
//																						//
//		Reads a 4-byte number (long,int,DWORD,var,float) and stores it at 'outdata'.	//
//																						//
//--------------------------------------------------------------------------------------//
//																						//
//		Parameters:																		//
//			char*	port 	= The VAR handle of a previously opened communications port.//
//			void*	outdata = A pointer to valid numeric object to store the data in.	//
//																						//
//--------------------------------------------------------------------------------------//
//		Returns:	-1   = The port handle was invalid or the Port is WRITE-ONLY.		//
//					 0	 = There was NO data in the READ-buffer to retrieve.			//
//					 4   = The length in bytes of the retrieved number.					//
//																						//
//																						//
//																						//
//======================================================================================//
//																						//
//	var port_read_double(var port, double* outdata);									//
//																						//
//--------------------------------------------------------------------------------------//
//																						//
//		Reads an 8-byte number (double)	and stores it at 'outdata'.						//
//																						//
//--------------------------------------------------------------------------------------//
//																						//
//		Parameters:																		//
//			char*	port 	= The VAR handle of a previously opened communications port.//
//			void*	outdata = A pointer to valid numeric object to store the data in.	//
//																						//
//--------------------------------------------------------------------------------------//
//		Returns:	-1   = The port handle was invalid or the Port is WRITE-ONLY.		//
//					 0	 = There was NO data in the READ-buffer to retrieve.			//
//					 8   = The length in bytes of the retrieved number.					//
//																						//
//																						//
//																						//
//======================================================================================//
//	PORT WRITING FUNCTIONS																//
//======================================================================================//
//																						//
//	var port_write_bytes(var port, void* data, long bytes, long ms_wait);				//
//																						//
//--------------------------------------------------------------------------------------//
//																						//
//		Writes a "block" of data from a buffer, for a length of 'bytes'.				//
//																						//
//--------------------------------------------------------------------------------------//
//																						//
//		Parameters:																		//
//			char*	port 	= The VAR handle of a previously opened communications port.//
//			void*	data 	= A pointer to an output-buffer to send the data in.		//
//			long	bytes	= The length in bytes of the output-buffer.					//
//			long	ms_wait	= The TIMEOUT period in milliseconds after which to abort.	//
//																						//
//--------------------------------------------------------------------------------------//
//		Returns:	 0   = The port handle was invalid or the Port is READ-ONLY.		//
//					 0	 = There 'data' buffer pointer is NULL.							//
//					< MAX_READ_BUFFER = The number of bytes INSTANTLY sent.				//
//					else = A spurious huge number because the send has been delayed.	//
//																						//
//																						//
//																						//
//======================================================================================//
//																						//
//	var port_write_string(var port, STRING* data, long ms_wait);						//
//																						//
//--------------------------------------------------------------------------------------//
//																						//
//		Writes a null-terminated string from the supplied STRING object.				//
//																						//
//--------------------------------------------------------------------------------------//
//																						//
//		Parameters:																		//
//			char*	port 	= The VAR handle of a previously opened communications port.//
//			void*	data 	= A pointer to valid STRING object to send the data from.	//
//			long	ms_wait	= The TIMEOUT period in milliseconds after which to abort.	//
//																						//
//--------------------------------------------------------------------------------------//
//		Returns:	 0   = The port handle was invalid or the Port is READ-ONLY.		//
//					 0	 = There 'data' buffer pointer is NULL.							//
//					< MAX_READ_BUFFER = The number of bytes INSTANTLY sent.				//
//					else = A spurious huge number because the send has been delayed.	//
//																						//
//																						//
//																						//
//======================================================================================//
//																						//
//	var port_write_number(var port, DWORD* data, long ms_wait);							//
//																						//
//--------------------------------------------------------------------------------------//
//																						//
//		Writes a 4-byte number (long,int,DWORD,var,float) pointed to by 'outdata'.		//
//																						//
//--------------------------------------------------------------------------------------//
//																						//
//		Parameters:																		//
//			char*	port 	= The VAR handle of a previously opened communications port.//
//			void*	data 	= A pointer to valid numeric object to send the data from.	//
//			long	ms_wait	= The TIMEOUT period in milliseconds after which to abort.	//
//																						//
//--------------------------------------------------------------------------------------//
//		Returns:	 0   = The port handle was invalid or the Port is READ-ONLY.		//
//					 0	 = There 'data' buffer pointer is NULL.							//
//					< MAX_READ_BUFFER = The number of bytes INSTANLT sent.				//
//					else = A spurious huge number because the send has been delayed.	//
//																						//
//																						//
//																						//
//======================================================================================//
//																						//
//	var port_write_double(var port, double* data, long ms_wait);						//
//																						//
//--------------------------------------------------------------------------------------//
//																						//
//		Writes an 8-byte number (double) pointed to by 'outdata'.						//
//																						//
//--------------------------------------------------------------------------------------//
//																						//
//		Parameters:																		//
//			char*	port 	= The VAR handle of a previously opened communications port.//
//			void*	data 	= A pointer to valid numeric object to send the data from.	//
//			long	ms_wait	= The TIMEOUT period in milliseconds after which to abort.	//
//																						//
//--------------------------------------------------------------------------------------//
//		Returns:	 0   = The port handle was invalid or the Port is READ-ONLY.		//
//					 0	 = There 'data' buffer pointer is NULL.							//
//					< MAX_READ_BUFFER = The number of bytes INSTANLT sent.				//
//					else = A spurious huge number because the send has been delayed.	//
//																						//
//																						//
//																						//
//======================================================================================//
//======================================================================================//
//																						//
//																						//
//======================================================================================//
//======================================================================================//
//																						//
//	NOTES#1	::	PORT Naming Convention	(from known and tested ports)					//
//		"COM1", "com1", "COM1:", "com1:"												//
//		"COM2", "com2", "COM2:", "com2:"												//
//		"COM3", "com3", "COM3:", "com3:"												//
//		"COM4", "com4", "COM4:", "com4:"												//
//																						//
//======================================================================================//
//======================================================================================//
//																						//
//	NOTES#2	::	SERIAL PORT SETTINGS - "WWWWW,X,Y,Z [,A]"	(eg "9600,n,8,1" )			//
//																						//
//	WWWWWW	= Baud Rate (110, 300, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200)	//
//	X		= Parity ( 'n' = None, 'o' = Odd, 'e' = Even, 'm' = Mark, 's' = Space )		//
//	Y		= Data Bits ( 5, 6, 7, 8 )													//
//	Z		= Stop Bits ( 1, 1.5, 2 )													//
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -//
//	A		= [ OPTIONAL ] Hardware Flow Control										//
//					no entry	= NONE	(default)		(eg "9600,n,8,1" )				//
//					,x			= Xon/Xoff				(eg "9600,n,8,1,x" )			//
//					,p			= Hardware				(eg "9600,n,8,1,p" )			//
//																						//
//	NOTE:: Option 'A' being other than default has not HARDWARE tested					//
//																						//
//======================================================================================//
//======================================================================================//
//																						//
//	NOTES#3 :: TWEAKABLES																//
//																						//
#define	MAX_PORTS		20		//Maximum number of open IO-Ports						//
#define	MAX_READ_BUFFER	10240	//Size (in bytes) in READ buffer/s	(10240 = 10kb)		//
//																						//
//																						//
//======================================================================================//
//======================================================================================//
//
//
//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
//	ANY CHANGES MADE FROM HERE ON IN ARE AT YOUR OWN RISK !  PROCEED WITH CAUTION !		//
//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
//
//
//
//////////////////////////////////////////////////////////////////////////////////////////
//	API linkages																		//
//////////////////////////////////////////////////////////////////////////////////////////
//																						//
long __stdcall _GetLastError();															//
#define PRAGMA_API _GetLastError;kernel32!GetLastError									//
//																						//
#ifndef windows_h																		//
//	long __stdcall GetCommState(long hFile, long lpDCB);								//
//	#define PRAGMA_API GetCommState;kernel32!GetCommState								//
	long __stdcall BuildCommDCB(char* lpDef, long lpDCB);								//
	#define PRAGMA_API BuildCommDCB;kernel32!BuildCommDCBA								//
	long __stdcall SetCommState(long hFile, long lpDCB);								//
	#define PRAGMA_API SetCommState;kernel32!SetCommState								//
	long __stdcall CreateFile(char*,long,long,long,long,long,long);						//
	#define PRAGMA_API CreateFile;kernel32!CreateFileA									//
	long __stdcall ReadFile(long,long,long,long,long);									//
	#define PRAGMA_API ReadFile;kernel32!ReadFile										//
	long __stdcall WriteFile(long,long,long,long,long);									//
	#define PRAGMA_API WriteFile;kernel32!WriteFile										//
	long __stdcall CreateEvent(long,long,long,char*);									//
	#define PRAGMA_API CreateEvent;kernel32!CreateEventA								//
	long __stdcall WaitForSingleObject(long,long);										//
	#define PRAGMA_API WaitForSingleObject;kernel32!WaitForSingleObject					//
	long __stdcall GetOverlappedResult(long,long,long,long);							//
	#define PRAGMA_API GetOverlappedResult;kernel32!GetOverlappedResult					//
	long __stdcall CloseHandle(long);													//
	#define PRAGMA_API CloseHandle;kernel32!CloseHandle									//
	long __stdcall FormatMessage(long,long,long,long,char,long,long);					//
	#define PRAGMA_API FormatMessage;kernel32!FormatMessageA							//
#endif	//windows_h																		//
//																						//
//																						//
//======================================================================================//
//======================================================================================//
//	Port Access WORKSPACE																//
//======================================================================================//
//																						//
long open_port[MAX_PORTS][3];															//
void open_port_startup()  {  var i;  for(i=0;i<MAX_PORTS;i++)  open_port[i][0]=0;  }	//
void port_read_worker(var);	//function prototype for PORT-READing worker 'thread'		//
//																						//
//////////////////////////////////////////////////////////////////////////////////////////
//
//
//
//////////////////////////////////////////////////////////////////////////////////////////
//																						//
//	PORT ACCESS FUNCTIONS																//
//																						//
//////////////////////////////////////////////////////////////////////////////////////////
//
var port_open_read(char* portname, char* config)
{	if((!portname)||(!config))	return(0);	//invalid (EMPTY) data pointer/s
	STRING* dev_name = str_create("\\\\.\\");	str_cat(dev_name, _str(portname));
	long *ols  = malloc(sizeof(long)*6);		memset(ols,0,sizeof(long)*6);
	long *dcb  = malloc(sizeof(long)*8);		memset(dcb,0,sizeof(long)*8);
	long *buff = malloc(MAX_READ_BUFFER);		memset(buff,0,MAX_READ_BUFFER);
	long port;		var s=0, i;	
	port = CreateFile(dev_name.chars, 0x80000000, 0,0, 0x3, 0x40000000, 0);
	str_remove(dev_name);
	if(port!=-1)
	{	if(BuildCommDCB( config, dcb))	//decode supplied port-config
		{	if(SetCommState(port, dcb))		//configure port to new config
			{	if(ols[4]=CreateEvent(NULL,true,false,NULL))
				{	for(i=1;i<MAX_PORTS;i++)  if(!open_port[i][0])  break;	
					if(i<MAX_PORTS)
					{	open_port[i][0] = port;
						open_port[i][1] = ols;
						open_port[i][2] = buff;
						ols[5]          = 0;
						port_read_worker(i);
						return(i);				//SUCCESS, return port-handle
		}	}	}	}
		CloseHandle(port);
	}
	free(dcb);				free(ols);
	return(s);	//file has NOT been opened.
}
//
void port_read_worker(var port)
{	if(!open_port[port][0])		return;		//ABORT - invalid handle
	long  rport = open_port[port][0];	
	long* ols   = (long*)open_port[port][1];	ols[5] = 0; //filled-to pos
	void* data  = (void*)open_port[port][2];
	long fWaitingonread=false;
	while(open_port[port][0])
	{	if(!fWaitingonread)
		{	if(!ReadFile(rport, (long)data+ols[5], MAX_READ_BUFFER-ols[5], NULL, ols))
			{	if(_GetLastError()==997)	fWaitingonread = true;	 }
			else	
			{	fWaitingonread = false;   ols[5] += ols[1];   }	//INSTANT-read succeeded
		}
		else
			if(!WaitForSingleObject(ols[4],0))
			{	fWaitingonread = false;   ols[5] += ols[1];   }	//DELAYED-read succeeded
		wait(1);
}	}
//
//
//
//////////////////////////////////////////////////////////////////////////////////////////
//
var port_read_status(var port)
{	if(!open_port[port][0])		return(0);	//invalid handle
	long* ols 	= (long*)open_port[port][1];	
	if(WaitForSingleObject(ols[4],1)==0x00000102)	return(1);		//port idle
	return(0);		//port busy
}
//
//
//
//////////////////////////////////////////////////////////////////////////////////////////
//
var port_read_buffer_size(var port)
{	if(!open_port[port][0])		return(0);	//invalid handle
	long* ols 	= (long*)open_port[port][1];	
	return(ols[5]);
}
//
//
//
//////////////////////////////////////////////////////////////////////////////////////////
//
var port_open_write(char* portname, char* config)
{	if((!portname)||(!config))	return(0);	//invalid (EMPTY) data pointer/s
	STRING* dev_name = str_create("\\\\.\\");	str_cat(dev_name, _str(portname));
	long *ols = malloc(sizeof(long)*5);		memset(ols,0,sizeof(long)*5);
	byte *dcb = malloc(sizeof(long)*8);		memset(dcb,0,sizeof(long)*8);
	long port;		var s=0, i;	
	port = CreateFile(dev_name.chars, 0x40000000, 0,0, 0x3, 0x40000000, 0);
	str_remove(dev_name);
	if(port!=-1)
	{	if(BuildCommDCB( config, dcb))	//decode supplied port-config
		{	if(SetCommState(port, dcb))		//configure port to new config
			{	if(ols[4]=CreateEvent(NULL,true,false,NULL))
				{	for(i=1;i<MAX_PORTS;i++)  if(!open_port[i][0])  break;	
					if(i<MAX_PORTS)
					{	open_port[i][0] = port;
						open_port[i][1] = ols;
						open_port[i][2] = NULL;
						ols[5]          = -1;
						return(i);			//SUCCESS, return port-handle
		}	}	}	}
		CloseHandle(port);
	}
	free(dcb);				free(ols);
	return(s);	//file has NOT been opened.
}
//
//
//////////////////////////////////////////////////////////////////////////////////////////
//
var port_open_readwrite(char* portname, char* config)
{	if((!portname)||(!config))	return(0);	//invalid (EMPTY) data pointer/s
	STRING* dev_name = str_create("\\\\.\\");	str_cat(dev_name, _str(portname));
	long *ols  = malloc(sizeof(long)*5);	memset(ols,0,sizeof(long)*5);
	byte *dcb  = malloc(sizeof(long)*8);	memset(dcb,0,sizeof(long)*8);
	long *buff = malloc(MAX_READ_BUFFER);	memset(buff,0,MAX_READ_BUFFER);
	long port;		var s=0, i;	
	port = CreateFile(dev_name.chars, 0xC0000000, 0,0, 0x3, 0x40000000, 0);
	str_remove(dev_name);
	if(port!=-1)
	{	if(BuildCommDCB( config, dcb))	//decode supplied port-config
		{	if(SetCommState(port, dcb))		//configure port to new config
			{	if(ols[4]=CreateEvent(NULL,true,false,NULL))
				{	for(i=1;i<MAX_PORTS;i++)  if(!open_port[i][0])  break;	
					if(i<MAX_PORTS)
					{	open_port[i][0] = port;
						open_port[i][1] = ols;
						open_port[i][2] = buff;
						ols[5]          = 0;
						port_read_worker(i);
						return(i);			//SUCCESS, return port-handle
		}	}	}	}
		CloseHandle(port);
	}
	free(dcb);				free(ols);
	return(s);	//file has NOT been opened.
}
//
//
//////////////////////////////////////////////////////////////////////////////////////////
//
void port_close(var port)
{	if(open_port[port][0])
	{	//only close ports if it is still open.
		long* ols = (long*)open_port[port][1];
		proc_mode = PROC_LATE;		wait(1);
		while(ols[1]<=0)	wait(1);	//wait till idle
		CloseHandle(open_port[port][1]);		//close event
		CloseHandle(open_port[port][0]);		//close port
		free(open_port[port][0]);
	}
	if(open_port[port][2])	free(open_port[port][2]);
	open_port[port][0] = open_port[port][1] = open_port[port][2] = NULL;
}
//
//
//
//
//////////////////////////////////////////////////////////////////////////////////////////
//	Start Port READING Functions														//
//////////////////////////////////////////////////////////////////////////////////////////
//
var port_read_bytes(var port, void* outdata, long bytes)
{	if(!open_port[port][0])		return(-1);	//invalid handle
	if(!outdata)				return(-1);	//invalid pointer to buffer
	long* ols   = (long*)open_port[port][1];
	if(!ols[5])					return(0);	//No data to retrieve, buffer EMPTY
	if(bytes>ols[5])			bytes = ols[5];
	byte* data  = (byte*)open_port[port][2];
	long i;   for(i=0;i<bytes;i++)	if(i<MAX_READ_BUFFER)   ((byte*)outdata)[i]=data[i];
	for(i=0; i<(ols[5]-bytes); i++)		data[i] = data[i+bytes];		ols[5] -= bytes;
	for(i=ols[5]; i<MAX_READ_BUFFER; i++)		data[i] = 0;
	return(bytes);
}
//
//
//////////////////////////////////////////////////////////////////////////////////////////
//
var port_read_string(var port, STRING* outdata)
{	if(!open_port[port][0])		return(-1);	//invalid handle
	if(!outdata)				return(-1);	//invalid pointer to buffer
	long* ols   = (long*)open_port[port][1];	
	if(!ols[5])					return(0);	//No data to retrieve, buffer EMPTY
	char* data  = (char*)open_port[port][2];			str_cpy(outdata, data);	
	long bytes;   for(bytes=0;bytes<ols[5];bytes++)		if(data[bytes])		break;
	long i;   for(i=0;i<bytes;i++)	if(i<MAX_READ_BUFFER)   ((byte*)outdata)[i]=data[i];
	for(i=0; i<(ols[5]-bytes); i++)		data[i] = data[i+bytes];		ols[5] -= bytes;
	for(i=ols[5]; i<MAX_READ_BUFFER; i++)		data[i] = 0;
	return(bytes-1);
}
//
//
//////////////////////////////////////////////////////////////////////////////////////////
//
var port_read_number(var port, DWORD* outdata)
{	if(!open_port[port][0])		return(-1);	//invalid handle
	if(!outdata)				return(-1);	//invalid pointer to buffer
	long* ols   = (long*)open_port[port][1];	
	if(ols[5]<4)				return(0);	//Not enough data to retrieve a 4-byte number
	byte* data  = (byte*)open_port[port][2];	*outdata = ((DWORD*)data)[0];	
	long i;	for(i=0; i<(ols[5]-4); i++)		data[i] = data[i+4];		ols[5] -= 4;
	for(i=ols[5]; i<MAX_READ_BUFFER; i++)		data[i] = 0;
	return(4);
}
//
//
//////////////////////////////////////////////////////////////////////////////////////////
//
var port_read_double(var port, double* outdata)
{	if(!open_port[port][0])		return(-1);	//invalid handle
	if(!outdata)				return(-1);	//invalid pointer to buffer
	long* ols   = (long*)open_port[port][1];	
	if(ols[5]<8)				return(0);	//Not enough data to retrieve a 8-byte number
	byte* data  = (byte*)open_port[port][2];	*outdata = ((double*)data)[0];	
	long i;	for(i=0; i<(ols[5]-8); i++)		data[i] = data[i+8];		ols[5] -= 8;
	for(i=ols[5]; i<MAX_READ_BUFFER; i++)		data[i] = 0;
	return(8);
}
//
//
//
//////////////////////////////////////////////////////////////////////////////////////////
//	Start Port WRITING Functions														//
//////////////////////////////////////////////////////////////////////////////////////////
//
var port_write_bytes(var port, void* data, long bytes, long ms_wait)
{	if(!open_port[port][0])		return(0);	//invalid handle
	long* ols = (long*)open_port[port][1];	
	while((proc_status(port_write_bytes))&&(ols[1]==-1))	wait(1);
	if(WriteFile(open_port[port][0], data, bytes, NULL, ols)!=-1)
	{	if(_GetLastError()==997)
		{	ols[1] = -1;	proc_mode = PROC_LATE;
			float timr=0;	while(timr<ms_wait)
			{	if(!WaitForSingleObject(ols[4],0))	break;
				timr += time_frame*64;				wait(1);
}	}	}	}
//
//
//////////////////////////////////////////////////////////////////////////////////////////
//
var port_write_string(var port, STRING* data, long ms_wait)
{	if(!open_port[port][0])		return(0);	//invalid handle
	return(port_write_bytes(port, data.chars, data.length, ms_wait));
}
//
//
//////////////////////////////////////////////////////////////////////////////////////////
//
var port_write_number(var port, DWORD* data, long ms_wait)
{	if(!open_port[port][0])		return(0);	//invalid handle
	return(port_write_bytes(port, data, 4, ms_wait));
}
//
//
//////////////////////////////////////////////////////////////////////////////////////////
//
var port_write_double(var port, double* data, long ms_wait)
{	if(!open_port[port][0])		return(0);	//invalid handle
	return(port_write_bytes(port, data, 8, ms_wait));
}
//
//
//////////////////////////////////////////////////////////////////////////////////////////
//
////
#endif	//port_io_h






Last edited by EvilSOB; 05/23/10 03:03. Reason: COM>9 bugfix

"There is no fate but what WE make." - CEO Cyberdyne Systems Corp.
A8.30.5 Commercial
Re: Serial Communications Header [Re: EvilSOB] #280520
07/23/09 05:28
07/23/09 05:28
Joined: Dec 2008
Posts: 528
Wagga, Australia
the_mehmaster Offline
User
the_mehmaster  Offline
User

Joined: Dec 2008
Posts: 528
Wagga, Australia
Wonderful contribution evilSOB!
I'll be sure to test it out.smile

I think you should 'ask the developers' to implement this into the engine.

Last edited by the_mehmaster; 07/23/09 05:34.
Re: Serial Communications Header [Re: the_mehmaster] #280528
07/23/09 07:56
07/23/09 07:56
Joined: May 2003
Posts: 567
Spain, Canary Islands
Felixsg Offline
User
Felixsg  Offline
User

Joined: May 2003
Posts: 567
Spain, Canary Islands
if I renember wheel is already implement

Re: Serial Communications Header [Re: Felixsg] #280531
07/23/09 08:48
07/23/09 08:48
Joined: Oct 2004
Posts: 4,134
Netherlands
Joozey Offline
Expert
Joozey  Offline
Expert

Joined: Oct 2004
Posts: 4,134
Netherlands
Can you explain what this exactly is/does?

Thanks,
Joozey


Click and join the 3dgs irc community!
Room: #3dgs
Re: Serial Communications Header [Re: Felixsg] #280534
07/23/09 08:59
07/23/09 08:59
Joined: Oct 2004
Posts: 4,134
Netherlands
Joozey Offline
Expert
Joozey  Offline
Expert

Joined: Oct 2004
Posts: 4,134
Netherlands
Can you explain what this exactly is/does?

Thanks,
Joozey


Click and join the 3dgs irc community!
Room: #3dgs
Re: Serial Communications Header [Re: Joozey] #280535
07/23/09 09:13
07/23/09 09:13
Joined: Dec 2008
Posts: 528
Wagga, Australia
the_mehmaster Offline
User
the_mehmaster  Offline
User

Joined: Dec 2008
Posts: 528
Wagga, Australia
What it does:
This header enables lite-c to interface to the (9 pin) serial communication ports.
The existing port io header only works with (25 pin) parallel ports.

Why it is needed:
Serial communication is a quick, simple way to interface to slave devices such as:

-Microcontrollers
-Sensors (accelerometer, GPS)
-External LCDs

Using these devices you could make a lightgun or something like that.

Re: Serial Communications Header [Re: the_mehmaster] #280536
07/23/09 09:26
07/23/09 09:26
Joined: Oct 2004
Posts: 4,134
Netherlands
Joozey Offline
Expert
Joozey  Offline
Expert

Joined: Oct 2004
Posts: 4,134
Netherlands
Nice contribution indeed smile
Thanks!


Click and join the 3dgs irc community!
Room: #3dgs
Re: Serial Communications Header [Re: Joozey] #280569
07/23/09 12:06
07/23/09 12:06
Joined: Feb 2008
Posts: 3,232
Australia
EvilSOB Offline OP
Expert
EvilSOB  Offline OP
Expert

Joined: Feb 2008
Posts: 3,232
Australia
Bump!

Lead-Post updated a bit to clarify what it actually does! And its plans for the future.
Sorry Joozey, I was at the end of a 12hr night-shift, and the brain was a bit blurry.

Ive updated the header again, as the "bi-directional" code is now included and looks good.
But I feel like doing something else tonight, but I will still respond if anyone posts any problems/suggestions.


"There is no fate but what WE make." - CEO Cyberdyne Systems Corp.
A8.30.5 Commercial
Re: Serial Communications Header [Re: EvilSOB] #280714
07/23/09 22:17
07/23/09 22:17
Joined: Dec 2008
Posts: 528
Wagga, Australia
the_mehmaster Offline
User
the_mehmaster  Offline
User

Joined: Dec 2008
Posts: 528
Wagga, Australia
I'm assuming you have tested this..
Could you post your test-script please?

Just for simple port reading.

Re: Serial Communications Header [Re: the_mehmaster] #280813
07/24/09 10:30
07/24/09 10:30
Joined: Feb 2008
Posts: 3,232
Australia
EvilSOB Offline OP
Expert
EvilSOB  Offline OP
Expert

Joined: Feb 2008
Posts: 3,232
Australia
It was tested, but only lightly.
I have since discovered there was a TYPO in it which meant it only worked if you included windows.h, which I was doing accidently.

To fix, replace all the #define's with what is in it now. (Ive fixed the header-post code).
Or find the line long __stdcall BuildCommDCB(char lpDef, long lpDCB); and replace it with long __stdcall BuildCommDCB(char* lpDef, long lpDCB);
(just one missing asterix...)

I have been doing my testing using a null-model cable connecting twp PC's and using the windows program "HyperTerminal" on the 'other' PC.
(The code was tested using a "factory" null-modem cable with both real serial ports and ONE type of USB->Serial adapter, that fakes a serial port very well)

NOTE: I think I MAY have found a minor bug that is preventing the port from being configured correctly.
This USED to work, so it shouldnt be too hard to fix. Im looking at it now.
NO FAULT FOUND

the_mehmaster :: here is a test "main" for you to try. All it does is display the last byte recieved.
If you need something more 'specific' than this, let me know what you are doing...
MAIN.C
Code:
#include <acknex.h>
#include <default.c>
#include "Port_IO.h"

TEXT* debug = {  pos_x=20;  pos_y=20;  size_y=400; font="Arial#20b";  strings=20;  flags=SHOW + WWRAP;  }

function main()
{
	wait(1);	level_load(NULL);	wait(1);	diag("\n\n\n");
	on_esc = NULL;
	//
	//
	byte last_recieved = 0;
	var hPort = port_open_read("COM1", "9600,n,8,1");
	//	
	while(1)
	{
		if(port_read_bytes(hPort,&last_recieved,1))
		{
			str_cpy((debug.pstring)[0], "Last Byte Recieved = ");
			str_cat((debug.pstring)[0], _chr(str_for_int(NULL,(long)last_recieved)));
		}
		if(key_esc)	break;
		wait(1);
	}
	port_close(hPort);
	//
	//
	sys_exit("");	
}



Last edited by EvilSOB; 07/29/09 23:58.

"There is no fate but what WE make." - CEO Cyberdyne Systems Corp.
A8.30.5 Commercial
Page 1 of 7 1 2 3 4 5 6 7

Moderated by  HeelX, Lukas, rayp, Rei_Ayanami, Superku, Tobias, TWO, VeT 

Gamestudio download | chip programmers | Zorro platform | shop | Data Protection Policy

oP group Germany GmbH | Birkenstr. 25-27 | 63549 Ronneburg / Germany | info (at) opgroup.de

Powered by UBB.threads™ PHP Forum Software 7.7.1