// SDK_USBm_SONYDlg.cpp : implementation file
//

#include "stdafx.h"
#include "SDK_USBm_SONY.h"
#include "SDK_USBm_SONYDlg.h"
#include "DlgChnlAssign.h"
#include <time.h>

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

/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog
{
public:
	CAboutDlg();

// Dialog Data
	//{{AFX_DATA(CAboutDlg)
	enum { IDD = IDD_ABOUTBOX };
	//}}AFX_DATA

	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CAboutDlg)
	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
	//}}AFX_VIRTUAL

// Implementation
protected:
	//{{AFX_MSG(CAboutDlg)
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
	//{{AFX_DATA_INIT(CAboutDlg)
	//}}AFX_DATA_INIT
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CAboutDlg)
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
	//{{AFX_MSG_MAP(CAboutDlg)
		// No message handlers
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CSDK_USBm_SONYDlg dialog

CSDK_USBm_SONYDlg::CSDK_USBm_SONYDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CSDK_USBm_SONYDlg::IDD, pParent)
	, m_bOutTrg(FALSE)
{
	//{{AFX_DATA_INIT(CSDK_USBm_SONYDlg)
	m_strSaveFileName = _T("");
	m_strChkChnl = _T("");
	m_strChkCnct = _T("");
	m_lIntTime = 0;
	m_iTimeAve = 0;
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CSDK_USBm_SONYDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CSDK_USBm_SONYDlg)
	DDX_Control(pDX, IDC_BTN_ASSIGN, m_btnAssign);
	DDX_Control(pDX, IDC_EDIT_FILENAME, m_edSaveFileName);
	DDX_Control(pDX, IDC_EDIT_TIMEAVE, m_edTimeAve);
	DDX_Control(pDX, IDC_EDIT_INTTIME, m_edIntTime);
	DDX_Control(pDX, IDC_CB_CHNLNUM, m_cbChnlNum);
	DDX_Control(pDX, IDC_BTN_GETDATACURRENT, m_btnGetDataCrnt);
	DDX_Control(pDX, IDC_BTN_GETDATAALL, m_btnGetDataAll);
	DDX_Control(pDX, IDC_BTN_CLOSE, m_btnClose);
	DDX_Control(pDX, IDC_BTN_CHKCONNECT, m_btnChkCnct);
	DDX_Control(pDX, IDC_BTN_CHKCHNL, m_btnChkChnl);
	DDX_Text(pDX, IDC_EDIT_FILENAME, m_strSaveFileName);
	DDX_Text(pDX, IDC_STATIC_CHKCHNL, m_strChkChnl);
	DDX_Text(pDX, IDC_STATIC_CHKCNT, m_strChkCnct);
	DDX_Text(pDX, IDC_EDIT_INTTIME, m_lIntTime);
	DDV_MinMaxLong(pDX, m_lIntTime, 1, 65536);
	DDX_Text(pDX, IDC_EDIT_TIMEAVE, m_iTimeAve);
	DDV_MinMaxInt(pDX, m_iTimeAve, 1, 10000);
	//}}AFX_DATA_MAP
	DDX_Radio(pDX, IDC_CHK_FREERUN, (int&)m_TriggerMode);
	DDX_Control(pDX, IDC_CHECK_OUTTRG, m_btnOutTrg);
	DDX_Check(pDX, IDC_CHECK_OUTTRG, m_bOutTrg);
	DDX_Control(pDX, IDC_COMBO_USBSPEED, m_cUSBTx);
}

