#include "stdafx.h" #include "IRayDMCtrl.h" IRayCtrl* g_pIRayCtrl = nullptr; const int INIT_TIMEOUT = 10000; void SDKCallbackProxy(int nDetectorID, int nEventID, int nEventLevel, const char* pszMsg, int nParam1, int nParam2, int nPtrParamLen, void* pParam) { g_pIRayCtrl->ProcessEvent(nDetectorID, nEventID, nEventLevel, pszMsg, nParam1, nParam2, nPtrParamLen, pParam); } void FpdScanResult(DetectorProfile* pDetectorProfile) { g_pIRayCtrl->ScanResult(pDetectorProfile); } IRayCtrl::IRayCtrl() { m_hInitThread = NULL; m_hScanEventThread = NULL; m_pDPC2PanelID = new map(); m_pPanelID2DPC = new map(); //m_pImageBuffer = NULL; m_nPanelCount = 0; m_nCurrentPanelID = 0; m_strWorkPath = ""; m_bOpened = false; m_eAppStatus = APP_STATUS_IDLE; m_nCurrentMode = -1; m_nImageWidth = 0; m_nImageHeight = 0; m_nRawImgWidth = 0; m_nRawImgHeight = 0; m_nWidthOffset = 0; m_nHeightOffset = 0; m_pImgBuffer = NULL; m_nImgBits = 16; m_nPixelPitch = 150; m_bPreviewEnable = false; m_nPreviewWidth = 0; m_nPreviewHeight = 0; m_bModuleConnecting = false; m_bModulePresent = false; m_bInCalibrating = false; m_pwPreviewImg = NULL; m_pwRawImageData = NULL; m_pXWindowoffThread = NULL; m_pOffsetThread = NULL; m_bInExposure = false; m_bWindowOn = false; m_nRecoverImageTimes = 0; m_hInitThread = NULL; m_hScanEventThread = NULL; for (int i = 0; i < SCAN_EVENT_NUM; ++i) { m_hArrayEvent[i] = nullptr; } m_hExitEvent = NULL; m_hRecoverImage = NULL; m_hCofirmCalib = NULL; m_hEndCalibEvent = NULL; m_hIRayModule = nullptr; m_fpGetSDKVersion = nullptr; m_fpSetUserCode = nullptr; m_fpNotifyScanResult = nullptr; m_fpRegisterScanNotify = nullptr; m_fpScanOnce = nullptr; m_fpCallback = nullptr; m_fpCreate = nullptr; m_fpDestroy = nullptr; m_fpGetAttr = nullptr; m_fpSetAttr = nullptr; m_fpInvoke = nullptr; m_fpAbort = nullptr; m_fpOpenDefectTemplateFile = nullptr; m_fpSaveDefectTemplateFile = nullptr; m_fpCloseDefectTemplateFile = nullptr; m_bOpened = false; m_bInitialing = false; m_nAppMode = 0; m_nExpMode = 0; m_nFilterMode = 0; m_nTotalFrameNum = 0; m_nCurrentFrame = 0; m_nTriggerMode = 0; m_nClinicalApplicationMode = 0; } IRayCtrl::~IRayCtrl() { ExitDetectorScanThread(); if (m_pImgBuffer) { delete[] m_pImgBuffer; m_pImgBuffer = NULL; } if (m_pwPreviewImg) { delete[]m_pwPreviewImg; m_pwPreviewImg = NULL; } if (m_pwRawImageData) { delete[]m_pwRawImageData; m_pwRawImageData = NULL; } delete m_pDPC2PanelID; m_pDPC2PanelID = NULL; delete m_pPanelID2DPC; m_pPanelID2DPC = NULL; } bool IRayCtrl::ExitDetectorScanThread() { m_bOpened = false; SetEvent(m_hExitEvent); Info("Waiting iRay ScanEvent Thread End"); DWORD nResult = WaitForSingleObject(m_hIRayScanEnd, 5000); if (WAIT_TIMEOUT == nResult) //m_hIRayScanEnd { Error("Detector ScanEvent Thread Quit TimeOut"); ::TerminateThread(m_hScanEventThread, 0); } else { Info("Detector ScanEvent Thread Quit Success"); } m_hScanEventThread = NULL; DeleteHandle(); Info("Free IRay DLL"); FreeIRayDLL(); return true; } void IRayCtrl::DeleteHandle() { if (m_hSharedEvent) { CloseHandle(m_hSharedEvent); m_hSharedEvent = NULL; } if (m_hExitEvent) { CloseHandle(m_hExitEvent); m_hExitEvent = NULL; } if (m_hRecoverImage) { CloseHandle(m_hRecoverImage); m_hRecoverImage = NULL; } if (m_hCofirmCalib) { CloseHandle(m_hCofirmCalib); m_hCofirmCalib = NULL; } if (m_hEndCalibEvent) { CloseHandle(m_hEndCalibEvent); m_hEndCalibEvent = NULL; } if (m_hIRayScanEnd) { CloseHandle(m_hIRayScanEnd); m_hIRayScanEnd = NULL; } } bool IRayCtrl::Init(string strAppPath) { m_strWorkPath = strAppPath + "OEMDrivers\\Detector\\IRayDM\\IRay"; Info("IRayCtrl::Init {$}", m_strWorkPath.c_str()); bool ret = false; ret = LoadIRayDLL(m_strWorkPath); if (!ret) { Error("LoadIRayDLL failed"); return false; } //同步事件锁 m_hSharedEvent = CreateEvent(NULL, FALSE, FALSE, NULL); //开窗控制事件 m_hWindowOffEvent = CreateEvent(NULL, FALSE, FALSE, NULL); int nResult = 0; char szVersion[32] = { 0 }; nResult = m_fpGetSDKVersion(szVersion); if (Err_OK != nResult) { Fatal("Get Attachment SDK Version failed!"); return false; } Info("Get iRay Mammo SDK version: {$}", szVersion); /*Info("Call RegisterScanNotify"); DetectorProfile* FpdScanResult = nullptr; m_fpNotifyScanResult(FpdScanResult);*/ Info("Init over\n"); return ret; } bool IRayCtrl::LoadIRayDLL(string strWorkPath) { Info("IRayCtrl::LoadIRayDLL"); string strDllDir = strWorkPath; if (::SetDllDirectory(strDllDir.c_str()) == 0) { DWORD dwErrorCode = GetLastError(); Info("SetDllDirectory error, error code ({$})", dwErrorCode); return false; } string strDllPath = strWorkPath + "\\FpdSys_MAM.dll"; Info("Load {$}", strDllPath); m_hIRayModule = ::LoadLibrary(strDllPath.c_str()); if (NULL == m_hIRayModule) { Fatal("Load FpdSys_MAM.dll failed!"); return false; } m_fpGetSDKVersion = (FnGetSDKVersion)GetProcAddress(m_hIRayModule, IRAY_FPD_PROC_NAME_VERSION); if (NULL == m_fpGetSDKVersion) { Fatal("API GetSDKVersion failed"); return false; } m_fpSetUserCode = (FnSetUserCode)GetProcAddress(m_hIRayModule, IRAY_FPD_PROC_SET_USERCODE); if (NULL == m_fpSetUserCode) { Fatal("API SetUserCode failed"); return false; } m_fpNotifyScanResult = (FnNotifyScanResult)GetProcAddress(m_hIRayModule, IRAY_FPD_PROC_NAME_REGISTER_SCANNotify); if (NULL == m_fpNotifyScanResult) { Fatal("API NotifyScanResult failed"); return false; } m_fpCreate = (FnCreate)GetProcAddress(m_hIRayModule, IRAY_FPD_PROC_NAME_CREATE); if (NULL == m_fpCreate) { Fatal("GetProcAddress:Create failed!"); return false; } m_fpDestroy = (FnDestroy)GetProcAddress(m_hIRayModule, IRAY_FPD_PROC_NAME_DESTROY); if (NULL == m_fpDestroy) { Fatal("GetProcAddress:Destroy failed!"); return false; } m_fpGetAttr = (FnGetAttr)GetProcAddress(m_hIRayModule, IRAY_FPD_PROC_NAME_GETATTR); if (NULL == m_fpGetAttr) { Fatal("GetProcAddress:GetAttr failed!"); return false; } m_fpSetAttr = (FnSetAttr)GetProcAddress(m_hIRayModule, IRAY_FPD_PROC_NAME_SETATTR); if (NULL == m_fpSetAttr) { Fatal("GetProcAddress:SetAttr failed!"); return false; } m_fpInvoke = (FnInvoke)GetProcAddress(m_hIRayModule, IRAY_FPD_PROC_NAME_INVOKE); if (NULL == m_fpInvoke) { Fatal("GetProcAddress:Invoke failed!"); return false; } Info("LoadIRayDLL over"); return true; } bool IRayCtrl::FreeIRayDLL() { if (m_hIRayModule) { FreeLibrary(m_hIRayModule); m_hIRayModule = NULL; Info("Free IRay DLL"); } return true; } bool IRayCtrl::AddDPCs(nsDPC::FPDDeviceIRay* pDrvDPC, ResDataObject& Configuration, DeviceIndexStruct& DeviceStruct) { Info("IRayCtrl::AddDPCs {$}", pDrvDPC); map::iterator DPCsIter = m_pDPC2PanelID->find(pDrvDPC); if (DPCsIter != m_pDPC2PanelID->end()) { Info("IRayCtrl::AddDPCs This DPC already exist"); return false; } //拿到当前探测器的配置 m_stDeviceIndex[m_nPanelCount] = DeviceStruct; m_ObjFPDsInfo[m_nPanelCount] = Configuration; Info("AddDPCs, {$}{$} \n", m_stDeviceIndex[m_nPanelCount].strDetectorModel, m_stDeviceIndex[m_nPanelCount].strDeviceName); m_pDPC2PanelID->insert(pair(pDrvDPC, m_nPanelCount)); m_pPanelID2DPC->insert(pair(m_nPanelCount, pDrvDPC)); m_ModeConfig = m_ObjFPDsInfo[m_nCurrentPanelID]; m_nPanelCount++; Info("AddDPCs over, Panel count: {$}", m_nPanelCount); return true; } bool IRayCtrl::DelDPCs(nsDPC::FPDDeviceIRay* pDrvDPC) { Info("IRayCtrl::DelDPCs {$}", pDrvDPC); map::iterator DPCsIter = m_pDPC2PanelID->find(pDrvDPC); if (DPCsIter != m_pDPC2PanelID->end()) { map::iterator PanelIdIter = m_pPanelID2DPC->find(DPCsIter->second); if (PanelIdIter != m_pPanelID2DPC->end()) { m_pPanelID2DPC->erase(PanelIdIter); } m_stDeviceIndex[DPCsIter->second] = {}; m_ObjFPDsInfo[DPCsIter->second].clear(); m_pDPC2PanelID->erase(DPCsIter); m_nPanelCount--; Info("DelDPCs over {$}\n", m_nPanelCount); } return true; } void IRayCtrl::ConfFeedback(int nEventID, int nDetectorID, const char* pszMsg, int nParam1, float fParam2, int nPtrParamLen, void* pParam) { if (-1 == nDetectorID) { nDetectorID = m_nCurrentPanelID; } ((*m_pPanelID2DPC)[nDetectorID])->OnFPDCallback(nDetectorID, nEventID, EVT_LEVEL_CONFIGURATION, pszMsg, nParam1, fParam2, nPtrParamLen, pParam); } void IRayCtrl::InfoFeedback(int nEventID, int nDetectorID, int nParam1, float fParam2, const char* pszMsg, int nPtrParamLen, void* pParam) { if (-1 == nDetectorID) { nDetectorID = m_nCurrentPanelID; } ((*m_pPanelID2DPC)[nDetectorID])->OnFPDCallback(nDetectorID, nEventID, EVT_LEVEL_INFORMATOION, pszMsg, nParam1, fParam2, nPtrParamLen, pParam); } void IRayCtrl::StatusFeedback(int nEventID, int nParam1, const char* pszMsg, int nDetectorID, float fParam2, int nPtrParamLen, void* pParam) { if (-1 == nDetectorID) { nDetectorID = m_nCurrentPanelID; } ((*m_pPanelID2DPC)[nDetectorID])->OnFPDCallback(nDetectorID, nEventID, EVT_LEVEL_STATUS, pszMsg, nParam1, fParam2, nPtrParamLen, pParam); } void IRayCtrl::DataFeedback(int nEventID, void* pParam, int nParam1, float fParam2, const char* pszMsg, int nPtrParamLen, int nDetectorID) { if (-1 == nDetectorID) { nDetectorID = m_nCurrentPanelID; } ((*m_pPanelID2DPC)[nDetectorID])->OnFPDCallback(nDetectorID, nEventID, EVT_LEVEL_DATA, pszMsg, nParam1, fParam2, nPtrParamLen, pParam); } void IRayCtrl::WarnFeedback(int nEventID, const char* pszMsg, int nParam1, float fParam2, int nPtrParamLen, void* pParam, int nDetectorID) { if (-1 == nDetectorID) { nDetectorID = m_nCurrentPanelID; } ((*m_pPanelID2DPC)[nDetectorID])->OnFPDCallback(nDetectorID, nEventID, EVT_LEVEL_WARNING, pszMsg, nParam1, fParam2, nPtrParamLen, pParam); } void IRayCtrl::ErrorFeedback(int nEventID, const char* pszMsg, int nDetectorID, int nParam1, float fParam2, int nPtrParamLen, void* pParam) { if (-1 == nDetectorID) { nDetectorID = m_nCurrentPanelID; } ((*m_pPanelID2DPC)[nDetectorID])->OnFPDCallback(nDetectorID, nEventID, EVT_LEVEL_ERROR, pszMsg, nParam1, fParam2, nPtrParamLen, pParam); } /*** ** 说明:连接,加载SDK,初始化SDK,连接探测器等初始化操作。 ** 参数:strWorkPath,初始化SDK必须的conf路径 ***/ bool IRayCtrl::Connect(string strAppPath, nsDPC::FPDDeviceIRay* pDrvDPC) { Info("IRayCtrl::Connect"); if ((*m_pDPC2PanelID)[pDrvDPC] != m_nCurrentPanelID) { Warn("Not current DPC, return true"); return true; } g_strAppPath = strAppPath; Info("APP Path: {$}", g_strAppPath); StartInitFPDThread(); Info("=== Connect detector OK ==="); return true; } /*** * 说明:断连探测器 * 参数:pDrvDPC: 探测器的ID。 ***/ bool IRayCtrl::DisConnect(nsDPC::FPDDeviceIRay* pDrvDPC) { if ((*m_pDPC2PanelID)[pDrvDPC] != m_nCurrentPanelID) { Warn("Not current DPC, return"); return true; } Info("IRayCtrl::DisConnect"); int nPanelID = m_nCurrentPanelID + 1; int nResult = IrayFnInvoke(nPanelID, Cmd_Disconnect, NULL, 0); if (TestError(m_nCurrentPanelID, nResult)) { Info("Disconnect Detector {$} Failed", nPanelID); } Info("Call Destroy"); nResult = m_fpDestroy(nPanelID); TestError(m_nCurrentPanelID, nResult); Info("DisConnect Over"); return true; } FPDRESULT IRayCtrl::IrayFnInvoke(int nDetectorID, int nCommandID, IRayCmdParam pars[], int nParCount) { int trytimes = 0; FPDRESULT nResult = Err_OK; while (trytimes++ < 6) { nResult = m_fpInvoke(nDetectorID, nCommandID, pars, nParCount); if (Err_StateErr != nResult) return nResult; else Sleep(1000); } return nResult; } bool IRayCtrl::TestError(int nDetectorID, int nErrorStatus) { string strLog = ""; switch (nErrorStatus) { case Err_OK: return false; case Err_TaskPending: { return false; } case Err_Unknown: Fatal("Err_Unknown"); break; case Err_NotInitialized: Fatal("Err_NotInitialized"); break; case Err_TemplateFileNotExist: case Err_TemplateFileNotMatch: break; case Err_InvalidPacketNo: case Err_InvalidPacketFormat: case Err_PacketDataCheckFailed: Fatal("25/26/27 Transfering image not finished"); break; case Err_ImgChBreak: Fatal("Err_ImgChBreak"); break; case Err_GeneralSocketErr: Fatal("Err_GeneralSocketErr"); break; case Err_ApplyFirmwareFailed: case Err_FPD_General_Detector_Error: case Err_FPD_Busy: case Err_TaskTimeOut: case Err_DetectorRespTimeout: break; case Err_NotEnoughMemorySpace: break; case Err_ConfigFileNotExist: default: Error("Get ErrCode: {$} ", nErrorStatus); break; } return true; } //启动初始化线程 void IRayCtrl::StartInitFPDThread() { Info("-----Start Init Thread------"); DWORD dwThreadID; if (m_hInitThread == NULL) { m_hInitThread = CreateThread(0, 0, onInitPanel, this, 0, &dwThreadID); if (m_hInitThread == NULL) { Fatal("Start Init Thread Error"); } } } //初始化 DWORD IRayCtrl::onInitPanel(void* pParam) { IRayCtrl* pInstance = reinterpret_cast(pParam); pInstance->Action_Init(); pInstance->m_hInitThread = NULL; return true; } void IRayCtrl::Action_Init() { Info("IRayCtrl::Action_Init"); m_bInitialing = true; int nPanelID = 0; m_stDeviceIndex[nPanelID].strWorkDir = g_strAppPath + "\\OEMDrivers\\Detector\\IRayDM\\IRay\\work_dir\\Mammo1012F2"; string strWorkDir = (m_stDeviceIndex[nPanelID].strWorkDir); Info("Call Create: {$}", strWorkDir.c_str()); int nRet = m_fpCreate(strWorkDir.c_str(), SDKCallbackProxy, &nPanelID); if (TestError(nPanelID, nRet)) { Error("Create Detector {$} Callback Failed", nPanelID); } Info("Create Detector {$} Callback Success", nPanelID); bool bRet = DetectorInitProcess(nPanelID); if (!bRet) { Info("Detector init process connect failed"); } iRayScanEventThread(); //获取探测器当前触发模式 GetSyncMode(nPanelID, m_nTriggerMode); Info("Get Mammo trigger mode: {$}({$})", TriggerModeName(m_nTriggerMode), m_nTriggerMode); //if (m_nTriggerMode != Enm_TriggerMode_Prep) //如果不是Prep触发方式,那么切换到该模式 if (m_nTriggerMode != Enm_TriggerMode_SyncOut) { SetSyncMode(nPanelID, Enm_TriggerMode_SyncOut); } int nOffsetType = 0; //生成HW_Offset PerformOffset(nPanelID, nOffsetType); m_bInitialing = false; Info("Action init over"); } /************************************************************************************ 功能:启动辅助线程,处理一些异步消息 ************************************************************************************/ void IRayCtrl::iRayScanEventThread() { m_hExitEvent = CreateEvent(NULL, FALSE, FALSE, NULL); m_hRecoverImage = CreateEvent(NULL, FALSE, FALSE, NULL); m_hCofirmCalib = CreateEvent(NULL, FALSE, FALSE, NULL); m_hEndCalibEvent = CreateEvent(NULL, FALSE, FALSE, NULL); m_hOffsetEvent = CreateEvent(NULL, FALSE, FALSE, NULL); m_hIRayScanEnd = CreateEvent(NULL, FALSE, FALSE, NULL); m_hArrayEvent[0] = m_hExitEvent; m_hArrayEvent[1] = m_hRecoverImage; m_hArrayEvent[2] = m_hCofirmCalib; m_hArrayEvent[3] = m_hEndCalibEvent; m_hArrayEvent[4] = m_hOffsetEvent; if (m_hScanEventThread != NULL) { Info("ScanEvent Thread already run\n"); return; } Info("Start ScanEvent Thread"); DWORD dwThreadID; m_hScanEventThread = (HANDLE)CreateThread(NULL, 0, onScanEvent, (LPVOID)this, 0, &dwThreadID); if (m_hScanEventThread == NULL) { Fatal("Start Scan Event Error"); } Info("Start ScanEvent Thread ok, ThreadID: {$}", dwThreadID); } /************************************************************************************ 功能:启动线程,处理一些异步消息 m_hRecoverImage 异步,恢复图像 m_hCofirmCalib 异步,确认每一次校正的结果,如剂量大了/小了/ m_hReconnectFD 异步,初始化探测器 ************************************************************************************/ DWORD IRayCtrl::onScanEvent(void* pParam) { IRayCtrl* pInstance = (IRayCtrl*)pParam; if (pInstance == NULL) { Error("onScanEvent parameter error!!!"); return false; } bool bExitFlag = true; while (bExitFlag) { Info("(Waiting for Signal...)"); DWORD dwResult = WaitForMultipleObjects(SCAN_EVENT_NUM, pInstance->m_hArrayEvent, FALSE, INFINITE); if (WAIT_OBJECT_0 == dwResult) //m_hExitEvent { Info("[Get Exit Event]"); bExitFlag = false; } else if (WAIT_OBJECT_0 + 1 == dwResult) //m_hRecoverImage { //pInstance->CallSiemensRecoverAction(true); if (pInstance->m_nRecoverImageTimes < 2) { Info("[Get RecoverImage Event]"); pInstance->m_nRecoverImageTimes++; //pInstance->RecoverLastImageAuto(); } else { Info("Get RecoverImage Event already retry 2 times, omit it"); } } else if (WAIT_OBJECT_0 + 2 == dwResult) //m_hCofirmCalib { Info("[Get Cofirm Calibration Event]"); //pInstance->ConfirmCalibration(); } else if (WAIT_OBJECT_0 + 3 == dwResult) //m_hEndCalibEvent { Info("[Get EndCalibraion Event]"); //pInstance->OnEndCalibraion(); } else if (WAIT_OBJECT_0 + 4 == dwResult) //m_hOffsetEvent { Info("[Get Offset Event]"); pInstance->PerformOffset(pInstance->m_nCurrentPanelID + 1, 0); } } SetEvent(pInstance->m_hIRayScanEnd); Info("iRay ScanEvent Thread End"); return true; } bool IRayCtrl::WaitRespond(int nTimeOut) { Info("---WaitRespond---:{$}", nTimeOut); DWORD nResult = WaitForSingleObject(m_hSharedEvent, nTimeOut); if (WAIT_TIMEOUT == nResult) //偶尔会出现EVT_HARDWARE太慢的情况 { Warn("Lock TimeOut");//出现超时,肯定是有问题了 ResetEvent(m_hSharedEvent); return false; } ResetEvent(m_hSharedEvent); return true; } void IRayCtrl::SendNotify() { Info("---SendNotify---"); SetEvent(m_hSharedEvent); } void IRayCtrl::ResetLock() { ResetEvent(m_hSharedEvent); } void IRayCtrl::Pausetime(DWORD dwSpan) { DWORD dtstart = ::GetTickCount(); while ((::GetTickCount() - dtstart) < dwSpan) { MSG msg; while (::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { ::TranslateMessage(&msg); ::DispatchMessage(&msg); } } } bool IRayCtrl::WaitReady(int nPanelIndex, int nMs) { int nState = 0; int nWaitMs = 0; bool bResult = true; string strLog; /*do { bResult = GetDetectorStatus(nPanelIndex, nState); if (nState == Enm_State_Ready) { return true; } else { nWaitMs += 100; Pausetime(100); Info("WaitReady has waited [{$}] ms", nWaitMs); } } while (nWaitMs < nMs);*/ return false; } bool IRayCtrl::DetectorInitProcess(int nDetectorID) { int nPanelIndex = nDetectorID - 1; Info("Call FnInvoke: Connect"); m_stDeviceIndex[nDetectorID].bEventReturn = false; int nRet = IrayFnInvoke(nDetectorID, Cmd_Connect, NULL, 0); if (TestError(nDetectorID, nRet)) { Error("Connect Detector {$} Failed", nDetectorID); return false; } bool bResult = WaitRespond(INIT_TIMEOUT); if (!m_stDeviceIndex[nDetectorID - 1].bConnectStatus) { Info("Connect Detector {$} Failed", nDetectorID); } Info("Connect Detector {$} Success", nDetectorID); m_stDeviceIndex[nPanelIndex].nPixelSpace = 139; m_stDeviceIndex[nPanelIndex].bExisted = true; m_stDeviceIndex[nPanelIndex].bInitOK = true; char pszSerialNo[64] = { 0 }; nRet = GetAttr(nDetectorID, Attr_UROM_SerialNo, pszSerialNo); if (TestError(nDetectorID, nRet)) { Info("Get detector serial number failed"); } Info("Detector serial number: {$}", pszSerialNo); char pszMainVersion[64] = { 0 }; nRet = GetAttr(nDetectorID, Attr_UROM_MainVersion, pszMainVersion); if (TestError(nDetectorID, nRet)) { Info("Get detector main version failed"); } Info("Detector main version: {$}", pszMainVersion); char pszSDKVersion[32] = { 0 }; nRet = m_fpGetSDKVersion(pszSDKVersion); if (TestError(nDetectorID, nRet)) { Info("Get SDK version failed"); } Info("SDK version: {$}", pszSDKVersion); OnInitStatus(nPanelIndex, PANEL_EVENT_END_OK); return true; } bool IRayCtrl::OnInitStatus(int nPanelIndex, ENUM_PANEL_EVENT_STATE ePanelState) { int nDetectorID = 0; if (PANEL_EVENT_START == ePanelState) { StatusFeedback(EVT_STATUS_INIT, PANEL_EVENT_START, ""); } else if (PANEL_EVENT_END_OK == ePanelState) { StatusFeedback(EVT_STATUS_INIT, PANEL_EVENT_END_OK, ""); } else if (PANEL_EVENT_END_ERROR == ePanelState) { StatusFeedback(EVT_STATUS_INIT, PANEL_EVENT_END_ERROR, ""); } else if (PANEL_EVENT_END == ePanelState) //未连接探测器 { StatusFeedback(EVT_STATUS_INIT, PANEL_EVENT_END, ""); } return true; } void IRayCtrl::ProcessEvent(int nDetectorID, int nEventID, int nEventLevel, const char* pszMsg, int nParam1, int nParam2, int nPtrParamLen, void* pParam) { string strDescrip = (pszMsg); Info("DetectorID:{$},Event:{$},Param1:{$},Param2:{$},Description:{$}", nDetectorID, nEventID, nParam1, nParam2, strDescrip.c_str()); switch (nEventID) { case Evt_Exp_Prohibit: { Info("[ Event:Evt_Exp_Prohibit]"); } break; case Evt_Exp_Enable: { Info("[ Event:Evt_Exp_Enable]"); StatusFeedback(EVT_STATUS_PANEL, PANEL_XWINDOW_ON); m_bWindowOn = true; StartXWindowOffThread(); } break; case Evt_TaskResult_Canceled: { Info("[ Evt_TaskResult_Canceled ]"); } break; case Evt_AutoTask_Started: { Info("[ Evt_AutoTask_Started ]"); } break; case Evt_TaskResult_Succeed: Info( "[ Evt_TaskResult_Succeed ]"); OnProcessTaskResult(nDetectorID, nParam1, nParam2, true); break; case Evt_TaskResult_Failed: Info( "[ Evt_TaskResult_Failed ]"); OnProcessTaskResult(nDetectorID, nParam1, nParam2, false); break; case Evt_Retransfer_Image: Info("[ Event:Evt_Retransfer_Image], Omit it"); break; case Evt_Image: { m_stDeviceIndex[nDetectorID - 1].bConnectStatus = true; Info("[ Event:Evt_Image],Image ReadOut = true"); IRayImage* pstImg = (IRayImage*)pParam; if (pstImg == NULL) { Fatal("Image Data is NULL"); return; } /*for (size_t i = 0; i < pstImg->propList.nItemCount; i++) { switch (pstImg->propList.pItems[i].nMapKey) { case Enm_ImageTag_AvgValue: { int nAvgValue = pstImg->propList.pItems[i].varMapVal.val.nVal; Info("Image Avg Value:{$}", nAvgValue); break; } case Enm_ImageTag_CenterValue: { int nCenterValue = pstImg->propList.pItems[i].varMapVal.val.nVal; Info("Image Center Value : {$}", nCenterValue); break; } } }*/ int nRawImgHeight = pstImg->nHeight; int nRawImgWidth = pstImg->nWidth; Info("Image Height:{$},Width:{$}", nRawImgHeight, nRawImgWidth); if (m_pwRawImageData) { delete[]m_pwRawImageData; m_pwRawImageData = NULL; } m_pwRawImageData = new WORD[nRawImgHeight * nRawImgWidth]; if (m_pwRawImageData == NULL) { Fatal("Allocate Raw Image Failed"); return; } memcpy(m_pwRawImageData, pstImg->pData, nRawImgHeight * nRawImgWidth * sizeof(WORD)); FlipX(m_pwRawImageData, nRawImgWidth, nRawImgHeight); //memcpy(m_pImgBuffer, m_pwRawImageData, m_nImageHeight * m_nImageWidth * sizeof(WORD)); OnProcessImg(); } break; case Evt_Prev_Image: { Info("[ Event:Evt_Prev_Image]"); IRayImage* pstImg = (IRayImage*)pParam; m_stDeviceIndex[nDetectorID - 1].nImageBits = pstImg->nBytesPerPixel * 8; int nPreviewHeight = pstImg->nHeight; int nPreviewWidth = pstImg->nWidth; if (m_pwPreviewImg != NULL) { delete[] m_pwPreviewImg; m_pwPreviewImg = NULL; } if (m_pwPreviewImg == NULL) { m_pwPreviewImg = new WORD[nPreviewHeight * nPreviewWidth]; if (m_pwPreviewImg == NULL) { Fatal("Allocate Preview Image Memery Failed"); return; } } memcpy(m_pwPreviewImg, pstImg->pData, nPreviewHeight * nPreviewWidth * sizeof(WORD)); //OnProcessPreImg(); } break; case Evt_WaitImage_Timeout: { Info("[ Evt_WaitImage_Timeout ],Omit"); //string strError = ERR_FPD_FATAL_ERROR; //bug 8113 //OnError(nDetectorID-1, strError, ""); } break; case Evt_Mammo_Flow_End: { Info("[ Evt_Mammo_Flow_End ]"); ((*m_pPanelID2DPC)[m_nCurrentPanelID])->m_bStatusInAEC = false; } break; default: break; } } void IRayCtrl::OnProcessTaskResult(int nPanelID, int nParam1, int nParam2, bool bResult) { int nDetectorID = nPanelID - 1; string strTaskResult = " Task Success"; if (!bResult) { strTaskResult = " Task Failed"; } switch (nParam1) { case 0: { TestError(nDetectorID, nParam2); if (Err_TemplateFileNotExist == nParam2) { Info("Template file no exist"); } } break; case Cmd_Disconnect: { Info("FPD {$} is Disconnected", nPanelID); SendNotify(); m_stDeviceIndex[nDetectorID].bExisted = false; //QUESTION m_stDeviceIndex[nDetectorID].bInitOK = false; m_stDeviceIndex[nDetectorID].bConnectStatus = false; //m_nBatteryCapacity = 0; //SendDetectorInfo(nDetectorID); //状态栏图标更新状态 } break; case Cmd_Connect: Info("[ Cmd_Connect ]"); m_stDeviceIndex[nDetectorID].bEventReturn = true; if (bResult) { Info("FPD {$} is Connected", nPanelID); m_stDeviceIndex[nDetectorID].bInitOK = true;//已经连接成功过了,后面不需要在connect了,等待SDK自动connect就可以了。 m_stDeviceIndex[nDetectorID].bConnectStatus = true; m_stDeviceIndex[nDetectorID].bConnectChanged = true; //连接恢复之后,都要先查询一次有没有未传输成功的图像 m_nCmdConnectResult = nParam2; SendNotify(); } else { m_stDeviceIndex[nDetectorID].bConnectStatus = false; Fatal("FPD {$} connect failed", nPanelID); m_nCmdConnectResult = nParam2; } break; case Cmd_SetCaliSubset: { Info("Cmd_SetCaliSubset{$}", strTaskResult); SendNotify(); } break; case Cmd_ReadUserROM: Info("[ Cmd_ReadUserROM ]"); break; case Cmd_WriteUserROM: { m_stDeviceIndex[nDetectorID].bWriteROM = bResult; Info("Cmd_WriteUserROM {$}", strTaskResult.c_str()); //SendNotify(); } break; case Cmd_OffsetGeneration: { Info("Cmd_OffsetGeneration{$}", strTaskResult.c_str()); SendNotify(); } break; case Cmd_GainInit: { Info("Cmd_GainInit{$}", strTaskResult.c_str()); SendNotify(); } break; case Cmd_DefectInit: { Info("Cmd_DefectInit{$}", strTaskResult.c_str()); SendNotify(); } break; case Cmd_DefectSelectCurrent: { Info("Cmd_DefectSelectCurrent{$}", strTaskResult.c_str()); SendNotify(); } break; case Cmd_FinishGenerationProcess: { Info("Cmd_FinishGenerationProcess{$}", strTaskResult.c_str()); SendNotify(); } break; case Cmd_UpdateFirmware: { Info("Cmd_UpdateFirmware{$}", strTaskResult.c_str()); m_stDeviceIndex[nDetectorID].bUpdateFirmware = bResult; if (TestError(nDetectorID, nParam2)) {//失败时,发notify结束超时等待 SendNotify(); } //else 不发,等探测器重启后,由SDK callback Cmd_connect时发notify结束 } break; case Cmd_ReadTemperature: { Info("Cmd_ReadTemperature{$}", strTaskResult.c_str()); m_stDeviceIndex[nDetectorID].bReadTemperature = bResult; SendNotify(); } break; case Cmd_SetCorrectOption: { Info("Cmd_SetCorrectOption{$}", strTaskResult.c_str()); m_stDeviceIndex[nDetectorID].bSetCorrection = bResult; SendNotify(); } break; case Cmd_ReadHumidity: { Info("Cmd_ReadHumidity"); } break; case Cmd_ClearAcq: { Info("Cmd_ClearAcq{$}", strTaskResult.c_str()); m_bInExposure = false; m_stDeviceIndex[nDetectorID].bTaskEnd = true; } break; case Cmd_Clear: { Info("Cmd_Clear"); } break; case Cmd_StartAcq: { Info("Cmd_StartAcq{$}", strTaskResult.c_str()); } break; case Cmd_HwGeneratePreOffsetTemplate: { m_stDeviceIndex[nDetectorID].bEventReturn = bResult; Info("Cmd_HwGeneratePreOffsetTemplate{$}", strTaskResult.c_str()); m_stDeviceIndex[nDetectorID].bOffsetOver = false; SendNotify(); } break; case Cmd_DownloadCaliFile: { Info("Cmd_DownloadCaliFile{$}", strTaskResult.c_str()); SendNotify(); } break; case Cmd_UploadCaliFile: { m_stDeviceIndex[nDetectorID].bUploadCalibFile = bResult; Info("Cmd_UploadCaliFile{$}", strTaskResult.c_str()); SendNotify(); break; } case Cmd_SelectCaliFile: { m_stDeviceIndex[nDetectorID].bUploadCalibFile = bResult; Info("Cmd_SelectCaliFile{$}", strTaskResult.c_str()); SendNotify(); } break; case Cmd_SetCurAppMode: Info("Cmd_SetCurAppMode{$}", strTaskResult.c_str()); SendNotify(); break; default: break; } } bool IRayCtrl::ScanResult(DetectorProfile* pDetectorProfile) { Info("Scan Product No:{$}", pDetectorProfile->nProdNo); string strIP = pDetectorProfile->szIP; Info("Scan Detector IP:{$}", strIP.c_str()); string strSN = pDetectorProfile->szSN; Info("Scan Detector SN:{$}", strSN.c_str()); if (m_nPanelCount > 0)//SDK 会自动恢复连接,不需要再调用connect,反而会影响SDK的动作 { } return true; } bool IRayCtrl::GetAttr(int nDetectorID, int nAttrID, int& nValue) { IRayVariant var; var.vt = IVT_INT; var.val.nVal = 0; FPDRESULT nResult = m_fpGetAttr(nDetectorID, nAttrID, &var); if (TestError(nDetectorID - 1, nResult)) { Fatal("Get Attribute Failed"); return false; } nValue = var.val.nVal; return true; } bool IRayCtrl::GetAttr(int nDetectorID, int nAttrID, float& fValue) { float ftemp = 0.0f; IRayVariant var; var.vt = IVT_FLT; var.val.fVal = ftemp; FPDRESULT nResult = m_fpGetAttr(nDetectorID, nAttrID, &var); if (TestError(nDetectorID - 1, nResult)) { Fatal("Get Attribute Failed"); return false; } fValue = var.val.fVal; return true; } bool IRayCtrl::GetAttr(int nDetectorID, int nAttrID, char* pszAttr) { IRayVariant var; var.vt = IVT_STR; memset(var.val.strVal, 0, IRAY_MAX_STR_LEN); FPDRESULT nResult = m_fpGetAttr(nDetectorID, nAttrID, &var); if (TestError(nDetectorID - 1, nResult)) { Fatal("Get Attribute Failed"); return false; } size_t len = strlen(var.val.strVal); strcpy_s(pszAttr, len + 1, var.val.strVal); return true; } bool IRayCtrl::SetAttr(int nDetectorID, int nAttrID, int nValue) { IRayVariant var; var.vt = IVT_INT; var.val.nVal = nValue; FPDRESULT nResult = m_fpSetAttr(nDetectorID, nAttrID, &var); if (TestError(nDetectorID - 1, nResult)) { Fatal("Get Attribute Failed"); return false; } return true; } bool IRayCtrl::ActiveConfigurationMode(int nDetectorID, int nConfigurationID) { Info("Set current detector {$} configuration to {$}", nDetectorID, nConfigurationID); string strConfigurationMode = "FfdmMainFilter1"; if (nConfigurationID == 2) { strConfigurationMode = "FfdmPreFilter1"; } IRayCmdParam param[1]; param[0].pt = IPT_VARIANT; param[0].var.vt = IVT_STR; strncpy(param[0].var.val.strVal, strConfigurationMode.c_str(), IRAY_MAX_STR_LEN - 1); int nResult = IrayFnInvoke(nDetectorID, Cmd_SetCaliSubset, param, 1); if (TestError(nDetectorID, nResult)) { Error("Cmd_SetCaliSubset to FfdmMainFilter1 failed"); return false; } WaitRespond(5000); Info("({$})", strConfigurationMode); Info("ActiveConfigurationMode over"); return true; } bool IRayCtrl::ActivePanel(nsDPC::FPDDeviceIRay* pDrvDPC, bool bActive) { Info("ActivePanel: {$}, m_nCurrentPanelID {$}", pDrvDPC, m_nCurrentPanelID); map::iterator DPCsIter = m_pDPC2PanelID->find(pDrvDPC); return true; } /*** ** 说明:设置当前的曝光模式 ** 参数:nLogicMode,从配置文件读取,与SDK配置application mode对应 ***/ bool IRayCtrl::SelectExamMode(int nLogicMode, nsDPC::FPDDeviceIRay* pDrvDPC) { Info("IRayCtrl::SelectExamMode({$})", nLogicMode); if ((*m_pDPC2PanelID)[pDrvDPC] != m_nCurrentPanelID) { Warn("Not current DPC {$}, {$} != {$}, return\n", pDrvDPC, (*m_pDPC2PanelID)[pDrvDPC], m_nCurrentPanelID); return false; } if (m_stDeviceIndex[m_nCurrentPanelID].bConnectStatus == false) { Error("Current detector {$} is not connect, return\n", m_nCurrentPanelID); return false; } m_nClinicalApplicationMode = nLogicMode; if (m_nCurrentMode == nLogicMode) //同样appmode下没必要再次走下面的流程 { Info("Same appmode, return true"); return true; } m_nCurrentMode = nLogicMode; int nModeCount = (int)m_ModeConfig["ModeTable"].GetKeyCount("DetectorMode"); string strCoef; for (int i = 0; i < nModeCount; i++) { if (nLogicMode == (int)m_ModeConfig["ModeTable"][i]["LogicMode"]) { try { m_nRawImgHeight = (int)m_ModeConfig["ModeTable"][i]["RawImgHeight"]; m_nRawImgWidth = (int)m_ModeConfig["ModeTable"][i]["RawImgWidth"]; m_nImageWidth = (int)m_ModeConfig["ModeTable"][i]["ImageWidth"]; m_nImageHeight = (int)m_ModeConfig["ModeTable"][i]["ImageHeight"]; m_nWidthOffset = (int)m_ModeConfig["ModeTable"][i]["WidthOffset"]; m_nRightOffset = (int)m_ModeConfig["ModeTable"][i]["RightOffset"]; m_nHeightOffset = (int)m_ModeConfig["ModeTable"][i]["HeightOffset"]; m_nBottomOffset = (int)m_ModeConfig["ModeTable"][i]["BottomOffset"]; m_nImgBits = (int)m_ModeConfig["ModeTable"][i]["PhySizeInfoBit"]; m_nPixelPitch = (int)m_ModeConfig["ModeTable"][i]["PixelPitch"]; m_nSaveRaw = (int)m_ModeConfig["ModeTable"][i]["IsSaveRaw"]; strCoef = (string)m_ModeConfig["ModeTable"][i]["Sensitivity"]; if (m_pImgBuffer) { delete m_pImgBuffer; m_pImgBuffer = NULL; } m_pImgBuffer = new WORD[m_nImageHeight * m_nImageWidth]; Info("Image size(W*H), Raw({$}*{$}), Effective({$}*{$}), Offset({$} {$} {$} {$}), Bits({$}), PixelPitch({$}), SaveRaw({$})", m_nRawImgWidth, m_nRawImgHeight, m_nImageWidth, m_nImageHeight, m_nHeightOffset, m_nBottomOffset, m_nWidthOffset, m_nRightOffset, m_nImgBits, m_nPixelPitch, m_nSaveRaw); int nTmp = (int)m_ModeConfig["ModeTable"][i]["PreviewEnable"]; if (nTmp > 0) { m_bPreviewEnable = true; } else { m_bPreviewEnable = false; } m_nPreviewWidth = (int)m_ModeConfig["ModeTable"][i]["PreviewWidth"]; m_nPreviewHeight = (int)m_ModeConfig["ModeTable"][i]["PreviewHeight"]; Info("Preview size(W*H {$}*{$}), PreviewEnable({$})", m_nPreviewWidth, m_nPreviewHeight, m_bPreviewEnable); Info("Sensitivity: {$}", strCoef.c_str()); break; } catch (ResDataObjectExption& exp) { Error("Get config failed: {$}", exp.what()); } } } Info("SelectExamMode {$} over", m_nCurrentMode); return true; } //设置应用模式模式+设置曝光模式+设置校正项 bool IRayCtrl::SelectMode(int nAppMode, int nExpMode, int nFilterMode) { int nPanelID = m_nCurrentPanelID + 1; //ActiveConfigurationMode(nPanelID, nExpMode); //获取应用模式信息 GetMammoAppMode(nPanelID); //设置当前需要的模式到探测器 //int nFilterMode = m_stDeviceIndex[m_nCurrentPanelID].nFilterMode; if ((m_nAppMode != nAppMode) || (m_nExpMode != nExpMode) || (m_nFilterMode != nFilterMode)) { if (!SetMammoAppMode(nPanelID, nAppMode, nExpMode, nFilterMode)) { Error("Set Mammo configuration parameter failed"); } m_nAppMode = nAppMode; m_nExpMode = nExpMode; m_nFilterMode = nFilterMode; } //SetMammoAppMode(nPanelID, nAppMode, nExpMode, nFilterMode); //设置校正参数 SetCorrectionOption(nPanelID, nExpMode); return true; } bool IRayCtrl::SetSyncMode(int nDetectorID, int nSetSyncMode) { Info("IRayCtrl::SetSyncMode({$})", nSetSyncMode); int nPanelID = nDetectorID + 1; if (!WaitReady(nPanelID, 1000)) { return false; } int nTriggerMode = 0; if (GetSyncMode(nPanelID, nTriggerMode)) { Info("Current SyncMode is {$}", TriggerModeName(nSetSyncMode)); } else { Error("Get Sync Mode Failed"); return false; } if (nTriggerMode == nSetSyncMode) { Info("Same Sync Mode, return"); return true; } Info("Set Sync Mode:{$}", TriggerModeName(nSetSyncMode)); if (!SetAttr(nPanelID, Attr_UROM_TriggerMode_W, nSetSyncMode)) { Error("Set Sync Mode Failed"); return false; } m_nTriggerMode = nSetSyncMode; Info("Set Sync Mode Success"); Info("SetSyncMode over"); return true; } bool IRayCtrl::GetSyncMode(int nDetectorID, int& nTriggerMode) { return GetAttr(nDetectorID, Attr_UROM_TriggerMode, nTriggerMode); } string IRayCtrl::TriggerModeName(int nTriggerMode) { string strTriggerMode = ""; switch (nTriggerMode) { case Enm_TriggerMode_Outer: strTriggerMode = "Enm_TriggerMode_Outer"; break; case Enm_TriggerMode_Soft: strTriggerMode = "Enm_TriggerMode_Soft"; break; case Enm_TriggerMode_Prep: strTriggerMode = "Enm_TriggerMode_Prep"; break; case Enm_TriggerMode_AED: strTriggerMode = "Enm_TriggerMode_AED"; break; case Enm_TriggerMode_SyncOut: strTriggerMode = "Enm_TriggerMode_SyncOut"; break; default: strTriggerMode = "Unknown"; break; } return strTriggerMode; } // pOutImg: 裁剪后图像; pInImg: 裁剪前图像; nInWidth: 裁剪前图像宽度 bool IRayCtrl::GetEffectiveImage(WORD* pOutImg, WORD* pInImg, int nInWidth) { if (pOutImg == NULL || pInImg == NULL || nInWidth < 0) { Error("Illegal parameter, can not get effective image"); return false; } try { for (int i = 0; i < m_nImageHeight; i++) { memcpy(pOutImg + i * m_nImageWidth, pInImg + (i + m_nHeightOffset) * nInWidth + m_nWidthOffset, m_nImageWidth * sizeof(WORD)); } } catch (...) { Error("Get effective image crashed. m_nImageWidth {$},m_nImageHeight {$},m_nWidthOffset {$},m_nHeightOffset {$},m_nBottomOffset {$}", m_nImageWidth, m_nImageHeight, m_nWidthOffset, m_nHeightOffset, m_nBottomOffset); return false; } return true; } void IRayCtrl::OnProcessImg() { if (m_nWidthOffset != 0 || m_nHeightOffset != 0) { if (m_nSaveRaw) { } Info("Begin get effect image, m_nRawImgWidth {$}\n", m_nRawImgWidth); if (!GetEffectiveImage(m_pImgBuffer, m_pwRawImageData, m_nRawImgWidth)) { Error("Get effect image failed"); return; } Info("Get effect image over"); } if ((m_nClinicalApplicationMode == 2) && ((++m_nCurrentFrame) < m_nTotalFrameNum)) { DataFeedback(EVT_DATA_AEC_PREEXP_IMAGE, m_pwRawImageData); } else { DataFeedback(EVT_DATA_RAW_IMAGE, m_pwRawImageData); m_nCurrentFrame = 0; } } bool IRayCtrl::EnterExam(APP_STATUS eStatus) { string strLog = ""; switch (eStatus) { case APP_STATUS_IDLE: strLog = "APP_STATUS_IDLE"; break; case APP_STATUS_WORK_BEGIN: strLog = "APP_STATUS_WORK_BEGIN"; m_bInCalibrating = false; break; case APP_STATUS_WORK_END: strLog = "APP_STATUS_WORK_END"; break; case APP_STATUS_CAL_BEGIN: strLog = "APP_STATUS_CAL_BEGIN"; break; case APP_STATUS_CAL_END: strLog = "APP_STATUS_CAL_END"; m_bInCalibrating = false; break; default: break; } Info("Enter exam: {$}", strLog.c_str()); m_eAppStatus = eStatus; return true; } RET_STATUS IRayCtrl::PrepareAcquisition(nsDPC::FPDDeviceIRay* pDrvDPC) { if ((*m_pDPC2PanelID)[pDrvDPC] != m_nCurrentPanelID) { Warn("Not current DPC, return"); return RET_STATUS::RET_FAILED; } if (m_stDeviceIndex[m_nCurrentPanelID].bConnectStatus == false) { Info("Current detector is not connect, return"); return RET_STATUS::RET_FAILED; } int nPanelID = m_nCurrentPanelID + 1; //获取应用模式信息 GetMammoAppMode(nPanelID); //StatusFeedback(EVT_STATUS_ACQUISITION, PANEL_EVENT_START); return RET_STATUS::RET_SUCCEED; } bool IRayCtrl::GetMammoAppMode(int nDetectorID) { string strAppMode = "Unknown"; GetAttr(nDetectorID, Attr_UROM_AppMode, m_nAppMode); GetAttr(nDetectorID, Attr_UROM_ExpMode, m_nExpMode); GetAttr(nDetectorID, Cfg_CurFilter, m_nFilterMode); Info("Get detector application mode: AppMode({$}), ExpMode({$}), FilterMode({$})", m_nAppMode, m_nExpMode, m_nFilterMode); if ((m_nAppMode == 0 && m_nExpMode == 1) || (m_nAppMode == 1 && m_nExpMode == 1)) // manual { m_nTotalFrameNum = 1; strAppMode = "Normal exposure"; } else if ((m_nAppMode == 0 && m_nExpMode == 2) || // AEC (m_nAppMode == 1 && m_nExpMode == 2) || // AEC (m_nAppMode == 2 && m_nExpMode == 5)) // Stereo { m_nTotalFrameNum = 2; strAppMode = "AEC exposure"; } Info("Detector Application mode: {$}, Total frame number: {$}", strAppMode, m_nTotalFrameNum); return true; } bool IRayCtrl::SetMammoAppMode(int nDetectorID, int nAppMode, int nExpMode, int nFilterMode) { IRayCmdParam param[3]; param[0].pt = IPT_VARIANT; param[0].var.vt = IVT_INT; param[0].var.val.nVal = nAppMode; param[1].pt = IPT_VARIANT; param[1].var.vt = IVT_INT; param[1].var.val.nVal = nExpMode; param[2].pt = IPT_VARIANT; param[2].var.vt = IVT_INT; param[2].var.val.nVal = nFilterMode; int nResult = IrayFnInvoke(nDetectorID, Cmd_SetCurAppMode, param, 3); WaitRespond(5000); Info("Change current application mode: AppMode({$}), ExpMode({$}), FilterMode({$})", nAppMode, nExpMode, nFilterMode); //GetMammoAppMode(nDetectorID); return true; } RET_STATUS IRayCtrl::StartAcquisition(nsDPC::FPDDeviceIRay* pDrvDPC) { if ((*m_pDPC2PanelID)[pDrvDPC] != m_nCurrentPanelID) { Warn("Not current DPC, return"); return RET_STATUS::RET_FAILED; } RET_STATUS Ret = RET_STATUS::RET_FAILED; if (-1 == m_nCurrentMode) { Warn("Current mode({$}) is illegal, may not select exam mode successfully, return failed", m_nCurrentMode); return Ret; } ////如果当前探测器断连,则不开始采集,直接返回失败 //if (!m_stDeviceIndex[m_nCurrentPanelID].bConnectStatus) //{ // Warn("Detector not in connection when start acq, return failed"); // return RET_STATUS::RET_FAILED; //} StatusFeedback(EVT_STATUS_ACQUISITION, PANEL_EVENT_START); m_bInExposure = true; m_bWindowOn = false; StatusFeedback(EVT_STATUS_ACQUISITION, PANEL_EVENT_END_OK); return RET_STATUS::RET_SUCCEED; } bool IRayCtrl::StartXWindowOffThread() { if (m_pXWindowoffThread == NULL) { DWORD m_NotifyThreadID; m_pXWindowoffThread = CreateThread(0, 0, XWindowOffThread, this, 0, &m_NotifyThreadID); if (m_pXWindowoffThread == NULL) { Fatal("Start Inner Exp Thread Failed"); return false; } } return true; } DWORD IRayCtrl::XWindowOffThread(LPVOID pParam) { IRayCtrl* pCurPanel = (IRayCtrl*)pParam; if (pCurPanel == NULL) { return false; } DWORD dwTimer = 500; DWORD dwResult = WaitForSingleObject(pCurPanel->m_hWindowOffEvent, dwTimer); Info("Simulate XWINDOW_OFF"); pCurPanel->StatusFeedback(EVT_STATUS_PANEL, PANEL_XWINDOW_OFF); pCurPanel->m_pXWindowoffThread = NULL; return true; } RET_STATUS IRayCtrl::StopAcquisition(nsDPC::FPDDeviceIRay* pDrvDPC) { if ((*m_pDPC2PanelID)[pDrvDPC] != m_nCurrentPanelID) { Warn("Not current DPC, return"); return RET_STATUS::RET_FAILED; } m_bInExposure = false; RET_STATUS Ret = RET_STATUS::RET_SUCCEED; return Ret; } //Normal曝光模式才使用SW_Offset bool IRayCtrl::PerformOffset(int nDetectorID, int nOffsetType) { int nPanelID = m_nCurrentPanelID + 1; int nOffsetTimeOut = 0; int nOffsetTotalFramesNum = 0; int nIntervalTimeOfEachFrame = 0; if (nOffsetType == 0) //HW_Offset { Info("Call Cmd_HwGeneratePreOffsetTemplate"); FPDRESULT nResult = IrayFnInvoke(nPanelID, Cmd_HwGeneratePreOffsetTemplate, NULL, 0); if (TestError(nPanelID, nResult)) { Error("Cmd_HwGeneratePreOffsetTemplate Cmd Failed"); StatusFeedback(EVT_STATUS_PANEL, PANEL_OFFSET_FAILED); return false; } ResetLock(); m_stDeviceIndex[m_nCurrentPanelID].bEventReturn = false; bool bResult = WaitRespond(20000); //刷新一次20秒 if (!bResult) { Error("Generate HW PreOffset Template failed"); } else { Info("Generate HW PreOffset Template success"); } } else if (nOffsetType == 1) //SW_Offset { GetAttr(nPanelID, Attr_OffsetTotalFrames, nOffsetTotalFramesNum); GetAttr(nPanelID, Attr_UROM_SequenceIntervalTime, nIntervalTimeOfEachFrame); nOffsetTimeOut = (nOffsetTotalFramesNum + 11) * nIntervalTimeOfEachFrame + 5000; Info("Offset ToTal Frames Number: {$}, Interval Time Of EachFrame: {$}(ms), Offset TimeOut: {$}(ms)", nOffsetTotalFramesNum, nIntervalTimeOfEachFrame, nOffsetTimeOut); Info("Call Cmd_OffsetGeneration"); FPDRESULT nResult = IrayFnInvoke(nDetectorID, Cmd_OffsetGeneration, NULL, 0); if (TestError(nPanelID, nResult)) { Error("Cmd_OffsetGeneration command Failed"); StatusFeedback(EVT_STATUS_PANEL, PANEL_OFFSET_FAILED); return false; } ResetLock(); m_stDeviceIndex[m_nCurrentPanelID].bEventReturn = false; bool bResult = WaitRespond(nOffsetTimeOut); //刷新一次需要的时间 if (!bResult) { Error("Generate SW Offset Template failed"); return false; } else { Info("Generate SW Offset Template success"); } } else { Error("Unknown offset type"); } /*if (m_stDeviceIndex[m_nCurrentPanelID].bEventReturn) { StatusFeedback(EVT_STATUS_PANEL, PANEL_OFFSET_FINISH); } else { StatusFeedback(EVT_STATUS_PANEL, PANEL_OFFSET_FAILED); }*/ return true; } bool IRayCtrl::ClearCorrectionOption(int nDetectorID) { Info("Clear Correction Option"); int nPanelIndex = nDetectorID - 1; if (!WaitReady(nDetectorID, 1000)) { return false; } int nOption = 0; IRayCmdParam param[1]; param[0].var.vt = IVT_INT; param[0].var.val.nVal = nOption; FPDRESULT result = IrayFnInvoke(nDetectorID, Cmd_SetCorrectOption, param, 1); //Cmd_SetCorrectOption if (TestError(nDetectorID, result)) { Fatal("Call SetCorrectionOption Failed"); return false; } bool bResult = WaitRespond(8000); if (m_stDeviceIndex[nPanelIndex].bSetCorrection) { Info("Clear Correction Success"); } else { Fatal("Clear Correction Failed"); return false; } return true; } bool IRayCtrl::GetCorrectionOption(int nDetectorID, int& nOption) { return GetAttr(nDetectorID, Attr_CurrentCorrectOption, nOption); } // 设置探测器端校正参数,加载校正文件 bool IRayCtrl::SetCorrectionOption(int nDetectorID, int nExpMode) { Info("Set Mammo Correction Option"); /*if (!WaitReady(nDetectorID, 1000)) { return false; }*/ int nDetectorIndex = nDetectorID - 1; int nOffsetOption = Enm_CorrectOp_HW_PostOffset; //HW_PostOffset //1:RAD;2:AEC;default:0;//从别的项目里找到的注释 //这里之前是Exp_Normal,但是这个枚举在哪里定义的并没有,故此处根据其他项目的曝光模式的值先修改,后续有人知道此处如何修改时再改,先能编译过,否则编译不过 if (nExpMode == 0) { nOffsetOption = Enm_CorrectOp_SW_PreOffset; } int nOption = 0; nOption = nOption | nOffsetOption; nOption = nOption | Enm_CorrectOp_SW_Gain; nOption = nOption | Enm_CorrectOp_SW_Defect; int nOldOption = 0; GetCorrectionOption(nDetectorID, nOldOption); if (nOption == nOldOption) { Info("Same Correction Option, Omit Set Correction Option"); return true; } if (22 == nOption) { Info("Set FPD {$} Correction Option: PostOffset+All", nDetectorID); } else { Info("Set FPD {$} Correction Option: {$}", nDetectorID, nOption); } IRayCmdParam param[1]; param[0].var.vt = IVT_INT; param[0].var.val.nVal = nOption; FPDRESULT result = IrayFnInvoke(nDetectorID, Cmd_SetCorrectOption, param, 1); //Cmd_SetCorrectOption if (TestError(nDetectorID, result)) { Error("Call SetCorrectionOption Failed"); return false; } bool bResult = WaitRespond(10000); //加载校正策略 if (m_stDeviceIndex[nDetectorIndex].bSetCorrection) { Info("SetCorrectionOption Success"); } else { Error("SetCorrectionOption Failed"); return false; } return true; } /* * 镜像翻转 */ bool IRayCtrl::FlipX(WORD* pData, int nWidth, int nHeight) { int j = 0; int i = 0; Info("Flip Image Width:{$}, Height:{$}", nWidth, nHeight); WORD temp; for (i = 0; i < nHeight; i++) { for (j = 0; j < nWidth / 2; j++) { temp = pData[i * nWidth + j]; pData[i * nWidth + j] = pData[(i + 1) * nWidth - j - 1]; pData[(i + 1) * nWidth - j - 1] = temp; } } Info("Flip Image Over"); return true; } /* 功能:对SDK输出的图像,先旋转90度,再做镜像,做到所见即所得。 */ bool IRayCtrl::FlipXRotate90(WORD* pData, int nWidth, int nHeight) { Info("Rotate 270 angle"); WORD* ptempData = new WORD[nWidth * nHeight]; memcpy(ptempData, pData, nWidth * nHeight * sizeof(WORD)); for (int i = 0; i < nWidth; i++) for (int j = 0; j < nHeight; j++) pData[i * nWidth + j] = ptempData[j * nWidth + (nWidth - 1 - i)]; delete[]ptempData; ptempData = NULL; FlipX(pData, nWidth, nHeight); return true; }