
// NSeries_MEMAccessDlg.cpp: 구현 파일
//

#include "pch.h"
#include "framework.h"
#include "NSeries_MEMAccess.h"
#include "NSeries_MEMAccessDlg.h"
#include "afxdialogex.h"
#include "TabBurstMode.h"
#include "TabMEMAccess.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// 응용 프로그램 정보에 사용되는 CAboutDlg 대화 상자입니다.

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

// 대화 상자 데이터입니다.
#ifdef AFX_DESIGN_TIME
	enum { IDD = IDD_ABOUTBOX };
#endif

	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 지원입니다.

// 구현입니다.
protected:
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialogEx(IDD_ABOUTBOX)
{
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP()


// CNSeriesMEMAccessDlg 대화 상자



CNSeriesMEMAccessDlg::CNSeriesMEMAccessDlg(CWnd* pParent /*=nullptr*/)
	: CDialogEx(IDD_NSERIES_MEMACCESS_DIALOG, pParent)
	, m_iTimeAvg(0)
	, m_iGain(0)
	, m_iOffset(0)
	, m_dIntTime(0)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CNSeriesMEMAccessDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_TAB, m_cTab);
	DDX_Control(pDX, IDC_COMBO_DEVLIST, m_cbDevList);
	DDX_Text(pDX, IDC_EDIT_AVGTIME, m_iTimeAvg);
	DDX_Text(pDX, IDC_EDIT_GAIN, m_iGain);
	DDX_Text(pDX, IDC_EDIT_OFFSET, m_iOffset);
	DDX_Control(pDX, IDC_EDIT_AVGTIME, m_editAvgTime);
	DDX_Control(pDX, IDC_EDIT_GAIN, m_editGain);
	DDX_Control(pDX, IDC_EDIT_INTTIME, m_editIntTime);
	DDX_Control(pDX, IDC_EDIT_OFFSET, m_editOffset);
	DDX_Control(pDX, IDC_BTN_GAINOFFSETGET, m_btnGainOffsetGet);
	DDX_Control(pDX, IDC_BTN_DEVSET, m_btnDevSet);
	DDX_Control(pDX, IDC_BTN_GAINOFFSETSET, m_btnGainOffsetSet);
	DDX_Text(pDX, IDC_EDIT_INTTIME, m_dIntTime);
}

BEGIN_MESSAGE_MAP(CNSeriesMEMAccessDlg, CDialogEx)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDC_BTN_SCAN, &CNSeriesMEMAccessDlg::OnBnClickedBtnScan)
	ON_BN_CLICKED(IDC_BTN_DEVSET, &CNSeriesMEMAccessDlg::OnBnClickedBtnDevset)
	ON_BN_CLICKED(IDC_BTN_CONNECT, &CNSeriesMEMAccessDlg::OnBnClickedBtnConnect)
	ON_BN_CLICKED(IDC_BTN_GAINOFFSETSET, &CNSeriesMEMAccessDlg::OnBnClickedBtnGainoffsetset)
	ON_BN_CLICKED(IDC_BTN_GAINOFFSETGET, &CNSeriesMEMAccessDlg::OnBnClickedBtnGainoffsetget)
	ON_WM_DESTROY()
	ON_CBN_SELCHANGE(IDC_COMBO_DEVLIST, &CNSeriesMEMAccessDlg::OnCbnSelchangeComboDevlist)
	ON_NOTIFY(TCN_SELCHANGE, IDC_TAB, &CNSeriesMEMAccessDlg::OnTcnSelchangeTab)
END_MESSAGE_MAP()


// CNSeriesMEMAccessDlg 메시지 처리기

BOOL CNSeriesMEMAccessDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	// 시스템 메뉴에 "정보..." 메뉴 항목을 추가합니다.

	// IDM_ABOUTBOX는 시스템 명령 범위에 있어야 합니다.
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

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

	// 이 대화 상자의 아이콘을 설정합니다.  응용 프로그램의 주 창이 대화 상자가 아닐 경우에는
	//  프레임워크가 이 작업을 자동으로 수행합니다.
	SetIcon(m_hIcon, TRUE);			// 큰 아이콘을 설정합니다.
	SetIcon(m_hIcon, FALSE);		// 작은 아이콘을 설정합니다.

	// TODO: 여기에 추가 초기화 작업을 추가합니다.

	sTotChnl = 0;

	TabControlInit();
	DeactivateCtrl();

	return TRUE;  // 포커스를 컨트롤에 설정하지 않으면 TRUE를 반환합니다.
}

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

// 대화 상자에 최소화 단추를 추가할 경우 아이콘을 그리려면
//  아래 코드가 필요합니다.  문서/뷰 모델을 사용하는 MFC 애플리케이션의 경우에는
//  프레임워크에서 이 작업을 자동으로 수행합니다.

void CNSeriesMEMAccessDlg::OnPaint()
{
	if (IsIconic())
	{
		CPaintDC dc(this); // 그리기를 위한 디바이스 컨텍스트입니다.

		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

		// 클라이언트 사각형에서 아이콘을 가운데에 맞춥니다.
		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;

		// 아이콘을 그립니다.
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialogEx::OnPaint();
	}
}