BEGIN_MESSAGE_MAP(CSDK_USBm_SONYDlg, CDialog)
	//{{AFX_MSG_MAP(CSDK_USBm_SONYDlg)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDC_BTN_CLOSE, OnBtnClose)
	ON_BN_CLICKED(IDC_BTN_ASSIGN, OnBtnAssign)
	ON_BN_CLICKED(IDC_BTN_CHKCONNECT, OnBtnChkConnect)
	ON_BN_CLICKED(IDC_BTN_CHKCHNL, OnBtnChkChannels)
	ON_WM_CLOSE()
	ON_CBN_SELCHANGE(IDC_CB_CHNLNUM, OnSelchangeCbChannelNum)
	ON_EN_CHANGE(IDC_EDIT_INTTIME, OnChangeEditIntTime)
	ON_BN_CLICKED(IDC_BTN_GETDATACURRENT, OnBtnGetDataCurrentChnl)
	ON_BN_CLICKED(IDC_BTN_GETDATAALL, OnBtnGetDataAllChannels)
	ON_BN_CLICKED(IDC_BUTTON_TRGSET, OnButtonTrgset)
	//}}AFX_MSG_MAP
	ON_COMMAND_RANGE(IDC_CHK_FREERUN, IDC_CHK_HWTRG_RISING, TrgModeChange)
	ON_CBN_SELCHANGE(IDC_COMBO_USBSPEED, OnSelchangeComboUsbspeed)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CSDK_USBm_SONYDlg message handlers

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

	// Add "About..." menu item to system menu.

	// IDM_ABOUTBOX must be in the system command range.
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		CString strAboutMenu;
		strAboutMenu.LoadString(IDS_ABOUTBOX);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// 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_cUSBTx.AddString(_T("1.2ms"));
	m_cUSBTx.AddString(_T("2.3ms"));
	m_cUSBTx.AddString(_T("3.8ms"));
	m_cUSBTx.AddString(_T("7.6ms"));

	m_cUSBTx.SetCurSel(2);
	
	//// Initialize the Controllers ////
	// Initial the variables
	m_lIntTime = 25;	// Integration Time: 25msec	(a dummy initial value)
	m_iTimeAve = 1;	// Time averaging number: 1
	m_sPixelNum = SP_CCD_PIXEL_SONY;	// Sony ILX 511 : 2080
	m_sCurChnl = 0;		// USB port channel number
	m_strSaveFileName = _T("SDK_Data");
	// Define the ComboBox size
	CRect rt;
	m_cbChnlNum.GetWindowRect(&rt);
	ScreenToClient(&rt);
	rt.bottom = rt.top + rt.Height()*3;
	m_cbChnlNum.MoveWindow(rt);
	m_TriggerMode = m_TriggerModeOld = 1;
	m_bTrgModeChange = false;
	m_bExtTrigger = false;
	// Disable all other controllers first
	DeactivateCtrls();
	// Update
	UpdateData(FALSE);

	//// USB connection check run ////
	OnBtnChkConnect();
	
	return TRUE;  // return TRUE  unless you set the focus to a control
}

void CSDK_USBm_SONYDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialog::OnSysCommand(nID, lParam);
	}
}

// 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 CSDK_USBm_SONYDlg::OnPaint() 
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

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

void CSDK_USBm_SONYDlg::OnBtnClose() 
{	// Close Window
	short i;
	for(i=0 ; i<m_sTotChnlNum ; i++){
		spCloseGivenChannel(m_asChnIDs[i]);
	}

	CDialog::OnCancel();
}

void CSDK_USBm_SONYDlg::OnClose() 
{
	// TODO: Add your message handler code here and/or call default
	spCloseAllChannels();

	CDialog::OnClose();
}

void CSDK_USBm_SONYDlg::OnBtnChkConnect() 
{	// USB Connection Check
	short sRtn;

	// sp DLL function use ; test all channels
	sRtn = spTestAllChannels(SP_ORDER_BY_CHANNELID);	// Check the total number of USB ports connected
	// NOTE1: 
	// The "SP_ORDER_BY_CHANNELID" in the spTestAllChannels argument means 
	// that the DLL will determine the connection information by the channel ID already assigned before.
	// The "SP_ORDER_BY_USBPORTNUM" in the spTestAllChannels argument means
	// that the DLL will determine the connection information by the order of the USB port connection.
	// If you assigned the channel ID on each spectrometer somehow and want to distinguish the spectrometer
	// by the assigned channel ID, set the argument as "SP_ORDER_BY_CHANNELID".
	// If you don't need to use the assigned the channel ID and just wan to distinguish the spectrometer 
	// by the order of the USB port connection, set the argument as "SP_ORDER_BY_USBPORTNUM".
	// In case of "SP_ORDER_BY_USBPORTNUM", some DLL functions shouldn't be used.
	// In this SDK example, the "SP_ORDER_BY_CHANNELID" is assumed.

	if(sRtn > 0)
	{	// OK!
		m_sTotChnlNum = sRtn;
		m_strChkCnct.Format(_T("The total USB ports connected are %d."), (int)m_sTotChnlNum);
		m_btnChkChnl.EnableWindow();
		m_btnAssign.EnableWindow();
	}
	else
	{	// ERROR!
		m_sTotChnlNum = 0;
		m_strChkCnct.Format(_T("There is no USB connection."));
		DeactivateCtrls();
	}
	UpdateData(FALSE);

}

