/*------------------------------------------------------------------------------*
 * File Name:				 													*
 * Creation:JCG 02/08/2002														*
 * Purpose: OriginC Source C file												*
 * Copyright (c) OriginLab Corp. 2001											*
 * All Rights Reserved															*
 *------------------------------------------------------------------------------*/

////////////////////////////////////////////////////////////////////////////////////
// A sample program to illustrate a serial port communication with Origin C.	  
// the following commands are supported once this file is compiled
// rso [1,2]; like rso 2; to open COM2
// rsr; default will read and dump to script window
// rsw str;write str to COM port
// rsc; close the COM port open in rso
////////////////////////////////////////////////////////////////////////////////////

#include <origin.h> //Gernal header file
#include <mscomm.h> //Commication header file

#define	BUFFER_BYTES    256

// Globle variable member
file ffComm; // the RS232 file object

// Function Prototypes go here.
BOOL rsr( int TimeoutRead = 5000 );
BOOL rsw( string str );
BOOL rsc();
BOOL rso( UINT nComm = 1 );

// static functions are not visible from labtalk
static BOOL SetDCB( UINT hCom, DWORD dwBaudRate, UINT nByteSize, UINT Parity, UINT StopBits );

// Function: rsr()
// rsr; default will read and dump to script window
BOOL rsr( int TimeoutRead )
{
	if( !ffComm.IsOpen() )
	{
		printf("Please use rso[1,2] to open COM first.\n" );
		return FALSE;
	}

	UINT hCom = ffComm.GetHandle();
	
	if ( hCom == file::hFileNull ) 
	{
		ASSERT(FALSE);
		return FALSE;
	}
	
	COMMTIMEOUTS tTimeout; 
	tTimeout.ReadIntervalTimeout = MAXWORD; 
	tTimeout.ReadTotalTimeoutMultiplier = 0; 
	tTimeout.ReadTotalTimeoutConstant = TimeoutRead; // pas de time out = 0 
	tTimeout.WriteTotalTimeoutMultiplier = 0; 
	tTimeout.WriteTotalTimeoutConstant = 0; 
	
	// config the timeout 
	if( !SetCommTimeouts((HANDLE)hCom,&tTimeout) )
	{
		ASSERT(FALSE);
		return FALSE;
	}
			
	char lpBuff[BUFFER_BYTES];
	
	DWORD dwRead = 0;
	DWORD dwTotal = 0;
	
	string strTotal = "";
	
	//read loop for comm port.
	while ( dwRead = ffComm.Read( lpBuff, BUFFER_BYTES - 1 ) )
	{
		dwTotal += dwRead;
		string str(lpBuff, dwRead);	
		strTotal += str;
	}	

	printf("%d bytes chars have been read:\n", dwTotal );
	
	printf( strTotal );
	
	return TRUE;
}

// Function: rsw( string str);
// rsw str;write str to COM port
BOOL rsw( string str )
{
	if( !ffComm.IsOpen( ) )
	{
		printf("Please use rso[1,2] to open COM first.\n" );
		return FALSE;
	}
	
	UINT hCom = ffComm.GetHandle();
	
	if (hCom == file::hFileNull ) 
	{
		ASSERT(FALSE);
		return FALSE;
	}
			
	int nLength = str.GetLength();	
	DWORD dwWrite = ffComm.Write( str.GetBuffer(nLength), nLength );	
	
	printf("%d bytes chars have been sent COM.\n", dwWrite );
	
	return TRUE;
}

// Function: rsc; 
//close the COM port open in rso
BOOL rsc()
{
	if( ffComm.IsOpen() )
	{
		if( !ffComm.Close() )
		{
			printf("Error when close COM.\n");
			return FALSE;
		}
		
		printf("COM was closed successfully\n");
		
		return TRUE;
	}
	
	printf("COM was already closed.\n");
	return TRUE;
}

// Function: rso( UINT nComm )
// rso [1,2]; like rso( 2 ); to open COM2
BOOL rso( UINT nComm )
{
	//First redirect into Script Window
	LT_execute("Type.redirection = 1");
	
	//Check comm prot is open or not
	if( ffComm.IsOpen() )
	{
		printf("COM%d was already openned.\n", nComm);
		return TRUE;
	}
	
	//Comm port name
	string szCommPort;
	szCommPort.Format( "COM%d:", nComm );
		
	//Open comm port
	if (!ffComm.Open(szCommPort,  file::modeReadWrite ))
	{
		ASSERT(FALSE);
		return FALSE;
	}
	
	UINT hCom = ffComm.GetHandle();
	
	if (hCom == file::hFileNull ) 
	{
		ASSERT(FALSE);
		return FALSE;
	}

	//Set DCB structure with some parameters
	if ( !SetDCB( hCom, CBR_9600, 8, NOPARITY, ONESTOPBIT ) )
	{
		ASSERT(FALSE);
		return FALSE;
	}
		
	printf("COM%d was openned successfully.\n", nComm);
	
	return TRUE;
}
	
//Set DCB structure.
static BOOL SetDCB( UINT hCom, DWORD dwBaudRate, UINT nByteSize, UINT Parity, UINT StopBits )
{	
	// It will build on the current configuration, and skip setting the size
	// of the input and output buffers with SetupComm. at the same time the DCB structure was tested.
	DCB dcb;

	if (!GetCommState((HANDLE)hCom, &dcb)) 
	{
		ASSERT(FALSE);
		return FALSE;
	}

	//dcb parameters for user
	dcb.BaudRate = dwBaudRate;  // set the baud rate
	dcb.ByteSize = nByteSize;   // data size, xmit, and rcv
	dcb.Parity = Parity;        // no parity bit
	dcb.StopBits = StopBits;    // one stop bit
	
	//dcb fixed parameters 
	dcb.fBinary=1; 
	dcb.fParity=0; 
	dcb.fOutxCtsFlow=0; 
	dcb.fOutxDsrFlow=0; 
	dcb.fDtrControl=0; 
	dcb.fDsrSensitivity=0; 
	
	dcb.fTXContinueOnXoff=0; 
	dcb.fRtsControl=0;
		
	if (!SetCommState((HANDLE)hCom, &dcb)) 
	{
		ASSERT(FALSE);
		return FALSE;
	}
		
	return TRUE;
}

