// AIPacerDlg.cpp : implementation file
//

#include "stdafx.h"
#include "AIPacer.h"
#include "AIPacerDlg.h"
#include "UniDAQ.h"
#pragma comment(lib,"UniDAQ.lib")

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

WORD wRtn;
WORD wBoardNo;

IXUD_DEVICE_INFO sDevInfo[MAX_BOARD_NUMBER];
IXUD_CARD_INFO sCardInfo[MAX_BOARD_NUMBER];
char szModelName[20]="Unknow Device";

const DWORD dwDataNo = 2000;
volatile unsigned long lCallbackCount;
float * fBuffer= new float[dwDataNo];
HANDLE hEvent=NULL;
WORD wCfgcode;
float fRange;
double fRangeMax,fRangeMin;
WORD wProcessing;
bool bActive = false ;

long   lmx, lmy;
float  fDeltaX, fDeltaY;

VOID WINAPI MyCallbackFun(DWORD param);
//typedef void (* CALLBACK) (DWORD);

/////////////////////////////////////////////////////////////////////////////
// CAIPacerDlg dialog

CAIPacerDlg::CAIPacerDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CAIPacerDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CAIPacerDlg)
	m_IDC_STATIC_MAX = _T("");
	m_IDC_STATIC_MIN = _T("");
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CAIPacerDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CAIPacerDlg)
	DDX_Control(pDX, IDCANCEL, m_IDCANCEL);
	DDX_Control(pDX, IDC_BTN_Active, m_IDC_BTN_Active);
	DDX_Control(pDX, IDC_EDIT_SamplingRate, m_IDC_EDIT_SamplingRate);
	DDX_Control(pDX, IDC_COMBO_Type, m_IDC_COMBO_Type);
	DDX_Control(pDX, IDC_COMBO_SelectBoard, m_IDC_COMBO_SelectBoard);
	DDX_Control(pDX, IDC_COMBO_Channel, m_IDC_COMBO_Channel);
	DDX_Control(pDX, IDC_COMBO_CfgCode, m_IDC_COMBO_CfgCode);
	DDX_Text(pDX, IDC_STATIC_MAX, m_IDC_STATIC_MAX);
	DDX_Text(pDX, IDC_STATIC_MIN, m_IDC_STATIC_MIN);
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CAIPacerDlg, CDialog)
	//{{AFX_MSG_MAP(CAIPacerDlg)
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_CBN_SELCHANGE(IDC_COMBO_SelectBoard, OnSelchangeCOMBOSelectBoard)
	ON_BN_CLICKED(IDC_BTN_Active, OnBTNActive)
	ON_CBN_EDITCHANGE(IDC_COMBO_CfgCode, OnEditchangeCOMBOCfgCode)
	ON_CBN_SELCHANGE(IDC_COMBO_CfgCode, OnSelchangeCOMBOCfgCode)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CAIPacerDlg message handlers