void CSDK_USBm_SONYDlg::OnBtnChkChannels() 
{	// Connected Channel interface check
	if(m_sTotChnlNum < 1){	// there is no USB connection
		DeactivateCtrls();
		return;
	}
	short *sChannel;
	int i;
	short sRtn;
	short sChnlID;
	bool bMismatch = false;
	CString strChnl, strTmp;

	// Initializing
	strChnl = _T("");
	sChannel = new short[m_sTotChnlNum];
	ZeroMemory(sChannel, sizeof(short)*m_sTotChnlNum);
	
	// sp DLL function use ; setup all channels
	//sRtn = spSetupAllChannels();
	
	// sp DLL function use ; get the channel IDs assigned.
	spGetAssignedChannelID(sChannel);
	for(i=0 ; i<m_sTotChnlNum ; i++){
		// NOTE2: 
		// The "i" in this for-loop means the "USB port number".
		// This "i" will be determined according to the order of plugging.
		// The sChannel[i] means the assgined channel ID connected to the "i"th USB port.
		// sp DLL function use ; check each channel ID

		// sp DLL function use ; setup all channels
		sRtn = spSetupGivenChannel(sChannel[i]);
		if(sRtn < 0)
		{	// Error in communication via the USB port
			m_strChkChnl.Format(_T("There is an error on testing the channel# %d."), (int)sChannel[i]);
			UpdateData(FALSE);
			delete[] sChannel;
			DeactivateCtrls();
			return;
		}
		sRtn = spReadChannelID(&sChnlID, sChannel[i]);
		if(sRtn < 0)
		{	// Error in communication via the USB port
			m_strChkChnl.Format(_T("There is an error on testing the channel# %d."), (int)sChannel[i]);
			UpdateData(FALSE);
			delete[] sChannel;
			DeactivateCtrls();
			return;
		}
		strTmp.Format(_T("\tUSB port #: %d, Assigned USB channel #: %d\n\r"), i, (int)sChnlID);
		strChnl += strTmp;
		if(sChnlID != i)
		{	// Mismatch in the assgined channel ID and the USB port number 
			bMismatch = true;
		}
	}
	if(bMismatch)
	{	// Channel ID doesn't match the USB port number
		strTmp = _T("More than one channel doesn't match the USB port number as below. It doesn't affect the perforamnce but you can make the channel ID and the USB port number same i fyou want. Would you like to change them?\n\r"); 
		int nId = AfxMessageBox(strTmp + strChnl, MB_YESNO);
		if(nId == IDYES)
		{	// Change the "channel ID", i.e. sChannel[i] to be the same as the "USB port number", i.e. "i" same!!!
			for(i=0 ; i<m_sTotChnlNum ; i++){
				sChnlID = (short)i;
				// sp DLL function use ; write channel ID
				sRtn = spWriteChannelID(sChnlID, sChannel[i]);
				if(sRtn < 0)
				{	// Error in communication via the USB port
					m_strChkChnl.Format(_T("There is an error on testing the channel# %d."), (int)sChannel[i]);
					UpdateData(FALSE);
					delete[] sChannel;
					DeactivateCtrls();
					return;
				}
			}
			// NOTE3:
			// After change the channel ID, the spTestAllChannels() i.e. the OnBtnChkConnect() function should be run again.
			// Also spGetAssignedChannelID() function should be run to get updated channel id per usb port number
			// sp DLL function use ; spTestChannels() ; check the new assigned channels
			OnBtnChkConnect();
			// sp DLL function use ; get the channel IDs assigned.
			spGetAssignedChannelID(sChannel);
		}
	}
	//// if everthing is OK, run the followings... ////
	// Editting channel number combo box 
	m_cbChnlNum.EnableWindow();
	CString str;
	m_cbChnlNum.ResetContent();	// Delete all strings
	for(i=0 ; i<m_sTotChnlNum ; i++){
		str.Format(_T("Chnl ID#%d"), (int)sChannel[i]);
		m_cbChnlNum.AddString(str);	// Add strings
		m_asChnIDs[i] = sChannel[i];	// Channel IDs
	}
	m_cbChnlNum.SetCurSel(0);
	m_strChkChnl.Format(_T("All connected channels work OK."));
	// Activate other controllers
	m_btnGetDataAll.EnableWindow();
	m_btnGetDataCrnt.EnableWindow();
	m_cbChnlNum.EnableWindow();
	m_edIntTime.EnableWindow();
	m_edSaveFileName.EnableWindow();
	m_edTimeAve.EnableWindow();
	((CButton*)GetDlgItem(IDC_CHK_FREERUN))->EnableWindow();
	((CButton*)GetDlgItem(IDC_CHK_SWTRG))->EnableWindow();
	((CButton*)GetDlgItem(IDC_CHK_HWTRG_FALLING))->EnableWindow();
	((CButton*)GetDlgItem(IDC_CHK_HWTRG_RISING))->EnableWindow();
	((CButton*)GetDlgItem(IDC_BUTTON_TRGSET))->EnableWindow();
	((CButton*)GetDlgItem(IDC_CHECK_OUTTRG))->EnableWindow();
	m_cUSBTx.EnableWindow();
	//// Now initialize the DLL function...
	// sp DLL function use ; Initialized the setting variables in all channels.
	sRtn = spInitAllChannels(SP_CCD_SONY);	// CCD Detector is SONY ILX511
	// Note4:
	// This SDK example assumes that all CCDs are Sony ILX511.
	// If there is any different CCD spectrometer connected together,
	// spInitGivenChannel() function has to be called to set each detector type separately.
	if(sRtn < 0)
	{	// Error in initializing DLL setting variables
		m_strChkChnl.Format(_T("There is an error in initializing the DLL setting variables."));
		UpdateData(FALSE);
		delete[] sChannel;
		DeactivateCtrls();
		return;
	}
	// Set the current integration time per each channel (USB port number based) as the dummy inital integration time (25msec)
	for(i=0 ; i<m_sTotChnlNum ; i++){
		m_alIntTime[sChannel[i]] = m_lIntTime;
	}

	delete[] sChannel;
	UpdateData(FALSE);
}