// 사용자가 최소화된 창을 끄는 동안에 커서가 표시되도록 시스템에서
//  이 함수를 호출합니다.
HCURSOR CNSeriesMEMAccessDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}

void CNSeriesMEMAccessDlg::TabControlInit()
{
	m_cTab.InsertItem(0, _T("Memory Access"));
	m_cTab.InsertItem(1, _T("Burst Mode"));

	CRect rect;
	m_cTab.GetWindowRect(&rect);

	pDlgTabMemAccess = new TabMEMAccess;
	pDlgTabMemAccess->Create(IDD_DLGTABMEMACCESS, &m_cTab);
	pDlgTabMemAccess->SetBackgroundColor(RGB(255, 255, 255));
	pDlgTabMemAccess->MoveWindow(1, 21, rect.Width() - 4, rect.Height() - 22);
	pDlgTabMemAccess->ShowWindow(SW_SHOW);

	pDlgTabBurstMode = new TabBurstMode;
	pDlgTabBurstMode->Create(IDD_DLGTABBURSTMODE, &m_cTab);
	pDlgTabBurstMode->SetBackgroundColor(RGB(255,255, 255));
	pDlgTabBurstMode->MoveWindow(1, 21, rect.Width()-4, rect.Height()-22);
	pDlgTabBurstMode->ShowWindow(SW_HIDE);
}

void CNSeriesMEMAccessDlg::OnBnClickedBtnScan()
{
	// TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.
	short sRtn;

	if (sTotChnl > 0)
	{		
		for (int i = 0; i < sTotChnl; i++)
		{
			m_cbDevList.DeleteString(0);
			spNDevClose(i);
		}
	}

	sRtn = spNScanDevice(SP_SCAN_ALLDEVICE);
	if (sRtn < 0)
	{
		CString strLine;
		strLine.Format(_T("There are no matching devices. error = %d"), sTotChnl);
		AfxMessageBox(strLine);
		return;
	}

	sTotChnl = sRtn;
	m_stDevList = new _DevceList[sRtn];
	m_stDeviceInfo = new _DevInformation[sRtn];
	m_bConnect = new bool[sRtn];

	for(int i = 0 ; i < sRtn ; i ++)
		m_bConnect[i] = false;

	sRtn = spNGetDeviceList(m_stDevList);
	if (sRtn < 0)
	{
		CString strLine;
		strLine.Format(_T("Error Function : spNGetDeviceList(). error = %d"), sRtn);
		AfxMessageBox(strLine);
	}

	for (int i = 0; i < sTotChnl; i++)
	{
		CString strTemp,strModel,strSerial;
		
		strModel = m_stDevList[i].cModel;
		strSerial = m_stDevList[i].cSerial;
		if(m_stDevList[i].sInterfaceType == SP_INTERFACE_USB)
			strTemp.Format(_T("%d. (USB) : %s_%s"),i, strModel,strSerial);
		else
			strTemp.Format(_T("%d. (ETH) : %s_%s"), i, strModel,strSerial);
		m_cbDevList.AddString(strTemp);
	}

	m_cbDevList.SetCurSel(0);	
}

void CNSeriesMEMAccessDlg::DeactivateCtrl()
{
	m_editIntTime.EnableWindow(FALSE);
	m_editAvgTime.EnableWindow(FALSE);
	m_editGain.EnableWindow(FALSE);
	m_editOffset.EnableWindow(FALSE);
	m_btnDevSet.EnableWindow(FALSE);
	m_btnGainOffsetGet.EnableWindow(FALSE);
	m_btnGainOffsetSet.EnableWindow(FALSE);
	m_cTab.EnableWindow(FALSE);
}

void CNSeriesMEMAccessDlg::ActivateCtrl()
{
	m_editIntTime.EnableWindow();
	m_editAvgTime.EnableWindow();
	m_editGain.EnableWindow();
	m_editOffset.EnableWindow();
	m_btnDevSet.EnableWindow();
	m_btnGainOffsetGet.EnableWindow();
	m_btnGainOffsetSet.EnableWindow();
	m_cTab.EnableWindow();
}

void CNSeriesMEMAccessDlg::OnBnClickedBtnDevset()
{
	// TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.
	UpdateData();
	short sRtn; 

	iSelectedListIndex = m_cbDevList.GetCurSel();

	sRtn = spNSetDevice(m_dIntTime, m_iTimeAvg, m_stDeviceInfo[iSelectedListIndex].sTrgMode, m_stDeviceInfo[iSelectedListIndex].sChannel);
	if(sRtn < 0)
	{
		CString strLine;
		strLine.Format(_T("Error Function : spNSetDevice(). error = %d"), sRtn);
		AfxMessageBox(strLine);
		return;
	}
}

