// DFUDlg.cpp : implementation file
//

#include "stdafx.h"
#include "DFU.h"
#include "DFUDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif


extern CDFUApp theApp;

DWORD dwDownloadThreadId; 
HANDLE hDownloadThread;  
DWORD WINAPI Thread_Download (LPVOID lpParam );
BOOL blnInDownload;
BOOL blnInProcess;
/////////////////////////////////////////////////////////////////////////////
// CDFUDlg dialog

CDFUDlg::CDFUDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CDFUDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CDFUDlg)
	m_strFileName = _T("");
	m_strPID = _T("030B");
	m_strVID = _T("0E6A");
	m_strCheckSum = _T("0x0000");
	m_strCodeSize = _T("0x0000");
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CDFUDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CDFUDlg)
	//DDX_Control(pDX, IDC_EDIT_ADDRESS, m_CtrlAddress);
	DDX_Control(pDX, IDC_EDIT_VID, m_CtrlVID);
	DDX_Control(pDX, IDC_EDIT_PID, m_CtrlPID);
	DDX_Control(pDX, IDC_EDIT_BUFFER, m_CtrlBinaryCodeBuffer);
	DDX_Text(pDX, IDC_EDIT_PATH, m_strFileName);
	DDX_Text(pDX, IDC_EDIT_PID, m_strPID);
	DDV_MaxChars(pDX, m_strPID, 4);
	DDX_Text(pDX, IDC_EDIT_VID, m_strVID);
	DDV_MaxChars(pDX, m_strVID, 4);
	DDX_Text(pDX, IDC_EDIT_CHECK_SUM, m_strCheckSum);
	DDX_Text(pDX, IDC_EDIT_CODE_SIZE, m_strCodeSize);	
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CDFUDlg, CDialog)
	//{{AFX_MSG_MAP(CDFUDlg)
	ON_BN_CLICKED(IDC_BUTTON_LOAD, OnButtonLoad)
	ON_BN_CLICKED(IDC_BUTTON_UPDATE, OnButtonUpdate)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CDFUDlg message handlers

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

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon
	m_CtrlBinaryCodeBuffer.SetAddressSize(4, FALSE);
	m_CtrlBinaryCodeBuffer.SetShowAddress(TRUE, FALSE);
	m_CtrlBinaryCodeBuffer.SetShowAscii(TRUE, FALSE);
	m_CtrlBinaryCodeBuffer.SetAdrCol(RGB(0xFF, 0xFF, 0x00), RGB(0x00, 0x00, 0x00), FALSE);
	m_CtrlBinaryCodeBuffer.SetHexCol(RGB(0xFF, 0xFF, 0x00), RGB(0x00, 0x00, 0x00), FALSE);
	m_CtrlBinaryCodeBuffer.SetAsciiCol(RGB(0xFF, 0xFF, 0x00), RGB(0x00, 0x00, 0x00), FALSE);
	m_CtrlBinaryCodeBuffer.SetBytesPerRow(16, FALSE);
	m_CtrlBinaryCodeBuffer.SetNotUsedCol(RGB(0xFF, 0xFF, 0x00));
	m_CtrlBinaryCodeBuffer.SetReadonly(TRUE);
	m_CtrlBinaryCodeBuffer.SetFont(GetFont());
	
	return TRUE;  // return TRUE  unless you set the focus to a control
}

void CDFUDlg::OnButtonLoad()
{
	CFileDialog fd(TRUE);
	fd.m_ofn.lpstrFilter = _T("*.bin; *.hex; *.rom\0*.hex;*.bin;*.rom\0All file (*.*)\0*.*\0");
	if (fd.DoModal() == IDOK)
	{
		UpdateData();
		LPBYTE pBuffer = NULL;
		DWORD dwLength = 0;
		DWORD dwCheckSum = 0;
		BOOL bDataEnable(FALSE);
		m_strFileName = fd.GetPathName();
		if (!fd.GetFileExt().CompareNoCase("hex"))
		{
			CHexFile hFile;
			if (hFile.Open(fd.GetPathName()))
			{
				bDataEnable = TRUE;
				dwLength = hFile.GetLength();
				pBuffer = new BYTE[dwLength];
				hFile.ReadHuge(pBuffer, dwLength);
				hFile.Close();
			}
		}
		else
		{
			CFile hFile;
			if (hFile.Open(fd.GetPathName(), CFile::modeRead))
			{
				bDataEnable = TRUE;
				dwLength = hFile.GetLength();
				pBuffer = new BYTE[dwLength];
				hFile.ReadHuge(pBuffer, dwLength);
				hFile.Close();
			}
		}
		if (bDataEnable)
		{
			m_CtrlBinaryCodeBuffer.SetData(pBuffer, dwLength);
			m_strCodeSize.Format("0x%X", dwLength);
			__asm
			{
				mov ecx, dwLength
				mov edx, pBuffer
				add edx, ecx
L_Next:			dec	edx
				movzx eax, byte ptr[edx]
				add	dwCheckSum, eax
				loop L_Next
			}
			m_strCheckSum.Format("0x%04X", dwCheckSum&0xffff);
		}
		else
		{
			AfxMessageBox("Cannot open \"" + fd.GetPathName() + "\" !");
		}
		if (pBuffer)
			delete []pBuffer;
		UpdateData(FALSE);
	}
}