void CSDK_USBm_SONYDlg::OnBtnAssign() 
{	// Assign the channel ID manually
	CDlgChnlAssign dlgAssign;
	
	// Transfer the current data to the dialog
	dlgAssign.m_sTotChnlNum = m_sTotChnlNum;
	memcpy(dlgAssign.m_asChnIDs, m_asChnIDs, sizeof(short)*MAX_USB_PORT_NUM);
	// Run Dialog
	dlgAssign.DoModal();
	if(dlgAssign.m_bIsChanged)
	{	// if there is any change
		// Re-transfer the new data from the dialog
		memcpy(m_asChnIDs, dlgAssign.m_asChnIDs, sizeof(short)*MAX_USB_PORT_NUM);
		// NOTE2:
		// After change the channel ID, the spTestAllChannels() i.e. the OnBtnChkConnect() function should be run again.
		// Also spGetAssignedChannelID() function should be run to get updated channel id per usb port number
		// sp DLL function use ; spTestChannels() ; check the new assigned channels
		OnBtnChkConnect();
		CString str;
		m_cbChnlNum.ResetContent();	// Delete all strings
		for(int i=0 ; i<m_sTotChnlNum ; i++){
			str.Format(_T("Chnl ID#%d"), (int)m_asChnIDs[i]);
			m_cbChnlNum.AddString(str);	// Add strings
		}
		m_cbChnlNum.SetCurSel(0);
	}
}

void CSDK_USBm_SONYDlg::OnSelchangeCbChannelNum() 
{	// Channel number selection combo box
	int nId;
	
	// Verify the current channel selected
	nId = m_cbChnlNum.GetCurSel();
	// First update the current integration time setting according to the change
	m_lIntTime = m_alIntTime[m_asChnIDs[nId]];
	UpdateData(FALSE);
}

void CSDK_USBm_SONYDlg::OnChangeEditIntTime() 
{	// Edit change; Integration time setting
	// TODO: If this is a RICHEDIT control, the control will not
	// send this notification unless you override the CDialog::OnInitDialog()
	// function and call CRichEditCtrl().SetEventMask()
	// with the ENM_CHANGE flag ORed into the mask.
	
	// Update the integration time per each channel
	UpdateData();
	int nId = m_cbChnlNum.GetCurSel();

	m_alIntTime[m_asChnIDs[nId]] = m_lIntTime;
}