void CNSeriesMEMAccessDlg::OnBnClickedBtnConnect()
{
	// TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.
	iSelectedListIndex = m_cbDevList.GetCurSel();

	short sRtn = -1;
	if (m_stDevList[iSelectedListIndex].sInterfaceType == SP_INTERFACE_ETHERNET)
		sRtn = spNConnect(m_stDevList[iSelectedListIndex].sInterfaceType, m_stDevList[iSelectedListIndex].cIPAddr);
	else if (m_stDevList[iSelectedListIndex].sInterfaceType == SP_INTERFACE_USB)
		sRtn = spNConnect(m_stDevList[iSelectedListIndex].sInterfaceType, m_stDevList[iSelectedListIndex].cCOM);
	if (sRtn < 0)
	{
		CString strLine;

		if (sRtn == -116)
			strLine.Format(_T("Error Function : SPNConnect(). error = %d\nIt is already connected to another interface."), sRtn);
		else
			strLine.Format(_T("Error Function : SPNConnect(). error = %d"), sRtn);

		AfxMessageBox(strLine);
		return;
	}

	sRtn = spNGetDevParam(&m_stDeviceInfo[iSelectedListIndex], sRtn);
	if (sRtn < 0)
	{
		CString strLine;

		strLine.Format(_T("Error Function : spNGetDevParam(). error = %d"), sRtn);
		AfxMessageBox(strLine);
		return;
	}

	CString Model(m_stDeviceInfo[iSelectedListIndex].strModel);

	if (Model.Find(L"SM245") >= 0)
		m_dIntTime = m_stDeviceInfo[iSelectedListIndex].iInttime;
	else
		m_dIntTime = m_stDeviceInfo[iSelectedListIndex].iInttime / 1000.0;

	m_iTimeAvg = m_stDeviceInfo[iSelectedListIndex].iTimeavg;

	pDlgTabBurstMode->m_stDeviceInfo = m_stDeviceInfo[iSelectedListIndex];
	pDlgTabMemAccess->m_stDeviceInfo = m_stDeviceInfo[iSelectedListIndex];
	m_bConnect[iSelectedListIndex] = true;

	pDlgTabMemAccess->InitMemRead();
//  	sRtn = spNGetGainOffsetValue(&m_iGain, &m_iOffset, 0);
// 	if (sRtn < 0)
// 	{
// 		CString strLine;
// 		strLine.Format(_T("Error Function : spNGetGainOffsetValue(). error = %d"), sRtn);
// 		AfxMessageBox(strLine);
// 		return;
// 	}

	ActivateCtrl();
	UpdateData(FALSE);
}


void CNSeriesMEMAccessDlg::OnBnClickedBtnGainoffsetset()
{
	// TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.
	UpdateData();
	short sRtn;

	sRtn = spNSetGainOffsetValue(m_iGain, m_iOffset, 0);
	if (sRtn < 0)
	{
		CString strLine;
		strLine.Format(_T("Error Function : spNSetGainOffsetValue(). error = %d"), sRtn);
		AfxMessageBox(strLine);
		return;
	}
}

void CNSeriesMEMAccessDlg::OnBnClickedBtnGainoffsetget()
{
	// TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.
	short sRtn;

	sRtn = spNGetGainOffsetValue(&m_iGain, &m_iOffset, 0);
	if (sRtn < 0)
	{
		CString strLine;
		strLine.Format(_T("Error Function : spNGetGainOffsetValue(). error = %d"), sRtn);
		AfxMessageBox(strLine);
		return;
	}
	UpdateData(FALSE);
}


BOOL CNSeriesMEMAccessDlg::DestroyWindow()
{
	// TODO: 여기에 특수화된 코드를 추가 및/또는 기본 클래스를 호출합니다.

	return CDialogEx::DestroyWindow();
}


void CNSeriesMEMAccessDlg::OnDestroy()
{
	CDialogEx::OnDestroy();
	for (int i = 0; i < sTotChnl; i++)
	{
		spNDevClose(m_stDeviceInfo[i].sChannel);
	}

	delete pDlgTabBurstMode;
	delete pDlgTabMemAccess;
	delete m_stDeviceInfo;
	delete m_stDevList;
	// TODO: 여기에 메시지 처리기 코드를 추가합니다.
}

void CNSeriesMEMAccessDlg::OnCbnSelchangeComboDevlist()
{
	// TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.
	iSelectedListIndex = m_cbDevList.GetCurSel();

	if (m_bConnect[iSelectedListIndex])
	{
		ActivateCtrl();
		pDlgTabMemAccess->InitMemRead();
	}
	else
		DeactivateCtrl();
}


void CNSeriesMEMAccessDlg::OnTcnSelchangeTab(NMHDR* pNMHDR, LRESULT* pResult)
{
	// TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.
	int sel = m_cTab.GetCurSel();

	switch (sel) {
	case 0:
		pDlgTabBurstMode->ShowWindow(SW_HIDE);
		pDlgTabMemAccess->ShowWindow(SW_SHOW);
		
		break;
	case 1:
		pDlgTabBurstMode->ShowWindow(SW_SHOW);
		pDlgTabMemAccess->ShowWindow(SW_HIDE);
		break;
	}
	*pResult = 0;
}