void CDFUDlg::OnButtonUpdate()
{
    CString strTmp;		
	int ChangeState;
    int PreValue;
	int CurValue;
	UpdateData();
	hDownloadThread = ::CreateThread( NULL,                        // no security attributes 
			 						  0,                           // use default stack size  
									  Thread_Download,                 // thread function 
									  NULL,                        // argument to thread function 
									  0,                           // use default creation flags 
									  &dwDownloadThreadId);// returns the thread identifier 
	blnInProcess = TRUE;
    ChangeState = 0;

    while(blnInProcess == TRUE)	
	{
	    if (blnInDownload == TRUE)
		{
		    CurValue = DFU_Get_ProcessCount();
			switch (CurValue)
			{
			case 0xFF:
				 if (ChangeState == 0)
				 {
					strTmp.Format("Searching device...");	
					((CEdit*)GetDlgItem(IDC_edtProcessCount))->SetWindowText(strTmp);         
				 }
				 PreValue = 0xFF;
				 ChangeState = 1;
				 break;
			default:
			     if (PreValue != CurValue)
				 {
				    strTmp.Format("ProcessCount = %d%%",CurValue);
				    ((CEdit*)GetDlgItem(IDC_edtProcessCount))->SetWindowText(strTmp);
				    PreValue = CurValue;
				 }
				 break;
			}        

		}
		 MSG msg;
		 while(::PeekMessage(&msg,NULL,0,0,PM_NOREMOVE))
		 {
			 if(!AfxGetApp()->PumpMessage())
			 {
				 ::PostQuitMessage(0);	
				 break;		
			 }
		}
	}


	((CEdit*)(theApp.GetMainWnd()->GetDlgItem(IDC_edtProcessCount)))->SetWindowText("");
}
DWORD WINAPI Thread_Download (LPVOID lpParam )
{
	WORD wVid = 0;
	WORD wPid = 0;
	LPBYTE pBuf = NULL;
	DWORD dwAddr = 0;   // Must
	DWORD dwSize = 0;
	WORD wCheckSum = 0;
	BOOL Result;
	
	sscanf(((CDFUDlg*)theApp.GetMainWnd())->m_strVID, "%x", &wVid);
	sscanf(((CDFUDlg*)theApp.GetMainWnd())->m_strPID, "%x", &wPid);
	sscanf(((CDFUDlg*)theApp.GetMainWnd())->m_strCheckSum, "0x%x", &wCheckSum);
	dwSize = ((CDFUDlg*)theApp.GetMainWnd())->m_CtrlBinaryCodeBuffer.GetDataSize();
	if (!dwSize)
	{
		AfxMessageBox(_T("Buffer size is zero !"));
		return 0;
	}
	pBuf = new BYTE[dwSize];
	if (!pBuf)
	{
		AfxMessageBox(_T("Out of memory !"));
		return 0;
	}
	((CDFUDlg*)theApp.GetMainWnd())->m_CtrlBinaryCodeBuffer.GetData(pBuf, dwSize);
	if (MessageBox(
	    NULL,
		_T(" Upgrade Firmware ? "),
		_T("Confirm File"),
		MB_ICONWARNING | MB_YESNO) == IDYES)
	{
		Result = DFU_Reset_To_ISP(wVid, wPid);					
		
		if ( Result == TRUE )
		  { 
			HCURSOR hCursor;
			hCursor = LoadCursor(theApp.m_hInstance,MAKEINTRESOURCE(IDC_CURSOR1));
			SetCursor(hCursor);		
			blnInDownload = TRUE;
			Result = DFU_Download(pBuf, 0, dwSize, wCheckSum);   // The second parameter is never used again. Fill it with 0.
			
			blnInDownload = FALSE;
			if ( Result == TRUE )
			  { 			    
				
				Result = DFU_Reset_To_AP();
				if ( Result == FALSE )
				  AfxMessageBox(_T("DFU_Reset_To_AP fail !"));
				else
				  AfxMessageBox(_T("Upgrade successfully !"));				
			  }
			else
			  AfxMessageBox(_T("DFU_Download fail !"));

			hCursor = LoadCursor(theApp.m_hInstance,MAKEINTRESOURCE(IDC_ARROW));
			SetCursor(hCursor);
		  }
		else
		  AfxMessageBox(_T("DFU_Reset_To_ISP fail !"));
	

	}
	delete []pBuf;
	blnInProcess = FALSE;
	return 1;
}