/*---------------------------------------------------------------------------* Project: HIO2 demos - dual File: dual.cpp (C)2005 HUDSON SOFT $Header: /home/cvsroot/SDK/build/demos/hio2demo/vc++/dual/dual.cpp,v 1.3 2006/03/15 06:31:26 mitu Exp $ $NoKeywords: $ *---------------------------------------------------------------------------*/ // dual.cpp : Defines the class behaviors for the application. // #include "stdafx.h" #include "dual.h" #include "MainFrm.h" #include "dualDoc.h" #include "dualView.h" #include ".\dual.h" #ifdef _DEBUG #define new DEBUG_NEW #endif ///////// for dualApp ///////// /////////////////////////////////////////////////////////////////////////////// // // Local function and thread function definition // // Get active view static CDualView* GetActiveView() { POSITION pos; CDocTemplate* pDocTemplate; CDualDoc* pDoc; // Document Template pos = GetApp()->GetFirstDocTemplatePosition(); if ( pos == NULL ) return NULL; pDocTemplate = GetApp()->GetNextDocTemplate(pos); // Document pos = pDocTemplate->GetFirstDocPosition(); if ( pos == NULL ) return NULL; pDoc = static_cast(pDocTemplate->GetNextDoc(pos)); // View pos = pDoc->GetFirstViewPosition(); if ( pos == NULL ) return NULL; return static_cast(pDoc->GetNextView(pos)); } // CHioIf::HIOIF_EVENT_CALLBACK static void HioIfEventCallback(HIO2IF_ID id, HIO2IF_EVENT event) { CDualView* pView; if ( (pView=GetActiveView()) == NULL ) return ; CDualApp* pApp = GetApp(); switch ( event ) { case HIO2IF_EVENT_CONNECT: // Establish connection { BYTE clearBuf[DUAL_BUFFER_SIZE]; DWORD dwAddr; // Activate the View static text and button when connected to NNGC // When open mode is write only if ( pApp->m_pHioIf->GetOpenMode(id) == HIO2IF_MODE_WRONLY ) { pApp->m_nSendID = id; dwAddr = DUAL_PC2NNGC_ADDR; if ( (pView=GetActiveView()) != NULL ) { pView->PostMessage(WM_USER, CDualView::EVENT_SET_SEND_STATUS, CDualView::EVENT_CONNECT); } } else { pApp->m_nRecvID = id; dwAddr = DUAL_NNGC2PC_ADDR; if ( (pView=GetActiveView()) != NULL ) { pView->PostMessage(WM_USER, CDualView::EVENT_SET_RECV_STATUS, CDualView::EVENT_CONNECT); pView->PostMessage(WM_USER, CDualView::EVENT_VALID_RECV_COLOR, 0); } } // Clear the RGB data settings region ZeroMemory(clearBuf, sizeof(clearBuf)); pApp->m_pHioIf->WriteFree(id, dwAddr, clearBuf, DUAL_BUFFER_SIZE, FALSE); } break; case HIO2IF_EVENT_DISCONNECT: // Connection released GetApp()->Disconnect(id); break; case HIO2IF_EVENT_RECEIVED: // Receive data { HIO2IF_RESULT result; if ( pApp->m_nRecvID != HIO2IF_INVALID_ID ) { result = pApp->m_pHioIf->Read(pApp->m_nRecvID, DUAL_NNGC2PC_ADDR, pApp->m_byRecvBuf, DUAL_BUFFER_SIZE, pApp->m_bSync); if ( HIO2IF_SUCCESS(result) && !pApp->m_bSync ) { if ( (pView=GetActiveView()) != NULL ) { pView->PostMessage(WM_USER, CDualView::EVENT_UPDATE_COLOR, (LPARAM) RGB( pApp->m_byRecvBuf[DUAL_DATA_IDX_RED], pApp->m_byRecvBuf[DUAL_DATA_IDX_GREEN], pApp->m_byRecvBuf[DUAL_DATA_IDX_BLUE] ) ); } } } } break; case HIO2IF_EVENT_READ_ASYNC_DONE: if ( (pView=GetActiveView()) != NULL ) { pView->PostMessage(WM_USER, CDualView::EVENT_UPDATE_COLOR, (LPARAM) RGB( pApp->m_byRecvBuf[DUAL_DATA_IDX_RED], pApp->m_byRecvBuf[DUAL_DATA_IDX_GREEN], pApp->m_byRecvBuf[DUAL_DATA_IDX_BLUE] ) ); } break; case HIO2IF_EVENT_WRITE_ASYNC_DONE: case HIO2IF_EVENT_SEND_POSSIBLE: // Send possible default: break; } } // ReadFree thread static DWORD WINAPI ReadFreeThread( LPVOID pHandle ) { CDualApp* pApp = static_cast(pHandle); pApp->m_bThreadBreak = FALSE; while ( !pApp->m_bThreadBreak ) { HIO2IF_RESULT result; if ( pApp->m_nRecvID != HIO2IF_INVALID_ID ) { result = pApp->m_pHioIf->ReadFree(pApp->m_nRecvID, DUAL_NNGC2PC_ADDR, pApp->m_byRecvBuf, DUAL_BUFFER_SIZE, pApp->m_bSync); if ( HIO2IF_SUCCESS(result) ) { // Reflect the received RGB data in View CDualView* pView = GetActiveView(); if ( (pView != NULL) && !pApp->m_bSync ) { pView->PostMessage(WM_USER, CDualView::EVENT_UPDATE_COLOR, (LPARAM)RGB( pApp->m_byRecvBuf[DUAL_DATA_IDX_RED], pApp->m_byRecvBuf[DUAL_DATA_IDX_GREEN], pApp->m_byRecvBuf[DUAL_DATA_IDX_BLUE] ) ); } } } // Read for roughly each 1V Sleep(1000 / 60); } return 0; } //----------------------------------------------------------------------------- BOOL CDualApp::HioIfInit() { // Initialization if ( HIO2IF_FAILED(m_pHioIf->Init()) ) return FALSE; m_nIDCount = 0; m_nSendID = m_nRecvID = HIO2IF_INVALID_ID; m_nOpenID[0] = m_nOpenID[1] = HIO2IF_INVALID_ID; // Open the detected number of channels or the APP_HIOIF_MAX number of channels for (int i=0; (iGetDeviceCount() && iOpen(m_pHioIf->GetDevicePath(i), HioIfEventCallback, (int)m_nOpenID[i])) ) return FALSE; m_nIDCount++; } #ifndef PROTOCOL_USED // Create a thread to run CHioIf -> ReadFree() within a set period DWORD dwTmp; m_bThreadBreak = TRUE; m_hThread = ::CreateThread(NULL, 0, ReadFreeThread, (LPVOID)this, 0, &dwTmp); // Wait until thread launches // Set m_bThreadBreak to FALSE within the ReadFreeThread function) while ( m_bThreadBreak ) ; #endif // PROTOCOL_USED // When protocol communication is taking place, use HIOIF_EVENT_CALLBACK to call CHioIf->Read // return TRUE; } //----------------------------------------------------------------------------- BOOL CDualApp::HioIfExit() { // Terminate thread if ReadFreeThread is valid StopReadFreeThread(); m_pHioIf->EnterCriticalSection(); m_pHioIf->Exit(); // HIO termination m_pHioIf->LeaveCriticalSection(); return TRUE; } //----------------------------------------------------------------------------- void CDualApp::StopReadFreeThread() { #ifndef PROTOCOL_USED // Terminate thread if ReadFreeThread is valid if ( m_hThread != INVALID_HANDLE_VALUE ) { // Halt the EXI thread m_bThreadBreak = TRUE; WaitForSingleObject(m_hThread,1000*30); CloseHandle(m_hThread); m_hThread = INVALID_HANDLE_VALUE; } #endif // PROTOCOL_USED } //----------------------------------------------------------------------------- HIO2IF_RESULT CDualApp::SendRGB(LPRGBQUAD pRGB) { HIO2IF_RESULT ret; m_bySendBuf[DUAL_DATA_IDX_RED] = pRGB->rgbRed; m_bySendBuf[DUAL_DATA_IDX_GREEN] = pRGB->rgbGreen; m_bySendBuf[DUAL_DATA_IDX_BLUE] = pRGB->rgbBlue; m_pHioIf->EnterCriticalSection(); #ifdef PROTOCOL_USED ret = m_pHioIf->Write(m_nSendID, DUAL_PC2NNGC_ADDR, m_bySendBuf, DUAL_BUFFER_SIZE, m_bSync); #else // PROTOCOL_USED ret = m_pHioIf->WriteFree(m_nSendID, DUAL_PC2NNGC_ADDR, m_bySendBuf, DUAL_BUFFER_SIZE, m_bSync); #endif // PROTOCOL_USED m_pHioIf->LeaveCriticalSection(); return ret; } //----------------------------------------------------------------------------- LPCSTR CDualApp::GetStatus(APP_HIOIF_TYPE nType) { // Get the status of send, receive channels as text strings static TCHAR l_szStatus[128]; static LPCSTR l_lpszDeviceName[HIO2_CHAN_MAX + 2] = { "UNKOWN", "EXI2USB0", "EXI2USB1", "MrEXI" }; LPCSTR lpszStatus, lpszExiDev; int nPcChan; HIO2IF_ID nID; nID = (nType == APP_HIOIF_SEND) ? m_nSendID : m_nRecvID; // Receive channel state if ( nID != HIO2IF_INVALID_ID) { lpszStatus = "CONNECT"; nPcChan = m_pHioIf->GetPcChan(nID); lpszExiDev = l_lpszDeviceName[m_pHioIf->GetDeviceType(nID) + 1]; } // Because NNGC opens Receive (Send for PC) with priority else if ( m_nIDCount > nType ) { lpszStatus = "DISCONNECT"; nPcChan = m_pHioIf->GetPcChan(m_nOpenID[nType]); lpszExiDev = l_lpszDeviceName[m_pHioIf->GetDeviceType(nID) + 1]; } else { lpszStatus = "NOT FIND"; nPcChan = -1; lpszExiDev = "UNKOWN"; } sprintf(l_szStatus,"%s CHAN : %s, PC%d, NNGC %s", ((nType == 0) ? "SEND" : "RECV"), lpszStatus, nPcChan, lpszExiDev); return l_szStatus; } //----------------------------------------------------------------------------- void CDualApp::Disconnect(HIO2IF_ID id) { if ( id == HIO2IF_INVALID_ID ) return ; CDualView* pView; // Send ID if ( id == m_nSendID ) { m_pHioIf->Close(m_nSendID); m_nSendID = HIO2IF_INVALID_ID; if ( (pView=GetActiveView()) != NULL ) { pView->PostMessage(WM_USER, CDualView::EVENT_SET_SEND_STATUS, CDualView::EVENT_DISCONNECT); } } // Receive ID else if ( id == m_nRecvID ) { StopReadFreeThread(); m_pHioIf->Close(m_nRecvID); m_nRecvID = HIO2IF_INVALID_ID; if ( (pView=GetActiveView()) != NULL ) { pView->PostMessage(WM_USER, CDualView::EVENT_SET_RECV_STATUS, CDualView::EVENT_DISCONNECT); pView->PostMessage(WM_USER, CDualView::EVENT_INVALID_RECV_COLOR, CDualView::EVENT_DISCONNECT); } } } /////////////////////////////////////////////////////////////////////////////// // // CDualApp // BEGIN_MESSAGE_MAP(CDualApp, CWinApp) ON_COMMAND(ID_APP_ABOUT, OnAppAbout) // Standard file based document commands ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew) ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen) END_MESSAGE_MAP() // CDualApp construction CDualApp::CDualApp() { ////////// for dualApp ////////// m_pHioIf = NULL; m_bSync = FALSE; m_nIDCount = 0; m_nSendID = m_nRecvID = HIO2IF_INVALID_ID; m_nOpenID[0] = m_nOpenID[1] = HIO2IF_INVALID_ID; } // The one and only CDualApp object CDualApp theApp; // CDualApp initialization BOOL CDualApp::InitInstance() { // InitCommonControls() is required on Windows XP if an application // manifest specifies use of ComCtl32.dll version 6 or later to enable // visual styles. Otherwise, any window creation will fail. InitCommonControls(); CWinApp::InitInstance(); // Initialize OLE libraries if (!AfxOleInit()) { AfxMessageBox(IDP_OLE_INIT_FAILED); return FALSE; } AfxEnableControlContainer(); // Standard initialization // If you are not using these features and wish to reduce the size // of your final executable, you should remove from the following // the specific initialization routines you do not need // Change the registry key under which our settings are stored // TODO: You should modify this string to be something appropriate // such as the name of your company or organization SetRegistryKey(_T("Local AppWizard-Generated Applications")); LoadStdProfileSettings(0); // Load standard INI file options (including MRU) ////////// for dualApp ////////// // Initialization m_pHioIf = Hio2CreateInterface(); if ( !HioIfInit() ) { MessageBox(NULL, m_pHioIf->GetMessage(), "ERROR", (MB_OK | MB_ICONWARNING)); return FALSE; } // Register the application's document templates. Document templates // serve as the connection between documents, frame windows and views CSingleDocTemplate* pDocTemplate; pDocTemplate = new CSingleDocTemplate( IDR_MAINFRAME, RUNTIME_CLASS(CDualDoc), RUNTIME_CLASS(CMainFrame), // main SDI frame window RUNTIME_CLASS(CDualView)); if (!pDocTemplate) return FALSE; AddDocTemplate(pDocTemplate); // Parse command line for standard shell commands, DDE, file open CCommandLineInfo cmdInfo; ParseCommandLine(cmdInfo); // Dispatch commands specified on the command line. Will return FALSE if // app was launched with /RegServer, /Register, /Unregserver or /Unregister. if (!ProcessShellCommand(cmdInfo)) return FALSE; ////////// for dualApp ////////// // default settings for send/receive status POSITION pos = pDocTemplate->GetFirstDocPosition(); CDualDoc* pDoc = static_cast(pDocTemplate->GetNextDoc(pos)); pos = pDoc->GetFirstViewPosition(); CDualView* pView = static_cast(pDoc->GetNextView(pos)); pView->PostMessage(WM_USER, CDualView::EVENT_SET_SEND_STATUS, 0); pView->PostMessage(WM_USER, CDualView::EVENT_SET_RECV_STATUS, 0); // The one and only window has been initialized, so show and update it m_pMainWnd->ShowWindow(SW_SHOW); m_pMainWnd->UpdateWindow(); // call DragAcceptFiles only if there's a suffix // In an SDI app, this should occur after ProcessShellCommand return TRUE; } // CDualApp message handlers int CDualApp::ExitInstance() { ////////// for dualApp ////////// HioIfExit(); Hio2ReleaseInterface(m_pHioIf); return CWinApp::ExitInstance(); } // CAboutDlg dialog used for App About class CAboutDlg : public CDialog { public: CAboutDlg(); // Dialog Data enum { IDD = IDD_ABOUTBOX }; protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support // Implementation protected: DECLARE_MESSAGE_MAP() }; CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) { } void CAboutDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); } BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) END_MESSAGE_MAP() // App command to run the dialog void CDualApp::OnAppAbout() { CAboutDlg aboutDlg; aboutDlg.DoModal(); }