BOOL CAIPacerDlg::OnInitDialog()
{
	WORD wTotalBoards;
	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
	
	// TODO: Add extra initialization here
	//Initial the resource form  Driver
	wRtn=Ixud_DriverInit(&wTotalBoards);
	if (wRtn!=0) return wRtn;


	m_IDC_COMBO_SelectBoard.Clear();
	//_ltoa( wTotalBoards, string, 10 );
	//SetDlgItemText(IDC_EDIT_TotalBoards, string);
	
	//Get Card Information
	for(WORD wBoardIndex = 0; wBoardIndex<wTotalBoards ; wBoardIndex++)
	{
		wRtn = Ixud_GetCardInfo(wBoardIndex,&sDevInfo[wBoardIndex],&sCardInfo[wBoardIndex],szModelName);
		
		m_IDC_COMBO_SelectBoard.AddString(szModelName);
	}
	
	m_IDC_COMBO_CfgCode.SetCurSel(IXUD_BI_10V);
	m_IDC_COMBO_Type.SetCurSel(0);
    m_IDC_EDIT_SamplingRate.SetWindowText("10000");
	for(WORD index = 0; index<dwDataNo;index++)
	{
		fBuffer[index] = 0.0F;
	}
	
	return TRUE;  // return TRUE  unless you set the focus to a control
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CAIPacerDlg::OnPaint() 
{
	CDialog::OnPaint();
	CWnd *pwnd = (CWnd*) GetDlgItem(IDC_PIC_Data);
	CPaintDC dc(pwnd);
	CRect rect;
	pwnd->GetClientRect(&rect);

	lmx = rect.left;
	lmy = rect.top + (rect.Height() / 2);
	fDeltaX = (float)(rect.Width() / (float)dwDataNo) ;
	fDeltaY = (float)(rect.Height() / (float)(fRangeMax-fRangeMin));

	CBrush brushGreen(RGB(0, 255, 0));
    CBrush* pOldBrush = dc.SelectObject(&brushGreen);
	CPen penBlack;
    penBlack.CreatePen(PS_SOLID, 1, RGB(0, 0, 0));
    CPen* pOldPen = dc.SelectObject(&penBlack);

    // draw a thick black rectangle filled with blue
    dc.Rectangle(rect);
	dc.MoveTo(lmx, lmy);
	dc.LineTo(rect.right, lmy);
	CPen penRed;
	penRed.CreatePen(PS_SOLID, 1, RGB(255, 0, 0) );
	dc.SelectObject(&penRed);

	//draw line
	dc.MoveTo(lmx,lmy - (int)(fBuffer[0]*fDeltaY));
	for(int index=1; index<dwDataNo; index++) 
	{
		dc.LineTo(lmx + (int)(index*fDeltaX),lmy - (int)(fBuffer[index]*fDeltaY));
	}

}

// The system calls this to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CAIPacerDlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}

void CAIPacerDlg::OnSelchangeCOMBOSelectBoard() 
{
		// TODO: Add your control notification handler code here
	WORD wChannelIndex; 
	
	wBoardNo = m_IDC_COMBO_SelectBoard.GetCurSel();
	static const int nLength = 10;
	char string[nLength];

	//Total AI Channel
	m_IDC_COMBO_Channel.Clear();

	for (wChannelIndex = 0; wChannelIndex < sCardInfo[wBoardNo].wAIChannels ;wChannelIndex++)
	{	
		_ltoa(wChannelIndex,string,10);
		m_IDC_COMBO_Channel.AddString(string);  
    }

	m_IDC_COMBO_Channel.SetCurSel(0);
	m_IDC_COMBO_CfgCode.SetCurSel(IXUD_BI_10V);

	fRangeMax = 10.0000;
	fRangeMin =-10.0000;
	SetDlgItemDouble(IDC_STATIC_MAX,fRangeMax);
	SetDlgItemDouble(IDC_STATIC_MIN,fRangeMin);		
}

void CAIPacerDlg::OnBTNActive() 
{
	DWORD lCallbackCountTemp;
	// TODO: Add your control notification handler code here
	bActive = !bActive;

	if(bActive != true )
	{
	    m_IDC_BTN_Active.SetWindowText("&ACTIVE");
		m_IDCANCEL.EnableWindow(true);
		
		if(Ixud_StopAI(wBoardNo))
		{
			MessageBox("Stop AI Error!");
            CDialog::OnOK();
		}

		//Remove the Callback event
		if(Ixud_RemoveEventCallback(wBoardNo,0))
		{
			MessageBox("Remove Callback function Error!");
            CDialog::OnOK();
		}
		return;
	}else{
		m_IDC_BTN_Active.SetWindowText("&STOP");
		m_IDCANCEL.EnableWindow(false);
		OnPaint();
		SetDlgItemInt(IDC_STATIC_DATANUM,dwDataNo);
		//Config AI 
		if(Ixud_ConfigAI(wBoardNo, 2, 2048, m_IDC_COMBO_Type.GetCurSel(), 0)!=0)
		{
			MessageBox("AI Config Error!");
			CDialog::OnOK();
		}

		//Set Callback function
		if(Ixud_SetEventCallback(wBoardNo, IXUD_HARDWARE_INT|IXUD_APC_READY_INT,1,&hEvent,MyCallbackFun,dwDataNo))
		{
			MessageBox("Set Callback function Error!");
			CDialog::OnOK();
		}

		wProcessing = 0;
		lCallbackCount = 0;
		lCallbackCountTemp = lCallbackCount;

		//Start AI to Continuous Mode
		if (Ixud_StartAI(wBoardNo, m_IDC_COMBO_Channel.GetCurSel(), m_IDC_COMBO_CfgCode.GetCurSel(),GetDlgItemFloat(IDC_EDIT_SamplingRate), 0) != 0)
		{
			MessageBox("AI Start Error!");
			CDialog::OnOK();
		}
	}

	// TODO: Add your control notification handler code here
	while(bActive == true )
	{	
        if((lCallbackCount!=lCallbackCountTemp)||(wProcessing==0))
		{
			Invalidate();    //update windows
			UpdateWindow();  //update windows			
		}

		MSG msg;
		if (::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) 
		{
			::TranslateMessage(&msg);
			::DispatchMessage(&msg);
		}	

		lCallbackCountTemp = lCallbackCount;
	
	}	
}

void CAIPacerDlg::OnCancel() 
{
	// TODO: Add extra cleanup here
	wRtn = Ixud_DriverClose();
	CDialog::OnCancel();
}

float CAIPacerDlg::GetDlgItemFloat(int nID)
{
	static const int nLength = 10;
	CString str;
	char szStr[nLength];//, * stopstring;
	
	GetDlgItemText(nID, str);
	strcpy(szStr, str.GetBuffer(nLength) );
	return (float)atof(szStr);
}

void CAIPacerDlg::OnEditchangeCOMBOCfgCode() 
{
	// TODO: Add your control notification handler code here	
}

void CAIPacerDlg::OnSelchangeCOMBOCfgCode() 
{
	// TODO: Add your control notification handler code here
	switch(m_IDC_COMBO_CfgCode.GetCurSel())
	{
		case IXUD_BI_10V: //0:Bipolar +/- 10V
			fRangeMax = 10.0;
			fRangeMin = -10.0;
		break;		
		case IXUD_BI_5V:  //1:Bipolar +/-  5V
			fRangeMax = 5.0;
			fRangeMin = -5.0;
		break; 
		case IXUD_BI_2V5:  //2:Bipolar +/-  2.5V
			fRangeMax = 2.5;
			fRangeMin = -2.5;
		break; 
		case IXUD_BI_1V25: //3:Bipolar +/-  1.25V
			fRangeMax = 1.25;
			fRangeMin = -1.25;
		break; 
		case IXUD_BI_0V625: //4:Bipolar +/-  0.625V
			fRangeMax = 0.625;
			fRangeMin = -0.625;
		break; 
		case IXUD_BI_0V3125: //5:Bipolar +/-  0.3125V
			fRangeMax = 0.3125;
			fRangeMin = -0.3125;
         break;
		case IXUD_BI_0V5:    //6:Bipolar +/-  0.5V
			fRangeMax = 0.5;
			fRangeMin = -0.5;
		 break;
		case IXUD_BI_0V05:    //7:Bipolar +/-  0.05V
			fRangeMax = 0.05;
			fRangeMin = -0.05;
         break;
		case IXUD_BI_0V005:   //8:Bipolar +/-  0.005V
			fRangeMax = 0.005;
			fRangeMin = -0.005;
         break;
		case IXUD_BI_1V:      //9:Bipolar +/-  1V
			fRangeMax = 1.0;
			fRangeMin = -1.0;
		 break;
		case IXUD_BI_0V1:     //10:Bipolar +/-  0.1V
			fRangeMax = 0.1;
			fRangeMin = -0.1;
		 break;
		case IXUD_BI_0V01:   //11:Bipolar +/-  0.01V
			fRangeMax = 0.01;
			fRangeMin = -0.01;
		 break; 
		case IXUD_BI_0V001:  //12:Bipolar +/-  0.001V
			fRangeMax = 0.001;
			fRangeMin = -0.001;
         break;
		case IXUD_UNI_20V:  //13:Unipolar 0 ~ 20V
			fRangeMax = 20.0;
			fRangeMin = 0.0;
		 break;
		case IXUD_UNI_10V:  //14:Unipolar 0 ~ 10V
			fRangeMax = 10.0;
			fRangeMin = 0.0;
		 break;
		case IXUD_UNI_5V:   //15:Unipolar 0 ~  5V
			fRangeMax = 5.0;
			fRangeMin = 0.0;
		 break;
		case IXUD_UNI_2V5:   //16:Unipolar 0 ~  2.5V
			fRangeMax = 2.5;
			fRangeMin = 0.0;
		 break;
		case IXUD_UNI_1V25:  //17:Unipolar 0 ~  1.25V
			fRangeMax = 1.25;
			fRangeMin = 0.0;
		 break;
		case IXUD_UNI_0V625: //18:Unipolar 0 ~  0.625V
			fRangeMax = 0.625;
			fRangeMin = 0.0;
		 break;
		case IXUD_UNI_1V:    //19:Unipolar 0 ~  1V
			fRangeMax = 1.0;
			fRangeMin = 0.0;
		 break;
		case IXUD_UNI_0V1:   //20:Unipolar 0 ~  0.1V
			fRangeMax = 0.1;
			fRangeMin = 0.0;
		 break;
		case IXUD_UNI_0V01:  //21:Unipolar 0 ~  0.01V
			fRangeMax = 0.01;
			fRangeMin = 0.0;
		 break;
		case IXUD_UNI_0V001: //22:Unipolar 0 ~  0.001V
			fRangeMax = 0.001;
			fRangeMin = 0.0;
		 break;
		case IXUD_BI_20V: //23:Bipolar +/- 20 V
			fRangeMax = 20;
			fRangeMin = -20;
		 break;
        default:
			fRangeMax = 10.0;
			fRangeMin = -10.0;
		 break;
	}

	SetDlgItemDouble(IDC_STATIC_MAX,fRangeMax);
	SetDlgItemDouble(IDC_STATIC_MIN,fRangeMin);
	
}

VOID CAIPacerDlg::SetDlgItemVal(int nID,double nVal)
{
	static const int nLength = 10;
	char string[nLength];
	
	_gcvt( nVal, 5, string );
	SetDlgItemText(nID, string);
}

VOID CAIPacerDlg::SetDlgItemDouble(int nID,double nVal)
{
	char buf[8];
	sprintf(buf,"%.4f",nVal);
	SetDlgItemText(nID,buf);
}

VOID WINAPI MyCallbackFun(DWORD param)
{
	if(wProcessing == 0)
	{
		wProcessing = 1;
		if(Ixud_GetAIBuffer(wBoardNo, dwDataNo, fBuffer))
		{
		//	MessageBox("Get AI Buffer Error!");
		//	CDialog::OnOK();
		}		
        wProcessing = 0;
	}

	lCallbackCount = lCallbackCount++;
}