short CSDK_USBm_SONYDlg::GetAndSaveData(CString strName, short sChnlID)
{	// Get Data from the CCD

	/////////////////////// Integration time & Trigger mode setting ////////////////////////////////////////
	short sRtn;
	long *plArrayData;
	plArrayData = new long[m_sPixelNum];
	ZeroMemory(plArrayData, sizeof(long)*m_sPixelNum);

	// sp DLL function use ; set the integration time
	sRtn = spSetIntEx(m_alIntTime[sChnlID], sChnlID);
	if(sRtn < 0){
		delete[] plArrayData;
		return sRtn;
	}

	/////////////////////////////////////////////////////////////////////////////////////////////////////////

	////////////////////// Get Data from the CCD ////////////////////////////////////////////////////////////
	int i, j;
	long *plTmpData;

	// Memory allocation
	plTmpData = new long[m_sPixelNum];
	// Initializing
	ZeroMemory(plTmpData, sizeof(long)*m_sPixelNum);
	ZeroMemory(plArrayData, sizeof(long)*m_sPixelNum);
	clock_t startT = clock();
	// sp DLL function use ; read data from the CCD
	if(!m_bExtTrigger){	// Not external triggering
		for(i=0 ; i<m_iTimeAve ; i++)
		{	// Time averaging
			if (m_bOutTrg)											//Outpug run signal
				sRtn = spReadDataExOutTrg(plArrayData, sChnlID);
			else
				sRtn = spReadDataEx(plArrayData, sChnlID);
			if(sRtn < 0)
			{	// There is an error in communication via USB
				delete[] plTmpData;
				delete[] plArrayData;
				return sRtn;
			}
			// Adding data
			for(j=0 ; j<(int)m_sPixelNum ; j++) plTmpData[j] += plArrayData[j];
		}
	}
	else{	// External triggering
		for(i=0 ; i<m_iTimeAve ; i++)
		{	// Time averaging
			do{
				if (m_bOutTrg)										//Outpug run signal
					sRtn = spReadDataExOutTrg(plArrayData, sChnlID);
				else
					sRtn = spReadDataEx(plArrayData, sChnlID);

			} while (sRtn == SP_EXT_TRG_WAITING);
			if(sRtn < 0)
			{	// There is an error in communication via USB
				delete[] plTmpData;
				delete[] plArrayData;
				return sRtn;
			}
			for(j=0 ; j<(int)m_sPixelNum ; j++) plTmpData[j] += plArrayData[j];
		}
	}
	clock_t endT = clock();
	CString strLine;
	TRACE("Measurement Time : %lf\n", (double)(endT - startT) / CLOCKS_PER_SEC);
	// Average data
	if(m_iTimeAve == 1){
		CopyMemory(plArrayData, plTmpData, sizeof(long)*m_sPixelNum);
	}
	else{
		for(j=0 ; j<(int)m_sPixelNum ; j++) plArrayData[j] = (long)((double)plTmpData[j]/m_iTimeAve + 0.5);
	}

	delete[] plTmpData;
	/////////////////////////////////////////////////////////////////////////////////////////////////////////

	////////////////////// Data converion from long to float ////////////////////////////////////////////////
	int iNum = SP_CCD_PIXEL_SONY_REAL;	// The first 32 pixels are optical blank pixels. 
										// The real data is 2048 for Sony ILX 511.
	float *fData;	// 
	
	// Memory allocation
	fData = new float[iNum]; 
	// Initializing
	ZeroMemory(fData, sizeof(float)*iNum);
	// Data converting
	for(i=0 ; i<iNum ; i++)	fData[i] = (float)plArrayData[i+32];

	delete[] plArrayData;
	/////////////////////////////////////////////////////////////////////////////////////////////////////////

	////////////////////// Calibration data converion ///////////////////////////////////////////////////////
	//// Spectrometer wavelength vs. pixel number Calibration Data set ////
	//// This set was given as an example.
	//// The customer has to use the proper calibration data set per each channel
	int nCalibNo=12 ;	// A number of the calibration data
	double dWaveLength[12];
	double dPixelNo[12];
	double dRCoefficient[5];
	double dCoefficient[5];
	//Random calibration sample data (This is only for Sony ILX 511 CCD, assumed the total pixel number is 2048) 
	dWaveLength[0] =  253.7; dPixelNo[0] = 348;
	dWaveLength[1] =  313.2; dPixelNo[1] = 465;
	dWaveLength[2] =  365.0; dPixelNo[2] = 567;
	dWaveLength[3] =  404.7; dPixelNo[3] = 643;
	dWaveLength[4] =  435.8; dPixelNo[4] = 703;
	dWaveLength[5] =  546.1; dPixelNo[5] = 910;
	dWaveLength[6] =  577.0; dPixelNo[6] = 967;
	dWaveLength[7] =  579.1; dPixelNo[7] = 971;
	dWaveLength[8] =  696.5; dPixelNo[8] = 1186;
	dWaveLength[9] =  763.5; dPixelNo[9] = 1306;
	dWaveLength[10] =  811.5; dPixelNo[10] = 1392;
	dWaveLength[11] =  912.3; dPixelNo[11] = 1570;

	// Polynomial fitting
	spPolyFit(dPixelNo, dWaveLength, nCalibNo, dCoefficient, 3);
	spPolyFit(dWaveLength, dPixelNo, nCalibNo, dRCoefficient, 3);
	/////////////////////////////////////////////////////////////////////////////////////////////////////////

	////////////////////// Save data  ///////////////////////////////////////////////////////////////////////
	CString strFile;
	CStdioFile sioFile;
	CString strSave;
	double dWL;

	// File Name setting
	strFile.Format(_T("_Chn%d.txt"), (int)sChnlID);
	strFile = strName + strFile;

	// File Open
	sioFile.Open(strFile, CFile::modeCreate|CFile::modeWrite);

	// Save data
	strSave.Format(_T("Pixel\tWavelength(nm)\tIntensity\n"));
	sioFile.WriteString(strSave);
	for(i=0 ; i<iNum ; i++){
		spPolyCalc(dCoefficient, 3, (i+1) ,&dWL);
		strSave.Format(_T("%5d\t%5.2f\t%12.4f\n"), i+1, dWL, fData[i]);
		sioFile.WriteString(strSave);
	}
	sioFile.Close();
	delete[] fData;
	/////////////////////////////////////////////////////////////////////////////////////////////////////////

	return 1;
}

