// WtRdCOMDlg.cpp : 實作檔
//

#include "stdafx.h"
#include "WtRdCOM.h"
#include "WtRdCOMDlg.h"
#include "stdio.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

#define BUFFER_SIZE 1000
CRITICAL_SECTION CS;
extern CWtRdCOMApp theApp;
BYTE * pTxBuffer = NULL;
BOOL bStopThread;
HANDLE mHandle;
DWORD dwThreadId; 
HANDLE hThread;
DWORD dwThreadIdW; 
HANDLE hThreadW;
//CHAR Buffer[BUFFER_SIZE];
ULONG ulRxCounter;
UINT bShowRxData;
DWORD dwTxFileSize;
HANDLE hEvent;
// CWtRdCOMDlg 對話方塊

CWtRdCOMDlg::CWtRdCOMDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CWtRdCOMDlg::IDD, pParent)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CWtRdCOMDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_cblCOMPort, m_CtrlCOMPort);
	DDX_Control(pDX, IDC_cblBaurRate, m_cblBaudrate);
	DDX_Control(pDX, IDC_cblDatabit, m_cblStopbit);
	DDX_Control(pDX, IDC_cblParityValue, m_cblParityValue);
}

BEGIN_MESSAGE_MAP(CWtRdCOMDlg, CDialog)
#if defined(_DEVICE_RESOLUTION_AWARE) && !defined(WIN32_PLATFORM_WFSP)
	ON_WM_SIZE()
#endif
	//}}AFX_MSG_MAP
	ON_BN_CLICKED(IDC_btnOpenCOMPort, &CWtRdCOMDlg::OnBnClickedbtnopencomport)
	ON_BN_CLICKED(IDC_btnSendData, &CWtRdCOMDlg::OnBnClickedbtnsenddata)
	ON_BN_CLICKED(IDC_btnExit, &CWtRdCOMDlg::OnBnClickedbtnexit)
	//ON_BN_CLICKED(IDC_btnRdData, &CWtRdCOMDlg::OnBnClickedbtnrddata)
	ON_BN_CLICKED(IDC_btnClearRxData, &CWtRdCOMDlg::OnBnClickedbtnclearrxdata)
	ON_BN_CLICKED(IDC_btnClearTxData, &CWtRdCOMDlg::OnBnClickedbtncleartxdata)
	ON_BN_CLICKED(IDC_btnCloseCOMPort, &CWtRdCOMDlg::OnBnClickedbtnclosecomport)
	ON_BN_CLICKED(IDC_btnClearRxCounter, &CWtRdCOMDlg::OnBnClickedbtnclearrxcounter)
	ON_BN_CLICKED(IDC_chkShowRxData, &CWtRdCOMDlg::OnBnClickedchkshowrxdata)
	ON_BN_CLICKED(IDC_btnLoadFile, &CWtRdCOMDlg::OnBnClickedbtnloadfile)
	ON_BN_CLICKED(IDC_btnSendFile, &CWtRdCOMDlg::OnBnClickedbtnsendfile)
END_MESSAGE_MAP()


// CWtRdCOMDlg 訊息處理常式

BOOL CWtRdCOMDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// 設定此對話方塊的圖示。當應用程式的主視窗不是對話方塊時，
	// 框架會自動從事此作業
	SetIcon(m_hIcon, TRUE);			// 設定大圖示
	SetIcon(m_hIcon, FALSE);		// 設定小圖示

	// TODO: 在此加入額外的初始設定
	m_CtrlCOMPort.AddString(_T("COM1"));
	m_CtrlCOMPort.AddString(_T("COM2"));
	m_CtrlCOMPort.AddString(_T("COM3"));
	m_CtrlCOMPort.AddString(_T("COM4"));

	m_CtrlCOMPort.SetCurSel(0);   

	ulRxCounter = 0;
	bShowRxData = 0;
	m_cblBaudrate.AddString(L"110");
    m_cblBaudrate.AddString(L"300");
    m_cblBaudrate.AddString(L"600");
	m_cblBaudrate.AddString(L"1200");
	m_cblBaudrate.AddString(L"2400");
	m_cblBaudrate.AddString(L"4800");
	m_cblBaudrate.AddString(L"9600");
	m_cblBaudrate.AddString(L"14400");
	m_cblBaudrate.AddString(L"19200");	
	m_cblBaudrate.AddString(L"38400");
	m_cblBaudrate.AddString(L"57600");
	m_cblBaudrate.AddString(L"115200");
	m_cblBaudrate.AddString(L"128000");
	m_cblBaudrate.AddString(L"256000");
    m_cblBaudrate.SetCurSel(11);
 
	m_cblStopbit.AddString(L"1");
	m_cblStopbit.AddString(L"2");
    m_cblStopbit.SetCurSel(0);

    m_cblParityValue.AddString(L"None");
	m_cblParityValue.AddString(L"Odd");
	m_cblParityValue.AddString(L"Even");	
    m_cblParityValue.SetCurSel(0);

	//InitializeCriticalSection(&CS);
    //hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
	/*
	hMutex = CreateMutex(NULL,FALSE,TEXT("MW_COM"));
	if (hMutex == NULL)
	{
        MessageBox(L"Create Mutex Fail");
	}
	*/
	return TRUE;  // 傳回 TRUE，除非您對控制項設定焦點
}

