/* ------------------------------------------------------------------------- // 文件名 : PZMedical2121ZCtrl.cpp // 创建者 : wangyuedong // 创建时间 : 2022-08-08 // 功能描述 : PZMedical2121Z动态探测器功能实现 // -----------------------------------------------------------------------*/ #include "StdAfx.h" #include "ModeAbstract.h" #include "EComRFMessage_i.h" #include "PZMedical2121ZCtrl.h" #include "CShareMemManager.h" extern CString strAppPath; extern CAppSettings *g_pAcqParam; extern CString g_strConfFilePath; extern CString g_strHWConfFilePath; #define BUFFER_NUM 10 #define IMAGEWIDTH 2880 PZMedical2121ZCtrl* PZMedical2121ZCtrl::g_pPZMedicalInstance = NULL; PZMedical2121ZCtrl::PZMedical2121ZCtrl(void) { m_bFPDConnected = false; g_pPZMedicalInstance = this; m_nModeSize = 1; m_RadMode.nLogicMode = 1; m_RadMode.nOffIndex = 0; m_FluMode.nLogicMode = 3; m_FluMode.nOffIndex = 0; m_CINEMode.nLogicMode = 3; m_CINEMode.nOffIndex = 0; m_ActiveMode.nLogicMode = -1; m_ActiveMode.nOffIndex = -1; m_CalSynParam.frenquency = 1; m_CalSynParam.xWindow = 500; m_PreSynParam.frenquency = 1; m_PreSynParam.xWindow = 500; m_CurSynParam.frenquency = 1; m_CurSynParam.xWindow = 500; m_bOffsetDone = false; m_bCalStart = false; m_hWnd = NULL; m_pWnd = NULL; m_eStatus = NotInit; m_eSubStatus = SubStatus_Unknown; m_bIsWorkingMode = false; m_bAbortOffset = false; m_bOffsetAll = true; m_nRADSpeed = 0; //0时默认为单帧点片 m_nFLUSpeed = 15; //透视模式默认为15帧 m_nCINSpeed = 0; m_bExit = false; m_EnableProcessChain = false; m_EnableDrvLog = false; m_pDataBuffer = new CShareMem(_T("ImageBuffer")); m_pDataBuffer->CreateShareMem(IMAGEWIDTH*(IMAGEWIDTH + 1)*BUFFER_NUM*sizeof(WORD)); m_nCurrentFrame = -1; m_nTotalFrameGrab = 0; m_bWaitLastImg = false; //默认不需要等最后一张图 m_nXrayOnNum = 0; m_pImgBufferSize = 1024 * 1024; //linshi m_ImgInfo.pwData = new WORD[m_pImgBufferSize]; m_nRawWidth = 1024; m_nTotalGainGroup = 3; g_bTestTrue = false; g_TestSavingImage = NULL; //初始化为NULL值 API_COM_Init = NULL; API_COM_Open = NULL; API_COM_SetCfgFilePath = NULL; API_COM_HstAcq = NULL; API_COM_Trigger = NULL; API_COM_Dacq = NULL; API_COM_Cbct = NULL; API_COM_Stop = NULL; API_COM_GetImage = NULL; API_COM_GetImageMode = NULL; API_COM_SetFPConf = NULL; API_COM_GetFPConf = NULL; API_COM_GetFPsn = NULL; API_COM_GetFPsnEx = NULL; API_COM_GetFPCompatibleVer = NULL; API_COM_GetDllVer = NULL; API_COM_GetBinningMode = NULL; API_COM_SetBinningMode = NULL; API_COM_GetPreCalibMode = NULL; API_COM_SetPreCalibMode = NULL; API_COM_GetCalibMode = NULL; API_COM_SetCalibMode = NULL; API_COM_GenOffsetTpl = NULL; API_COM_GenGainTpl = NULL; API_COM_GenDefectTpl = NULL; API_COM_UploadFPZMTpl = NULL; API_COM_RegisterEvCallBack = NULL; API_COM_Dst = NULL; API_COM_Prep = NULL; API_COM_SetDynamicPara = NULL; API_COM_Dexit = NULL; API_COM_GetFPCurStatus = NULL; API_COM_GetFPStatus = NULL; m_pScanThreadProc = NULL; m_hInitEvent = NULL; m_hExitEvent = NULL; m_hGenTplEvent = NULL; for (int i = 0; i < PZ_EVENT_COUNT; i++) m_hEventArray[i] = NULL; m_hCallbackEvent = NULL; m_nTriggerMode = 2; m_nImgID = 1; m_nOffsetImgID = 1; //SDK逻辑是从1开始的 m_nGainImgID = 1; //SDK逻辑是从1开始的 m_cEventNum = -1; m_cImgBuff = NULL; m_ucState = -1; m_ucPerCent = -1; m_bGetImage = false; m_bSendRadImage = false; m_bExiChecked = false; m_bTimeChecked = false; m_nExiStdWork = 1000; m_nExiStdCali = 30000; m_cFPDCalibMode = 5; //初始时,设置成一个不存在的校正模式 strCalMode = "-1"; m_bSaveRaw = false; m_cCalibMode = PZ_OFFSET_GAIN_DEFECT; m_bTriggered = true; //默认为true,使初始化时可以stop一次 m_nBinningMode = -1; m_nWinTime = -1; m_nStartLine = 0; m_nEndLine = 0; m_nStartColumn = 0; m_nEndColumn = 0; m_dwBeginT = 0; m_dwEndT = 0; m_nDelayT = 0; m_nPixelSpacing = 140; m_bTimerSwitch = true; m_dwGetImageT = 0; m_dwLastT = 0; m_nSaturation = 50000; m_nStandbyRate = 2; m_nRadImgCount = 3; m_vecCycleTime.clear(); m_vecDelayTime.clear(); //addend } PZMedical2121ZCtrl::~PZMedical2121ZCtrl(void) { map::iterator iter1 = m_ROImap.begin(); while (iter1 != m_ROImap.end()) { delete iter1->second; ++iter1; } if (m_ImgInfo.pwData != NULL) { delete[] m_ImgInfo.pwData; } m_ROImap.clear(); } BEGIN_MESSAGE_MAP(PZMedical2121ZCtrl, CAcqCtrl) END_MESSAGE_MAP() bool PZMedical2121ZCtrl::InitDETECTOR(HWND hWnd, bool bState) { //如果探测器未连接则直接返回 if (CAcqCtrl::InitDETECTOR(hWnd, bState)) return true; LogInfo("===== Init PZMedical2121Z system ====="); m_bState = bState; m_hWnd = hWnd; m_bFPDConnected = false; m_eStatus = Init; CString strLog = ""; // 读取模式配置文件 // 1.获取RFModeConf.xml路径 (RFOC\conf\hw\PZMedical2121Z\RFModeConf.xml) LogInfo(g_strHWConfFilePath); CAppSettings appDetectorSet; if (appDetectorSet.Load(g_strHWConfFilePath + _T("\\Detector.xml"))) { LogInfo("Load Detector.xml OK"); } else { LogError("Load Detector.xml failed"); return false; } m_SubConfigPath = appDetectorSet.GetValueByKey(_T("DetectorType")); //m_SubConfigPath 为 PZMedical2121Z CString strRFConfPath; strRFConfPath.Format("%s\\%s\\RFModeConf.xml", g_strHWConfFilePath, m_SubConfigPath); //LogInfo(strRFConfPath); //CalibrationType 配置项。0: RAW; 1: OFFSET; 7: OFFSET_GAIN_DEFECT strCalMode = appDetectorSet.GetValueByKey(_T("CalibrationType")); if (strCalMode == "0") m_cCalibMode = PZ_RAW; else if (strCalMode == "1") m_cCalibMode = PZ_OFFSET; else if (strCalMode == "7") m_cCalibMode = PZ_OFFSET_GAIN_DEFECT; CString strSaveRaw = appDetectorSet.GetValueByKey(_T("SaveRawDataMode")); if (strSaveRaw == "0") { m_bSaveRaw = false; LogInfo("Not save Raw"); } else if (strSaveRaw == "1") { m_bSaveRaw = true; LogInfo("Save Raw"); } else { strLog.Format("Unknown save raw mode: %s. Not save", strSaveRaw); m_bSaveRaw = false; } // 2.加载 RFModeConf.xml 配置 if (RFModeConf.Load(strRFConfPath)) { LogInfo("Load mode configuration file OK"); } else { LogError("Load mode configuration file Failed"); return false; } m_nModeSize = (int)RFModeConf.DetectorMode.m_nodes.size(); // 3.上层应用模式和RFMode对应的模式映射表 (RFOC\conf\hw\PZMedical2121Z\RealModeMatch.xml) CString strRealModeConfFile; strRealModeConfFile.Format("%s\\%s\\RealModeMatch.xml", g_strHWConfFilePath, m_SubConfigPath); //LogInfo(strRealModeConfFile); if (m_appRealModeConf.Load(strRealModeConfFile)) { LogInfo("Load RealModeMatch.xml OK"); } else { LogError("Load file failed: " + strRealModeConfFile); return false; } m_appRealModeConf.GetAllDataToVector(); // 4.写入AbstractModeConfig.xml (RFOC\conf\AbstractModeConfig.xml) AbstractModeConfig AbstractModes; CString strAbstractModeFile; strAbstractModeFile.Format("%s\\AbstractModeConfig.xml", g_strConfFilePath); //LogInfo(strAbstractModeFile); if (AbstractModes.Load(strAbstractModeFile)) { AbstractModes.DetectorMode.Clear(); } else { CStdioFile file; if (file.Open(strAbstractModeFile, CFile::modeCreate | CFile::modeReadWrite)) { file.WriteString(_T("\n")); file.WriteString(_T("\n")); file.WriteString(_T("\n")); file.Close(); } AbstractModes.Load(strAbstractModeFile); } for (int i = 0; i < m_nModeSize; ++i) { ModeNode modeNode; modeNode.LogicMode = RFModeConf.DetectorMode.m_nodes[i].LogicMode; modeNode.PUMode = RFModeConf.DetectorMode.m_nodes[i].PUMode; int nCount = (int)RFModeConf.DetectorMode.m_nodes[i].OffsetMode.m_nodes.size(); modeNode.ModeDescription = RFModeConf.DetectorMode.m_nodes[i].OffsetMode.m_nodes[nCount - 1].Description; modeNode.Frequency = RFModeConf.DetectorMode.m_nodes[i].OffsetMode.m_nodes[nCount - 1].Frequency; if (modeNode.Frequency < 1.0) { m_nTOMOMode = modeNode.LogicMode; } modeNode.ExamType = RFModeConf.DetectorMode.m_nodes[i].ExamType; modeNode.AutoOffset = RFModeConf.DetectorMode.m_nodes[i].OffsetMode.m_nodes[nCount - 1].AutoOff; modeNode.XWindow = RFModeConf.DetectorMode.m_nodes[i].OffsetMode.m_nodes[nCount - 1].Xwindow; modeNode.OffsetMode = nCount - 1; modeNode.PF2CF = RFModeConf.DetectorMode.m_nodes[i].PolyGainEnable; CString strtemp; strtemp.Format("%d", modeNode.LogicMode); for (DWORD j = 0; j < m_appRealModeConf.vecData.size(); ++j) { if (m_appRealModeConf.vecData[j].value == strtemp) { strtemp = m_appRealModeConf.vecData[j].key; break; } } modeNode.MatchCode = strtemp; AbstractModes.DetectorMode.Add(modeNode); } AbstractModes.Save(strAbstractModeFile); if (!m_bState) { LogInfo("===== INIT SYSTEM OVER, IN DEMO ====="); return true; } /////////////////////// // 5.对品臻模式配置文件的读取 (RFOC\conf\hw\PZMedical2121Z\PZAppModeConf.xml) CString strModeConfPath; strModeConfPath.Format("%s\\%s\\PZAppModeConf.xml", g_strHWConfFilePath, m_SubConfigPath); //LogInfo(strModeConfPath); if (PZModeConf.Load(strModeConfPath)) { LogInfo("Load PZAppModeConf.xml file OK"); } else { LogError("Load PZAppModeConf.xml file Failed"); MSGControl(m_pWnd, ZSKK_MSG_RFDT_WFOUT, ZSKK_DETECTOR_WF_QUERY_STATUS, ZSKK_DETECTOR_LPARAM_STATUS_UNCONNECTED, 0); return false; } // 6.读取品臻探测器的配置文件 (RFOC\conf\hw\PZMedical2121Z\PZParamSetConf.xml) CString pzConfPath; pzConfPath.Format("%s\\%s\\PZParamSetConf.xml", g_strHWConfFilePath, m_SubConfigPath); //LogInfo(pzConfPath); CAppSettings pzConf; if (pzConf.Load(pzConfPath)) { LogInfo("Load PZParamSetConf.xml OK"); } else { LogError("Load PZParamSetConf.xml failed"); MSGControl(m_pWnd, ZSKK_MSG_RFDT_WFOUT, ZSKK_DETECTOR_WF_QUERY_STATUS, ZSKK_DETECTOR_LPARAM_STATUS_UNCONNECTED, 0); return false; } m_strFPSN = pzConf.GetValueByKey("FPSN").GetBuffer(); m_nExiStdWork = atoi(pzConf.GetValueByKey("EXIstdWork").GetBuffer()); m_nExiStdCali = atoi(pzConf.GetValueByKey("EXIstdCal").GetBuffer()); m_bTimerSwitch = atoi(pzConf.GetValueByKey("TimerSwitch").GetBuffer()); m_nSaturation = atoi(pzConf.GetValueByKey("Saturation").GetBuffer()); m_nStandbyRate = atoi(pzConf.GetValueByKey("StandbyRate").GetBuffer()); m_nRadImgCount = atoi(pzConf.GetValueByKey("RadImgCount").GetBuffer()); m_nBinningMode = atoi(pzConf.GetValueByKey("BinningModeParam").GetBuffer()); m_nTriggerMode = atoi(pzConf.GetValueByKey("TriggerMode").GetBuffer()); if (m_nSaturation < 10000) { strLog.Format("Some Saturation(%d) not in reason at %s, use 50000 as default", m_nSaturation, pzConfPath); m_nSaturation = 50000; } strLog.Format("CalibMode(%d), EXIstdWork(%d), EXIstdCal(%d), TimerSwitch(%d), Saturation(%d), StandbyRate(%d), RadImgCount(%d)", m_cCalibMode, m_nExiStdWork, m_nExiStdCali, m_bTimerSwitch, m_nSaturation, m_nStandbyRate, m_nRadImgCount); LogInfo(strLog); CString strConfTemp, strTemp; int nPos = 0; vector::iterator iter; vector::iterator begin; vector::iterator end; m_vecCycleTime.clear(); m_vecDelayTime.clear(); strConfTemp = pzConf.GetValueByKey("CycleTime"); strTemp = strConfTemp.Tokenize(",", nPos); while (strTemp != "") { m_vecCycleTime.push_back(atoi(strTemp)); strTemp = strConfTemp.Tokenize(",", nPos); } begin = m_vecCycleTime.begin(); end = m_vecCycleTime.end(); strLog = "CycleTime: "; for (iter = begin; iter != end; iter++) { strTemp.Format("%d,", *iter); strLog += strTemp; } LogInfo(strLog); nPos = 0; strConfTemp = pzConf.GetValueByKey("DelayTime"); strTemp = strConfTemp.Tokenize(",", nPos); while (strTemp != "") { m_vecDelayTime.push_back(atoi(strTemp)); strTemp = strConfTemp.Tokenize(",", nPos); } begin = m_vecDelayTime.begin(); end = m_vecDelayTime.end(); strLog = "DelayTime: "; for (iter = begin; iter != end; iter++) { strTemp.Format("%d,", *iter); strLog += strTemp; } LogInfo(strLog); if (m_vecCycleTime.empty() || m_vecDelayTime.empty()) { MSGControl(m_pWnd, ZSKK_MSG_RFDT_WFOUT, ZSKK_DETECTOR_WF_QUERY_STATUS, ZSKK_DETECTOR_LPARAM_STATUS_UNCONNECTED, 0); return false; } //LoadROIParams(); //品臻动态不用RFModeConf.xml中的ROI配置 if (!LoadPZMedicalDLL()) { MSGControl(m_pWnd, ZSKK_MSG_RFDT_WFOUT, ZSKK_DETECTOR_WF_QUERY_STATUS, ZSKK_DETECTOR_LPARAM_STATUS_UNCONNECTED, 0); return false; } if (!StartScanThread()) { MSGControl(m_pWnd, ZSKK_MSG_RFDT_WFOUT, ZSKK_DETECTOR_WF_QUERY_STATUS, ZSKK_DETECTOR_LPARAM_STATUS_UNCONNECTED, 0); return false; } //SetEvent(m_hInitEvent); if (!InitHW(m_hWnd)) { MSGControl(m_pWnd, ZSKK_MSG_RFDT_WFOUT, ZSKK_DETECTOR_WF_QUERY_STATUS, ZSKK_DETECTOR_LPARAM_STATUS_UNCONNECTED, 0); return false; } LogInfo("===== INIT SYSTEM OVER ====="); return true; } // 判断SDK接口返回值 bool PZMedical2121ZCtrl::TestError(int nErrorStatus) { CString strLog = ""; switch (nErrorStatus) { case TRUE: { LogInfo("return ok"); return true; } break; case FALSE: { LogError("return error"); } break; default: { strLog.Format("Error: %d", nErrorStatus); LogError(strLog); } break; } return false; } // 加载PZMedical的SDK bool PZMedical2121ZCtrl::LoadPZMedicalDLL() { LogInfo("## LoadPZMedicalDLL ##"); ::SetDllDirectory(strAppPath + "\\PZMedical\\"); CString strLog = ""; strLog.Format("Path: %s\\PZMedical\\", strAppPath); LogInfo(strLog); m_hModule = ::LoadLibrary(strAppPath + "\\PZMedical\\ComApi.dll"); if (m_hModule != NULL) { API_COM_Init = (PZ_COM_Init)GetProcAddress(m_hModule, "COM_Init"); if (API_COM_Init == NULL) { LogError("Load COM_Init failed"); return false; } API_COM_List = (PZ_COM_List)GetProcAddress(m_hModule, "COM_List"); if (API_COM_List == NULL) { LogError("Load COM_List failed"); return false; } API_COM_Open = (PZ_COM_Open)GetProcAddress(m_hModule, "COM_Open"); if (API_COM_Open == NULL) { LogError("Load COM_Open failed"); return false; } API_COM_Close = (PZ_COM_Close)GetProcAddress(m_hModule, "COM_Close"); if (API_COM_Close == NULL) { LogError("Load COM_Close failed"); return false; } API_COM_SetCfgFilePath = (PZ_COM_SetCfgFilePath)GetProcAddress(m_hModule, "COM_SetCfgFilePath"); if (API_COM_SetCfgFilePath == NULL) { LogError("Load COM_SetCfgFilePath failed"); return false; } API_COM_LogPathGet = (PZ_COM_LogPathGet)GetProcAddress(m_hModule, "COM_LogPathGet"); if (API_COM_LogPathGet == NULL) { LogError("Load COM_LogPathGet failed"); return false; } API_COM_LogPathSet = (PZ_COM_LogPathSet)GetProcAddress(m_hModule, "COM_LogPathSet"); if (API_COM_LogPathSet == NULL) { LogError("Load COM_LogPathSet failed"); return false; } API_COM_HstAcq = (PZ_COM_HstAcq)GetProcAddress(m_hModule, "COM_HstAcq"); if (API_COM_HstAcq == NULL) { LogError("Load COM_HstAcq failed"); return false; } API_COM_Trigger = (PZ_COM_Trigger)GetProcAddress(m_hModule, "COM_Trigger"); if (API_COM_Trigger == NULL) { LogError("Load COM_Trigger failed"); return false; } API_COM_Dacq = (PZ_COM_Dacq)GetProcAddress(m_hModule, "COM_Dacq"); if (API_COM_Dacq == NULL) { LogError("Load COM_Dacq failed"); return false; } API_COM_Cbct = (PZ_COM_Cbct)GetProcAddress(m_hModule, "COM_Cbct"); if (API_COM_Cbct == NULL) { LogError("Load COM_Cbct failed"); return false; } API_COM_Stop = (PZ_COM_Stop)GetProcAddress(m_hModule, "COM_Stop"); if (API_COM_Stop == NULL) { LogError("Load COM_Stop failed"); return false; } API_COM_GetImage = (PZ_COM_GetImage)GetProcAddress(m_hModule, "COM_GetImage"); if (API_COM_GetImage == NULL) { LogError("Load COM_GetImage failed"); return false; } API_COM_GetImageMode = (PZ_COM_GetImageMode)GetProcAddress(m_hModule, "COM_GetImageMode"); if (API_COM_GetImageMode == NULL) { LogError("Load COM_GetImageMode failed"); return false; } API_COM_SetFPConf = (PZ_COM_SetFPConf)GetProcAddress(m_hModule, "COM_SetFPConf"); if (API_COM_SetFPConf == NULL) { LogError("Load COM_SetFPConf failed"); return false; } API_COM_GetFPConf = (PZ_COM_GetFPConf)GetProcAddress(m_hModule, "COM_GetFPConf"); if (API_COM_GetFPConf == NULL) { LogError("Load COM_GetFPConf failed"); return false; } API_COM_GetFPsn = (PZ_COM_GetFPsn)GetProcAddress(m_hModule, "COM_GetFPsn"); if (API_COM_GetFPsn == NULL) { LogError("Load COM_GetFPsn failed"); return false; } API_COM_GetFPsnEx = (PZ_COM_GetFPsnEx)GetProcAddress(m_hModule, "COM_GetFPsnEx"); if (API_COM_GetFPsnEx == NULL) { LogError("Load COM_GetFPsn failed"); return false; } API_COM_GetFPCompatibleVer = (PZ_COM_GetFPCompatibleVer)GetProcAddress(m_hModule, "COM_GetFPCompatibleVer"); if (API_COM_GetFPCompatibleVer == NULL) { LogError("Load COM_GetFPCompatibleVer failed"); return false; } API_COM_GetDllVer = (PZ_COM_GetDllVer)GetProcAddress(m_hModule, "COM_GetDllVer"); if (API_COM_GetDllVer == NULL) { LogError("Load COM_GetDllVer failed"); return false; } API_COM_GetBinningMode = (PZ_COM_GetBinningMode)GetProcAddress(m_hModule, "COM_GetBinningMode"); if (API_COM_GetBinningMode == NULL) { LogError("Load COM_GetBinningMode failed"); return false; } API_COM_SetBinningMode = (PZ_COM_SetBinningMode)GetProcAddress(m_hModule, "COM_SetBinningMode"); if (API_COM_SetBinningMode == NULL) { LogError("Load COM_SetBinningMode failed"); return false; } API_COM_GetPreCalibMode = (PZ_COM_GetPreCalibMode)GetProcAddress(m_hModule, "COM_GetPreCalibMode"); if (API_COM_GetPreCalibMode == NULL) { LogError("Load COM_GetPreCalibMode failed"); return false; } API_COM_SetPreCalibMode = (PZ_COM_SetPreCalibMode)GetProcAddress(m_hModule, "COM_SetPreCalibMode"); if (API_COM_SetPreCalibMode == NULL) { LogError("Load COM_SetPreCalibMode failed"); return false; } API_COM_GetCalibMode = (PZ_COM_GetCalibMode)GetProcAddress(m_hModule, "COM_GetCalibMode"); if (API_COM_GetCalibMode == NULL) { LogError("Load COM_GetCalibMode failed"); return false; } API_COM_SetCalibMode = (PZ_COM_SetCalibMode)GetProcAddress(m_hModule, "COM_SetCalibMode"); if (API_COM_SetCalibMode == NULL) { LogError("Load COM_SetCalibMode failed"); return false; } API_COM_GenOffsetTpl = (PZ_COM_GenOffsetTpl)GetProcAddress(m_hModule, "COM_GenOffsetTpl"); if (API_COM_GenOffsetTpl == NULL) { LogError("Load COM_GenOffsetTpl failed"); return false; } API_COM_GenGainTpl = (PZ_COM_GenGainTpl)GetProcAddress(m_hModule, "COM_GenGainTpl"); if (API_COM_GenGainTpl == NULL) { LogError("Load COM_GenGainTpl failed"); return false; } API_COM_GenDefectTpl = (PZ_COM_GenDefectTpl)GetProcAddress(m_hModule, "COM_GenDefectTpl"); if (API_COM_GenDefectTpl == NULL) { LogError("Load COM_GenDefectTpl failed"); return false; } API_COM_RegisterEvCallBack = (PZ_COM_RegisterEvCallBack)GetProcAddress(m_hModule, "COM_RegisterEvCallBack"); if (API_COM_RegisterEvCallBack == NULL) { LogError("Load COM_RegisterEvCallBack failed"); return false; } API_COM_UploadFPZMTpl = (PZ_COM_UploadFPZMTpl)GetProcAddress(m_hModule, "COM_UploadFPZMTpl"); if (API_COM_UploadFPZMTpl == NULL) { LogError("Load COM_UploadFPZMTpl failed"); return false; } API_COM_Dst = (PZ_COM_Dst)GetProcAddress(m_hModule, "COM_Dst"); if (API_COM_Dst == NULL) { LogError("Load COM_Dst failed"); return false; } API_COM_Prep = (PZ_COM_Prep)GetProcAddress(m_hModule, "COM_Prep"); if (API_COM_Prep == NULL) { LogError("Load COM_Prep failed"); return false; } API_COM_SetDynamicPara = (PZ_COM_SetDynamicPara)GetProcAddress(m_hModule, "COM_SetDynamicPara"); if (API_COM_SetDynamicPara == NULL) { LogError("Load COM_SetDynamicPara failed"); return false; } API_COM_Dexit = (PZ_COM_Dexit)GetProcAddress(m_hModule, "COM_Dexit"); if (API_COM_Dexit == NULL) { LogError("Load COM_Dexit failed"); return false; } API_COM_GetFPCurStatus = (PZ_COM_GetFPCurStatus)GetProcAddress(m_hModule, "COM_GetFPCurStatus"); if (API_COM_GetFPCurStatus == NULL) { LogError("Load COM_GetFPCurStatus failed"); return false; } API_COM_GetFPStatus = (PZ_COM_GetFPStatus)GetProcAddress(m_hModule, "COM_GetFPStatus"); if (API_COM_GetFPStatus == NULL) { LogError("Load COM_GetFPStatus failed"); return false; } } else { DWORD dw = GetLastError(); strLog.Format("Load dll failed: %d", dw); LogError(strLog); return false; } LogInfo("LoadPZMedicalDLL OVER"); return true; } // 卸载PZMedical的SDK void PZMedical2121ZCtrl::FreePZMedicalDLL() { LogInfo("## FreePZMedicalDLL ##"); if (m_hModule) { FreeLibrary(m_hModule); m_hModule = NULL; LogInfo("FreePZMedicalDLL OVER"); } else LogWarn("FreePZMedicalDLL failed"); } // 调用SDK接口初始化探测器 bool PZMedical2121ZCtrl::InitHW(HWND hWnd) { LogInfo("## InitHW ##"); BOOL nRet; CHAR cRet; CString strLog; LogInfo("Call COM_RegisterEventCallBack: EVENT_LINKUPEX"); nRet = API_COM_RegisterEvCallBack(EVENT_LINKUPEX, FuncLinkEXCallBack); if (!TestError(nRet)) { LogError("Call COM_RegisterEventCallBack: EVENT_LINKUPEX failed"); return false; } LogInfo("Call COM_RegisterEventCallBack: EVENT_LINKUP"); nRet = API_COM_RegisterEvCallBack(EVENT_LINKUP, FuncLinkCallBack); if (!TestError(nRet)) { LogError("Call COM_RegisterEventCallBack: EVENT_LINKUP failed"); return false; } LogInfo("Call RegisterImageCallBack: EVENT_LINKDOWN"); nRet = API_COM_RegisterEvCallBack(EVENT_LINKDOWN, FuncBreakCallBack); if (!TestError(nRet)) { LogError("Call RegisterImageCallBack: EVENT_LINKDOWN failed"); return false; } LogInfo("Call RegisterEventCallBack: EVENT_IMAGEVALID"); nRet = API_COM_RegisterEvCallBack(EVENT_IMAGEVALID, FuncImageCallBack); if (!TestError(nRet)) { LogError("Call RegisterEventCallBack: EVENT_IMAGEVALID failed"); return false; } LogInfo("Call RegisterEventCallBack: EVENT_HEARTBEAT"); nRet = API_COM_RegisterEvCallBack(EVENT_HEARTBEAT, FuncHeartBeatCallBack); if (!TestError(nRet)) { LogError("Call RegisterEventCallBack: EVENT_HEARTBEAT failed"); return false; } LogInfo("Call RegisterEventCallBack: EVENT_OFFSETDONE"); nRet = API_COM_RegisterEvCallBack(EVENT_OFFSETDONE, FuncOffsetDoneCallBack); if (!TestError(nRet)) { LogError("Call RegisterEventCallBack: EVENT_OFFSETDONE failed"); return false; } LogInfo("Call RegisterEventCallBack: EVENT_READY"); nRet = API_COM_RegisterEvCallBack(EVENT_READY, FuncReadyCallBack); if (!TestError(nRet)) { LogError("Call RegisterEventCallBack: EVENT_READY failed"); return false; } LogInfo("Call RegisterEventCallBack: EVENT_EXPOSE"); nRet = API_COM_RegisterEvCallBack(EVENT_EXPOSE, FuncExposeCallBack); if (!TestError(nRet)) { LogError("Call RegisterEventCallBack: EVENT_EXPOSE failed"); return false; } LogInfo("Call RegisterEventCallBack: EVENT_IMAGESTART"); nRet = API_COM_RegisterEvCallBack(EVENT_IMAGESTART, FuncImageStartCallBack); if (!TestError(nRet)) { LogError("Call RegisterEventCallBack: EVENT_IMAGESTART failed"); return false; } LogInfo("Call RegisterEventCallBack: EVENT_IMAGEEND"); nRet = API_COM_RegisterEvCallBack(EVENT_IMAGEEND, FuncImageEndCallBack); if (!TestError(nRet)) { LogError("Call RegisterEventCallBack: EVENT_IMAGEEND failed"); return false; } //设置PCConfig.ini配置文件路径, 一般的情况下PCConfig.ini与ComApi.dll保持平行 LogInfo("Call SetCfgFilePath"); CString strCfgFilePath = strAppPath + _T("\\PZMedical"); nRet = API_COM_SetCfgFilePath(strCfgFilePath.GetBuffer()); if (!TestError(nRet)) { LogWarn("Set SetCfgFilePath failed"); } strCfgFilePath.ReleaseBuffer(); //设置SDK日志保存路径 LogInfo("Call SdkLog"); CString strSDKFilePath = strAppPath + _T("\\PZMedical\\log"); nRet = API_COM_LogPathSet(strSDKFilePath.GetBuffer()); if (!TestError(nRet)) { LogWarn("Set SdkLog failed"); } strSDKFilePath.ReleaseBuffer(); LogInfo("Call Init"); nRet = API_COM_Init(); if (!TestError(nRet)) { strLog.Format("===== InitHW failed: COM_Init return(%d) =====", nRet); LogError(strLog); return false; } //因为不能确认连接到RFOC前探测器的状态,所以默认close一次 if (!CloseDetector()) return false; //连接平板, 此处会触发平板的两个事件: EVENT_LINKUP, EVENT_HEARTBEAT //CString cFpSN = "AGA1BT309461"; strLog.Format("Call Open, SN: %s", m_strFPSN); LogInfo(strLog); nRet = API_COM_Open(m_strFPSN.GetBuffer()); if (!TestError(nRet)) { LogWarn("Open FPD failed"); return false; } bool bRet = WaitRespond(8000); //8秒钟之内回调,否则视为超时 if (bRet) { //连接之后获取探测器基本信息 if (!GetFPInfo()) { LogWarn("GetFPInfo failed"); } //连接之后设置校正模式 if (!GetSetCalibMode(m_cCalibMode)) { LogWarn("GetSetCalibMode failed"); } MSGControl(m_pWnd, ZSKK_MSG_RFDT_WFOUT, ZSKK_DETECTOR_WF_QUERY_STATUS, ZSKK_DETECTOR_LPARAM_STATUS_CONNECTED, 0); } else { LogError("===== InitHW failed: Timeout ====="); return false; } m_eStatus = Standby; m_eSubStatus = SubStatus_IDLE; LogInfo("InitHW OVER"); return true; } //PZ2121Z先stop接口后close接口 bool PZMedical2121ZCtrl::StopDetector() { LogInfo("## StopDtector ##"); LogInfo("Call Stop"); BOOL nRet = API_COM_Stop(); if (!TestError(nRet)) { LogError("COM_Stop failed"); return false; } LogInfo("StopDtector OVER"); return true; } //PZ2121Z的close接口一般要在stop接口之后探测器处于idle状态时才调用,探测器非idle状态时不要直接调用 bool PZMedical2121ZCtrl::CloseDetector() { LogInfo("## CloseDetector ##"); if (m_eStatus != Standby) { StopDetector(); } LogInfo("Call Close"); BOOL nRet = API_COM_Close(); if (!TestError(nRet)) { LogError("COM_Close failed"); return false; } LogInfo("CloseDetector OVER"); return true; } //PZ2121Z连接之前回调函数,COM_Open()接口之前触发 BOOL CALLBACK PZMedical2121ZCtrl::FuncLinkEXCallBack(CHAR cEvent) { g_pPZMedicalInstance->LogInfo("[FuncLinkEXCallBack]"); //这里列出所有与该电脑建立连接的探测器 g_pPZMedicalInstance->LogInfo("Call List"); BOOL nRet; CString strLog; TComFpList tFPList; nRet = g_pPZMedicalInstance->API_COM_List(&tFPList); if (!g_pPZMedicalInstance->TestError(nRet)) { g_pPZMedicalInstance->LogWarn("List FPD failed"); return false; } strLog.Format("List FP number: %d, SN: %s", tFPList.ncount, tFPList.tFpNode[0].FPPsn); g_pPZMedicalInstance->LogInfo(strLog); return TRUE; } //PZ2121Z连接成功回调函数,COM_Open()接口触发 BOOL CALLBACK PZMedical2121ZCtrl::FuncLinkCallBack(CHAR cEvent) { CString strLog = ""; strLog.Format("[EVENT_LINKUP] EventNum(%d): Detector connected.", cEvent); g_pPZMedicalInstance->LogInfo(strLog); g_pPZMedicalInstance->m_cEventNum = cEvent; g_pPZMedicalInstance->m_bFPDConnected = true; SetEvent(g_pPZMedicalInstance->m_hCallbackEvent); return TRUE; } //PZ2121Z连接失败回调函数, 断开连接触发 BOOL CALLBACK PZMedical2121ZCtrl::FuncBreakCallBack(CHAR cEvent) { if (g_pPZMedicalInstance->m_cEventNum == cEvent) //当断线的时候,SDK会一直给EVENT_LINKDOWN回调,这个判断避免记录日志过多 return FALSE; g_pPZMedicalInstance->m_cEventNum = cEvent; CString strLog = ""; strLog.Format("[EVENT_LINKDOWN] EventNum(%d): Detector disconnected!", cEvent); g_pPZMedicalInstance->LogInfo(strLog); g_pPZMedicalInstance->m_bFPDConnected = false; return TRUE; } //PZ2121Z探测器心跳回调函数,COM_Open()接口触发 BOOL CALLBACK PZMedical2121ZCtrl::FuncHeartBeatCallBack(CHAR cEvent) { CString strLog = ""; strLog.Format("[EVENT_HEARTBEAT] EventNum(%d): Detector activate", cEvent); g_pPZMedicalInstance->LogInfo(strLog); if (!g_pPZMedicalInstance->GetFPCurStatus()) { g_pPZMedicalInstance->LogError("GetFPCurStatus Error"); } if (!g_pPZMedicalInstance->GetFPWifiTempBat()) { g_pPZMedicalInstance->LogError("GetFPWifiTempBat Error"); } return TRUE; } //PZ2121Z图像采集准备好的回调函数,之后可调用COM_GetImage()接口 BOOL CALLBACK PZMedical2121ZCtrl::FuncImageCallBack(CHAR cEvent) { CString strLog; if (g_pPZMedicalInstance->m_bTimerSwitch) { g_pPZMedicalInstance->m_dwGetImageT = GetTickCount(); DWORD dwTemp = g_pPZMedicalInstance->m_dwGetImageT - g_pPZMedicalInstance->m_dwLastT; g_pPZMedicalInstance->m_dwLastT = g_pPZMedicalInstance->m_dwGetImageT; strLog.Format("[EVENT_IMAGEVALID] EventNum(%d): No.(%d), Interval(%d)", cEvent, g_pPZMedicalInstance->m_nImgID, dwTemp); } else strLog.Format("[EVENT_IMAGEVALID] EventNum(%d): No.(%d)", cEvent, g_pPZMedicalInstance->m_nImgID); g_pPZMedicalInstance->LogInfo(strLog); g_pPZMedicalInstance->OnImageEvt(); return TRUE; } //PZ2121Z探测器offset刷新完成回调函数, COM_Prep()接口触发 BOOL CALLBACK PZMedical2121ZCtrl::FuncOffsetDoneCallBack(CHAR cEvent) { CString strLog = ""; strLog.Format("[EVENT_OFFSETDONE] EventNum(%d): Detector offset done.", cEvent); g_pPZMedicalInstance->LogInfo(strLog); g_pPZMedicalInstance->m_bOffsetDone = true; SetEvent(g_pPZMedicalInstance->m_hCallbackEvent); return TRUE; } //PZ2121Z探测器 BOOL CALLBACK PZMedical2121ZCtrl::FuncReadyCallBack(CHAR cEvent) { g_pPZMedicalInstance->LogInfo("[FuncReadyCallBack]"); return TRUE; } //PZ2121Z探测器检测到X-ray时触发 BOOL CALLBACK PZMedical2121ZCtrl::FuncExposeCallBack(CHAR cEvent) { g_pPZMedicalInstance->LogInfo("[FuncExposeCallBack]"); return TRUE; } //开始传输图像 BOOL CALLBACK PZMedical2121ZCtrl::FuncImageStartCallBack(CHAR cEvent) { g_pPZMedicalInstance->LogInfo("[FuncImageStartCallBack]"); return TRUE; } //传输图像完成 BOOL CALLBACK PZMedical2121ZCtrl::FuncImageEndCallBack(CHAR cEvent) { g_pPZMedicalInstance->LogInfo("[FuncImageEndCallBack]"); return TRUE; } //PZ2121Z在获取到EVENT_LINKUP事件之后,获取平板的基本信息 bool PZMedical2121ZCtrl::GetFPInfo() { BOOL nRet; CHAR cRet; CString strLog; #if 0 //获取探测器型号以及SDK版本信息 LogInfo("Call GetFPType"); cRet = API_COM_GetFPType(); switch (cRet) { case FP_TYPE_3543: LogInfo("FP_TYPE_3543"); break; case FP_TYPE_4343: LogInfo("FP_TYPE_4343"); break; case FP_TYPE_2121: LogInfo("FP_TYPE_2121"); break; default: LogInfo("Unknow Type"); break; } #endif //获取序列号和SDK版本 CHAR cFpSN[32] = { '\0' }; CHAR cSDKVer[32] = { '\0' }; LogInfo("Call GetFPsn"); nRet = API_COM_GetFPsn(cFpSN); //nRet = API_COM_GetFPsnEx(0, cFpSN); if (!TestError(nRet)) { LogWarn("GetFPsn failed"); } LogInfo("Call GetDllVer"); nRet = API_COM_GetDllVer(cSDKVer); if (!TestError(nRet)) { LogWarn("GetDllVer failed"); } strLog.Format("FPD SN(%s), SDK Ver(%s)", cFpSN, cSDKVer); LogInfo(strLog); //获取Binning模式, 如果当前探测器内部的Binnin模式和配置文件中的Binning模式不同, 则重新设置 LogInfo("Call GetBinningMode"); CHAR cBinningMode = 0; nRet = API_COM_GetBinningMode(&cBinningMode); if (!TestError(nRet)) { LogWarn("GetBinningMode failed"); //return false; } else { if (cBinningMode == PZ_ONExONE) strLog = "BinningMode is 1x1"; else if (cBinningMode == PZ_TWOxTWO) strLog = "BinningMode is 2x2"; else if (cBinningMode == PZ_THRxTHR) strLog = "BinningMode is 3x3"; else if (cBinningMode == PZ_FOURxFOUR) strLog = "BingingMode is 4x4"; else if (cBinningMode == PZ_SIXxSIX) strLog = "BingingMode is 6x6"; else strLog.Format("No support BinningMode: %d", cBinningMode); LogInfo(strLog); } if (m_nBinningMode != cBinningMode) { //设置探测器的 BinningMode 为 m_nBinningMode 值 LogInfo("Call SetBinningMode"); nRet = API_COM_SetBinningMode(m_nBinningMode); if (!TestError(nRet)) { LogError("SetBinningMode failed"); //return false; } strLog.Format("Change BinningMode to %d", m_nBinningMode); LogInfo(strLog); } return true; } bool PZMedical2121ZCtrl::GetFPCurStatus() { LogInfo("Call GetFPCurStatus"); m_nFPCurStatus = API_COM_GetFPCurStatus(); switch (m_nFPCurStatus) { case STATUS_IDLE: LogInfo("FP current status: IDLE"); break; case STATUS_HST: LogInfo("FP current status: HST"); break; case STATUS_AED1: LogInfo("FP current status: AED1"); break; case STATUS_AED2: LogInfo("FP current status: AED2"); break; case STATUS_RECOVER: LogInfo("FP current status: RECOVER"); break; case STATUS_DST: LogInfo("FP current status: DST"); break; default: LogError("FP current status: ERROR"); break; } return true; } bool PZMedical2121ZCtrl::GetFPWifiTempBat() { CString strLog = ""; BOOL nRet; TFPStat tFPStat = { 0 }; nRet = API_COM_GetFPStatus(&tFPStat); strLog.Format(_T("Wifi signal: %d"), tFPStat.tWifiStatus.ucSignal_level); LogInfo(strLog); strLog.Format(_T("Temperature: %.1f, Humidity:%.1f"), (double(tFPStat.tFpTempHum.Temp)) / 10, (double(tFPStat.tFpTempHum.Hum)) / 10); LogInfo(strLog); if (0 != (tFPStat.tBatInfo1.full + tFPStat.tBatInfo2.full)) strLog.Format(_T("Battery: %.2f"), (double(tFPStat.tBatInfo1.Remain + tFPStat.tBatInfo2.Remain) / (tFPStat.tBatInfo1.full + tFPStat.tBatInfo2.full))); else strLog = "Battery: NULL"; LogInfo(strLog); return true; } bool PZMedical2121ZCtrl::GetImageInfo() { BOOL nRet; CString strLog; TImageMode* ptImageMode = NULL; LogInfo("Call GetImageMode"); nRet = API_COM_GetImageMode(ptImageMode); if (!TestError(nRet)) { LogWarn("Get image mode failed"); return false; } UINT16 u16ImageRow = ptImageMode->usRow; UINT16 u16ImageCol = ptImageMode->usCol; UINT16 u16ImagePixel = ptImageMode->usPix; strLog.Format("ImageRow(%d), ImageCol(%d), ImagePixel(%d)", u16ImageRow, u16ImageCol, u16ImagePixel); LogInfo(strLog); return true; } bool PZMedical2121ZCtrl::ExpEnable() //父类AcqCtrl有,暂时没用 { CAcqCtrl::ExpEnable(); return true; } bool PZMedical2121ZCtrl::ExpDisable() //父类AcqCtrl有,暂时没用 { CAcqCtrl::ExpDisable(); return true; } bool PZMedical2121ZCtrl::FluEnable() //父类AcqCtrl有,暂时没用 { CAcqCtrl::FluEnable(); return true; } bool PZMedical2121ZCtrl::FluDisable() //父类AcqCtrl有,暂时没用 { CAcqCtrl::FluDisable(); return true; } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////// Functions ////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // 获取当前校正文件状态 bool PZMedical2121ZCtrl::GetCalibrationStatus(int nLogicMode, int nOffsetIndex, ZSKK_CAL_STATUS& modeStatus) { return true; } // 激活当前模式 bool PZMedical2121ZCtrl::ActiveLogicMode(int nmode, int nOffRef) { LogInfo("## ActiveLogicMode ##"); if (!m_bFPDConnected) { LogError("No connect, return false"); return false; } if ((m_eStatus == Offset) || (m_eStatus == XrayCalibration)) { LogError("Detector is in calibration state, ignore Active Mode"); return false; } MSGControl(m_pWnd, ZSKK_MSG_RFDT_WFOUT, ZSKK_DETECTOR_WF_QUERY_STATUS, ZSKK_DETECTOR_LPARAM_STATUS_PREPARE, 0); // Notify Prepare m_PreSynParam.xWindow = m_CurSynParam.xWindow; m_PreSynParam.frenquency = m_CurSynParam.frenquency; DetectorMode tempDetectMode; OffsetMode tempOffsetMode; CString strLog = ""; int ntempOffsetNum = 0; int nXSize, nYSize; // 根据激活模式状态,切换改采集卡配置,切换同步方式 size_t nsize = RFModeConf.DetectorMode.m_nodes.size(); for (int i = 0; i < nsize; i++) { tempDetectMode = RFModeConf.DetectorMode.m_nodes[i]; ntempOffsetNum = tempDetectMode.OffsetMode.m_nodes.size(); if (tempDetectMode.LogicMode == nmode) { if (nmode != m_ActiveMode.nLogicMode) { LogInfo("Change ApplicationMode"); } else { LogInfo("No Change just return"); //return true; break; //改为break,可以执行下面的修改配置操作 } if (nOffRef < tempDetectMode.OffsetMode.m_nodes.size()) { tempOffsetMode = tempDetectMode.OffsetMode.m_nodes[nOffRef]; m_CurSynParam.frenquency = tempOffsetMode.Frequency; m_CurSynParam.xWindow = tempOffsetMode.Xwindow; strLog.Format("Frenquency(%f), Xwindow(%f)", m_CurSynParam.frenquency, m_CurSynParam.xWindow); LogInfo(strLog); COPYDATASTRUCT copyData; copyData.lpData = &m_CurSynParam; copyData.cbData = sizeof(ZSKK_CAL_SYN_PARAM); MSGControl(m_pWnd, ZSKK_MSG_RFDATA_OUT, ZSKK_DETECTOR_DATA_CALDETECTOR_FPSXWIN, (LPARAM)©Data, ZSKK_MSG_TYPE_SYNC_YES); } //使用PZAppModeConf.xml中的起始行列计算图像大小,避免在使用自定义开窗模式时需要修改PZAppModeConf.xml和RFModeConf.xml两个文件 APPMode objPZMode; bool bGetMode = false; for (int n = 0; n < PZModeConf.APPMode.m_nodes.size(); n++) { if (PZModeConf.APPMode.m_nodes[n].AppModeKey == nmode) { objPZMode = PZModeConf.APPMode.m_nodes[nmode]; bGetMode = true; break; } } if (!bGetMode) { strLog.Format("Not found the mode: %d", nmode); LogError(strLog); return false; } nXSize = (objPZMode.EndColum - objPZMode.StartColum + 1) / (objPZMode.BinningMode + 1); nYSize = (objPZMode.EndLine - objPZMode.StartLine + 1) / (objPZMode.BinningMode + 1); ChangeActiveMode(tempDetectMode.ExamType, tempDetectMode.PUMode , /*tempDetectMode.ImageSizeX*/nXSize, /*tempDetectMode.ImageSizeY*/nYSize , tempDetectMode.DeadLineLeft, tempDetectMode.DeadLineTop , tempDetectMode.DeadLineRight, tempDetectMode.DeadLineBottom); break; } } m_ActiveMode.nLogicMode = nmode; m_ActiveMode.nOffIndex = nOffRef; strLog.Format("Active mode(%d) successfully", m_ActiveMode.nLogicMode); LogInfo(strLog); ZSKK_CAL_STATUS CalStatus; if (GetCalibrationStatus(nmode, nOffRef, CalStatus)) { MSGControl(m_pWnd, ZSKK_MSG_RFDT_PARAMOUT, ZSKK_DETECTOR_PA_CURMODE_ACTIVE, m_ActiveMode.nLogicMode * 10 + m_ActiveMode.nOffIndex, 0); COPYDATASTRUCT copyData; copyData.lpData = &CalStatus; copyData.cbData = sizeof(ZSKK_CAL_STATUS); MSGControl(m_pWnd, ZSKK_MSG_RFDATA_OUT, ZSKK_DETECTOR_DATA_CALIBRATIONSTATUS, (LPARAM)©Data, ZSKK_MSG_TYPE_SYNC_YES); MSGControl(m_pWnd, ZSKK_MSG_RFDT_PARAMOUT, ZSKK_DETECTOR_PA_CURMODE_CALSTATUS, ZSKK_DETECTOR_LPARAM_CALSTATUS_REFRESH, 0); } //调用SDK接口,进入采集状态 if (!StartAcquisition(nmode)) { return false; } MSGControl(m_pWnd, ZSKK_MSG_RFDT_WFOUT, ZSKK_DETECTOR_WF_QUERY_STATUS, ZSKK_DETECTOR_LPARAM_STATUS_MODEACTIVESUCCESS, 0); MSGControl(m_pWnd, ZSKK_MSG_RFDT_WFOUT, ZSKK_DETECTOR_WF_QUERY_STATUS, ZSKK_DETECTOR_LPARAM_STATUS_READYACQ, 0); LogInfo("------ActiveLogicMode Send message: ACQ_READY------"); return true; } bool PZMedical2121ZCtrl::ChangeActiveMode(CString ExamType, int nPUMode, int nSizeX, int nSizeY, int nCropLeft, int nCropTop, int nCropRight, int nCropBottom) { LogInfo(" ## ChangeActiveMode ## "); CString strLog = ""; DWORD ImgSize = nSizeX * nSizeY; m_nRawWidth = nSizeX; m_nRawHeight = nSizeY; if (m_ImgInfo.pwData == NULL) { m_pImgBufferSize = ImgSize; m_ImgInfo.pwData = new WORD[m_pImgBufferSize]; } else { if (ImgSize > m_pImgBufferSize) { delete[]m_ImgInfo.pwData; m_pImgBufferSize = ImgSize; m_ImgInfo.pwData = new WORD[m_pImgBufferSize]; } } strLog.Format("Change active mode: SizeX = %d, SizeY = %d", m_nRawWidth, m_nRawHeight); LogInfo(strLog); if (m_cImgBuff != NULL) { delete m_cImgBuff; m_cImgBuff = NULL; } m_cImgBuff = new CHAR[nSizeX * nSizeY * 2]; m_nCropLeft = nCropLeft; m_nCropTop = nCropTop; m_nCropRight = nCropRight; m_nCropBottom = nCropBottom; m_ImgInfo.nWidth = nSizeX - m_nCropLeft - m_nCropRight; m_ImgInfo.nHeight = nSizeY - m_nCropTop - m_nCropBottom; m_ImgInfo.nBits = 16; m_ACQInfo.nColumn = m_ImgInfo.nWidth; m_ACQInfo.nRow = m_ImgInfo.nHeight; m_ACQInfo.nBits = 16; m_ACQInfo.fACQElementSpacing = (float)(m_nPixelSpacing*0.001); CWnd *pWndTest = NULL; if (ExamType == _T("RAD") || ExamType == _T("TOMO")) { strLog.Format("Send RAD image information: SizeX = %d, SizeY = %d, PixelSpacing = %.3f", m_ACQInfo.nColumn, m_ACQInfo.nRow, m_ACQInfo.fACQElementSpacing); LogInfo(strLog); COPYDATASTRUCT copyData; copyData.lpData = &m_ACQInfo; copyData.cbData = sizeof(ZSKK_ACQ_INFO); MSGControl(pWndTest, ZSKK_MSG_RFDATA_OUT, ZSKK_DETECTOR_DATA_RAD_IMAGESIZEBIT, (LPARAM)©Data, ZSKK_MSG_TYPE_SYNC_YES); } else { strLog.Format("Send Flu Image information: SizeX = %d, SizeY = %d, PixelSpacing = %.3f,", m_ACQInfo.nColumn, m_ACQInfo.nRow, m_ACQInfo.fACQElementSpacing); LogInfo(strLog); COPYDATASTRUCT copyData; copyData.lpData = &m_ACQInfo; copyData.cbData = sizeof(ZSKK_ACQ_INFO); MSGControl(pWndTest, ZSKK_MSG_RFDATA_OUT, ZSKK_DETECTOR_DATA_FLU_IMAGESIZEBIT, (LPARAM)©Data, ZSKK_MSG_TYPE_SYNC_YES); } LogInfo("CHANGE OVER"); return true; } void PZMedical2121ZCtrl::setNextStepEvent() { LogInfo(" ## setNextStepEvent ## "); } bool PZMedical2121ZCtrl::DownloadCorrectionFile2Device() { LogInfo(" ## DownloadCorrectionFile2Device ## "); return true; } // For detector x-ray calibration bool PZMedical2121ZCtrl::OnXrayGenStart() { LogInfo("Calibration request to start Xray"); //Send message to upper layer MSGControl(m_pWnd, ZSKK_MSG_RFDT_CALOUT, ZSKK_DETECTOR_CALIBRATION_STARTXRAY, NULL, ZSKK_MSG_TYPE_SYNC_NO); return true; } // For detector x-ray calibration bool PZMedical2121ZCtrl::OnXrayGenStop() { LogInfo("Calibration request to stop Xray"); //Send message to upper layer MSGControl(m_pWnd, ZSKK_MSG_RFDT_CALOUT, ZSKK_DETECTOR_CALIBRATION_STOPXRAY, NULL, ZSKK_MSG_TYPE_SYNC_YES); return true; } // For detector x-ray calibration bool PZMedical2121ZCtrl::OnXrayGenSetDose() { LogInfo(" ## OnXrayGenSetDose ## "); return true; } // For detector x-ray calibration bool PZMedical2121ZCtrl::OnXrayCalSuccess() { LogInfo("------Calibration success---"); MSGControl(m_pWnd, ZSKK_MSG_RFDT_CALOUT, ZSKK_DETECTOR_CALIBRATION_CALRESULT, ZSKK_DETECTOR_LPARAM_CALIBRATION_CALSUCCESS, 0); MSGControl(m_pWnd, ZSKK_MSG_RFDT_WFOUT, ZSKK_DETECTOR_WF_QUERY_STATUS, ZSKK_DETECTOR_LPARAM_STATUS_READYACQ, 0); MSGControl(m_pWnd, ZSKK_MSG_RFDT_WFOUT, ZSKK_DETECTOR_WF_ALARM_CODE, 0, 0); //clear alarm error LogInfo("------OnXrayCalSuccess Send message: ACQ_READY---"); return true; } // For detector x-ray calibration bool PZMedical2121ZCtrl::OnXrayCalFail() { //Send message to upper layer m_strCalWarning = "ERR_CALIBRATION_COMPUTATION"; LogInfo("Calibration failed: ERR_CALIBRATION_COMPUTATION"); MSGControl(m_pWnd, ZSKK_MSG_RFDT_CALOUT, ZSKK_DETECTOR_CALIBRATION_CALRESULT, ZSKK_DETECTOR_LPARAM_CALIBRATION_CALFAILED, 0); return true; } bool PZMedical2121ZCtrl::OnSYNC() { //Send message to upper layer CString strdose; strdose.Format("Get syn message,Xwindow = %d, Frequency = %f", m_CalSynParam.xWindow, m_CalSynParam.frenquency); LogInfo(strdose); //修改该信号,回调函数通知外部给信号 COPYDATASTRUCT copyData; copyData.lpData = &m_CalSynParam; copyData.cbData = sizeof(ZSKK_CAL_SYN_PARAM); MSGControl(m_pWnd, ZSKK_MSG_RFDATA_OUT, ZSKK_DETECTOR_DATA_CALDETECTOR_FPSXWIN, (LPARAM)©Data, ZSKK_MSG_TYPE_SYNC_YES); return true; } bool PZMedical2121ZCtrl::OnWarning() { LogInfo(" ## OnWarning ## "); return true; } bool PZMedical2121ZCtrl::OnStatus() { LogInfo(" ## OnStatus ## "); return true; } bool PZMedical2121ZCtrl::OnModeActive() { LogInfo(" ## OnModeActive ## "); MSGControl(m_pWnd, ZSKK_MSG_RFDT_WFOUT, ZSKK_DETECTOR_WF_QUERY_STATUS, ZSKK_DETECTOR_LPARAM_STATUS_MODEACTIVESUCCESS, 0); MSGControl(m_pWnd, ZSKK_MSG_RFDT_WFOUT, ZSKK_DETECTOR_WF_QUERY_STATUS, ZSKK_DETECTOR_LPARAM_STATUS_READYACQ, 0); return true; } bool PZMedical2121ZCtrl::OnTimeOut() { if (m_bState)return false; return true; } //获取LogicMode列表,4343D不太依赖这个配置,所以用不到 bool PZMedical2121ZCtrl::GetLogicModeList(vector &vecDetectorMode) { //if (CAcqCtrl::GetLogicModeList(vecDetectorMode)) return true; LogInfo(" ## GetLogicModeList ## "); DetectorMode tempDetectMode; OffsetMode tempOffsetMode; ZSKK_DETECTOR_MODE_INFO tempDetectorModeInfo; vector &tempvecDetectorMode = vecDetectorMode; tempvecDetectorMode.clear(); int ntempOffsetNum = 0; int nsize = RFModeConf.DetectorMode.m_nodes.size(); for (int i = 0; i < nsize; i++) { tempDetectMode = RFModeConf.DetectorMode.m_nodes[i]; tempDetectorModeInfo.nLogicMode = tempDetectMode.LogicMode; tempDetectorModeInfo.nPUMode = tempDetectMode.PUMode; tempDetectorModeInfo.strExpType = tempDetectMode.ExamType; tempDetectorModeInfo.strConfFile = tempDetectMode.ConfigurationFile; //tempDetectorModeInfo.strBinMode = tempDetectMode tempDetectorModeInfo.nGainValue = tempDetectMode.GainValue; tempDetectorModeInfo.nModeEnable = tempDetectMode.ModeEnable; tempDetectorModeInfo.nColumn = tempDetectMode.ImageSizeX; tempDetectorModeInfo.nRow = tempDetectMode.ImageSizeY; //offset info ntempOffsetNum = tempDetectMode.OffsetMode.m_nodes.size(); for (int j = 0; j < ntempOffsetNum; j++) { tempOffsetMode = tempDetectMode.OffsetMode.m_nodes[j]; tempDetectorModeInfo.nOffsetIndex = tempOffsetMode.OffsetIndex; tempDetectorModeInfo.nXwindow = tempOffsetMode.Xwindow; tempDetectorModeInfo.fFrequency = tempOffsetMode.Frequency; tempDetectorModeInfo.strDescription = tempOffsetMode.Description; tempvecDetectorMode.push_back(tempDetectorModeInfo); } } //vecDetectorMode = tempvecDetectorMode; LogInfo("End to get logicModelist"); return true; } bool PZMedical2121ZCtrl::CalibrateAllModes() { LogInfo(" ## CalibrateAllModes ## "); return true; } // 从RFModeConf.xml中获取OffsetMode,4343D闲时自己刷offset,用不到这个函数 int PZMedical2121ZCtrl::GetOffsetMode(int nLogicMode, int nOffsetIndex, int nSpeed) { LogInfo("## GetOffsetMode ##"); CString strlog; int res = nOffsetIndex; DetectorMode tempDetectMode; OffsetMode tempOffsetMode; int ntempOffsetNum = 0; int nsize = RFModeConf.DetectorMode.m_nodes.size(); for (int i = 0; i < nsize; i++) { tempDetectMode = RFModeConf.DetectorMode.m_nodes[i]; if (tempDetectMode.LogicMode == nLogicMode) { ntempOffsetNum = tempDetectMode.OffsetMode.m_nodes.size(); for (int j = 0; j < ntempOffsetNum; j++) { tempOffsetMode = tempDetectMode.OffsetMode.m_nodes[j]; if (nSpeed == (int)(tempOffsetMode.Frequency)) { res = j; strlog.Format("current logic mode is %d speed is %0.2f, offset mode is %d", nLogicMode, tempOffsetMode.Frequency, res); LogInfo(strlog); return res; } } } } return res; } // [xxxDlg.cpp]OnMSGPARAMETER() -> [xxxCtrl.cpp]OnMSGPARAMETER_Process(WPARAM, LPARAM) // WPARAM 0: ZSKK_DETECTOR_PA_SET_RADMODE 设置点片模式 bool PZMedical2121ZCtrl::SelectRADMode(int nLogicMode, int nOffsetIndex) { LogInfo("## SelectRADMode ##"); if (CAcqCtrl::SelectRADMode(nLogicMode, nOffsetIndex)) return true; if (!m_bFPDConnected) { LogError("No connect, return false"); return false; } CString strLog = ""; //从上层传过来的模式为ZSKK模式,301或302一类的code值,需要通过文件RealModeMatch.xml转换成当前平板的真实逻辑模式。 CString strMode; strMode.Format("%04d", nLogicMode); m_RadMode.nLogicMode = atoi(m_appRealModeConf.GetValueByKey(strMode)); m_RadMode.nOffIndex = nOffsetIndex; strLog.Format("Select RAD Mode(%d), Offset index(%d)", m_RadMode.nLogicMode, m_RadMode.nOffIndex); LogInfo(strLog); LogInfo("SelectRADMode OVER"); return true; } // WPARAM 1: ZSKK_DETECTOR_PA_SET_FLUMODE 设置透视模式 bool PZMedical2121ZCtrl::SelectFLUMode(int nLogicMode, int nOffsetIndex) { LogInfo(" ## SelectFLUMode ## "); if (CAcqCtrl::SelectFLUMode(nLogicMode, nOffsetIndex))return true; if (!m_bFPDConnected) { LogWarn("Not connected"); } CString strLog = ""; //从上层传过来的模式为ZSKK模式,101或202一类的code值,需要通过文件RealModeMatch.xml转换成当前平板的真实逻辑模式。 CString strMode; strMode.Format("%04d", nLogicMode); m_FluMode.nLogicMode = atoi(m_appRealModeConf.GetValueByKey(strMode)); m_FluMode.nOffIndex = nOffsetIndex; strLog.Format("SELECT OVER, FLU MODE(%d), OFFSET INDEX(%d)", m_FluMode.nLogicMode, nOffsetIndex); LogInfo(strLog); //LogInfo("->CBCTStart"); //int nRet = COM_MFPCBCTSTART(); //调用CBCT接口,提前终止SDK的Idle状态,避免在出射线的时候还在刷新offset文件 //if (!TestError(nRet)) //{ // LogError("CBCTStart failed"); // return false; //} return true; } // WPARAM 2: ZSKK_DETECTOR_PA_SET_CINEMODE 没有这个模式,用不到 bool PZMedical2121ZCtrl::SelectCINEMode(int nLogicMode, int nOffsetIndex) //选择CINE模式 { LogInfo(" ## SelectCINEMode ## "); if (CAcqCtrl::SelectCINEMode(nLogicMode, nOffsetIndex))return true; if (!m_bFPDConnected) { LogError("No connect, return false"); return false; } CString strLog = ""; strLog.Format("-----Select CINE mode: %d, Offset index: %d----", nLogicMode, nOffsetIndex); LogInfo(strLog); return true; //4343D没有这个模式 //从上层传过来的模式为ZSKK模式,101或202一类的code值,需要通过文件RealModeMatch.xml转换成当前平板的真实逻辑模式。 //CString strMode; //strMode.Format("%04d", nLogicMode); //LogInfo(strMode); //m_CINEMode.nLogicMode = atoi(m_appRealModeConf.GetValueByKey(strMode)); //strMode.Format("nLogicMode %04d", m_CINEMode.nLogicMode); //LogInfo(strMode); m_CINEMode.nLogicMode = nLogicMode; m_CINEMode.nOffIndex = nOffsetIndex; return true; } // WPARAM 3: ZSKK_DETECTOR_PA_SET_RADSPEED 设置点片帧频 // 每种曝光模式只有一个帧频,接口中只记录日志,返回true bool PZMedical2121ZCtrl::SetRadOffsetMode(int nLogicMode, int nOffsetIndex, int nSpeed) { LogInfo("## SetRadOffsetMode ##"); if (!m_bFPDConnected) { LogError("No connect, return false"); return false; } CString strlog = ""; //int ApplicationMode = GetOffsetMode(nLogicMode, nOffsetIndex, nSpeed); strlog.Format("Set RAD speed to: %d", nSpeed); LogInfo(strlog); return true; //不支持获取校正状态(校正文件有效期等) ZSKK_CAL_STATUS CalStatus; if (GetCalibrationStatus(m_RadMode.nLogicMode, m_RadMode.nOffIndex, CalStatus)) { COPYDATASTRUCT copyData; copyData.lpData = &CalStatus; copyData.cbData = sizeof(ZSKK_CAL_STATUS); MSGControl(m_pWnd, ZSKK_MSG_RFDATA_OUT, ZSKK_DETECTOR_DATA_CALIBRATIONSTATUS, (LPARAM)©Data, ZSKK_MSG_TYPE_SYNC_YES); MSGControl(m_pWnd, ZSKK_MSG_RFDT_PARAMOUT, ZSKK_DETECTOR_PA_RADMODE_CALSTATUS, ZSKK_DETECTOR_LPARAM_CALSTATUS_REFRESH, 0); } return true; } // WPARAM 4: ZSKK_DETECTOR_PA_SET_FLUSPEED 设置透视帧频 // 目前4343D每种曝光模式只有一个帧频,接口中只记录日志,返回true bool PZMedical2121ZCtrl::SetFluOffsetMode(int nLogicMode, int nOffsetIndex, float fSpeed) { LogInfo(" ## SetFluOffsetMode ## "); if (!m_bFPDConnected) { LogError("No connect, return false"); return false; } CString strlog = ""; //int ApplicationMode = GetOffsetMode(nLogicMode, nOffsetIndex, fSpeed); strlog.Format("Set FLU speed to: %0.2f", fSpeed/*, ApplicationMode*/); LogInfo(strlog); return true; //不支持获取校正状态(校正文件有效期等) ZSKK_CAL_STATUS CalStatus; if (GetCalibrationStatus(m_FluMode.nLogicMode, m_FluMode.nOffIndex, CalStatus)) { COPYDATASTRUCT copyData; copyData.lpData = &CalStatus; copyData.cbData = sizeof(ZSKK_CAL_STATUS); MSGControl(m_pWnd, ZSKK_MSG_RFDATA_OUT, ZSKK_DETECTOR_DATA_CALIBRATIONSTATUS, (LPARAM)©Data, ZSKK_MSG_TYPE_SYNC_YES); MSGControl(m_pWnd, ZSKK_MSG_RFDT_PARAMOUT, ZSKK_DETECTOR_PA_RADMODE_CALSTATUS, ZSKK_DETECTOR_LPARAM_CALSTATUS_REFRESH, 0); } return true; } // WPARAM 5: ZSKK_DETECTOR_PA_SET_FLUSPEED 没有这个模式,用不到 bool PZMedical2121ZCtrl::SetCinOffsetMode(int nLogicMode, int nOffsetIndex, float fSpeed) { LogInfo(" ## SetCinOffsetMode ## "); int ApplicationMode = GetOffsetMode(nLogicMode, nOffsetIndex, fSpeed); CString strlog; strlog.Format("current CIN speed is %0.2f, OffseMode is %d", fSpeed, ApplicationMode); LogInfo(strlog); if (!m_bFPDConnected) { LogError("No connect, return false"); return false; } return true; //4343D没有这个模式 ZSKK_CAL_STATUS CalStatus; if (GetCalibrationStatus(m_CINEMode.nLogicMode, m_CINEMode.nOffIndex, CalStatus)) { COPYDATASTRUCT copyData; copyData.lpData = &CalStatus; copyData.cbData = sizeof(ZSKK_CAL_STATUS); MSGControl(m_pWnd, ZSKK_MSG_RFDATA_OUT, ZSKK_DETECTOR_DATA_CALIBRATIONSTATUS, (LPARAM)©Data, ZSKK_MSG_TYPE_SYNC_YES); MSGControl(m_pWnd, ZSKK_MSG_RFDT_PARAMOUT, ZSKK_DETECTOR_PA_RADMODE_CALSTATUS, ZSKK_DETECTOR_LPARAM_CALSTATUS_REFRESH, 0); } return false; } // WPARAM 6: ZSKK_DETECTOR_PA_ACTIVE_RADMODE 激活点片模式 // 只是设置上传帧频、窗口、图像大小等参数 bool PZMedical2121ZCtrl::ActiveRADMode() { LogInfo("## ActiveRADMode ##"); if (CAcqCtrl::ActiveRADMode()) return true; if (!m_bFPDConnected) { LogError("No connect, return false"); return false; } if (m_eStatus == Acquire) { LogWarn("Already in acquiring image, return true"); return true; } MSGControl(m_pWnd, ZSKK_MSG_RFDT_WFOUT, ZSKK_DETECTOR_WF_QUERY_STATUS, ZSKK_DETECTOR_LPARAM_STATUS_PREPARE, 0); LogInfo("------ActiveRADMode Send message: PREPARE---"); if (!ActiveHSTMode()) { LogError("Set FPD in HST failed"); } //check if the mode is active already bool bActive = false; m_bSendRadImage = false; m_nPixelSpacing = 140; //图像的Pixel Spacing CString strtemp; strtemp.Format("RAD Mode: %d, Target offset Index: %d", m_RadMode.nLogicMode, m_RadMode.nOffIndex); LogInfo(strtemp); if (ActiveLogicMode(m_RadMode.nLogicMode, m_RadMode.nOffIndex)) { bActive = true; } else { bActive = false; } if (bActive) { MSGControl(m_pWnd, ZSKK_MSG_RFDT_WFOUT, ZSKK_DETECTOR_WF_QUERY_STATUS, ZSKK_DETECTOR_LPARAM_STATUS_MODEACTIVESUCCESS, 0); LogInfo("Success, Current RAD mode active success"); return true; } else { MSGControl(m_pWnd, ZSKK_MSG_RFDT_WFOUT, ZSKK_DETECTOR_WF_QUERY_STATUS, ZSKK_DETECTOR_LPARAM_STATUS_MODEACTIVEFAILED, 0); LogInfo("Failed, Current RAD mode active failed."); return false; } } // WPARAM 7: ZSKK_DETECTOR_PA_ACTIVE_FLUMODE 激活透视模式 // 只是设置上传帧频、窗口、图像大小等参数 bool PZMedical2121ZCtrl::ActiveFLUMode() { LogInfo("## ActiveFLUMode ##"); if (CAcqCtrl::ActiveFLUMode()) return true; if (!m_bFPDConnected) { LogError("No connect, return false"); return false; } if (m_eStatus == Acquire) { LogInfo("Acquiring image,return true"); return true; } //::PostMessage(this->m_hWnd,MSG_ACQ_STATUS,ACQ_PREPARE,NULL); MSGControl(m_pWnd, ZSKK_MSG_RFDT_WFOUT, ZSKK_DETECTOR_WF_QUERY_STATUS, ZSKK_DETECTOR_LPARAM_STATUS_PREPARE, 0); LogInfo("------ActiveFLUMode Send message: ACQ_PREPARE---"); if (!ActiveDSTMode()) { LogError("Set FPD in DST failed"); } //check if the mode is active already bool bActive = false; //通过配置文件获取binning模式,用来计算PixelSpacing CString strLog = ""; APPMode objPZMode; bool bGetMode = false; for (int n = 0; n < PZModeConf.APPMode.m_nodes.size(); n++) { if (PZModeConf.APPMode.m_nodes[n].AppModeKey == m_FluMode.nLogicMode) { objPZMode = PZModeConf.APPMode.m_nodes[m_FluMode.nLogicMode]; bGetMode = true; break; } } if (!bGetMode) { strLog.Format("Not found the mode: %d", m_FluMode.nLogicMode); LogError(strLog); return false; } m_nPixelSpacing = (objPZMode.BinningMode + 1) * 140;//图像的PixelSpacing根据binning模式自动扩大相应倍数 CString strtemp; strtemp.Format("Flu Mode: %d, Target offset Index: %d", m_FluMode.nLogicMode, m_FluMode.nOffIndex); LogInfo(strtemp); if (ActiveLogicMode(m_FluMode.nLogicMode, m_FluMode.nOffIndex)) { bActive = true; } else { bActive = false; } if (bActive) { MSGControl(m_pWnd, ZSKK_MSG_RFDT_WFOUT, ZSKK_DETECTOR_WF_QUERY_STATUS, ZSKK_DETECTOR_LPARAM_STATUS_MODEACTIVESUCCESS, 0); LogInfo("# ActiveFLUMode # successfully"); return true; } else { MSGControl(m_pWnd, ZSKK_MSG_RFDT_WFOUT, ZSKK_DETECTOR_WF_QUERY_STATUS, ZSKK_DETECTOR_LPARAM_STATUS_MODEACTIVEFAILED, 0); LogError("# ActiveFLUMode # failed"); return false; } } // WPARAM 8: ZSKK_DETECTOR_PA_ACTIVE_CINEMODE 没有这个模式,用不到 bool PZMedical2121ZCtrl::ActiveCINEMode() { LogInfo("## ActiveCINEMode ##"); if (CAcqCtrl::ActiveCINEMode())return true; if (!m_bFPDConnected) { LogError("No connect, return false"); return false; } if (m_eStatus == Acquire) { LogInfo("Acquiring image,return true"); return true; } return true; //2121Z没有这个模式 //::PostMessage(this->m_hWnd,MSG_ACQ_STATUS,ACQ_PREPARE,NULL); MSGControl(m_pWnd, ZSKK_MSG_RFDT_WFOUT, ZSKK_DETECTOR_WF_QUERY_STATUS, ZSKK_DETECTOR_LPARAM_STATUS_PREPARE, 0); LogInfo("------ActiveFLUMode Send message: ACQ_PREPARE---"); if (!ActiveDSTMode()) { LogError("Set FPD in DST failed"); } //check if the mode is active already bool bActive = false; CString strtemp; strtemp.Format("CINE Mode: %d, Target offset Index, %d", m_CINEMode.nLogicMode, m_CINEMode.nOffIndex); LogInfo(strtemp); if (ActiveLogicMode(m_CINEMode.nLogicMode, m_CINEMode.nOffIndex)) { bActive = true; } else { bActive = false; } if (bActive) { MSGControl(m_pWnd, ZSKK_MSG_RFDT_WFOUT, ZSKK_DETECTOR_WF_QUERY_STATUS, ZSKK_DETECTOR_LPARAM_STATUS_MODEACTIVESUCCESS, 0); LogInfo("Success, Current CINE mode active success"); return true; } else { MSGControl(m_pWnd, ZSKK_MSG_RFDT_WFOUT, ZSKK_DETECTOR_WF_QUERY_STATUS, ZSKK_DETECTOR_LPARAM_STATUS_MODEACTIVEFAILED, 0); LogError("Failed, Current CINE mode active failed."); return false; } } //对于PZ2121Z探测器,调用SDK的 COM_HstAcq() 接口,激活HST模式 bool PZMedical2121ZCtrl::ActiveHSTMode() { BOOL nRet; LogInfo("## ActiveHSTMode ##"); if (!m_bFPDConnected) { LogError("No connect, return false"); return false; } LogInfo("Set FPD in HST mode"); nRet = API_COM_HstAcq(); if (!TestError(nRet)) { LogError("COM_hstAcq failed"); return false; } m_eSubStatus = SubStatus_HST; return true; } //对于PZ2121Z探测器,调用SDK的 COM_Dst() 接口,激活DST模式 bool PZMedical2121ZCtrl::ActiveDSTMode() { BOOL nRet; LogInfo("## ActiveDSTMode ##"); if (!m_bFPDConnected) { LogError("No connect, return false"); return false; } LogInfo("Set FPD in DST mode"); nRet = API_COM_Dst(); if (!TestError(nRet)) { LogError("COM_Dst failed"); return false; } m_eSubStatus = SubStatus_DST; return true; } bool PZMedical2121ZCtrl::SetSpotFrameRate(float fps) { LogInfo("## SetSpotFrameRate ##"); if (CAcqCtrl::SetSpotFrameRate(fps))return true; return true; } bool PZMedical2121ZCtrl::SetFLUFrameRate(float fps) { LogInfo("## SetFLUFrameRate ##"); if (CAcqCtrl::SetFLUFrameRate(fps))return true; return true; } bool PZMedical2121ZCtrl::SetCINEFrameRate(float fps) { LogInfo("## SetCINEFrameRate ##"); if (CAcqCtrl::SetCINEFrameRate(fps))return true; return true; } bool PZMedical2121ZCtrl::GetActiveMode(int &nLogicMode, int &nOffsetIndex) { LogInfo(" ## GetActiveMode ## "); nLogicMode = m_ActiveMode.nLogicMode; nOffsetIndex = m_ActiveMode.nOffIndex; return true; } bool PZMedical2121ZCtrl::GetOffsetInfo(int nLogicMode, vector &vecOffsetInfo) { LogInfo(" ## GetOffsetInfo ## "); if (CAcqCtrl::GetOffsetInfo(nLogicMode, vecOffsetInfo))return true; return true; } // [xxxDlg.cpp]OnMSGWORKFLOW() -> [xxxCtrl.cpp]OnMSGWORKFLOW_Process(WPARAM, LPARAM) // WRARAM 2: ZSKK_DETECTOR_WF_EXIT 退出 bool PZMedical2121ZCtrl::ExitDETECTOR() { if (CAcqCtrl::ExitDETECTOR()) return true; //if (m_eStatus==Offset||m_eStatus==XrayCalibration) //{ // AbortCalibration(); //} if (m_eStatus == Acquire) { StopGrab(1); } if (!CloseDetector()) return false; if (m_cImgBuff != NULL) { delete m_cImgBuff; m_cImgBuff = NULL; } StopScanThread(); FreePZMedicalDLL(); LogInfo("================================Exit PZMedical system===========================\n\n\n"); return true; } // WRARAM 3: ZSKK_DETECTOR_WF_REINIT 暂时不支持 bool PZMedical2121ZCtrl::ResetConnection() { LogInfo("ResetConnection()"); if (CAcqCtrl::ResetConnection()) return true; return true; } // WRARAM 7: ZSKK_DETECTOR_WF_BEGINWORK 进入检查状态 bool PZMedical2121ZCtrl::BeginWorkMode(void) { LogInfo("## BeginWorkMode ##"); if (CAcqCtrl::BeginWorkMode()) return true; if (!m_bFPDConnected) { LogError("FPD no connected, return false"); return false; } m_bIsWorkingMode = true; LogInfo("BeginWorkMode OVER"); return true; } // WRARAM 8: ZSKK_DETECTOR_WF_ENDWORK 退出检查状态 bool PZMedical2121ZCtrl::EndWorkMode(void) { LogInfo("## EndWorkMode ##"); if (CAcqCtrl::EndWorkMode()) return true; if (!m_bFPDConnected) { LogError("FPD no connected, return false"); return false; } m_bIsWorkingMode = false; m_ActiveMode.nLogicMode = -1; m_ActiveMode.nOffIndex = -1; if (!StopDetector()) return false; LogInfo("EndWorkMode OVER"); return true; } // WRARAM 9: ZSKK_DETECTOR_WF_SETGRABMODE 设置采集模式 bool PZMedical2121ZCtrl::SetGrabMode(int nMode) { LogInfo("## SetGrabMode ##"); CString strLog = ""; if (!m_bFPDConnected) { LogError("No connect, return false"); return false; } m_nGrabMode = nMode; switch (nMode) { case ZSKK_HARDWARE_SEQUENCE_SINGLERAD: strLog = "single rad"; break; case ZSKK_HARDWARE_SEQUENCE_SEQUENCERAD: strLog = "sequence rad"; break; case ZSKK_HARDWARE_SEQUENCE_PULSEFLU: strLog = "pulse flu"; break; case ZSKK_HARDWARE_SEQUENCE_CONTINOUSFLU: strLog = "continous flu"; break; default: strLog.Format("unknown mode, %d", nMode); break; } LogInfo("Set current grab mode: " + strLog); LogInfo("SetGrabMode OVER"); return true; } // WRARAM 10: ZSKK_DETECTOR_WF_BEGINGRAB // 同步模式:通过触发调用这个接口;连续透视模式:这个接口之后才将图像传给上层 bool PZMedical2121ZCtrl::StartGrab() { LogInfo("## StartGrab ##"); if (!m_bFPDConnected) { LogError("No connect, return false"); return false; } if (m_eStatus == Acquire) { LogWarn("Acquiring image, return true"); return true; } CString strLog = ""; m_nImgID = 1; m_eStatus = Acquire; if (m_nGrabMode == ZSKK_HARDWARE_SEQUENCE_SINGLERAD || m_nGrabMode == ZSKK_HARDWARE_SEQUENCE_SEQUENCERAD) { m_dwBeginT = GetTickCount(); strLog.Format("exposure at %d", m_dwBeginT); LogInfo(strLog); } LogInfo("StartGrab OVER"); return true; } // WRARAM 11: ZSKK_DETECTOR_WF_ENDGRAB 结束采集 bool PZMedical2121ZCtrl::StopGrab(int nXRayOnNum) { LogInfo("## StopGrab ##"); if (!m_bFPDConnected) { LogError("No connect, return false"); return false; } CString strLog = ""; if (m_nGrabMode == ZSKK_HARDWARE_SEQUENCE_SINGLERAD) return true; else if (m_nGrabMode == ZSKK_HARDWARE_SEQUENCE_SEQUENCERAD) { m_nXrayOnNum = nXRayOnNum; if (nXRayOnNum > m_nTotalFrameGrab) { //序列点片,有可能会在最后一张图到来之前,停止采集,如果这样,就等一个采集周期的时间; int nTimeout = (nXRayOnNum - m_nTotalFrameGrab)*m_nWinTime; strLog.Format("XrayOnNum(%d), FrameNum(%d), wait %d ms", nXRayOnNum, m_nTotalFrameGrab, nTimeout); LogWarn(strLog); m_bWaitLastImg = true; //将此标志位置为true, if (!WaitRespond(nTimeout)) LogWarn("Can not get the images"); m_bWaitLastImg = false; //无论超时与否,结束后将标志位置为false } m_nImgID = 1; m_eStatus = Standby; m_bExiChecked = false; //结束采集后将标志位置回false if (!StopAcquisition()) return false; } else { m_nImgID = 1; m_eStatus = Standby; m_bExiChecked = false; //结束采集后将标志位置回false if (!StopAcquisition()) return false; } LogInfo("StopGrab OVER"); return true; } // 调用SDK接口,进入采集状态,nMode是RFModeConf.xml中的LogicMode bool PZMedical2121ZCtrl::StartAcquisition(int nMode) { CString strLog = ""; m_nCurrentFrame = -1; //每次采集前将其恢复初值,使每个采集序列写共享内存时从0开始 m_bExiChecked = false; //采集前,将标志位置为false,认为EXI检查不通过 m_bTimeChecked = false; //采集前,将标志位置为false,任务时间检查不通过 BOOL nRet; if (m_bTriggered) //设置参数前,需要确保处于stop状态 { if (!StopAcquisition(1)) return false; } m_nImgID = 1; APPMode objPZMode; bool bGetMode = false; for (int n = 0; n < PZModeConf.APPMode.m_nodes.size(); n++) { if (PZModeConf.APPMode.m_nodes[n].AppModeKey == nMode) { objPZMode = PZModeConf.APPMode.m_nodes[nMode]; bGetMode = true; break; } } if (!bGetMode) { strLog.Format("Not found the mode: %d", nMode); LogError(strLog); return false; } strLog.Format("Key(%d) Name(%s) Binning(%d) FrameRate(%d) DelayT1(%d) DelayT2(%d) DelayT3(%d) StartendLine(%d %d), StartendColumn(%d %d)", objPZMode.AppModeKey, objPZMode.APPModeName, objPZMode.BinningMode, objPZMode.FrameRate, objPZMode.DelayT1, objPZMode.DelayT2, objPZMode.DelayT3, objPZMode.StartLine, objPZMode.EndLine, objPZMode.StartColum, objPZMode.EndColum); LogInfo(strLog); if (objPZMode.APPModeName.Find("RAD") >= 0) { m_dwBeginT = 0; m_dwEndT = 0; m_nTotalFrameGrab = 0; m_nXrayOnNum = 0; m_bWaitLastImg = false; #if 0 if (m_nRADSpeed == 0) //单帧点片和序列点片采用一套配置,只有上层传下来的m_nRADSpeed值不同,该值为0时为单帧点片 { int nRepeatNum = 1; if (!SetAcquisitionParam(objPZMode.FrameRate, nRepeatNum, objPZMode.BinningMode)) return false; } else //序列点片// { if (!SetAcquisitionParam(objPZMode.FrameRate, m_nRADSpeed, objPZMode.BinningMode)) return false; } #endif // 0 //if (!RefreshOffset()) return false; //if (m_bOffsetDone == true) { LogInfo("Call Trigger"); nRet = API_COM_Trigger(); if (!TestError(nRet)) { LogError("Trigger failed"); return false; } m_bTriggered = true; } } else if (objPZMode.APPModeName.Find("PF") >= 0) //脉冲透视 { /*//设置ROI if (objPZMode.OpenROI != 0) { if (!SetROIMode(objPZMode.StartLine, objPZMode.EndLine, objPZMode.StartColum, objPZMode.EndColum)) return false; } */ int nRepeatNum = 0; if (!SetAcquisitionParam(objPZMode.FrameRate, nRepeatNum, objPZMode.BinningMode)) { return false; } if (!RefreshOffset()) return false; if ((m_bOffsetDone == true) && (m_nTriggerMode == 0)) //内部触发方式 { LogInfo("Using internal trigger"); nRet = API_COM_Dacq(); if (!TestError(nRet)) { LogError("Internal Trigger failed"); return false; } } else if ((m_bOffsetDone == true) && (m_nTriggerMode == 1)) //外部触发方式 { LogInfo("Using external trigger"); nRet = API_COM_Cbct(); if (!TestError(nRet)) { LogError("External Trigger failed"); return false; } } else if ((m_bOffsetDone == true) && (m_nTriggerMode == 2)) //自动选择触发方式 { LogInfo("Using external trigger"); nRet = API_COM_Cbct(); if (!TestError(nRet)) { LogError("External Trigger failed"); return false; } } else { LogError("Unknowned trigger mode, return false"); } m_bTriggered = true; } else if (objPZMode.APPModeName.Find("CF") >= 0) //连续透视 { int nRepeatNum = 0; if (!SetAcquisitionParam(objPZMode.FrameRate, nRepeatNum, objPZMode.BinningMode)) return false; if (!RefreshOffset()) return false; if ((m_bOffsetDone == true) && (m_nTriggerMode == 0)) //内部触发方式 { LogInfo("Using internal trigger"); nRet = API_COM_Dacq(); if (!TestError(nRet)) { LogError("Internal Trigger failed"); return false; } } else if ((m_bOffsetDone == true) && (m_nTriggerMode == 1)) //外部触发方式 { LogInfo("Using external trigger"); nRet = API_COM_Cbct(); if (!TestError(nRet)) { LogError("External Trigger failed"); return false; } } else if ((m_bOffsetDone == true) && (m_nTriggerMode == 2)) //自动选择触发方式 { LogInfo("Using internal trigger"); nRet = API_COM_Dacq(); if (!TestError(nRet)) { LogError("Internal Trigger failed"); return false; } } else { LogError("Unknowned trigger mode, return false"); } m_bTriggered = true; } else { LogError("Unknowned mode"); return false; } return true; } /************************ * 结束采集,主要用于调用SDK的COM_Stop()接口或者COM_Dexit()接口。 * 厂商建议:探测器在IDLE状态下刷binning 1X1的offset,在设置binning2X2刷另一种offset * 因为前者的耗时比较久,所以结束采集后要置为binning 1X1模式来刷这个模式下的offset * nMode = 0, 设置回binning 1X1, XWinTime 500模式 ************************/ bool PZMedical2121ZCtrl::StopAcquisition(int nMode) { if (m_bTriggered) { LogInfo("Call Stop"); BOOL nRet = API_COM_Stop(); //BOOL nRet = API_COM_Dexit(); if (!TestError(nRet)) { LogError("COM_Stop failed"); return false; } m_bTriggered = false; } m_eSubStatus = SubStatus_IDLE; return true; } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////// MSG Process ////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool PZMedical2121ZCtrl::OnCOPYDATA_MSG_Process(WPARAM wParam, LPARAM lParam) { COPYDATASTRUCT* tempCopyDataStruct; switch (wParam) { case ZSKK_DETECTOR_PA_SETIMGPROC: { tempCopyDataStruct = (COPYDATASTRUCT*)lParam; CString mode = (char*)(tempCopyDataStruct->lpData); CString strlog; strlog.Format("ApplyProcessChainMode: %s", mode); LogInfo(strlog); LogInfo("do not support now"); //ApplyProcessChainMode(mode); break; } default: break; } return true; } bool PZMedical2121ZCtrl::OnMSGWORKFLOW_Process(WPARAM wParam, LPARAM lParam) { switch (wParam) { case ZSKK_DETECTOR_WF_HANDLE: break; case ZSKK_DETECTOR_WF_INIT: break; case ZSKK_DETECTOR_WF_REINIT: ResetConnection(); break; case ZSKK_DETECTOR_WF_EXIT: ExitDETECTOR(); break; case ZSKK_DETECTOR_WF_TURNOFF: break; case ZSKK_DETECTOR_WF_QUERY_STATUS: break; case ZSKK_DETECTOR_WF_ALARM_CODE: break; case ZSKK_DETECTOR_WF_BEGINWORK: LogInfo("MSG: Begin Work"); BeginWorkMode(); break; case ZSKK_DETECTOR_WF_ENDWORK: LogInfo("MSG: End Work"); EndWorkMode(); break; case ZSKK_DETECTOR_WF_SETGRABMODE: LogInfo("MSG: Set Grab Mode"); SetGrabMode((int)lParam); break; case ZSKK_DETECTOR_WF_BEGINGRAB: LogInfo("MSG: Begin Grab Image"); StartGrab(); break; case ZSKK_DETECTOR_WF_ENDGRAB: LogInfo("MSG: End Grab Image"); StopGrab((int)lParam); break; case ZSKK_DETECTOR_WF_APPREADY: break; case ZSKK_DETECTOR_WF_RELOADCONFIG: break; case ZSKK_DETECTOR_WF_RELOADABS: break; default: break; } return true; } bool PZMedical2121ZCtrl::OnMSGCALIBRATION_Process(WPARAM wParam, LPARAM lParam) { CString strLog = ""; strLog.Format("OnMsgCali wParam(%d) lParam(%d)", (int)wParam, (int)lParam); //LogInfo(strLog); //调用频率高,日志过大 switch (wParam) { case ZSKK_DETECTOR_CALIBRATION_START_TYPE: if ((m_ActiveMode.nLogicMode == -1) && (m_ActiveMode.nOffIndex == -1)) { return false; } switch (lParam) { case ZSKK_DETECTOR_LPARAM_CALIBRATION_OFFSET_REQUEST: BeginCalibration(m_ActiveMode.nLogicMode, m_ActiveMode.nOffIndex, 4); break; case ZSKK_DETECTOR_LPARAM_CALIBRATION_LINEARGAIN_REQUEST: BeginCalibration(m_ActiveMode.nLogicMode, m_ActiveMode.nOffIndex, 2); break; case ZSKK_DETECTOR_LPARAM_CALIBRATION_POLYGAIN_REQUEST: BeginCalibration(m_ActiveMode.nLogicMode, m_ActiveMode.nOffIndex, 8); break; case ZSKK_DETECTOR_LPARAM_CALIBRATION_DEFECT_REQUEST: BeginCalibration(m_ActiveMode.nLogicMode, m_ActiveMode.nOffIndex, 1); break; case ZSKK_DETECTOR_LPARAM_CALIBRATION_BLINKING_REQUEST: BeginCalibration(m_ActiveMode.nLogicMode, m_ActiveMode.nOffIndex, 16); break; default: break; } break; case ZSKK_DETECTOR_CALIBRATION_STOP: ExitCalibration(); break; case ZSKK_DETECTOR_CALIBRATION_ABORT: AbortCalibration(); break; case ZSKK_DETECTOR_CALIBRATION_REFRESH_OFFSET: break; case ZSKK_DETECTOR_CALIBRATION_SETDOSE: break; case ZSKK_DETECTOR_CALIBRATION_STARTXRAY: break; case ZSKK_DETECTOR_CALIBRATION_STOPXRAY: break; case ZSKK_DETECTOR_CALIBRATION_CALRESULT: break; case ZSKK_DETECTOR_CALIBRATION_CALMANUAL: LogInfo("MSG: calibration manual"); OffsetByUser((int)lParam); break; case ZSKK_MSG_RFHW_CAL_OFFSETABORT: break; case ZSKK_DETECTOR_CALIBRATION_NEXTSTEP: CalibNextStep(); break; default: break; } return true; } bool PZMedical2121ZCtrl::OnMSGPARAMETER_Process(WPARAM wParam, LPARAM lParam) { CString strLog; switch (wParam) { case ZSKK_DETECTOR_PA_SET_RADMODE: SelectRADMode((int)lParam / 10, (int)lParam % 10); break; case ZSKK_DETECTOR_PA_SET_FLUMODE: SelectFLUMode((int)lParam / 10, (int)lParam % 10); break; case ZSKK_DETECTOR_PA_SET_CINEMODE: SelectCINEMode((int)lParam / 10, (int)lParam % 10); break; case ZSKK_DETECTOR_PA_SET_RADSPEED: strLog.Format("Get set rad speed message, receive rad speed: %d", int(lParam)); LogInfo(strLog); m_nRADSpeed = (int)lParam / 100; SetRadOffsetMode(m_RadMode.nLogicMode, m_RadMode.nOffIndex, m_nRADSpeed); break; case ZSKK_DETECTOR_PA_SET_FLUSPEED: strLog.Format("Get set flu speed message, receive flu speed %d", int(lParam)); LogInfo(strLog); m_nFLUSpeed = (int)lParam; SetFluOffsetMode(m_FluMode.nLogicMode, m_FluMode.nOffIndex, int(lParam)); break; case ZSKK_DETECTOR_PA_SET_FLUSPEED_EX: m_nFLUSpeed = (int)lParam / 100; strLog.Format("receive flu speedEx %d, %d", int(lParam), m_nFLUSpeed); LogInfo(strLog); SetFluOffsetMode(m_FluMode.nLogicMode, m_FluMode.nOffIndex, int(lParam)); break; case ZSKK_DETECTOR_PA_SET_CINESPEED: LogInfo("Get set cin speed message"); strLog.Format("receive cin speed %d", int(lParam)); LogInfo(strLog); m_nCINSpeed = (int)lParam; SetCinOffsetMode(m_FluMode.nLogicMode, m_FluMode.nOffIndex, int(lParam)); break; case ZSKK_DETECTOR_PA_SET_CINESPEED_EX: m_nCINSpeed = (int)lParam / 100; strLog.Format("receive cin speedEx %d, %d", int(lParam), m_nCINSpeed); LogInfo(strLog); SetCinOffsetMode(m_nGrabMode, m_FluMode.nOffIndex, int(lParam)); break; case ZSKK_DETECTOR_PA_ACTIVE_RADMODE: ActiveRADMode(); break; case ZSKK_DETECTOR_PA_ACTIVE_FLUMODE: ActiveFLUMode(); break; case ZSKK_DETECTOR_PA_ACTIVE_CINEMODE: ActiveCINEMode(); break; case ZSKK_DETECTOR_PA_SETGRABSTART: if (ZSKK_DETECTOR_LPARAM_STARTTYPE_FLU == lParam) { MSGControl(NULL, ZSKK_MSG_RFHW_WFOUT, ZSKK_MSG_RFHW_WF_XRAYON, NULL, ZSKK_MSG_TYPE_SYNC_NO); StartGrab(); } else StopGrab(100); break; default: strLog.Format("Unknow parameter: %d", wParam); LogWarn(strLog); break; } return true; } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////// Calibration ////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool PZMedical2121ZCtrl::EnterCalibration() { if (CAcqCtrl::EnterCalibration()) return true; return true; } // [xxxDlg.cpp]OnMSGCALIBRATION() -> [xxxCtrl.cpp]OnMSGCALIBRATION_Process(WPARAM, LPARAM) // WRARAM 0: ZSKK_DETECTOR_CALIBRATION_START_TYPE 设置校正类型 // CAL Mode: 1 defect, 2: Linear Gain, 4: Offset 8: Polynomial gain, 16: Blinking // 2121Z进行offset校正(4)和gain校正(2) bool PZMedical2121ZCtrl::BeginCalibration(int nLogicMode, int nOffsetIndex, int nCalMode) { CString strLog = ""; strLog.Format("## BeginCalibration ## nLogicMode(%d), nOffsetIndex(%d), nCalMode(%d)", nLogicMode, nOffsetIndex, nCalMode); LogInfo(strLog); if (CAcqCtrl::BeginCalibration(nLogicMode, nOffsetIndex, nCalMode)) return true; if (!m_bFPDConnected) { LogError("No connect, return false"); return false; } m_nOffsetImgID = 1; //modify20210331 SDK逻辑是从1开始的 m_nGainImgID = 1; //modify20210331 SDK逻辑是从1开始的 m_bGetImage = false; //当发生器出线时才获取gain图像,所以先置为false //在找剂量点的时候,会调用StopGrab,停止采集,这时候应该再开始采集 if (!m_bTriggered) { //调用SDK接口,进入采集状态 if (!StartAcquisition(m_ActiveMode.nLogicMode)) { return false; } } if (nCalMode == 4) //offset { if (m_eStatus == Offset) { LogInfo("At offset state, return true"); return true; } LogInfo("Start current offset calibration send message: START"); //MSGControl(m_pWnd, ZSKK_MSG_RFDT_CALOUT, ZSKK_DETECTOR_CALIBRATION_CALMANUAL, ZSKK_DETECTOR_LPARAM_CALMANUAL_START, ZSKK_MSG_TYPE_SYNC_NO); //del20210331 此消息需要成对发送,没有发结束的地方,此处也就先不发开始了 StartOffsetCalibration(m_ActiveMode.nLogicMode); ZSKK_CAL_STATUS CalStatus; if (GetCalibrationStatus(nLogicMode, nOffsetIndex, CalStatus)) { COPYDATASTRUCT copyData; copyData.lpData = &CalStatus; copyData.cbData = sizeof(ZSKK_CAL_STATUS); MSGControl(m_pWnd, ZSKK_MSG_RFDATA_OUT, ZSKK_DETECTOR_DATA_CALIBRATIONSTATUS, (LPARAM)©Data, ZSKK_MSG_TYPE_SYNC_YES); MSGControl(m_pWnd, ZSKK_MSG_RFDT_PARAMOUT, ZSKK_DETECTOR_PA_CURMODE_CALSTATUS, ZSKK_DETECTOR_LPARAM_CALSTATUS_REFRESH, 0); } } else if (nCalMode == 2) //gain { if (m_eStatus == XrayCalibration) { LogInfo("At xray calibration, return true"); return true; } m_eStatus = XrayCalibration; StartGainCalibration(nLogicMode, nOffsetIndex, nCalMode); } else MSGControl(m_pWnd, ZSKK_MSG_RFDT_CALOUT, ZSKK_DETECTOR_CALIBRATION_CALRESULT, ZSKK_DETECTOR_LPARAM_CALIBRATION_CALSUCCESS, ZSKK_MSG_TYPE_SYNC_NO); return true; } // WRARAM 1: ZSKK_DETECTOR_CALIBRATION_STOP bool PZMedical2121ZCtrl::ExitCalibration() { LogInfo(" ## ExitCalibration ## "); if (CAcqCtrl::ExitCalibration())return true; if (!m_bFPDConnected) { LogError("No connect, return false"); return false; } //还原active模式,重新加载模式 if (m_bCalStart) { LogInfo("Calibration already started.. Need reload all modes"); MSGControl(m_pWnd, ZSKK_MSG_RFDT_WFOUT, ZSKK_DETECTOR_WF_QUERY_STATUS, ZSKK_DETECTOR_LPARAM_STATUS_PREPARE, 0); XMODE tmpMode; tmpMode.nLogicMode = m_ActiveMode.nLogicMode; tmpMode.nOffIndex = m_ActiveMode.nOffIndex; //校正结束后模式被清空,需要重新装载模式 ActiveLogicMode(tmpMode.nLogicMode, tmpMode.nOffIndex); } if (m_bTriggered) { if (!StopAcquisition()) return false; } m_eStatus = Standby; m_bCalStart = false; m_bGetImage = false; m_bExiChecked = false; //结束校正后,将标志位置回false return true; } // WRARAM 2: ZSKK_DETECTOR_CALIBRATION_ABORT 终止校正 bool PZMedical2121ZCtrl::AbortCalibration() { LogInfo(" ## AbortCalibration ## "); if (CAcqCtrl::AbortCalibration())return true; if (!m_bFPDConnected) { LogError("No connect, return false"); return false; } if (m_bTriggered) { if (!StopAcquisition()) return false; } if (m_eStatus == Offset) { m_bAbortOffset = true; } OnXrayGenStop(); m_eStatus = Standby; m_bCalStart = false; m_bGetImage = false; m_bExiChecked = false; //终止校正后,将标志位置回false return true; } // WRARAM 8: ZSKK_DETECTOR_CALIBRATION_CALMANUAL 开始offset校正 // 4343D非work状态下自动刷offset,所以不做手动处理 bool PZMedical2121ZCtrl::OffsetByUser(int nOffsetType) { if (CAcqCtrl::OffsetByUser()) return true; MSGControl(m_pWnd, ZSKK_MSG_RFDT_CALOUT, ZSKK_DETECTOR_CALIBRATION_CALMANUAL, ZSKK_DETECTOR_LPARAM_CALMANUAL_START, ZSKK_MSG_TYPE_SYNC_NO); Sleep(50); MSGControl(m_pWnd, ZSKK_MSG_RFDT_CALOUT, ZSKK_DETECTOR_CALIBRATION_CALMANUAL, ZSKK_DETECTOR_LPARAM_CALMANUAL_END, ZSKK_MSG_TYPE_SYNC_NO); return true; } //刷新offset模板,调用 COM_Prep()接口后等待回调EVENT_OFFSETDONE到来, 表示模板刷新完成 bool PZMedical2121ZCtrl::RefreshOffset() { BOOL nRet; bool bRet; LogInfo("## RefreshOffset ##"); LogInfo("Call Prep"); nRet = API_COM_Prep(); if (!TestError(nRet)) { LogError("COM_Prep failed"); return false; } bRet = WaitRespond(5000); //等待EVENT_OFFSETDONE回调5秒,否则视为超时 if (bRet) { LogInfo("RefreshOffset Done"); } else { LogInfo("Waiting FPD Offset TimeOut"); return false; } return true; } // 开始offset,向上层发送消息 bool PZMedical2121ZCtrl::StartOffsetCalibration(int nMode) { LogInfo("## StartOffsetCalibration ##"); if (CAcqCtrl::StartOffsetCalibration()) return true; CString strLog = ""; if (!m_bFPDConnected) { LogError("No connect, return false"); return false; } LogInfo("Start current offset calibration send message: ACQ_PREPARE"); MSGControl(m_pWnd, ZSKK_MSG_RFDT_WFOUT, ZSKK_DETECTOR_WF_QUERY_STATUS, ZSKK_DETECTOR_LPARAM_STATUS_PREPARE, ZSKK_MSG_TYPE_SYNC_NO); m_eStatus = Offset; COPYDATASTRUCT copyData; copyData.lpData = &m_CurSynParam; copyData.cbData = sizeof(ZSKK_CAL_SYN_PARAM); MSGControl(m_pWnd, ZSKK_MSG_RFDATA_OUT, ZSKK_DETECTOR_DATA_CALDETECTOR_FPSXWIN, (LPARAM)©Data, ZSKK_MSG_TYPE_SYNC_YES); strLog.Format("Mode(%d) is doing offset now frenquency %d fps xWindow %d ", nMode, m_CurSynParam.frenquency, m_CurSynParam.xWindow); LogInfo(strLog); return true; } // 开始gain校正,向上层发送消息 bool PZMedical2121ZCtrl::StartGainCalibration(int nLogicmode, int nRefNum, int CalMode) { LogInfo(" ## StartGainCalibration ## "); CString strLog = ""; m_bExiChecked = false; //校正图像同样需要EXI检查,所以开始之前将标志位置为false LogInfo("Calibration Set Dose"); MSGControl(m_pWnd, ZSKK_MSG_RFDT_CALOUT, ZSKK_DETECTOR_CALIBRATION_SETDOSE, 30000, ZSKK_MSG_TYPE_SYNC_YES); OnXrayGenStart(); return true; } // 一级手闸按下或发生器出线时调用,品臻动态探测器在出线时调用这个接口 // 在BeginCalibration中调用Trigger,在此接口中将取图标志位置m_bGetImage为true bool PZMedical2121ZCtrl::CalibNextStep() { LogInfo("Begin get gain image"); m_bGetImage = true; return true; } // 生成校正文件并上传 bool PZMedical2121ZCtrl::GenTpl() { LogInfo(" ## GenTpl ## "); BOOL nRet, nRet2, nRet3; CString strLog = ""; UCHAR ucTplName[20] = "gain_defect.tpl"; //上传时只上传这个校正文件 CString strTplPath = strAppPath + "\\reference\\gain_defect.tpl"; LogInfo(strTplPath); CHAR* cTplPath = (CHAR*)strTplPath.GetBuffer(); LogInfo("->Tplgen"); nRet = API_COM_GenOffsetTpl(); nRet2 = API_COM_GenGainTpl(); nRet3 = API_COM_GenDefectTpl(); if (!TestError(nRet && nRet2 && nRet3)) { MSGControl(m_pWnd, ZSKK_MSG_RFDT_CALOUT, ZSKK_DETECTOR_CALIBRATION_CALRESULT, ZSKK_DETECTOR_LPARAM_CALIBRATION_CALFAILED, ZSKK_MSG_TYPE_SYNC_NO); LogError("Tplgen failed"); return false; } //上传到探测器内部才能生效 m_ucState = -1; m_ucPerCent = -1; //上传之前,将相关状态置为初始值 if (m_nBinningMode == PZ_ONExONE) { LogInfo("->Uploadtpl-1x1"); } else if (m_nBinningMode == PZ_TWOxTWO) { LogInfo("->Uploadtpl-2x2"); } else if (m_nBinningMode == PZ_THRxTHR) { LogInfo("->Uploadtpl-3x3"); } else { strLog.Format("->Uploadtpl-%d", m_nBinningMode); LogInfo(strLog); } nRet = API_COM_UploadFPZMTpl(m_nBinningMode + 1, cTplPath); if (!TestError(nRet)) { MSGControl(m_pWnd, ZSKK_MSG_RFDT_CALOUT, ZSKK_DETECTOR_CALIBRATION_CALRESULT, ZSKK_DETECTOR_LPARAM_CALIBRATION_CALFAILED, ZSKK_MSG_TYPE_SYNC_NO); LogError("Uploadtpl failed"); return false; } strTplPath.ReleaseBuffer(); return true; } // 加载RFModeConf.xml中的ROI配置,4343D用不到 void PZMedical2121ZCtrl::LoadROIParams() { DetectorMode tempDetectMode; ROIMode tempROIMode; int ntempROINum = 0; int nsize = RFModeConf.DetectorMode.m_nodes.size(); int nPUMode = 0; for (int i = 0; i < nsize; i++) { tempDetectMode = RFModeConf.DetectorMode.m_nodes[i]; ntempROINum = tempDetectMode.ROIMode.m_nodes.size(); nPUMode = tempDetectMode.PUMode; for (int j = 0; j < ntempROINum; j++) { tempROIMode = tempDetectMode.ROIMode.m_nodes[j]; if (tempROIMode.Active == 1) { ZSKK_ROI_PARAM *pPram = new ZSKK_ROI_PARAM; pPram->CenterColumnAdress = tempROIMode.CenterColumnAddress; pPram->CenterRowAdress = tempROIMode.CenterRowAddress; pPram->Height = tempROIMode.Height; pPram->Width = tempROIMode.Width; pPram->ROIIndex = tempROIMode.ROIIndex; pPram->Shape = tempROIMode.Shape; pPram->Active = true; m_ROImap[nPUMode] = pPram; } } } } // 裁剪图像,4343D用不到 int PZMedical2121ZCtrl::CropImageMargin(LPVOID pDstData, int& nDstWidth, int& nDstHeight, LPVOID pScrData, int nSrcWidth, int nSrcHeight, int nBits, int nLeftMargin, int nTopMargin, int nRightMargin, int nBottomMargin) { LogInfo("CropImageMargin()"); if (nLeftMargin == 0 && nTopMargin == 0 && nRightMargin == 0 && nBottomMargin == 0) return -1; if ((pDstData == NULL) || (pScrData == NULL) || (nSrcWidth <= 0) || (nSrcHeight <= 0) || (nBits <= 0)) return -1; if ((nLeftMargin >= nSrcWidth) || (nTopMargin >= nSrcHeight)) return -1; int nBitsToBYTE = (int)((nBits + 7)*0.125); if (nBitsToBYTE < 1) return -1; int nXL, nXR, nYL, nYR; nXL = nLeftMargin; nYL = nTopMargin; if (nSrcWidth - nRightMargin < 0) return -1; nXR = nSrcWidth - nRightMargin - 1; if (nXR < nXL) return -1; if (nSrcHeight - nBottomMargin < 0) return -1; nYR = nSrcHeight - nBottomMargin - 1; if (nYR < nYL) return -1; nDstWidth = nXR - nXL + 1; nDstHeight = nYR - nYL + 1; int i; #pragma omp parallel private(i) { #pragma omp for for (i = nYL; i <= nYR; i++) ::memcpy((WORD*)pDstData + (i - nYL) * nDstWidth, (WORD*)pScrData + (i * nSrcWidth + nXL), nDstWidth * nBitsToBYTE); } return 0; } // 获取图像并储存 void PZMedical2121ZCtrl::OnImageEvt(/*UINT32 uiImageNo, VOID* uiImgBuffAddr, UINT32 uiImgValidSize*/) { BOOL nRet; CString strLog = ""; bool bPass = true; //图像是否符合标准 if (m_eStatus != Acquire && m_eStatus != Offset && m_eStatus != XrayCalibration) { LogWarn("Omit Image, error status"); return; } if (m_eStatus == Acquire) //曝光出图流程 { LogInfo("Call GetImage"); nRet = API_COM_GetImage(m_cImgBuff); if (!TestError(nRet)) { LogError("GetImage failed"); return; } if (m_cImgBuff == NULL) { LogError("Image buffer is NULL"); return; } int res = CropImageMargin(m_ImgInfo.pwData, m_ImgInfo.nWidth, m_ImgInfo.nHeight, m_cImgBuff, m_nRawWidth, m_nRawHeight, m_ImgInfo.nBits, m_nCropLeft, m_nCropTop, m_nCropRight, m_nCropBottom); if (res != 0) { memcpy(m_ImgInfo.pwData, m_cImgBuff, m_ImgInfo.nWidth*m_ImgInfo.nHeight * 2); } //memcpy(m_ImgInfo.pwData, m_cImgBuff, m_ImgInfo.nWidth*m_ImgInfo.nHeight * 2); if (m_bSaveRaw) SaveImage(m_ImgInfo.pwData, m_ImgInfo.nWidth*m_ImgInfo.nHeight * 2); //检查EXI、时间间隔之前把图存一下,便于用其它工具查看 m_nImgID++; //从SaveImage函数里改到外面自增,避免不存图导致这个变量不自增 //标准1,EXI检查。正常的曝光图像剂量会在100~150以上 if (!m_bExiChecked) { if (!CheckImageExi(m_nExiStdWork)) { bPass = false; } else m_bExiChecked = true; //检查通过,将标志位置为true } //if (m_ActiveMode.nLogicMode == PZ_MODE_RAD4343H || m_ActiveMode.nLogicMode == PZ_MODE_RAD4343M ) //modifybyys20190515 改为用m_nGrabMode来判断当前的模式 if (m_nGrabMode == ZSKK_HARDWARE_SEQUENCE_SINGLERAD || m_nGrabMode == ZSKK_HARDWARE_SEQUENCE_SEQUENCERAD) { //标准2,出线(StartGrab)到出图回调时间间隔检查。 //发生器出线到探测器返回图像基本上需要将近一个采图周期的时间,如果少于这个时间,则是出线前的图像 if (!m_bTimeChecked && m_bExiChecked) { m_dwEndT = GetTickCount(); if (m_dwEndT - m_dwBeginT < m_nDelayT) { strLog.Format("Omit Image, the time interval(%d) is too short: %d", m_dwEndT - m_dwBeginT, m_nDelayT); LogWarn(strLog); bPass = false; } else m_bTimeChecked = true; } //应用饱和值处理,避免图像剂量过大,对后处理模块有影响 if (bPass) ApplyImgSaturation(m_ImgInfo.pwData, m_ImgInfo.nWidth, m_ImgInfo.nHeight, m_nSaturation); if (m_nGrabMode == ZSKK_HARDWARE_SEQUENCE_SINGLERAD) { if (m_bSendRadImage) { LogWarn("Omit Image, already send to upper"); return; } if (bPass) { WriteFrame(m_ImgInfo.pwData, m_ImgInfo.nWidth, m_ImgInfo.nHeight); MSGControl(m_pWnd, ZSKK_MSG_RFHW_WFOUT, ZSKK_MSG_RFHW_WF_DATAINFOSINGLE, m_nCurrentFrame, ZSKK_MSG_TYPE_SYNC_NO); } //已经得到符合标准的图像,或不合标准的图像超过了一定张数,就停止采集 if (bPass || m_nImgID > m_nRadImgCount) { m_bSendRadImage = true; m_nImgID = 1; m_eStatus = Standby; if (!StopAcquisition()) return; m_bExiChecked = false; //结束采集后将标志位置回false } } else // 序列点片 // { if (bPass) { m_nTotalFrameGrab++; WriteFrame(m_ImgInfo.pwData, m_ImgInfo.nWidth, m_ImgInfo.nHeight); MSGControl(m_pWnd, ZSKK_MSG_RFHW_WFOUT, ZSKK_MSG_RFHW_WF_DATAINFOSEQUENCE, m_nCurrentFrame, ZSKK_MSG_TYPE_SYNC_NO); //StopGrab的时候会等待最后一张图像,图像拿齐了,setEvent停止等待,避免时间过长 if (m_bWaitLastImg && m_nTotalFrameGrab == m_nXrayOnNum) SetEvent(m_hCallbackEvent); } } } else if (m_nGrabMode == ZSKK_HARDWARE_SEQUENCE_PULSEFLU || m_nGrabMode == ZSKK_HARDWARE_SEQUENCE_CONTINOUSFLU) { if (bPass) { WriteFrame(m_ImgInfo.pwData, m_ImgInfo.nWidth, m_ImgInfo.nHeight); MSGControl(m_pWnd, ZSKK_MSG_RFHW_WFOUT, ZSKK_MSG_RFHW_WF_DATAINFOFLU, m_nCurrentFrame, ZSKK_MSG_TYPE_SYNC_NO); } } else { strLog.Format("Omit Image, error work mode: %d", m_ActiveMode.nLogicMode); LogWarn(strLog); return; } } else if (m_eStatus == Offset) //暗场校正出图流程 { LogInfo("GetImage at offset state"); nRet = API_COM_GetImage(m_cImgBuff); if (!TestError(nRet)) { LogError("GetImage failed"); return; } if (m_cImgBuff == NULL) { LogError("Image buffer is NULL"); return; } memcpy(m_ImgInfo.pwData, m_cImgBuff, m_ImgInfo.nWidth*m_ImgInfo.nHeight * 2); strLog.Format("dark\\%d", m_nOffsetImgID); //modify20210331 探测器工具校正时命名不带flood,此处也不带此关键字,这样校正时可以直接覆盖上一次的图像 if (SaveImage(strLog, m_ImgInfo.pwData, m_ImgInfo.nWidth*m_ImgInfo.nHeight * 2)) m_nOffsetImgID++; else { m_nImgID = 1; m_eStatus = Standby; if (!StopAcquisition()) return; MSGControl(m_pWnd, ZSKK_MSG_RFDT_CALOUT, ZSKK_DETECTOR_CALIBRATION_CALRESULT, ZSKK_DETECTOR_LPARAM_CALIBRATION_CALFAILED, ZSKK_MSG_TYPE_SYNC_NO); return; } if (m_nOffsetImgID == PZ_OFFSET_COUNT + 1) { m_nImgID = 1; m_eStatus = Standby; //MSGControl(m_pWnd, ZSKK_MSG_RFDT_CALOUT, ZSKK_DETECTOR_CALIBRATION_CALRESULT, ZSKK_DETECTOR_LPARAM_CALIBRATION_CALSUCCESS, ZSKK_MSG_TYPE_SYNC_NO); OnXrayCalSuccess(); } } else if (m_eStatus == XrayCalibration) //增益校正出图流程 { // 要根据标志位m_bGetImage来决定是否取gain图像 if (!m_bGetImage) { LogWarn("Omit Gain Image, error status"); return; } LogInfo("->GetImage at gain state"); nRet = API_COM_GetImage(m_cImgBuff); if (!TestError(nRet)) { LogError("GetImage failed"); return; } if (m_cImgBuff == NULL) { LogError("Image buffer is NULL"); return; } memcpy(m_ImgInfo.pwData, m_cImgBuff, m_ImgInfo.nWidth*m_ImgInfo.nHeight * 2); if (!m_bExiChecked) //如果EXI检查没通过,就进行EXI检查 { if (!CheckImageExi(m_nExiStdCali)) return; m_bExiChecked = true; //检查通过,将标志位置为true } strLog.Format("flood\\%d", m_nGainImgID); //modify20210331 探测器工具校正时命名不带flood,此处也不带此关键字,这样校正时可以直接覆盖上一次的图像 if (SaveImage(strLog, m_ImgInfo.pwData, m_ImgInfo.nWidth*m_ImgInfo.nHeight * 2)) m_nGainImgID++; else { m_nImgID = 1; m_eStatus = Standby; if (!StopAcquisition()) return; MSGControl(m_pWnd, ZSKK_MSG_RFDT_CALOUT, ZSKK_DETECTOR_CALIBRATION_CALRESULT, ZSKK_DETECTOR_LPARAM_CALIBRATION_CALFAILED, ZSKK_MSG_TYPE_SYNC_NO); return;//shibai } if (m_nGainImgID == PZ_GAIN_COUNT + 1) { m_nImgID = 1; m_eStatus = Standby; if (!StopAcquisition(1)) //只停止采集,不修改binning mode,避免上传到错误的校正文件路径 return; OnXrayGenStop(); SetEvent(m_hGenTplEvent); } } else { strLog.Format("Omit Image, error status: %d", m_eStatus); LogError(strLog); return; } } // 调用WriteShareMemEx()向共享内存中写入图像 bool PZMedical2121ZCtrl::WriteFrame(WORD* pImgData, int nWidth, int nHeight) { if (pImgData == NULL) { LogError("ImgData is NULL"); return false; } if ((nWidth <= 0) || (nHeight <= 0)) { LogError("Width or Height error"); return false; } DWORD nTotalMem = m_pDataBuffer->GetShareMemSize(); int ntotal = nTotalMem / (nWidth*nHeight*sizeof(WORD)); if (ntotal == 0) { LogError("GetShareMemSize failed, shared memory size is 0"); return false; } m_nCurrentFrame = (m_nCurrentFrame + 1) % ntotal; m_pDataBuffer->WriteShareMemEx(m_nCurrentFrame*nWidth*nHeight*sizeof(WORD), (LPVOID)pImgData, nWidth*nHeight*sizeof(WORD)); if (g_bTestTrue) //如果g_bTestTrue=true, 那么测试保存图片 { LogInfo("Test Saving Image"); g_TestSavingImage->Write(pImgData, nWidth*nHeight*sizeof(WORD)); g_TestSavingImage->Close(); } return true; } bool PZMedical2121ZCtrl::LogInfo(LPCSTR strLog) { if (logfile == NULL) { return false; } else { logfile->WriteLog(strLog, LOG_INFORMATION, LOG_RELEASE, true); return true; } } bool PZMedical2121ZCtrl::LogError(LPCSTR strLog) { if (logfile == NULL) { return false; } else { logfile->WriteLog(strLog, LOG_ERROR, LOG_RELEASE, true); return true; } } bool PZMedical2121ZCtrl::LogWarn(LPCSTR strLog) { if (logfile == NULL) { return false; } else { logfile->WriteLog(strLog, LOG_WARNING, LOG_RELEASE, true); return true; } } // 辅助线程 UINT PZMedical2121ZCtrl::ScanThread(LPVOID pParam) { PZMedical2121ZCtrl* pMain = (PZMedical2121ZCtrl*)pParam; if (pMain == NULL) { return false; } CString strLog = ""; BOOL bExit = false; DWORD dwTimeOut = 5000; pMain->LogInfo("ScanThread..."); while (!bExit) { DWORD dwResult = WaitForMultipleObjects(PZ_EVENT_COUNT, pMain->m_hEventArray, FALSE, INFINITE); switch (dwResult) { case WAIT_OBJECT_0: //m_hInitEvent { pMain->LogInfo("Get Init Event"); if (!pMain->InitHW(pMain->m_hWnd)) { pMain->MSGControl(pMain->m_pWnd, ZSKK_MSG_RFDT_WFOUT, ZSKK_DETECTOR_WF_QUERY_STATUS, ZSKK_DETECTOR_LPARAM_STATUS_UNCONNECTED, 0); } } break; case WAIT_OBJECT_0 + 1: //m_hExitEvent { pMain->LogInfo("Get Exit Event"); bExit = true; } break; case WAIT_OBJECT_0 + 2: //m_hGenTplEvent { pMain->LogInfo("Get GenTpl Event"); pMain->GenTpl(); } break; case WAIT_OBJECT_0 + 3: //m_hImgEvent { pMain->OnImageEvt(); } break; default: { DWORD nErrorCode; nErrorCode = GetLastError(); strLog.Format("Unknown scan event! result: %d, error code: %d", dwResult, nErrorCode); pMain->LogError(strLog); bExit = true; } break; } } SetEvent(pMain->m_hScanThreadEnd); pMain->LogInfo("ScanThread End"); return 0; } // 开启辅助线程 bool PZMedical2121ZCtrl::StartScanThread() { LogInfo("## StartScanThread ##"); if (m_hInitEvent) { CloseHandle(m_hInitEvent); m_hInitEvent = NULL; } m_hInitEvent = CreateEvent(NULL, FALSE, FALSE, NULL); if (m_hExitEvent) { CloseHandle(m_hExitEvent); m_hExitEvent = NULL; } m_hExitEvent = CreateEvent(NULL, FALSE, FALSE, NULL); if (m_hScanThreadEnd) { CloseHandle(m_hScanThreadEnd); m_hScanThreadEnd = NULL; } m_hScanThreadEnd = CreateEvent(NULL, FALSE, FALSE, NULL); if (m_hGenTplEvent) { CloseHandle(m_hGenTplEvent); m_hGenTplEvent = NULL; } m_hGenTplEvent = CreateEvent(NULL, FALSE, FALSE, NULL); if (m_hImgEvent) { CloseHandle(m_hImgEvent); m_hImgEvent = NULL; } m_hImgEvent = CreateEvent(NULL, FALSE, FALSE, NULL); m_hEventArray[0] = m_hInitEvent; m_hEventArray[1] = m_hExitEvent; m_hEventArray[2] = m_hGenTplEvent; m_hEventArray[3] = m_hImgEvent; if (m_hCallbackEvent) { CloseHandle(m_hCallbackEvent); m_hCallbackEvent = NULL; } m_hCallbackEvent = CreateEvent(NULL, FALSE, FALSE, NULL); if (m_pScanThreadProc == NULL) m_pScanThreadProc = ::AfxBeginThread(ScanThread, this); if (NULL == m_pScanThreadProc) { LogError("Start scan thread failed"); return false; } LogInfo("StartScanThread OVER"); return true; } bool PZMedical2121ZCtrl::StopScanThread() { LogInfo("## StopScanThread ##"); SetEvent(m_hExitEvent); DWORD dwRet = WaitForSingleObject(m_hScanThreadEnd, 60000); //upload 1x1校正文件会比较耗时 if (dwRet == WAIT_OBJECT_0) LogInfo("Stop scan thread over"); else if (dwRet == WAIT_TIMEOUT) { TerminateThread(m_pScanThreadProc, 0); LogInfo("Terminate scan thread"); } else { CString strLog = ""; strLog.Format("Unknow event: %u", dwRet); LogWarn(strLog); } if (m_hInitEvent) { CloseHandle(m_hInitEvent); m_hInitEvent = NULL; } if (m_hExitEvent) { CloseHandle(m_hExitEvent); m_hExitEvent = NULL; } if (m_hGenTplEvent) { CloseHandle(m_hGenTplEvent); m_hGenTplEvent = NULL; } if (m_hImgEvent) { CloseHandle(m_hImgEvent); m_hImgEvent = NULL; } if (m_hCallbackEvent) { CloseHandle(m_hCallbackEvent); m_hCallbackEvent = NULL; } if (m_hScanThreadEnd) { CloseHandle(m_hScanThreadEnd); m_hScanThreadEnd = NULL; } LogInfo("StopScanThread OVER"); return true; } /* // 4343D图像上传回调 BOOL __stdcall PZMedical2121ZCtrl::FuncMFpDataUploadProcessCallback(UCHAR ucFileType, UCHAR ucState, UCHAR ucPerCent) { CString strLog = ""; if (g_pPZMedicalInstance->m_ucState == ucState && ucState != STATE_DATA) //每毫秒都有多次相同状体的回调,所以在这做一下拦截,避免日志文件太大 return 1; g_pPZMedicalInstance->m_ucState = ucState; if (ucState == STATE_ERASE) { g_pPZMedicalInstance->LogInfo("[DataUploadProcessCallback] State: ERASE"); } else if (ucState == STATE_DATA) { if (g_pPZMedicalInstance->m_ucPerCent == ucPerCent) //STATE_DATA状态下,相同百分比只记录一次,避免日志太大 return 1; g_pPZMedicalInstance->m_ucPerCent = ucPerCent; strLog.Format("[DataUploadProcessCallback] DATA PerCent(%d)", ucPerCent); g_pPZMedicalInstance->LogInfo(strLog); } else if (ucState == STATE_DONE) { g_pPZMedicalInstance->LogInfo("[DataUploadProcessCallback] State: UPLOAD DONE"); g_pPZMedicalInstance->StopAcquisition(); //再次停止,切回binning1x1 //g_pPZMedicalInstance->MSGControl(g_pPZMedicalInstance->m_pWnd, ZSKK_MSG_RFDT_CALOUT, ZSKK_DETECTOR_CALIBRATION_CALRESULT, ZSKK_DETECTOR_LPARAM_CALIBRATION_CALSUCCESS, ZSKK_MSG_TYPE_SYNC_NO); g_pPZMedicalInstance->OnXrayCalSuccess(); } else { strLog.Format("[DataUploadProcessCallback] Unknown State(%d)", ucState); g_pPZMedicalInstance->LogWarn(strLog); } return 1; } */ // 用于辅助线程中,等待SDK回调时的延时操作 // 等到回调,返回true; 等不到回调返回false,即为超时 bool PZMedical2121ZCtrl::WaitRespond(int nTimeOut) { CString strLog; strLog.Format("-----WaitRespond: %d ms-----", nTimeOut); LogInfo(strLog); DWORD dwRet = WaitForSingleObject(g_pPZMedicalInstance->m_hCallbackEvent, nTimeOut); if (dwRet == WAIT_TIMEOUT) { LogWarn("Time out in wait respond"); ResetEvent(m_hCallbackEvent); return false; } else if (dwRet == WAIT_FAILED) { DWORD dwSignal = GetLastError(); strLog.Format("Failed: %x", dwSignal); LogError(strLog); return false; } else if (dwRet == WAIT_OBJECT_0) { LogInfo("-----WaitRespond got Signal-----"); } else { strLog.Format("Unknow Signal: %d", dwRet); LogWarn(strLog); } return true; } // 存储曝光过程图像,用于查看图像质量 bool PZMedical2121ZCtrl::SaveImage(WORD* pImage, int nImgSize) { if (m_nImgID == IMG_COUNT + 1) m_nImgID = 1; CString strTemp; strTemp.Format("%s\\rawdata\\Image_%d.raw", strAppPath, m_nImgID); CFile fileImage; if (!fileImage.Open(strTemp.GetBuffer(), CFile::modeCreate | CFile::modeWrite)) { LogInfo("Save image failed"); return false; } else { fileImage.Write(pImage, nImgSize); LogInfo(strTemp); //m_nImgID++; //如果不存图,这个变量将不自增。而这个变量的用途又不止存图时的id,所以不在此处自增了 } fileImage.Close(); strTemp.ReleaseBuffer(); return true; } // 存储校正过程图像,用于生成校正文件 bool PZMedical2121ZCtrl::SaveImage(const char* szFileName, WORD* pImage, int nImgSize) { CString strTemp = ""; strTemp.Format("%s\\reference\\%s.raw", strAppPath, szFileName); CFile fileImage; if (!fileImage.Open(strTemp.GetBuffer(), CFile::modeCreate | CFile::modeWrite)) { LogInfo("Save image failed"); return false; } else { fileImage.Write(pImage, nImgSize); LogInfo(strTemp); } fileImage.Close(); strTemp.ReleaseBuffer(); return true; } // 检查图像的EXI值 bool PZMedical2121ZCtrl::CheckImageExi(WORD dwExiThrethold) { LogInfo(" ## Check EXI ## "); //bool bResult = CalculateEXI(m_ImgInfo.pwData, m_ImgInfo.nWidth, m_ImgInfo.nHeight, 16, dwExiThrethold); //if (bResult) int nRet = AEDCalcu(m_ImgInfo.pwData, m_ImgInfo.nWidth, m_ImgInfo.nHeight, 16, dwExiThrethold, 0.05f); if (nRet == 0) { return true; } LogWarn("Omit Image, Not meet the EXI requirements!!"); return false; } // 计算图像EXI值,目前用不到了,替换为AEDCalcu bool PZMedical2121ZCtrl::CalculateEXI(WORD* pImgData, int nImgWidth, int nImgHeight, int nImageBit, int nThreshold) { int nROIXL = static_cast(0.3 * nImgWidth); int nROIXR = static_cast(0.7 * nImgWidth); int nROIYL = static_cast(0.3 * nImgHeight); int nROIYR = static_cast(0.7 * nImgHeight); WORD* pSrc = NULL; long nCount = 0; DWORD64 nSum = 0; int nEXI = 0; CString strLog = ""; try { for (int i = nROIYL; i < nROIYR; i++) { pSrc = pImgData + nImgWidth; for (int j = nROIXL; j < nROIXR; j++) { nSum += *(pSrc + j); nCount++; } } nEXI = (int)(nSum / nCount); } catch (...) { return false; } strLog.Format("Image EXI Mean: %d, Threshold: %d", nEXI, nThreshold); LogInfo(strLog); if (nEXI >= nThreshold) { LogInfo("Exi Check Xray On the Image"); return true;//有x射线 } return false; } int PZMedical2121ZCtrl::AEDCalcu(WORD* pImage, int nWidth, int nHeight, int nImageBit, int nThreshold, float fArea) { CString str; //str.Format("Width(%d),hight(%d),bit(%d),threshold(%d),area(%0.2f)", nWidth, nHeight, nImageBit, nThreshold, fArea); //LogInfo(str); //日志太多了 if (!pImage) { LogError("Buffer is null"); return 2;//图像读入失败。 } int N = 65536; int *Histogram = NULL; Histogram = new int[N]; if (Histogram == NULL) { LogError("Alloc buffer failed"); return 4;//内存分配失败。 } memset(Histogram, 0, sizeof(int)* N); unsigned long int nCount = 0; unsigned long int temp = 0; int nIdxI = 0; int nIdxJ = 0; for (nIdxJ = 30; nIdxJ < nHeight - 30; nIdxJ = nIdxJ + 4) { for (nIdxI = 30; nIdxI < nWidth - 30; nIdxI = nIdxI + 4) { //temp=int(( pImage[ nIdxI * nWidth + nIdxJ ]+pImage[ nIdxI * nWidth + nIdxJ + 1] //+pImage[ nIdxI * nWidth + nIdxJ + 2]+pImage[ nIdxI * nWidth + nIdxJ + 3])/4); // or Algorithm N.2 temp = int(pImage[nIdxJ * nWidth + nIdxI]); Histogram[temp]++; nCount++; } } float fCoe = 0.01f; int nCoeCount = int(fCoe * nCount); int nAreaCount = int((1 - fCoe) * nCount * fArea); unsigned long int nIdx = 0; unsigned long int nSum = 0; for (nIdx = N - 1; nIdx >= 0; nIdx--) { nSum += Histogram[nIdx]; if (nSum >= nCoeCount) break; } unsigned long int fMean = 0; unsigned long int nflag = 0; for (int i = nIdx; i >= 0; i--) { if (Histogram[nIdx] == 0) { continue; } fMean += nIdx*Histogram[nIdx]; nflag += Histogram[nIdx]; if (nflag >= nAreaCount) { break; } } if (Histogram) { delete Histogram; Histogram = NULL; } if (nflag == 0) { LogInfo("Not have Xray image"); return 1;//无x射线 } fMean = unsigned long int(fMean / nflag); str.Format("Mean count(%d)", fMean); LogInfo(str); if (fMean >= nThreshold) { //LogInfo("Xray image"); return 0; } else { //LogInfo("Not have Xray image"); return 1; } } /************************* * 设置探测器的采图周期以及一次trigger的采图张图 * 只有初始化的时候需要获取一次参数信息,确保是符合binning1X1模式的采集周期 * nFrameRate:帧频; nRepeatNum:采集张数,默认为0,表示持续上图; cBinningMode:设置Binning模式 //***********************/ bool PZMedical2121ZCtrl::SetAcquisitionParam(int nFrameRate, int nRepeatNum, char cBinningMode) { CString strLog; BOOL nRet; UINT32 nXwinTime = 0; UINT32 nDelayTime = 0; LogInfo("## SetAcquisitionParam ##"); //参数检查 if (nFrameRate < 0) { strLog.Format("nFrameRate(%d) is not reasonable", nFrameRate); LogError(strLog); return false; } nXwinTime = m_vecCycleTime.at(nFrameRate); nDelayTime = m_vecDelayTime.at(nFrameRate); strLog.Format("FrameRate: %d, RepeatNum: %d, BinningMode: %d, XwinTime: %d, DelayTime: %d", nFrameRate, nRepeatNum, cBinningMode, nXwinTime, nDelayTime); LogInfo(strLog); LogInfo("Call SetDynamicPara"); nRet = API_COM_SetDynamicPara(nXwinTime, (UINT16)nRepeatNum, cBinningMode); if (!TestError(nRet)) { LogError("SetDynamicPara failed"); return false; } m_nWinTime = nXwinTime; m_nDelayT = nDelayTime; LogInfo("SetAcquisitionParam OVER"); return true; } /****************************** * nMode,要设置的binning模式 * 进行了判重处理,避免重复调用参数相同的SDK接口 //****************************/ bool PZMedical2121ZCtrl::SetBinningMode(int nMode) { CString strLog = ""; if (m_nBinningMode == nMode) //判重处理 { //根据和品臻方面讨论,闲时默认将采集周期设置为500,刷binning1x1模式的暗场图 //if (nMode == PZ_ONExONE && m_nWinTime != 500) //{ // if (!SetSDKCfg(2)) // return false; //} //当前不一定是停止采集了,所以没必要设置500周期的工作,由setbinning的地方去判断、设置周期 if (nMode == PZ_ONExONE) strLog = "Already in Binning 1X1 mode"; else if (nMode == PZ_TWOxTWO) strLog = "Already in Binning 2X2 mode"; else if (nMode == PZ_THRxTHR) strLog = "Already in Binning 3X3 mode"; else strLog.Format("Already in unknown Binning mode: %d", nMode); LogInfo(strLog); return true; } BOOL nRet; if (nMode == PZ_ONExONE) { LogInfo("SetBinning to 1x1"); } else if (nMode == PZ_TWOxTWO) { LogInfo("SetBinning to 2x2"); } else if (nMode == PZ_THRxTHR) { LogInfo("SetBinning to 3x3"); } else { strLog.Format("SetBinning to %d", nMode); LogInfo(strLog); } nRet = API_COM_SetBinningMode(nMode); if (!TestError(nRet)) { LogError("SetBinning failed"); return false; } m_nBinningMode = nMode; return true; } /****************************** * 获取、设置校正模式。 * 首先从探测器和SDK那里获取之前设置的校正模式,与当前用户配置的校正模式相对比,不同则修改为用户的矫正模式 * nMode = 0,获取校正模式 //****************************/ bool PZMedical2121ZCtrl::GetSetCalibMode(CHAR cCalibMode, int nMode) { CString strLog = ""; BOOL nRet; if (nMode) { LogInfo("Call GetPreCalibMode"); CHAR cFPDCalibMode = API_COM_GetPreCalibMode(); switch (cFPDCalibMode) { case IMG_CALIB_RAW: LogInfo("FPD calibration mode is raw"); break; case IMG_CALIB_OFFSET: LogInfo("FPD calibration mode is offset"); break; case IMG_CALIB_GAIN: LogInfo("FPD calibration mode is gain"); break; case IMG_CALIB_DEFECT: LogInfo("FPD calibration mode is defect"); break; case (IMG_CALIB_OFFSET | IMG_CALIB_GAIN): LogInfo("FPD calibration mode is offset+gain"); break; case(IMG_CALIB_OFFSET | IMG_CALIB_GAIN | IMG_CALIB_DEFECT): LogInfo("FPD calibration mode is offset+gain+defect"); break; default: LogInfo("FPD calibration mode is unknown"); break; } LogInfo("Call GetCalibMode"); CHAR cSDKCalibMode = API_COM_GetCalibMode(); switch (cSDKCalibMode) { case IMG_CALIB_RAW: LogInfo("SDK calibration mode is raw"); break; case IMG_CALIB_OFFSET: LogInfo("SDK calibration mode is offset"); break; case IMG_CALIB_GAIN: LogInfo("SDK calibration mode is gain"); break; case IMG_CALIB_DEFECT: LogInfo("SDK calibration mode is defect"); break; case (IMG_CALIB_OFFSET | IMG_CALIB_GAIN) : LogInfo("SDK calibration mode is offset+gain"); break; case(IMG_CALIB_OFFSET | IMG_CALIB_GAIN | IMG_CALIB_DEFECT) : LogInfo("SDK calibration mode is offset+gain+defect"); break; default: LogInfo("SDK calibration mode is unknown"); break; } if (cCalibMode != cFPDCalibMode) //设置FPD校正模式 { strLog.Format("Call SetPreCalibMode, User CalibMode(%d)", cCalibMode); LogInfo(strLog); nRet = API_COM_SetPreCalibMode(cCalibMode); if (!TestError(nRet)) { LogError("SetPreCalibMode failed"); return false; } } else { LogInfo("FPD same as User CalibMode"); } if (cCalibMode != cSDKCalibMode) //设置SDK校正模式 { strLog.Format("Call SetCalibMode, User CalibMode(%d)", cCalibMode); LogInfo(strLog); nRet = API_COM_SetCalibMode(cCalibMode); if (!TestError(nRet)) { LogError("SetCalibMode failed"); return false; } return true; } else { LogInfo("SDK same as User CalibMode"); } } return true; } // 对图像应用过饱和值处理 bool PZMedical2121ZCtrl::ApplyImgSaturation(WORD* pImgData, int nWidth, int nHeight, int nSaturation) { LogInfo(" ## ApplyImgSaturation ## "); WORD wSaturation = (WORD)nSaturation; for (int i = 0; i < nWidth; i++) { for (int j = 0; j < nHeight; j++) { if (pImgData[i * nHeight + j] > wSaturation) { pImgData[i * nHeight + j] = wSaturation; } } } LogInfo("APPLY OVER"); return true; } /****************************** * 设置开窗模式。 * nStartLine, nStartColumn, 起始行、列 * nEndLine, nEndColumn, 终止行、列 //****************************/ bool PZMedical2121ZCtrl::SetROIMode(int nStartLine, int nEndLine, int nStartColumn, int nEndColumn) { CString strLog = ""; //判重 if (nStartLine == m_nStartLine && nEndLine == m_nEndLine && nStartColumn == m_nStartColumn && nEndColumn == m_nEndColumn) { strLog.Format("The startendline is already(%d %d); the stratendcolumn is already(%d %d)", nStartLine, nEndLine, nStartColumn, nEndColumn); LogInfo(strLog); return true; } m_nStartLine = nStartLine; m_nEndLine = nEndLine; m_nStartColumn = nStartColumn; m_nEndColumn = nEndColumn; /* strLog.Format("->SetStartEndLine(%d %d)", nStartLine, nEndLine); LogInfo(strLog); nRet = COM_SETSTARTENDLINE(nStartLine, nEndLine); if (!TestError(nRet)) return false; strLog.Format("->SetStartEndColum(%d %d)", nStartColumn, nEndColumn); LogInfo(strLog); nRet = COM_SETSTARTENDCOLUM(nStartColumn, nEndColumn); if (!TestError(nRet)) return false; */ //测试输出,看是否成功设置了起始行列 //LogInfo("->GetStartEndLine"); //nRet = COM_GETSTARTENDLINE(&m_nStartLine, &m_nEndLine); //if (!TestError(nRet)) // return false; //LogInfo("->GetStartEndColum"); //nRet = COM_GETSTARTENDCOLUM(&m_nStartColumn, &m_nEndColumn); //if (!TestError(nRet)) // return false; //strLog.Format("StartEndLine(%d %d) StartEndColumn(%d %d)", m_nStartLine, m_nEndLine, m_nStartColumn, m_nEndColumn); //LogInfo(strLog); return true; }