void CSDK_USBm_SONYDlg::OnBtnGetDataCurrentChnl() 
{	// Get Data Current channel only
	int nId;
	CString strLine;
	short sRtn;
	short sChnlID;

	if(m_bTrgModeChange)
	{
		AfxMessageBox("The triggering mode changed. Set the trigger mode and please run again.");
		return;
	}

	BeginWaitCursor();	
	// Get current channel (USB port number)
	UpdateData();
	nId = m_cbChnlNum.GetCurSel();
	sChnlID = m_asChnIDs[nId];
	
	// Get data and save them
	sRtn = GetAndSaveData(m_strSaveFileName, sChnlID);
	if(sRtn < 0){
		strLine.Format(_T("Error in communication via USB port number %d [Channel ID = %d]"), nId, sChnlID);
		AfxMessageBox(strLine);
		DeactivateCtrls();

		EndWaitCursor();
		return;
	}

	EndWaitCursor();
}

void CSDK_USBm_SONYDlg::OnBtnGetDataAllChannels() 
{	// Get Data All Channels
	int i;
	CString strLine;
	short sRtn;
	short sChnlID;
	
	if(m_bTrgModeChange)
	{
		AfxMessageBox("The triggering mode changed. Set the trigger mode and please run again.");
		return;
	}

	BeginWaitCursor();	
	// Get all channel data consequently
	UpdateData();
	for(i=0 ; i<(int)m_sTotChnlNum; i++)
	{	// total channel number
		// Channel ID
		sChnlID = m_asChnIDs[i];
		sRtn = GetAndSaveData(m_strSaveFileName, sChnlID);
		if(sRtn < 0){
			strLine.Format(_T("Error in communication via USB port number %d [Channel ID = %d]"), i, sChnlID);
			AfxMessageBox(strLine);
			DeactivateCtrls();

			EndWaitCursor();
			return;
		}
	}

	EndWaitCursor();
}

