//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "main.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
}
//---------------------------------------------------------------------------
static DWORD WINAPI ThreadFunc_Receive(void);
static DWORD dwThreadID;
static HANDLE t_receive;
static DWORD dwExitCode;

static int comm_ok_flag[4];

// rs-232
static DCB dcb[4];
static HANDLE hCom[4];
static DWORD dwError;
static BOOL fSuccess;
static OVERLAPPED o;

int SIO_Init(int comport, int baudrate)
{
	comm_ok_flag[comport - 1] = 1;

	typedef char str5[5];
	str5 coms[] = {"COM1","COM2","COM3","COM4"};
	hCom[comport - 1] = CreateFile(coms[comport-1],
		GENERIC_READ | GENERIC_WRITE,
		0,    // can't be shared
		NULL, // no security attrs 
		OPEN_EXISTING, /* comm devices must use OPEN_EXISTING */
		0,
		NULL  /* hTemplate must be NULL for comm devices */
		);

	if (hCom[comport - 1] == INVALID_HANDLE_VALUE)
	{
//		error_msg("CreateFile");
		comm_ok_flag[comport - 1] = 0;
	}


	/*
	 * Omit the call to SetupComm to use the default queue sizes.
	 * Get the current configuration.
	 */

	fSuccess = GetCommState(hCom[comport - 1], &dcb[comport - 1]);

	if (!fSuccess) {
		// Handle the error.
		comm_ok_flag[comport - 1] = 0;
	}

	// AG-MD830P default : : 9600 Baud-rate, 8 Bit data, 1 Stop bit, None Parity
	dcb[comport - 1].BaudRate = baudrate;
	dcb[comport - 1].ByteSize = 8;
	dcb[comport - 1].Parity = NOPARITY;
	dcb[comport - 1].StopBits = ONESTOPBIT;
	dcb[comport - 1].EvtChar = 13;		// CR

	fSuccess = SetCommState(hCom[comport - 1], &dcb[comport - 1]);

	if (!fSuccess)
	{
//		error_msg("SetCommState");
		comm_ok_flag[comport - 1] = 0;
	}

	// set I/O internal buffer
	SetupComm(hCom[comport - 1],4096,4096);

	//
	DWORD a;
	GetCommMask(hCom[comport - 1],&a);
//	SetCommMask(hCom, a | EV_RXCHAR);
	SetCommMask(hCom[comport - 1], a | EV_RXCHAR | EV_ERR | EV_TXEMPTY | EV_RXFLAG);

	//
	COMMTIMEOUTS timeout;
	GetCommTimeouts(hCom[comport - 1],&timeout);
//	timeout.ReadIntervalTimeout = 1000;
	timeout.ReadTotalTimeoutMultiplier = 100;
	SetCommTimeouts(hCom[comport - 1],&timeout);

	return (comm_ok_flag[comport - 1]);
}
int SIO_Send(int comport, char c)
{
	DWORD a;
	return WriteFile(hCom[comport - 1],(LPVOID) &c,1 ,&a,NULL);
}
int SIO_Read(int comport, char *c)
{
	DWORD b;
	if (ReadFile(hCom[comport - 1],(LPVOID) c,1,&b,NULL) && b == 1)
		return 1;
	else
		return 0;
}
int SIO_SendStr(int comport, char *s)
{
	unsigned long r;
	return WriteFile(hCom[comport - 1],(LPVOID) s,strlen(s),&r,NULL);
}
int SIO_ReadStr(int comport, char *str)
{
	int final = 0;
	int index = 0;
	int success = 0;
	char c;

	while (!final)
	{
		Sleep(50);
		if (!SIO_Read(comport,&c))
			continue;

		if (c != 13)
	        {
		        str[index] = c;    
	        	index++;
	        }
		if (index >= 100)
	        {	// too long command
        		success = 0;
			final = 1;
	        }
        	if (c == 13)
	        { 	// carriage return -> success
        		success = 1;
	        	str[index] = 0;
			final = 1;
	        }
	}

	return success;
}
static int thread_exit = 0;
static DWORD WINAPI ThreadFunc_Receive( LPVOID )
{
        char c;
        static char command[100];
        int success = 0;
        int index;
        int final;

        //---- Place thread code here ----
        for(;;)
        {
        	if(thread_exit)
			return 1;
                success = index = 0;
        	final = 0;
                while (!final)
                {
			if (thread_exit)
				return 1;

//			while (command_send);

			Sleep(100);
			if (!SIO_Read(Form1->ComportRadioGroup->ItemIndex + 1,&c))
				continue;

			if (c != 13)
                        {
	            	        command[index] = c;
                                index++;
                        }
			if (index >= 100)
                        {	// too long command
                        	success = 0;
				final = 1;
                        }
                    	if (c == 13)
                        { 	// carriage return -> success
                	        success = 1;
                                command[index] = 0;
				final = 1;
                        }
                }
                if (!success)
                        Form1->ReceiveStringMemo->Lines->Add("Serial Comm Error!");
                else
                        Form1->ReceiveStringMemo->Lines->Add(command);
        }
}
void __fastcall TForm1::ComOpenButtonClick(TObject *Sender)
{
	int comport;
        int baudrate;

        comport = ComportRadioGroup->ItemIndex + 1;
        sscanf(BaudrateRadioGroup->Items->Strings[BaudrateRadioGroup->ItemIndex].c_str(),"%d",&baudrate);

        int r;
	r = SIO_Init(comport,baudrate);
        if (r == 0)
                CommGroupBox->Color = clRed;
        else
        {
                CommGroupBox->Color = clBtnFace;
         	t_receive = CreateThread (NULL, 0, (LPTHREAD_START_ROUTINE) ThreadFunc_Receive,
								NULL, 0, &dwThreadID) ;
        }
}
//---------------------------------------------------------------------------
static int command_send = 0;
void __fastcall TForm1::SendButtonClick(TObject *Sender)
{
        int i = 0;
        while (SendStringMemo->Lines->Strings[i] != "")
        {
                command_send = 1;
                SIO_SendStr(ComportRadioGroup->ItemIndex + 1,SendStringMemo->Lines->Strings[i].c_str());
                SIO_Send(ComportRadioGroup->ItemIndex + 1,13);
                command_send = 0;
                i++;
        }
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
{
	thread_exit = 1;
	if (t_receive)
		CloseHandle(t_receive);
}
//---------------------------------------------------------------------------


void __fastcall TForm1::ReceiveMemoClearButtonClick(TObject *Sender)
{
        ReceiveStringMemo->Lines->Clear();
}
//---------------------------------------------------------------------------