#if defined(_DEVICE_RESOLUTION_AWARE) && !defined(WIN32_PLATFORM_WFSP)
void CWtRdCOMDlg::OnSize(UINT /*nType*/, int /*cx*/, int /*cy*/)
{
	if (AfxIsDRAEnabled())
	{
		DRA::RelayoutDialog(
			AfxGetResourceHandle(), 
			this->m_hWnd, 
			DRA::GetDisplayMode() != DRA::Portrait ? 
			MAKEINTRESOURCE(IDD_WTRDCOM_DIALOG_WIDE) : 
			MAKEINTRESOURCE(IDD_WTRDCOM_DIALOG));
	}
}
#endif
/*
DWORD WINAPI Thread_Read (LPVOID lpParam )
{
	DWORD dwResult;
	DWORD EvtMask;
	DWORD dwRtSize;
	DWORD dwErrorFlags;
	COMSTAT comstat;
	WCHAR buf[10];
	UCHAR uCounter;
	memset(Buffer,0,BUFFER_SIZE);
    //while(bStopThread == FALSE)
	uCounter = 0;
    while( mHandle != INVALID_HANDLE_VALUE)
	{				
	
		 ClearCommError(mHandle, &dwErrorFlags, &comstat);
		 if (comstat.cbInQue > 0) 
		 {
         	  EnterCriticalSection(&CS);   			
			  dwResult = ReadFile(mHandle,(LPVOID)Buffer,comstat.cbInQue,&dwRtSize,NULL);				 
			  LeaveCriticalSection(&CS);
			  if (dwResult != 0)
			  {					 
				  ulRxCounter = ulRxCounter + dwRtSize ;
				  swprintf_s(buf,10,L"%X",ulRxCounter);
				  theApp.GetMainWnd()->SetDlgItemTextW(IDC_edtRxCounter,buf);
			  }
			  else
				  dwResult = GetLastError();			 		
	          GetCommModemStatus(mHandle,&EvtMask);	
			  uCounter = 0;         
	     }
		 else
		 {
		    if (uCounter < 20)
                uCounter ++;
			Sleep(uCounter);
		    //Sleep(2);
		 }
	}
    return (0);        
}
*/
DWORD WINAPI Thread_Read (LPVOID lpParam )
{
	DWORD dwResult;
	DWORD EvtMask;
	DWORD dwRtSize;
	DWORD dwErrorFlags;
	COMSTAT comstat;
	WCHAR buf[10];
	UCHAR uCounter;
	HANDLE hFile;
    int iCnt = 0;
	bool bFirst,bEnd;
	uCounter = 0;
	UCHAR * pRxData = NULL;
	UCHAR * pRxPnt = NULL;
	pRxData = new UCHAR[dwTxFileSize];
	pRxPnt = pRxData;
    //while( mHandle != INVALID_HANDLE_VALUE)
	bStopThread = FALSE;
	bFirst = TRUE;
	DWORD tStart,tEnd;
	while( mHandle != INVALID_HANDLE_VALUE)
	//while(bStopThread == FALSE)
	{					
		 ClearCommError(mHandle, &dwErrorFlags, &comstat);
		 if (comstat.cbInQue > 0) 
		 {
         	  EnterCriticalSection(&CS);   			
			  dwResult = ReadFile(mHandle,(LPVOID)pRxPnt,comstat.cbInQue,&dwRtSize,NULL);				 
			  LeaveCriticalSection(&CS);			  
			  if (dwResult != 0)
			  {		
                  ulRxCounter = ulRxCounter + dwRtSize ;
				  pRxPnt = pRxPnt + dwRtSize;
				  iCnt++;
				  if (iCnt > 10)
				  {				      
				      swprintf_s(buf,10,L"%X",ulRxCounter);
				      theApp.GetMainWnd()->SetDlgItemTextW(IDC_edtRxCounter,buf);
				      iCnt = 0;
				  }
				  if (bFirst == TRUE)
				  {
					  bFirst = FALSE;
                      tStart = GetTickCount();
                      //swprintf_s(buf,10,L"%X",tStart);
		              //theApp.GetMainWnd()->SetDlgItemTextW(IDC_edtRxStart,buf);
				  }
			  }
			  else
				  dwResult = GetLastError();			 		
	          GetCommModemStatus(mHandle,&EvtMask);	
			  uCounter = 0;   
			  bEnd = FALSE;
	     }
		 else
		 {
		     swprintf_s(buf,10,L"%X",ulRxCounter);
		     theApp.GetMainWnd()->SetDlgItemTextW(IDC_edtRxCounter,buf);
		     if (uCounter < 20)
                uCounter ++;
		 	 Sleep(uCounter);				 
			 if (bEnd == FALSE)
			 {
				 tEnd = GetTickCount(); 
                 swprintf_s(buf,10,L"%u",tEnd - tStart);
		         theApp.GetMainWnd()->SetDlgItemTextW(IDC_edtRxEnd,buf);
				 bEnd = TRUE;
			 }
		 }
	}
    hFile = CreateFile (TEXT ("\\EasyCOM\\Save.bin"), GENERIC_WRITE | GENERIC_READ,
                0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
	if (hFile != INVALID_HANDLE_VALUE )
	{
        dwResult = WriteFile(hFile,pRxData,ulRxCounter,&dwRtSize,NULL);
		if (dwRtSize != ulRxCounter)
			AfxMessageBox(L"Write to file failed !");
		else
            AfxMessageBox(L"Write to file OK !");
		CloseHandle(hFile);
	}
    return (0);        
}
void CWtRdCOMDlg::OnBnClickedbtnopencomport()
{
	// TODO: 在此加入控制項告知處理常式程式碼
	DWORD dwResult;
    int intCOMIndex;
	CHAR cCOM[20];
	WCHAR wcCOM[20];
	CString strTmp;
    intCOMIndex = m_CtrlCOMPort.GetCurSel();
    intCOMIndex ++;
	
    wsprintf(wcCOM,_T("COM%d:"),intCOMIndex); 
	mHandle = CreateFile(wcCOM,	
		                 GENERIC_READ | GENERIC_WRITE,
                         FILE_SHARE_READ | FILE_SHARE_WRITE,
                         NULL,
						 OPEN_EXISTING,
						 0,
						 0);
	if (mHandle == INVALID_HANDLE_VALUE)
	{
        dwResult = GetLastError();
		strTmp.Format(_T("Error Code = %X , Port = %s, wPort = %S"),dwResult,cCOM,wcCOM);
        MessageBox(strTmp);
	}
	else
	{		
        dwResult = SetupComm(mHandle , 4096, 2048 );  // setup device buffers
		dwResult = PurgeComm(mHandle, PURGE_TXABORT | PURGE_RXABORT |PURGE_TXCLEAR | PURGE_RXCLEAR ) ;
		DCB dcb;
	    dcb.DCBlength = sizeof( DCB );
		dwResult = GetCommState(mHandle, &dcb ) ;
		int index = m_cblBaudrate.GetCurSel();
		switch(index)
		{
		case 0: dcb.BaudRate = CBR_110; break;
		case 1: dcb.BaudRate = CBR_300; break;
		case 2: dcb.BaudRate = CBR_600; break;
		case 3: dcb.BaudRate = CBR_1200; break;		
		case 4: dcb.BaudRate = CBR_2400; break;
		case 5: dcb.BaudRate = CBR_4800; break;
		case 6: dcb.BaudRate = CBR_9600; break;
		case 7: dcb.BaudRate = CBR_14400; break;
		case 8: dcb.BaudRate = CBR_19200; break;        
		case 9: dcb.BaudRate = CBR_38400; break;
		case 10: dcb.BaudRate = CBR_57600; break;
		case 11: dcb.BaudRate = CBR_115200; break;		
		case 12: dcb.BaudRate = CBR_128000; break;
        case 13: dcb.BaudRate = CBR_256000; break;
		}
		//dcb.BaudRate = CBR_115200;
		dcb.ByteSize = 8;
		switch (m_cblParityValue.GetCurSel())
		{
		case 0:
			    dcb.Parity   = NOPARITY; break;
		case 1:
			    dcb.Parity   = ODDPARITY; break;
		case 2:
   		        dcb.Parity   = EVENPARITY; break;		
		}
        if (m_cblStopbit.GetCurSel() == 0)    
		    dcb.StopBits = ONESTOPBIT;
		else
            dcb.StopBits = TWOSTOPBITS;

		dcb.fBinary  = TRUE ;
		dcb.fParity  = 0;           // no parity check enable
		dwResult = SetCommState(mHandle, &dcb );		// set COM with dcb
        dwResult = SetCommMask(mHandle, EV_RXCHAR | EV_TXEMPTY);
		//dwResult = SetCommMask(mHandle, EV_RXCHAR );

        COMMTIMEOUTS CommTimeouts;
		dwResult = GetCommTimeouts ( mHandle,  &CommTimeouts);
		/*
		CommTimeouts.ReadIntervalTimeout = MAXDWORD;		 //250		
		CommTimeouts.ReadTotalTimeoutMultiplier = 0;  //10
		CommTimeouts.ReadTotalTimeoutConstant = 0;         //100
		*/
	    CommTimeouts.ReadIntervalTimeout = 250;		 //250		
		CommTimeouts.ReadTotalTimeoutMultiplier = 10;  //10
		CommTimeouts.ReadTotalTimeoutConstant = 100;         //100
		CommTimeouts.WriteTotalTimeoutConstant = 0;
		CommTimeouts.WriteTotalTimeoutMultiplier = 0;

        
        dwResult = SetCommTimeouts ( mHandle,  &CommTimeouts);

		((CEdit*)GetDlgItem(IDC_edtRxCounter))->SetWindowTextW(_T("0"));
		ulRxCounter = 0;
		if (hThread == NULL)
		{
			MessageBox(_T("Open Successful"));
			hThread = ::CreateThread( NULL,                        // no security attributes 
			 					      0,                           // use default stack size  
									  Thread_Read,                  // thread function 
									  NULL,                        // argument to thread function 
									  0,                           // use default creation flags 
									  &dwThreadId);                // returns the thread identifier 		
			
		}
		else
		{
            bStopThread = TRUE;
			hThread = NULL;
		}
	}
}

void CWtRdCOMDlg::OnBnClickedbtnsenddata()
{
	// TODO: 在此加入控制項告知處理常式程式碼
	DWORD dwResult;
	CString strTmp;
	//BYTE Buffer[]={'H','e','l','l','o',',','M','e','g','a','w','i','n'};
	LPTSTR pBuffer;
	DWORD dwWrite,dwWritten;
	((CEdit*)GetDlgItem(IDC_edtWtData))->GetWindowText(strTmp);
	dwWrite = strTmp.GetLength();
	
	pBuffer = strTmp.GetBuffer();	
    dwResult = WriteFile(mHandle,pBuffer,dwWrite*2,&dwWritten,NULL);
	if (dwResult == 0)
	{
        dwResult = GetLastError();
		strTmp.Format(_T("SendData Error Code = %X"),dwResult);
        MessageBox(strTmp);
	}
	else
	{
		strTmp.Format(_T("Writeen Bytes = %X"),dwWritten);
		//MessageBox(strTmp); 
	}
}

void CWtRdCOMDlg::OnBnClickedbtnexit()
{
	// TODO: 在此加入控制項告知處理常式程式碼
	bStopThread = TRUE;
	OnOK();
}

void CWtRdCOMDlg::OnBnClickedbtnclearrxdata()
{
	// TODO: 在此加入控制項告知處理常式程式碼
	((CEdit*)GetDlgItem(IDC_edtRdData))->SetWindowTextW(_T(""));
}

void CWtRdCOMDlg::OnBnClickedbtncleartxdata()
{
	// TODO: 在此加入控制項告知處理常式程式碼
	((CEdit*)GetDlgItem(IDC_edtWtData))->SetWindowTextW(_T(""));
}

void CWtRdCOMDlg::OnBnClickedbtnclosecomport()
{	
	// TODO: 在此加入控制項告知處理常式程式碼
	if (hThread != NULL) 
	{
		if (mHandle !=  NULL)
		{
			CloseHandle(mHandle);
			mHandle = INVALID_HANDLE_VALUE;
		}
        bStopThread = TRUE;
		hThread = NULL;
		EscapeCommFunction(mHandle,CLRDTR);
		EscapeCommFunction(mHandle,CLRRTS);
	};

}

void CWtRdCOMDlg::OnBnClickedbtnclearrxcounter()
{
	// TODO: 在此加入控制項告知處理常式程式碼
	((CEdit*)GetDlgItem(IDC_edtRxCounter))->SetWindowTextW(_T("0"));
	ulRxCounter = 0;
}

void CWtRdCOMDlg::OnBnClickedchkshowrxdata()
{
	// TODO: 在此加入控制項告知處理常式程式碼
    bShowRxData = ((CButton*)GetDlgItem(IDC_chkShowRxData))->GetState();
	bShowRxData = bShowRxData & 0x0003;
}

void CWtRdCOMDlg::OnBnClickedbtnloadfile()
{
	// TODO: 在此加入控制項告知處理常式程式碼
	CFileException ex;
    TCHAR szFilters[] = _T ("All files (*.*)|*.*||");
    CString strFilePath;
	CString strTmp;
    CFile m_TxFile;
	
	
    CFileDialog dlgOpen (TRUE, _T ("All files"), _T ("*.*"),
                         OFN_FILEMUSTEXIST | OFN_HIDEREADONLY, szFilters);

    if ( dlgOpen.DoModal () == IDOK )
	{	
		strFilePath = "";
        strFilePath = dlgOpen.GetPathName();    
		if ( !m_TxFile.Open( strFilePath, CFile::modeRead |CFile::shareDenyWrite , &ex) ) 
		{			 
			 TCHAR szError[1024];
			 ex.GetErrorMessage(szError, 1024);			     			
			 MessageBox(szError, NULL, MB_OK);     
		}   
		else
		{			
			 dwTxFileSize =(DWORD) (m_TxFile.GetLength()&0xFFFFFFFF); 			 
			 strTmp.Format(_T("%X"),dwTxFileSize);
			 ((CEdit *)GetDlgItem(IDC_edtTxFileSize))->SetWindowText(strTmp);				
			 if (pTxBuffer != NULL)
			     delete []pTxBuffer;
		     pTxBuffer = new BYTE[dwTxFileSize];                
		     m_TxFile.Read(pTxBuffer,(UINT)dwTxFileSize);							
			 m_TxFile.Close();
		}		
	}		
}
DWORD WINAPI Thread_Write (LPVOID lpParam )
{
	DWORD dwResult,dwWritten;
	DWORD dwWriteCount = 0;
    DWORD dwTxSize = 0;
	DWORD dwIndex = 0;
	DWORD WStart = 0;
	DWORD WEnd = 0;
    WCHAR buf[10];
	CString strTmp;	
	dwTxSize = 32;
	WStart = GetTickCount();
    //swprintf_s(buf,10,L"%X",WStart);
    //theApp.GetMainWnd()->SetDlgItemTextW(IDC_edtTxStart,buf);
	while (dwWriteCount < dwTxFileSize)
	{
		if ((dwIndex + dwTxSize) > dwTxFileSize)
            dwTxSize = dwTxFileSize - dwIndex;

        EnterCriticalSection(&CS);  		
	    dwResult = WriteFile(mHandle,pTxBuffer + dwIndex,dwTxSize,&dwWritten,NULL);			 
	    LeaveCriticalSection(&CS);
		 
		if (dwResult == 0)
		{
			dwResult = GetLastError();
			strTmp.Format(_T("Error Code = %X"),dwResult);
			AfxMessageBox(strTmp);
		}
		else
		{
			dwWriteCount = dwWriteCount + dwWritten;
			dwIndex = dwIndex + dwWritten;
			
		}
	}
	WEnd = GetTickCount();
    swprintf_s(buf,10,L"%u",WEnd - WStart);
    theApp.GetMainWnd()->SetDlgItemTextW(IDC_edtTxEnd,buf);
	return 0;
}
void CWtRdCOMDlg::OnBnClickedbtnsendfile()
{
	// TODO: 在此加入控制項告知處理常式程式碼
	// TODO: 在此加入控制項告知處理常式程式碼
			hThreadW = ::CreateThread( NULL,                        // no security attributes 
			 					      0,                           // use default stack size  
									  Thread_Write,                  // thread function 
									  NULL,                        // argument to thread function 
									  0,                           // use default creation flags 
									  &dwThreadIdW);                // returns the thread identifier 	
}