void CSDK_USBm_SONYDlg::DeactivateCtrls()
{
	// Disable all controllers except the m_btnChkCnct to run USB connection check!!!
	m_btnChkChnl.EnableWindow(FALSE);
	m_btnAssign.EnableWindow(FALSE);
	m_btnGetDataAll.EnableWindow(FALSE);
	m_btnGetDataCrnt.EnableWindow(FALSE);
	m_cbChnlNum.EnableWindow(FALSE);
	m_edIntTime.EnableWindow(FALSE);
	m_edSaveFileName.EnableWindow(FALSE);
	m_edTimeAve.EnableWindow(FALSE);
	((CButton*)GetDlgItem(IDC_CHK_FREERUN))->EnableWindow(FALSE);
	((CButton*)GetDlgItem(IDC_CHK_SWTRG))->EnableWindow(FALSE);
	((CButton*)GetDlgItem(IDC_CHK_HWTRG_FALLING))->EnableWindow(FALSE);
	((CButton*)GetDlgItem(IDC_CHK_HWTRG_RISING))->EnableWindow(FALSE);
	((CButton*)GetDlgItem(IDC_BUTTON_TRGSET))->EnableWindow(FALSE);
	((CButton*)GetDlgItem(IDC_CHECK_OUTTRG))->EnableWindow(FALSE);
	m_cUSBTx.EnableWindow(FALSE);
	
	//Initialize the variables
	ZeroMemory(m_asChnIDs, sizeof(short)*MAX_USB_PORT_NUM);
	ZeroMemory(m_alIntTime, sizeof(long)*MAX_USB_PORT_NUM);
	m_strChkChnl = _T("");
	m_strChkCnct = _T("There is no USB connection.");
	
	UpdateData(FALSE);
}

void CSDK_USBm_SONYDlg::OnButtonTrgset() 
{
	// TODO: Add your control notification handler code here
	short sRtn = 1;
	short sChnlID;
	short DevVersion;
	
	BeginWaitCursor();	
	// Get current channel (USB port number)
	UpdateData();
	for(int i=0 ; i<(int)m_sTotChnlNum; i++)
	{	// total channel number
		// Channel ID
		sChnlID = m_asChnIDs[i];
		DevVersion = spGetDevIsNew(sChnlID);			//0: Old version	1: New version

		m_bExtTrigger = false;

		if(DevVersion)		//New version
		{
			if(m_TriggerMode == 0)			//Free run Mode
				sRtn = spSetIntMode(SP_INTMODE_FREERUN_PREV, m_lIntTime, sChnlID);
			else if(m_TriggerMode == 1)		//Software Trigger Mode
				sRtn = spSetIntMode(SP_INTMODE_SWTRIGGER, m_lIntTime, sChnlID);
			else if(m_TriggerMode == 2)		//Hardware Trigger(Falling edge) Mode
			{
				m_bExtTrigger = true;
				sRtn = spSetExtEdgeMode(SP_EXTEDGE_FALLING, sChnlID);
			}
			else if(m_TriggerMode == 3)		//Hardware Trigger(Rising edge) Mode
			{
				m_bExtTrigger = true;
				sRtn = spSetExtEdgeMode(SP_EXTEDGE_RISING, sChnlID);
			}
		}
		else				//Old version
		{
			if(m_TriggerMode == 0)			//Free run Mode
				sRtn = spSetTrgEx(SP_TRIGGER_INTERNAL, sChnlID);
			else if(m_TriggerMode == 1)		//Software Trigger Mode
			{
				CString str;
				str.Format(_T("The device of USB Port #%d does not support."), sChnlID);
					AfxMessageBox(str);
			}
			else if(m_TriggerMode == 2)		//Hardware Trigger(Falling edge) Mode
			{
				m_bExtTrigger = true;
				sRtn = spSetTrgEx(SP_TRIGGER_EXTERNAL, sChnlID);
			}
			else if(m_TriggerMode == 3)		//Hardware Trigger(Rising edge) Mode
			{
				CString str;
				str.Format(_T("The device of USB Port #%d does not support."), sChnlID);
				AfxMessageBox(str);
			}
		}

		if(sRtn<0){
			CString str;
			str.Format(_T("Error on setting the triggering mode via the USB Port #%d."), sChnlID);
				AfxMessageBox(str);
		}
	}
	m_TriggerModeOld = m_TriggerMode;	// Save the old trigger mode setting before update
	m_bTrgModeChange = false;
}

void CSDK_USBm_SONYDlg::TrgModeChange(UINT nID)
{
	if(nID != m_TriggerModeOld)
		m_bTrgModeChange = true;
}


void CSDK_USBm_SONYDlg::OnSelchangeComboUsbspeed()
{
	// TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.
	UpdateData();
	int nId = m_cbChnlNum.GetCurSel();
	short selSpeed = m_cUSBTx.GetCurSel() + 1;	
	short sRtn = spSetUSBTx(selSpeed, nId);
}
