#include "stdafx.h" #include "PZMedicalCtrl.h" #include "CCOS.Dev.FPD.PZMedicalDM.h" #include "common_api.h" #define IMAGE_WIDTH 2816 #define IMAGE_HEIGHT 4096 PZMedicalCtrl* g_pDetector = nullptr; #define LOAD_PROC_ADDRESS(handle,func) \ if ((API_##func = (PZ_##func)GetProcAddress(handle, #func)) == NULL) { printf("Error occurs while loading entry point!!! \n'%s'\n", #func); }\ PZMedicalCtrl::PZMedicalCtrl() { m_pDPC2PanelID = new map(); m_pPanelID2DPC = new map(); m_nPanelCount = 0; m_strWorkPath = ""; m_nCurrentPanelID = 0; m_strTplDarkPath = ""; m_strTplFloodPath = ""; m_ePZDPCstate = PZDPC_STATE_INIT; m_nImageWidth = 0; m_nImageHeight = 0; m_nWidthOffset = 0; m_nHeightOffset = 0; m_nRawImgWidth = 0; m_nRawImgHeight = 0; m_pRawImgBuffer = nullptr; m_pImgBuffer = nullptr; m_nAppStatus = APP_STATUS_IDLE; m_eType = CCOS_CALIBRATION_TYPE_NONE; m_nOffsetImg = 0; m_nGainImg = 0; m_eCalState = PZ_CALIBRATION_MAX; m_bCalibrationOver = false; m_bWired = true; m_cFpCurStat = STATUS_NULL; m_nCalibrationRounds = 0; m_eStatus = DetStatus_NotIni; m_nCalibrationMode = CCOS_CALIBRATION_MODE_ZSKK; m_pZSKKCalib = nullptr; m_strPanelType = ""; m_bLoadedSDK = false; m_bInitializedSDK = false; m_bConnectWaiting = false; m_nImgBits = 16; m_nPixelPitch = 0; m_nSaveRaw = 0; m_nCalibCurrentCalibrationRound = 0; m_nCalibCurrentExposureIndex = 0; m_nExposureNumCurrentRound = 0; m_bConfirmCaliRst = false; m_bAutoContinueCal = false; m_bAutonumousMode = false; m_nGainExposureNum = 0; m_nHeartCount = 0; m_nCurrentLogicMode = 0; m_hPZSDKModule = nullptr; m_hRespond = CreateEvent(NULL, FALSE, FALSE, NULL); m_hToggleEvent = CreateEvent(NULL, FALSE, FALSE, NULL); m_hFPDScanThread = nullptr; m_hStopScanEvent = CreateEvent(NULL, FALSE, FALSE, NULL); m_hProcessImgEvent = CreateEvent(NULL, FALSE, FALSE, NULL); m_hXWinOnEvent = CreateEvent(NULL, FALSE, FALSE, NULL); m_hInitFPDEvent = CreateEvent(NULL, FALSE, FALSE, NULL); m_hReInitEvent = CreateEvent(NULL, FALSE, FALSE, NULL); m_hDarkEndEvent = CreateEvent(NULL, FALSE, FALSE, NULL); m_hArrayEvent[0] = m_hStopScanEvent; m_hArrayEvent[1] = m_hProcessImgEvent; m_hArrayEvent[2] = m_hXWinOnEvent; m_hArrayEvent[3] = m_hInitFPDEvent; m_hArrayEvent[4] = m_hReInitEvent; m_hArrayEvent[5] = m_hDarkEndEvent; m_hCalibrationThread = nullptr; m_hPZMPrepare = CreateEvent(NULL, FALSE, FALSE, NULL); m_hPZMStartOffset = CreateEvent(NULL, FALSE, FALSE, NULL); m_hPZMInOffset = CreateEvent(NULL, FALSE, FALSE, NULL); m_hPZMStartAED = CreateEvent(NULL, FALSE, FALSE, NULL); m_hPZMEndAED = CreateEvent(NULL, FALSE, FALSE, NULL); m_hPZMStartGain = CreateEvent(NULL, FALSE, FALSE, NULL); m_hPZMInGain = CreateEvent(NULL, FALSE, FALSE, NULL); m_hEndCalibEvent = CreateEvent(NULL, FALSE, FALSE, NULL); m_hPZMEndEvent = CreateEvent(NULL, FALSE, FALSE, NULL); m_hPZMCalibration[0] = m_hPZMPrepare; m_hPZMCalibration[1] = m_hPZMStartOffset; m_hPZMCalibration[2] = m_hPZMInOffset; m_hPZMCalibration[3] = m_hPZMStartAED; m_hPZMCalibration[4] = m_hPZMEndAED; m_hPZMCalibration[5] = m_hPZMStartGain; m_hPZMCalibration[6] = m_hPZMInGain; m_hPZMCalibration[7] = m_hEndCalibEvent; m_hPZMCalibration[8] = m_hPZMEndEvent; API_COM_Init = nullptr; API_COM_List = nullptr; API_COM_Open = nullptr; API_COM_Close = nullptr; API_COM_RegisterEvCallBack = nullptr; API_COM_SetCalibMode = nullptr; API_COM_GetCalibMode = nullptr; API_COM_Trigger = nullptr; API_COM_AedAcq = nullptr; API_COM_HstAcq = nullptr; API_COM_Prep = nullptr; API_COM_ExposeReq = nullptr; API_COM_Stop = nullptr; API_COM_GetImageMode = nullptr; API_COM_GetImageShiftMode = nullptr; API_COM_GetImage = nullptr; API_COM_SetAllTpl = nullptr; API_COM_GenOffsetTpl = nullptr; API_COM_GenGainTpl = nullptr; API_COM_GenDefectTpl = nullptr; API_COM_TplPathSet = nullptr; API_COM_TplPathGet = nullptr; API_COM_LogPathSet = nullptr; API_COM_GetFPType = nullptr; API_COM_SetAedCorrKB = nullptr; API_COM_GetDllVer = nullptr; API_COM_GetFPInfo = nullptr; API_COM_GetFPConf = nullptr; API_COM_SetFPConf = nullptr; API_COM_GetWifiMode = nullptr; API_COM_GetFPStatus = nullptr; API_COM_GetFPCurStatus = nullptr; API_COM_GetFPsn = nullptr; API_COM_GetFPWireState = nullptr; API_COM_GetFPLicense = nullptr; API_COM_ResetFP = nullptr; API_COM_GetErrNo = nullptr; API_COM_GetXwin = nullptr; API_COM_SetXwin = nullptr; API_COM_GetRBConf = nullptr; API_COM_SetRBConf = nullptr; } PZMedicalCtrl::~PZMedicalCtrl() { if (m_nPanelCount != 0) { for (int i = 0; i < m_nPanelCount; i++) { delete[]m_pStPanelStatus[i]; } } if (m_pRawImgBuffer) { delete[]m_pRawImgBuffer; m_pRawImgBuffer = nullptr; } if (m_pImgBuffer != nullptr) { delete[]m_pImgBuffer; m_pImgBuffer = nullptr; } if (nullptr != m_pDPC2PanelID) { delete m_pDPC2PanelID; m_pDPC2PanelID = nullptr; } if (nullptr != m_pPanelID2DPC) { delete m_pPanelID2DPC; m_pPanelID2DPC = nullptr; } if (m_hStopScanEvent) { CloseHandle(m_hStopScanEvent); m_hStopScanEvent = nullptr; } if (m_hProcessImgEvent) { CloseHandle(m_hProcessImgEvent); m_hProcessImgEvent = nullptr; } if (m_hXWinOnEvent) { CloseHandle(m_hXWinOnEvent); m_hXWinOnEvent = nullptr; } if (m_hInitFPDEvent) { CloseHandle(m_hInitFPDEvent); m_hInitFPDEvent = nullptr; } if (m_hToggleEvent) { CloseHandle(m_hToggleEvent); m_hToggleEvent = nullptr; } if (m_hRespond) { CloseHandle(m_hRespond); m_hRespond = nullptr; } if (m_hPZMPrepare) { CloseHandle(m_hPZMPrepare); m_hPZMPrepare = nullptr; } if (m_hPZMStartOffset) { CloseHandle(m_hPZMStartOffset); m_hPZMStartOffset = nullptr; } if (m_hPZMInOffset) { CloseHandle(m_hPZMInOffset); m_hPZMInOffset = nullptr; } if (m_hPZMStartAED) { CloseHandle(m_hPZMStartAED); m_hPZMStartAED = nullptr; } if (m_hPZMEndAED) { CloseHandle(m_hPZMEndAED); m_hPZMEndAED = nullptr; } if (m_hPZMStartGain) { CloseHandle(m_hPZMStartGain); m_hPZMStartGain = nullptr; } if (m_hPZMInGain) { CloseHandle(m_hPZMInGain); m_hPZMInGain = nullptr; } if (m_hReInitEvent) { CloseHandle(m_hReInitEvent); m_hReInitEvent = nullptr; } if (m_pZSKKCalib) { delete m_pZSKKCalib; m_pZSKKCalib = nullptr; } if (m_hEndCalibEvent) { CloseHandle(m_hEndCalibEvent); m_hEndCalibEvent = nullptr; } if (m_hDarkEndEvent) { CloseHandle(m_hDarkEndEvent); m_hDarkEndEvent = nullptr; } if (m_hPZMEndEvent) { CloseHandle(m_hPZMEndEvent); m_hPZMEndEvent = nullptr; } } bool PZMedicalCtrl::DriverEntry(FPDDevicePZMedical* pDrvDPC, ResDataObject & Configuration) { printf("========DriverEntry %p \n", pDrvDPC); //mLog::FINFO("========DriverEntry {$}", pDrvDPC); map::iterator DPCsIter = m_pDPC2PanelID->find(pDrvDPC); if (DPCsIter != m_pDPC2PanelID->end()) { printf("This DPC already exist\n"); //mLog::FERROR("This DPC already exist"); return false; } CPanelStatus* p = new CPanelStatus(); m_pStPanelStatus[m_nPanelCount] = p; m_pDPC2PanelID->insert(pair(pDrvDPC, m_nPanelCount)); m_pPanelID2DPC->insert(pair(m_nPanelCount, pDrvDPC)); //m_nPanelCount++; m_objFPDConfig = Configuration; //记录配置 --目前只有一个平板,多板时应该分别存储 m_pStPanelStatus[m_nPanelCount]->objPanelConfig = Configuration; return true; } /// /// 设备连接,启动开始Scan线程 /// [DONE.CHECKED.] /// /// /// /// bool PZMedicalCtrl::Connect(FPDDevicePZMedical* pDrvDPC, const char* szWorkPath) { printf("========Connect begin...\n"); //mLog::FINFO("========Connect. work path:{$}", szWorkPath); if ((*m_pDPC2PanelID)[pDrvDPC] != m_nCurrentPanelID) { printf("Not current DPC, return\n"); //mLog::FERROR("Not current DPC, return"); return true; } //初始化失败错误,基本不可以恢复了,直接返回false if (m_pStPanelStatus[m_nCurrentPanelID]->bInitError) { printf("\n Connect detector over(err_init) \n"); //mLog::FINFO("Connect detector over(err_init)"); return false; } //初始化阶段出现连接错误,这种状态下不再执行下面的流程,等待探测器自动重连 if (m_pStPanelStatus[m_nCurrentPanelID]->bConnErrorInInit) { if (!m_pStPanelStatus[m_nCurrentPanelID]->bConnectStatus) { printf("\n Connect detector over(err_connect) \n"); //mLog::FINFO("Connect detector over(err_connect)"); return false; } else { printf("\n Connect detector over \n"); //mLog::FINFO("Connect detector over"); return true; } } if (m_strWorkPath == "") { m_strWorkPath = szWorkPath; } if (!m_pZSKKCalib) { m_pZSKKCalib = new CZSKKCalibrationCtrl(); } DWORD dwThreadId; if (m_hFPDScanThread == nullptr) { m_hFPDScanThread = CreateThread(NULL, 0, onFPDScanThread, this, 0, &dwThreadId); //启动辅助线程 } SetPZDPCState(PZDPC_STATE_INIT); //进入初始化状态 SetEvent(m_hInitFPDEvent); //mLog::FINFO("======== Connect over"); return true; } bool PZMedicalCtrl::Disconnect() { //mLog::FINFO("========Disconnect"); //先退出线程,避免重连流程和调用关闭接口冲突 StopThread(); if (m_pStPanelStatus[m_nCurrentPanelID]->bConnectStatus) { BOOL nRet = FALSE; //mLog::FINFO("Call Close"); nRet = API_COM_Close(); if (!TestError(nRet)) { //mLog::FERROR("Close detector failed"); } } if (m_nCalibrationMode)//PZ自己的校正模式 { //什么也不用做 } else { //mLog::FINFO("Unload ZSKK Reference file"); m_pZSKKCalib->UnLoadZSKKGainMap(); m_pZSKKCalib->UnLoadZSKKPixMap(); } //mLog::FINFO("Disconnect over"); return true; } void PZMedicalCtrl::EnterExamMode(int nExamMode) { switch (nExamMode) { case APP_STATUS_WORK_BEGIN: //mLog::FINFO("Enter into Exam Windows"); m_nAppStatus = APP_STATUS_WORK_BEGIN; break; case APP_STATUS_WORK_END: //mLog::FINFO("Quit Exam Windows"); m_nAppStatus = APP_STATUS_WORK_END; break; case APP_STATUS_DETSHARE_BEGIN: //mLog::FINFO("Enter into Detector Share Windows"); m_nAppStatus = APP_STATUS_DETSHARE_BEGIN; break; case APP_STATUS_DETSHAR_END: m_nAppStatus = APP_STATUS_IDLE; //mLog::FINFO("Quit Detector Share Windows"); m_nAppStatus = APP_STATUS_DETSHAR_END; break; case APP_STATUS_CAL_BEGIN: //mLog::FINFO("Enter into Calibration Windows"); m_nAppStatus = APP_STATUS_CAL_BEGIN; break; case APP_STATUS_CAL_END: //mLog::FINFO("Quit Calibration Windows"); m_nAppStatus = APP_STATUS_CAL_END; break; case APP_STATUS_WORK_IN_SENSITIVITY: //mLog::FINFO("Enter into sensitivity test interface"); m_nAppStatus = APP_STATUS_WORK_IN_SENSITIVITY; break; default: break; } if (APP_STATUS_WORK_END == m_nAppStatus) { //mLog::FINFO("m_nAppStatus == APP_STATUS_WORK_END"); if (m_cFpCurStat > STATUS_IDLE) { BOOL nRet = FALSE; //mLog::FINFO("Call COM_Stop"); nRet = API_COM_Stop();//EnterExamMode TestError(nRet, "COM_Stop"); } SetPZDPCState(PZDPC_STATE_STANDBY); } } bool PZMedicalCtrl::PrepareAcquisition(FPDDevicePZMedical* pDrvDPC) { //mLog::FINFO("========PrepareAcquisition"); BOOL nRet = FALSE; int nTimeout = 12000; if ((*m_pDPC2PanelID)[pDrvDPC] != m_nCurrentPanelID) { printf("Not current DPC, return\n"); //mLog::FERROR("Not current DPC, return"); return false; } SetPZDPCState(PZDPC_STATE_WORK); //此时进入检查 if (!m_pStPanelStatus[m_nCurrentPanelID]->bConnectStatus) { //mLog::FERROR("There is no detector connected, return"); return false; } if (m_cFpCurStat > STATUS_IDLE) { //mLog::FINFO("Call COM_Stop"); nRet = API_COM_Stop();//PrepareAcquisition if (!TestError(nRet, "COM_Stop")) { return false; } } try { nTimeout = (int)m_objFPDConfig["ReadyTimeout"]; } catch (ResDataObjectExption& e) { //mLog::FERROR("Read configuration failed, Error code: {$}", e.what()); } if (SYNC_AED == m_pStPanelStatus[m_nCurrentPanelID]->eSyncMode) { //mLog::FINFO("Call API_COM_AedAcq"); nRet = API_COM_AedAcq(); if (!TestError(nRet, "API_COM_AedAcq")) { return false; } if (m_cFpCurStat == STATUS_AED2) { //mLog::FINFO("Detector already AED status!"); StatusFeedback(EVT_STATUS_PANEL, PANEL_READY_EXP); } else { if (!WaitRespond(nTimeout, "API_COM_AedAcq"))//等待心跳中返回状态 { return false; } } } else { //mLog::FINFO("Call API_COM_HstAcq"); nRet = API_COM_HstAcq(); if (!TestError(nRet, "API_COM_HstAcq")) { return false; } //如果此时状态就是hst 那么不等消息 if (m_cFpCurStat == STATUS_HST) { //mLog::FINFO("Detector already HST status!"); StatusFeedback(EVT_STATUS_PANEL, PANEL_READY_EXP); } else { if (!WaitRespond(nTimeout, "API_COM_HstAcq"))//等待心跳中返回状态 { return false; } } } //mLog::FINFO("PrepareAcquisition over"); return true; } bool PZMedicalCtrl::StartAcquisition(FPDDevicePZMedical* pDrvDPC) { //mLog::FINFO("========StartAcquisition"); if ((*m_pDPC2PanelID)[pDrvDPC] != m_nCurrentPanelID) { printf("Not current DPC, return\n"); //mLog::FERROR("Not current DPC, return"); return false; } if (!m_pStPanelStatus[m_nCurrentPanelID]->bConnectStatus) { //mLog::FERROR("There is no detector connected, return"); return false; } BOOL nRet = FALSE; if (SYNC_AED == m_pStPanelStatus[m_nCurrentPanelID]->eSyncMode) { StatusFeedback(EVT_STATUS_PANEL, PANEL_START_ACQ); } else { //品臻4.2.5版本的动态库,非AED模式,在ExposeReq后会有ready事件的回调 //mLog::FINFO("Call API_COM_ExposeReq"); nRet = API_COM_ExposeReq(); if (!TestError(nRet, "API_COM_ExposeReq")) { return false; } } return true; } /*** ** 调用api,结束采集 ** pDrvDPC,ctrl模块内部调用时为nullptr ***/ bool PZMedicalCtrl::StopAcquisition(FPDDevicePZMedical* pDrvDPC) { //mLog::FINFO("========StopAcquisition"); if (nullptr != pDrvDPC) { if ((*m_pDPC2PanelID)[pDrvDPC] != m_nCurrentPanelID) { printf("Not current DPC, return\n"); //mLog::FERROR("Not current DPC, return"); return false; } } BOOL nRet = FALSE; if (m_cFpCurStat > STATUS_IDLE) { //mLog::FINFO("Call COM_Stop"); nRet = API_COM_Stop();//StopAcquisition if (!TestError(nRet, "COM_Stop")) { return false; } } return true; } /*** ** 说明:激活校正 ** 增益校正(探测器采用post-offset,暗场校正基本没用了)时拿到dose回调,算作执行完毕 ***/ bool PZMedicalCtrl::ActiveCalibration(FPDDevicePZMedical* pDrvDPC, CCOS_CALIBRATION_TYPE eType) { //mLog::FINFO("========ActiveCalibration"); if ((*m_pDPC2PanelID)[pDrvDPC] != m_nCurrentPanelID) { printf("Not current DPC, return\n"); //mLog::FERROR("Not current DPC, return"); return false; } if (!m_pStPanelStatus[m_nCurrentPanelID]->bConnectStatus) { //mLog::FERROR("There is no detector connected, return"); return false; } StatusFeedback(EVT_STATUS_CALIBRATIOIN, PANEL_EVENT_START); DWORD dwThreadId; if (m_hCalibrationThread == nullptr) { m_hCalibrationThread = CreateThread(NULL, 0, onCalibrationThread, this, 0, &dwThreadId); } else { //mLog::FERROR("The calibration process is ongoing"); } if (nullptr == m_hCalibrationThread) { //mLog::FERROR("Start calibration process failed"); return false; } m_eType = eType; SetPZDPCState(PZDPC_STATE_CALIBRATION); m_nOffsetImg = 0; m_nGainImg = 0; m_eCalState = PZ_CALIBRATION_INIT; m_bCalibrationOver = false; printf("ActiveCalibration stop acquisition\n"); //mLog::FINFO("ActiveCalibration stop acquisition"); //停止采集,使探测器进入IDLE状态 if (!StopAcquisition(nullptr)) { return false; } //参考trixellDR 流程 if (CCOS_CALIBRATION_TYPE_DARK == eType) { //mLog::FINFO("Active Dark Calibration"); } else if (CCOS_CALIBRATION_TYPE_XRAY == eType) { //mLog::FINFO("Active Xray Calibration"); m_eStatus = DetStatus_XrayCalibration; if (m_nCalibrationMode) //PZ自己的校正模式 { } else //ZSKK校正 { if (!m_pZSKKCalib) { //mLog::FERROR("ZSKK Calibration object is undefined"); } else { //反馈Dose信息 DataFeedback(EVT_DATA_DOSEPARAM, NULL, 0, 2.5); //加载ZSKK的校正文件 m_pZSKKCalib->m_strRawImgPath = m_strWorkPath + "\\rawdata\\"; m_pZSKKCalib->m_strRefFilePath = m_strWorkPath + "\\references\\"; m_pZSKKCalib->m_nFullImgWidth = m_nImageWidth; m_pZSKKCalib->m_nFullImgHeight = m_nImageHeight; m_pZSKKCalib->m_nReferenceNum = m_nCalibrationRounds; m_pZSKKCalib->m_nSaturationValue = 50000; m_pZSKKCalib->LoadZSKKGainMap(false, m_strPanelType); m_pZSKKCalib->LoadZSKKPixelMap(false, m_strPanelType); //mLog::FINFO("Load ZSKK Gain map success!"); //mLog::FINFO("references file path: {$}", m_pZSKKCalib->m_strRefFilePath.c_str()); } } } else { //mLog::FINFO("Active not supported calibration({$}), return!", (int)eType); } return true; } /*** ** 说明:准备校正(状态机FramePrep) ** 刷暗场 开窗 ***/ bool PZMedicalCtrl::PrepareCalibration(FPDDevicePZMedical* pDrvDPC) { //mLog::FINFO("========PrepareCalibration"); if ((*m_pDPC2PanelID)[pDrvDPC] != m_nCurrentPanelID) { printf("Not current DPC, return\n"); //mLog::FERROR("Not current DPC, return"); return false; } if (!m_pStPanelStatus[m_nCurrentPanelID]->bConnectStatus) { //mLog::FERROR("There is no detector connected, return"); return false; } BOOL nRet = FALSE; //调用COM_Prep接口即可刷新暗场 //mLog::FINFO("PrepareCalibration Call Com_Stop"); if (m_cFpCurStat > STATUS_IDLE) { //mLog::FINFO("Call COM_Stop"); nRet = API_COM_Stop();//PrepareCalibration if (!TestError(nRet, "COM_Stop")) { return false; } } int nTimeout = 12000; //ready缺省等12s try { nTimeout = (int)m_objFPDConfig["ReadyTimeout"]; } catch (ResDataObjectExption& e) { //mLog::FERROR("Read configuration failed, Error code: {$}", e.what()); } if (CCOS_CALIBRATION_TYPE_XRAY == m_eType) { //mLog::FINFO("Calibration type -- GAIN"); m_eCalState = PZ_CALIBRATION_GAIN; if (SYNC_AED == m_pStPanelStatus[m_nCurrentPanelID]->eSyncMode) { //mLog::FINFO("Call AedAcq"); nRet = API_COM_AedAcq(); if (!TestError(nRet, "AedAcq")) { SetEvent(m_hPZMEndEvent); //设置采集模式失败 return false; } if (!WaitRespond(nTimeout, "API_COM_AedAcq")) { return false; } } else { //mLog::FINFO("Call HstAcq"); nRet = API_COM_HstAcq(); if (!TestError(nRet, "HstAcq")) { SetEvent(m_hPZMEndEvent);//设置采集模式失败 return false; } if (!WaitRespond(nTimeout, "API_COM_HstAcq"))//等待心跳中返回状态 { return false; } //品臻4.2.5版本的动态库,非AED模式,在ExposeReq后会有ready事件的回调 //mLog::FINFO("Call API_COM_ExposeReq"); nRet = API_COM_ExposeReq(); if (!TestError(nRet, "API_COM_ExposeReq")) { return false; } } } else { //mLog::FINFO("Calibration type -- DARK"); m_eCalState = PZ_CALIBRATION_OFFSET; //刷暗场 //mLog::FINFO("Call API_COM_Prep"); nRet = API_COM_Prep(); if (!TestError(nRet, "Com_Prep")) { //mLog::FERROR("refresh offset template fail"); } else { //mLog::FINFO("refresh offset template success"); } } return nRet; } bool PZMedicalCtrl::StartCalibration(FPDDevicePZMedical* pDrvDPC) { //mLog::FINFO("========StartCalibration"); if ((*m_pDPC2PanelID)[pDrvDPC] != m_nCurrentPanelID) { printf("Not current DPC, return\n"); //mLog::FERROR("Not current DPC, return"); return false; } if (!m_pStPanelStatus[m_nCurrentPanelID]->bConnectStatus) { //mLog::FERROR("There is no detector connected, return"); printf("the detector is not connected\n"); return false; } if (CCOS_CALIBRATION_TYPE_DARK == m_eType) { //mLog::FINFO("start dark Calibration"); m_eCalState = PZ_CALIBRATION_OFFSET; StatusFeedback(EVT_STATUS_CALIBRATIOIN, PANEL_EVENT_END_OK); } else if(CCOS_CALIBRATION_TYPE_XRAY == m_eType) { //mLog::FINFO("start gain Calibration"); m_eCalState = PZ_CALIBRATION_GAIN; StatusFeedback(EVT_STATUS_PANEL, PANEL_START_ACQ); } return true; } bool PZMedicalCtrl::StopCalibration(FPDDevicePZMedical* pDrvDPC) { //mLog::FINFO("========StopCalibration"); if ((*m_pDPC2PanelID)[pDrvDPC] != m_nCurrentPanelID) { printf("Not current DPC, return\n"); //mLog::FERROR("Not current DPC, return"); return false; } if (!m_pStPanelStatus[m_nCurrentPanelID]->bConnectStatus) { //mLog::FERROR("There is no detector connected, return"); return false; } m_bCalibrationOver = false; //用户停止校正 bool bWrite = false; BOOL bRet = FALSE; if (!StopAcquisition(nullptr)) { //mLog::FERROR("Stop acquisition in calibration failed"); return false; } TFPUserCfg stUserCfg; memset(&stUserCfg, 0, sizeof(stUserCfg)); //mLog::FINFO("Call GetFPConf"); bRet = API_COM_GetFPConf(&stUserCfg); if (!TestError(bRet, "GetFPConf")) { //mLog::FERROR("Get FPConf fail!"); } if (bRet && stUserCfg.wPreProcessing != 1) { stUserCfg.wPreProcessing = 1; // 前校正offset //mLog::FINFO("Call SetFPConf, Set PreProcessing to OFFSET"); bRet = API_COM_SetFPConf(&stUserCfg); if (!TestError(bRet, "SetFPConf")) { //mLog::FERROR("Set FPConf fail!"); } else { bWrite = true; } } if (bWrite) { Sleep(5000); // 5s延迟,保证配置完成 } return true; } /// /// 动态加载设备厂商SDK DLL,指定驱动目录 /// 动态拉取接口,并重命名 /// [DONE.CHECKED.] /// TBD. 接口是否够用?升级后需要新添加别的接口 /// /// bool PZMedicalCtrl::LoadSDK() { string strSDKPath = ""; string strDllpath = ""; try { strSDKPath = (string)m_objFPDConfig["SDKPath"]; } catch (ResDataObjectExption& e) { //mLog::FERROR("Read configuration failed, Error code: {$}", e.what()); return false; } strSDKPath = m_strWorkPath + "\\" + strSDKPath; strDllpath = strSDKPath + "\\ComApi.dll"; //mLog::FINFO("Load SDK path: {$}", strDllpath.c_str()); //将SDK路径加入环境变量 char* pathvar; pathvar = getenv("Path"); printf("pathvar = %s \n\n", pathvar); string strPath = "Path="; strPath += pathvar; strPath += ";"; strPath += strSDKPath; printf("strPath:%s \n\n", strPath.c_str()); if (_putenv(strPath.c_str()) != 0) { DWORD dw = GetLastError(); printf("put env failed! last error:%ld \n", dw); return false; } //pathvar = getenv("Path"); //test //printf("pathvar = %s \n\n", pathvar); m_hPZSDKModule = LoadLibraryEx(strDllpath.c_str(), NULL, LOAD_WITH_ALTERED_SEARCH_PATH); if (m_hPZSDKModule == nullptr) { DWORD dw = GetLastError(); //mLog::FERROR("Load %s failed: {$} \n", strDllpath.c_str(), dw); return false; } LOAD_PROC_ADDRESS(m_hPZSDKModule, COM_Init); LOAD_PROC_ADDRESS(m_hPZSDKModule, COM_List); LOAD_PROC_ADDRESS(m_hPZSDKModule, COM_Open); LOAD_PROC_ADDRESS(m_hPZSDKModule, COM_Close); LOAD_PROC_ADDRESS(m_hPZSDKModule, COM_RegisterEvCallBack); LOAD_PROC_ADDRESS(m_hPZSDKModule, COM_SetCalibMode); LOAD_PROC_ADDRESS(m_hPZSDKModule, COM_GetCalibMode); LOAD_PROC_ADDRESS(m_hPZSDKModule, COM_Trigger); LOAD_PROC_ADDRESS(m_hPZSDKModule, COM_AedAcq); LOAD_PROC_ADDRESS(m_hPZSDKModule, COM_HstAcq); LOAD_PROC_ADDRESS(m_hPZSDKModule, COM_Prep); LOAD_PROC_ADDRESS(m_hPZSDKModule, COM_ExposeReq); LOAD_PROC_ADDRESS(m_hPZSDKModule, COM_Stop); LOAD_PROC_ADDRESS(m_hPZSDKModule, COM_GetImageMode); LOAD_PROC_ADDRESS(m_hPZSDKModule, COM_GetImage); LOAD_PROC_ADDRESS(m_hPZSDKModule, COM_SetAllTpl); LOAD_PROC_ADDRESS(m_hPZSDKModule, COM_GenOffsetTpl); LOAD_PROC_ADDRESS(m_hPZSDKModule, COM_GenGainTpl); LOAD_PROC_ADDRESS(m_hPZSDKModule, COM_GenDefectTpl); LOAD_PROC_ADDRESS(m_hPZSDKModule, COM_TplPathSet); LOAD_PROC_ADDRESS(m_hPZSDKModule, COM_TplPathGet); LOAD_PROC_ADDRESS(m_hPZSDKModule, COM_LogPathSet); LOAD_PROC_ADDRESS(m_hPZSDKModule, COM_GetFPType); LOAD_PROC_ADDRESS(m_hPZSDKModule, COM_SetAedCorrKB); LOAD_PROC_ADDRESS(m_hPZSDKModule, COM_GetDllVer); LOAD_PROC_ADDRESS(m_hPZSDKModule, COM_GetFPInfo); LOAD_PROC_ADDRESS(m_hPZSDKModule, COM_GetFPConf); LOAD_PROC_ADDRESS(m_hPZSDKModule, COM_SetFPConf); LOAD_PROC_ADDRESS(m_hPZSDKModule, COM_GetWifiMode); LOAD_PROC_ADDRESS(m_hPZSDKModule, COM_GetFPStatus); LOAD_PROC_ADDRESS(m_hPZSDKModule, COM_GetFPCurStatus); LOAD_PROC_ADDRESS(m_hPZSDKModule, COM_GetFPsn); LOAD_PROC_ADDRESS(m_hPZSDKModule, COM_GetFPWireState); LOAD_PROC_ADDRESS(m_hPZSDKModule, COM_GetFPLicense); LOAD_PROC_ADDRESS(m_hPZSDKModule, COM_AedTrigger); LOAD_PROC_ADDRESS(m_hPZSDKModule, COM_ResetFP); LOAD_PROC_ADDRESS(m_hPZSDKModule, COM_GetErrNo); LOAD_PROC_ADDRESS(m_hPZSDKModule, COM_GetXwin); LOAD_PROC_ADDRESS(m_hPZSDKModule, COM_SetXwin); LOAD_PROC_ADDRESS(m_hPZSDKModule, COM_GetRBConf); LOAD_PROC_ADDRESS(m_hPZSDKModule, COM_SetRBConf); m_bLoadedSDK = true; //mLog::FINFO("Load SDK over"); return true; } /// /// 初始化 品臻 SDK /// [DONE.CHECKED.] /// /// bool PZMedicalCtrl::InitSDK() { printf("========InitSDK \n"); //mLog::FINFO("======== InitSDK"); BOOL nRet = FALSE; //mLog::FINFO("Call RegisterEvCallback, EVENT_LINKUP"); nRet = API_COM_RegisterEvCallBack(EVENT_LINKUP, FuncLinkUpCallBack); TestError(nRet, "Register EVENT_LINKUP"); //mLog::FINFO("Call RegisterEvCallback, EVENT_LINKDOWN"); nRet = API_COM_RegisterEvCallBack(EVENT_LINKDOWN, FuncLinkDownCallBack); TestError(nRet, "Register EVENT_LINKDOWN"); //mLog::FINFO("Call RegisterEvCallback, EVENT_IMAGEVALID"); nRet = API_COM_RegisterEvCallBack(EVENT_IMAGEVALID, FuncImageCallBack); TestError(nRet, "Register EVENT_IMAGEVALID"); //mLog::FINFO("Call RegisterEvCallback, EVENT_HEARTBEAT"); nRet = API_COM_RegisterEvCallBack(EVENT_HEARTBEAT, FuncHeartBeatCallBack); TestError(nRet, "Register EVENT_HEARTBEAT"); //mLog::FINFO("Call RegisterEvCallback, EVENT_READY"); nRet = API_COM_RegisterEvCallBack(EVENT_READY, FuncReadyCallBack); TestError(nRet, "Register EVENT_READY"); //mLog::FINFO("Call RegisterEvCallback, EVENT_EXPOSE"); nRet = API_COM_RegisterEvCallBack(EVENT_EXPOSE, FuncExposeCallBack); TestError(nRet, "Register EVENT_EXPOSE"); //mLog::FINFO("Call RegisterEvCallback, EVENT_EXPEND"); nRet = API_COM_RegisterEvCallBack(EVENT_EXPEND, FuncExposeEndCallBack); TestError(nRet, "Register EVENT_EXPEND"); //mLog::FINFO("Call RegisterEvCallback, EVENT_OFFSETDONE"); nRet = API_COM_RegisterEvCallBack(EVENT_OFFSETDONE, FuncOffsetDoneCallBack); TestError(nRet, "Register EVENT_OFFSETDONE"); //mLog::FINFO("Call RegisterEvCallback, EVENT_AED_A1"); nRet = API_COM_RegisterEvCallBack(EVENT_AED_A1, FuncAedA1CallBack); TestError(nRet, "Register EVENT_AED_A1"); //mLog::FINFO("Call RegisterEvCallback, EVENT_AED_A2"); nRet = API_COM_RegisterEvCallBack(EVENT_AED_A2, FuncAedA2CallBack); TestError(nRet, "Register EVENT_AED_A2"); //mLog::FINFO("Call RegisterEvCallback, EVENT_IMAGESTART"); nRet = API_COM_RegisterEvCallBack(EVENT_IMAGESTART, FuncImageStartCallBack); TestError(nRet, "Register EVENT_IMAGESTART"); //mLog::FINFO("Call RegisterEvCallback, EVENT_IMAGEEND"); nRet = API_COM_RegisterEvCallBack(EVENT_IMAGEEND, FuncImageEndCallBack); TestError(nRet, "Register EVENT_IMAGEEND"); //mLog::FINFO("Call RegisterEvCallback, EVENT_BATTLOW1"); nRet = API_COM_RegisterEvCallBack(EVENT_BATTLOW1, FuncBattLow1CallBack); TestError(nRet, "Register EVENT_BATTLOW1"); //mLog::FINFO("Call RegisterEvCallback, EVENT_BATTLOW2"); nRet = API_COM_RegisterEvCallBack(EVENT_BATTLOW2, FuncBattLow2CallBack); TestError(nRet, "Register EVENT_BATTLOW2"); // 设置SDK日志文件路径 string strLogPath = ""; strLogPath = m_strWorkPath + "\\Logs"; char* szLogPath = const_cast(strLogPath.c_str()); //mLog::FINFO("Call LogPathSet, Path: {$}", szLogPath); nRet = API_COM_LogPathSet(szLogPath); if (!TestError(nRet, "LogPathSet")) { return false; } // 初始化 //mLog::FINFO("Call Init"); nRet = API_COM_Init(); if (!TestError(nRet, "Init")) { return false; } Sleep(3000); //根据品臻工程师建议,Init接口要和Open接口间隔一段时间执行。 //mLog::FINFO("Initialize SDK over"); printf("Initialize SDK over \n"); m_bInitializedSDK = true; return true; } int PZMedicalCtrl::ConnectDetector() { printf("========ConnectDetector \n"); //mLog::FINFO("======== ConnectDetector"); BOOL nRet = FALSE; string strPanelSerial = ""; int nTimeoutInit = 10000; try { strPanelSerial = (string)m_objFPDConfig["SerialNumber"]; nTimeoutInit = (int)m_objFPDConfig["ConnectTimeout"]; } catch (ResDataObjectExption& e) { //mLog::FERROR("Read configuration failed! Error code: {$}", e.what()); return INIT_FAILED; } if (strPanelSerial == "") { //mLog::FERROR("Serial number is null!"); return INIT_FAILED; } char szPanelSerial[32] = { '\0' }; //SDK需要32位char* 否则有可能解析出乱码,导致初始化失败 memcpy(szPanelSerial, strPanelSerial.c_str(), strPanelSerial.length()); //mLog::FINFO("Call COM_Open, Detector Serial: {$}, Timeout: {$}", szPanelSerial, nTimeoutInit); nRet = API_COM_Open(szPanelSerial); if (!TestError(nRet, "Open")) { //mLog::FINFO("Call Open again"); nRet = API_COM_Open(szPanelSerial); //根据品臻工程师建议,OPEN接口失败一次后尝试再调用一次 if (!TestError(nRet, "Open")) { return INIT_FAILED; } } m_bConnectWaiting = true; if (!WaitRespond(nTimeoutInit, "Open")) //m_hRespond 初始化等待link回调 { //mLog::FERROR("connect detector timeout!"); return INIT_CONNECT_ERR; } m_bConnectWaiting = false; if (m_nCalibrationMode)//PZ自己的校正模式 { bool bRet = SetFPDCalibrationMode(); if (!bRet) { //mLog::FERROR("Load PZMedical template fail!"); return INIT_FAILED; } } else { //mLog::FINFO("Load ZSKK Reference file"); if (!m_pZSKKCalib->LoadZSKKGainMap(true, m_strPanelType)) { //mLog::FERROR("Load ZSKK Gain Map failed!"); } if (!m_pZSKKCalib->LoadZSKKPixelMap(true, m_strPanelType)) { //mLog::FERROR("Load ZSKK Defect Map failed!"); } } //mLog::FINFO("Connect detector over"); printf("Connect detector over \n"); //连接上探测器后获取gain校正曝光的总次数 m_nGainExposureNum = ((FPDDevicePZMedical*)(*m_pPanelID2DPC)[m_nCurrentPanelID])->GetGainExposureNum(); //mLog::FINFO("Gain Exposure Num:{$}",m_nGainExposureNum); return INIT_SUCCESS; } //设置校正文件路径,获取SDK版本信息,获取探测器信息:sn version ip mac... bool PZMedicalCtrl::InitDetector() { //mLog::FINFO("========InitDetector"); BOOL bRet = FALSE; //设置校正文件路径 bool bRes = SetFPDTplPath(); if (bRes) { TImageMode tImageMode; //mLog::FINFO("Call GetImageMode"); bRet = API_COM_GetImageMode(&tImageMode); //经过测试,这个接口要放到连接成功之后,否则获取不到信息 if (!TestError(bRet, "GetImageMode")) { return false; } else { //这里获取的图像大小,不一定是出图的大小,需要在GetImage的时候重新调用此接口获取图像大小 printf("Get Image Mode, Width: %d; Height: %d \n", tImageMode.usCol, tImageMode.usRow); //mLog::FINFO("Get Image Mode Width: {$}; Height: {$}", tImageMode.usCol, tImageMode.usRow); } CHAR szVersion[25] = { '\0' }; //字节数不能太小,否则会导致崩溃,经测试不能小于20 printf("Getting SDK version \n"); //mLog::FINFO("Call GetDllVer"); bRet = API_COM_GetDllVer(szVersion); if (!TestError(bRet, "GetDllVer")) { return false; } else { //mLog::FINFO("[DLL Version: {$}]", szVersion); } TFPInfo tFPInfo = { 0 }; //mLog::FINFO("Call GetFPInfo"); bRet = API_COM_GetFPInfo(&tFPInfo); if (!TestError(bRet, "GetFPInfo")) { return false; } else { //转换IP //IP格式是int32的4个字节,每个字节转换成10进制就是IP UCHAR* pData = (UCHAR*)&tFPInfo.dwFpIp; //mLog::FINFO("[SN:{$}, McuVer:{$}, FPGA:{$}, PPCVer:{$}, IP:{$}.{$}.{$}.{$}]", tFPInfo.dwBoardSn, tFPInfo.dwMcuVer, tFPInfo.dwFpgaVer, tFPInfo.dwSwVer, pData[3], pData[2], pData[1], pData[0]); } USHORT uXwin; //mLog::FINFO("Call GetXwin"); bRet = API_COM_GetXwin(&uXwin); if (!TestError(bRet, "GetXwin")) { return false; } else { //mLog::FINFO("Xwindow:{$}", uXwin); } //mLog::FINFO("Call SetXwin"); bRet = API_COM_SetXwin(uXwin); if (!TestError(bRet, "SetXwin")) { return false; } TRBConf RbConf = { 0 }; //mLog::FINFO("Call GetRbConf"); bRet = API_COM_GetRBConf(&RbConf); if (!TestError(bRet, "GetRbConf")) { return false; } else { RbConf.wXwin = uXwin; //mLog::FINFO("xwin_clock:{$}", RbConf.wXwin); } //mLog::FINFO("Call SetRBConf"); bRet = API_COM_SetRBConf(&RbConf); if (!TestError(bRet, "SetRBConf")) { return false; } } //mLog::FINFO("Initialize detector over"); return bRet; } /*** ** 设置校正文件路径 ** 说明:device\references\xxxxxx\dark是暗场校正过程文件 ** device\references\xxxxxx\gain是亮场校正过程文件 ** 校正完成后校正文件会生成到device\references\路径,strPanelSerial表示探测器序列号 ***/ bool PZMedicalCtrl::SetFPDTplPath() { //mLog::FINFO("========SetFPDTplPath"); BOOL nRet = FALSE; string strTplRootPath = m_strWorkPath + "\\references"; string strDarkTplPath = ""; string strFloodTplPath = ""; string strPanelSerial = ""; try { strPanelSerial = (string)m_objFPDConfig["SerialNumber"]; } catch (ResDataObjectExption& e) { //mLog::FERROR("Read configuration failed, Error code: {$}", e.what()); return false; } strDarkTplPath = strTplRootPath + "\\" + strPanelSerial + "\\dark\\"; strFloodTplPath = strTplRootPath + "\\" + strPanelSerial + "\\gain\\"; // 创建dark文件路径 if (CreateFileDirectory(strDarkTplPath)) { //mLog::FINFO("Create Directory: {$}", strDarkTplPath.c_str()); m_strTplDarkPath = strDarkTplPath; } else { //mLog::FERROR("Create Directory: {$} failed", strDarkTplPath.c_str()); return false; } // 创建flood文件路径 if (CreateFileDirectory(strFloodTplPath)) { //mLog::FINFO("Create Directory: {$}", strFloodTplPath.c_str()); m_strTplFloodPath = strFloodTplPath; } else { //mLog::FERROR("Create Directory: {$} failed", strFloodTplPath.c_str()); return false; } return true; } /*** ** 设置品臻板子出图时都应用哪些校正 * 当校正模式是PZ自己的校正时调用 ***/ bool PZMedicalCtrl::SetFPDCalibrationMode() { //mLog::FINFO("========SetFPDCalibrationMode"); BOOL nRet = FALSE; nRet = API_COM_SetCalibMode(IMG_CALIB_OFFSET | IMG_CALIB_GAIN | IMG_CALIB_DEFECT); if (!TestError(nRet, "SetCalibMode")) { return false; } //mLog::FINFO("Call SetAllTpl"); nRet = API_COM_SetAllTpl(); if (!TestError(nRet, "SetAllTpl")) { m_pStPanelStatus[m_nCurrentPanelID]->bLostTemplate = true; //mLog::FERROR("Set Template Failed, There are no Templates here"); return false; } return true; } /*** ** 获取探测器连接模式 ***/ void PZMedicalCtrl::GetConnectionMode() { //mLog::FINFO("========GetConnectionMode"); BOOL nRet; CHAR szFPSn[32] = { '\0' }; //SDK升级,改为32位数组 //mLog::FINFO("Call GetFPSn"); nRet = API_COM_GetFPsn(szFPSn); if (!TestError(nRet, "GetFPSn")) { //mLog::FERROR("Get detector serial number failed"); } else { //mLog::FINFO("FP Sn: {$}", szFPSn); } string panel_sn = szFPSn; ConfFeedback(EVT_CONF_PANEL_SERIAL, m_nCurrentPanelID, panel_sn.c_str()); //mLog::FINFO("Call GetFPWireState"); CHAR cStateTemp = API_COM_GetFPWireState(); //是否是wifi连接方式 if (cStateTemp == CONNECT_WIFI) { //mLog::FINFO("GetFPWireState return: Wireless Mode"); m_bWired = false; } else if (cStateTemp == CONNECT_WIRE) { //mLog::FINFO("GetFPWireState return: Wired Mode"); m_bWired = true; } else { //mLog::FERROR("GetFPWireState return unknown mode: {$}", (int)cStateTemp); } } DWORD __stdcall PZMedicalCtrl::onFPDScanThread(PVOID pvoid) { PZMedicalCtrl* pOpr = (PZMedicalCtrl*)pvoid; //mLog::FINFO("Enter Scan Thread"); bool bExit = false; while (!bExit) { DWORD dwRet = WaitForMultipleObjects(5, pOpr->m_hArrayEvent, FALSE, INFINITE); if (WAIT_OBJECT_0 == dwRet) //m_hStopScanEvent { bExit = true; } else if (WAIT_OBJECT_0 + 1 == dwRet) //m_hProcessImgEvent { pOpr->OnProcessImg(); } else if (WAIT_OBJECT_0 + 2 == dwRet) //m_hXWinOnEvent { DWORD dwXrayOnTime, dwXrayOffTime; dwXrayOnTime = dwXrayOffTime = GetTickCount(); printf("XWindowOn \n"); //mLog::FINFO("XWindowOn: {$}", dwXrayOnTime); pOpr->StatusFeedback(EVT_STATUS_PANEL, PANEL_XWINDOW_ON); while (dwXrayOffTime - dwXrayOnTime < 750) { dwXrayOffTime = GetTickCount(); } printf("XWindowOff \n"); //mLog::FINFO("XWindowOff: {$}", dwXrayOffTime); pOpr->StatusFeedback(EVT_STATUS_PANEL, PANEL_XWINDOW_OFF); } else if (WAIT_OBJECT_0 + 3 == dwRet) //m_hInitFPDEvent { pOpr->OnProcessInitFPD(); } else if (WAIT_OBJECT_0 + 4 == dwRet) //m_hReInitEvent { pOpr->OnReInitFPD(); } else if (WAIT_OBJECT_0 + 5 == dwRet) //m_hDarkEndEvent { pOpr->OnProcessDarkEnd(); } } //mLog::FINFO("Exit Scan Thread"); pOpr->m_hFPDScanThread = nullptr; SetEvent(pOpr->m_hToggleEvent); return 0; } void PZMedicalCtrl::StopThread() { //mLog::FINFO("========StopThread"); SetEvent(m_hStopScanEvent); //关闭Scan线程 DWORD result = WaitForSingleObject(m_hToggleEvent, 65000); if (result == WAIT_OBJECT_0) { //mLog::FINFO("Leave scan thread over"); } else if (result == WAIT_TIMEOUT) { //mLog::FERROR("wait time out"); } } /*** ** 处理图像 ***/ void PZMedicalCtrl::OnProcessImg() { BOOL bRet = FALSE; //mLog::FINFO("========Here Come the Image"); StatusFeedback(EVT_STATUS_PANEL, PANEL_XWINDOW_ON); TImageMode tImageMode; //mLog::FINFO("Call GetImageMode"); bRet = API_COM_GetImageMode(&tImageMode); //经过测试,这个接口要放到连接成功之后,否则获取不到信息 if (!TestError(bRet, "GetImageMode")) { return; } m_nRawImgWidth = tImageMode.usCol; m_nRawImgHeight = tImageMode.usRow; //mLog::FINFO("OnProcessImg Get Image Mode Width: {$}; Height: {$}", tImageMode.usCol, tImageMode.usRow); int nRawImgWidth = 0; int nRawImgHeight = 0; int nImageWidth = 0; int nImageHeight = 0; int nRightOffset = 0;//右侧裁剪宽度 int nBottomOffset = 0;//下方裁剪宽度 try { nRawImgWidth = (int)m_ModeConfig["ModeTable"][m_nCurrentLogicMode - 1]["RawImgWidth"]; nRawImgHeight = (int)m_ModeConfig["ModeTable"][m_nCurrentLogicMode-1]["RawImgHeight"]; nImageWidth = (int)m_ModeConfig["ModeTable"][m_nCurrentLogicMode - 1]["ImageWidth"]; nImageHeight = (int)m_ModeConfig["ModeTable"][m_nCurrentLogicMode - 1]["ImageHeight"]; } catch (ResDataObjectExption& exp) { //mLog::FERROR("Get config failed: {$}", exp.what()); return; } nRightOffset = nRawImgWidth - m_nWidthOffset - nImageWidth; nBottomOffset = nRawImgHeight - m_nHeightOffset - nImageHeight; if (m_nWidthOffset == 0 && nRightOffset == 0)//配置了左右裁剪 { m_nImageWidth = m_nRawImgWidth; } else { m_nImageWidth = IMAGE_WIDTH - m_nWidthOffset - nRightOffset; if (m_nImageWidth >= m_nRawImgWidth) { m_nImageWidth = m_nRawImgWidth; m_nWidthOffset = 0; } else { if (m_nRawImgWidth - m_nImageWidth < m_nWidthOffset) { m_nWidthOffset = m_nRawImgWidth - m_nImageWidth; } } } if (m_nHeightOffset == 0 && nBottomOffset == 0)//配置了上下裁剪 { m_nImageHeight = m_nRawImgHeight; } else { m_nImageHeight = IMAGE_HEIGHT - m_nHeightOffset - nBottomOffset; if (m_nImageHeight >= m_nRawImgHeight)//如果裁剪后依然大于等于实际出图大小,那么就按实际出图大小走 { m_nImageHeight = m_nRawImgHeight; m_nHeightOffset = 0; } else { if (m_nRawImgHeight - m_nImageHeight < m_nHeightOffset) { m_nHeightOffset = m_nRawImgHeight - m_nImageHeight; } } } //mLog::FINFO("m_nImageWidth:{$},m_nImageHeight:{$},m_nWidthOffset:{$},m_nHeightOffset:{$}", m_nImageWidth, m_nImageHeight, m_nWidthOffset, m_nHeightOffset); if (m_nImageWidth <= 0 || m_nImageHeight <= 0) { //mLog::FERROR("Please check crop size!"); return; } ConfFeedback(EVT_CONF_RAW_WIDTH, m_nCurrentPanelID, "ImageWidth", m_nImageWidth); ConfFeedback(EVT_CONF_RAW_HIGHT, m_nCurrentPanelID, "ImageHeight", m_nImageHeight); if (m_pRawImgBuffer) { delete m_pRawImgBuffer; m_pRawImgBuffer = nullptr; } m_pRawImgBuffer = new WORD[m_nRawImgWidth * m_nRawImgHeight]; if (m_pImgBuffer) { delete m_pImgBuffer; m_pImgBuffer = NULL; } m_pImgBuffer = new WORD[m_nImageWidth * m_nImageHeight]; bRet = API_COM_GetImage((CHAR*)m_pRawImgBuffer); if (!TestError(bRet, "GetImage")) { return; } if (m_nSaveRaw == 1 || m_nSaveRaw == 3)//保存应用校正文件前的图像 { SaveRawImage("BeforeCalibration.raw", m_pRawImgBuffer, m_nRawImgWidth, m_nRawImgHeight); } if (m_nWidthOffset != 0 || m_nHeightOffset != 0) { //mLog::FINFO("Begin get effect image"); if (!GetEffectiveImage(m_pImgBuffer, m_pRawImgBuffer, m_nRawImgWidth)) { return; } //mLog::FINFO("Get effect image over"); if (m_nAppStatus != APP_STATUS_CAL_BEGIN && m_nCalibrationMode == CCOS_CALIBRATION_MODE_ZSKK) { //mLog::FINFO("Apply ZSKK Calibration File"); m_pZSKKCalib->m_nGridSuppressed = 6; m_pZSKKCalib->ApplyZSKKReference(m_nImageHeight, m_nImageWidth, m_pImgBuffer); } if (m_nSaveRaw > 1) { SaveRawFunc(m_pImgBuffer, m_nImageWidth, m_nImageHeight); } DataFeedback(EVT_DATA_RAW_IMAGE, m_pImgBuffer); } else { //mLog::FINFO("m_nWidthOffset and m_nHeightOffset is 0"); if (m_nAppStatus != APP_STATUS_CAL_BEGIN && m_nCalibrationMode == CCOS_CALIBRATION_MODE_ZSKK) { //mLog::FINFO("Apply ZSKK Calibration File"); m_pZSKKCalib->m_nGridSuppressed = 6; m_pZSKKCalib->ApplyZSKKReference(m_nRawImgHeight, m_nRawImgWidth, m_pRawImgBuffer); } if (m_nSaveRaw > 1) { SaveRawFunc(m_pRawImgBuffer, m_nRawImgWidth, m_nRawImgHeight); } DataFeedback(EVT_DATA_RAW_IMAGE, m_pRawImgBuffer); } StatusFeedback(EVT_STATUS_PANEL, PANEL_XWINDOW_OFF); } void PZMedicalCtrl::SaveRawFunc(WORD* pInImg, int nImgWidth, int nImgHeight) { //mLog::FINFO("========SaveRawFunc"); FILE* fp; char filename[256] = {0}; //SYSTEMTIME st; //GetLocalTime(&st); ////mLog::FINFO("Date: [%04d:%02d:%02d] ", st.wYear, st.wMonth, st.wDay); //sprintf(filename, "\\RawData\\Raw%02d-%02d-%02d-%02d-%02d.raw", st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond); sprintf(filename, "\\RawData\\Raw.raw"); string strFileName = m_strWorkPath + filename; if ((fp = fopen(strFileName.c_str(), "wb")) == NULL) { DWORD dw = GetLastError(); //mLog::FERROR("fopen {$} failed, {$}", strFileName.c_str(), dw); return; } fwrite(pInImg, sizeof(WORD), nImgWidth * nImgHeight, fp); fclose(fp); //mLog::FINFO("Save image over"); } /*** * 保存RAW图像 ***/ bool PZMedicalCtrl::SaveRawImage(const char* pImgName, const WORD* pRawImg, int nWidth, int nHeight) { //mLog::FINFO("========SaveRawImage"); //mLog::FINFO("ImageName:{$}, width: {$}, height: {$}", pImgName, nWidth, nHeight); if (pRawImg == NULL || pImgName == NULL) { return false; } string strImagePath = ""; if (m_bAutonumousMode) { /*string strImageDir = m_strWorkPath + "\\rawdata\\Autonumous\\" + m_strAutonumousMetaData; if (GetFileAttributesA(strImageDir.c_str()) != FILE_ATTRIBUTE_DIRECTORY) { bool flag = CreateDirectory(strImageDir.c_str(), NULL); //mLog::FINFO("Create dir: {$}", strImageDir); } else { //mLog::FINFO("{$} already exist", strImageDir); } strImagePath = m_strWorkPath + "\\rawdata\\Autonumous\\" + m_strAutonumousMetaData + "\\" + pImgName;*/ } else { strImagePath = m_strWorkPath + "\\rawdata\\" + pImgName; } FILE* fp; if ((fp = fopen(strImagePath.c_str(), "wb")) == NULL) { DWORD dw = GetLastError(); //mLog::FERROR("fopen {$} failed, {$}", strImagePath.c_str(), dw); return false; } fwrite(pRawImg, sizeof(WORD), nWidth * nHeight, fp); fclose(fp); //mLog::FINFO("End to Save Raw Image"); return true; } /*** ** 裁剪图像 ** pOutImg: 裁剪后图像; pInImg: 裁剪前图像; nInWidth: 裁剪前图像宽度 ***/ bool PZMedicalCtrl::GetEffectiveImage(WORD* pOutImg, WORD* pInImg, int nInWidth) { //mLog::FINFO("========GetEffectiveImage"); if (pOutImg == NULL || pInImg == NULL || nInWidth < 0) { //mLog::FERROR("Illegal parameter, can not get effective image"); return false; } try { for (int i = 0; i < m_nImageHeight; i++) { memcpy(pOutImg + i * m_nImageWidth, pInImg + (i + m_nHeightOffset) * nInWidth + m_nWidthOffset, m_nImageWidth * sizeof(WORD)); } } catch (...) { //mLog::FERROR("Get effective image crashed"); return false; } return true; } /// /// 实际探测器初始化,事件触发 /// 连接探测器并进行初始化操作 /// void PZMedicalCtrl::OnProcessInitFPD() { //mLog::FINFO("========OnProcessInitFPD"); StatusFeedback(EVT_STATUS_INIT, PANEL_EVENT_START); int nRet = INIT_SUCCESS; //加载SDK if (!m_bLoadedSDK && !LoadSDK()) { nRet = INIT_FAILED; //mLog::FERROR("LoadSDK fail!"); } //初始化SDK if (INIT_SUCCESS == nRet && !m_bInitializedSDK && !InitSDK()) { nRet = INIT_FAILED; //mLog::FERROR("InitSDK fail!"); } //连接探测器 if (INIT_SUCCESS == nRet) { nRet = ConnectDetector(); if (INIT_SUCCESS == nRet) { //初始化探测器 if (!InitDetector()) { nRet = INIT_FAILED; //mLog::FERROR("InitDetector fail!"); } } else { //mLog::FERROR("ConnectDetector fail!"); } } if (INIT_FAILED == nRet) { //mLog::FERROR("INIT_FAILED"); m_pStPanelStatus[m_nCurrentPanelID]->bInitError = true; ErrorFeedback(EVT_ERR_INIT_FAILED, "true"); StatusFeedback(EVT_STATUS_INIT, PANEL_EVENT_END_ERROR); } else if (INIT_CONNECT_ERR == nRet) { //mLog::FERROR("INIT_CONNECT_ERR"); m_pStPanelStatus[m_nCurrentPanelID]->bConnErrorInInit = true; ErrorFeedback(EVT_ERR_COMMUNICATE, "true", m_nCurrentPanelID); StatusFeedback(EVT_STATUS_INIT, PANEL_EVENT_END); } else { StatusFeedback(EVT_STATUS_INIT, PANEL_EVENT_END_OK);//OnProcessInitFPD SetPZDPCState(PZDPC_STATE_STANDBY); } } /*** ** 说明:初始化阶段,未连接探测器,重连后需要继续初始化探测器 ***/ void PZMedicalCtrl::OnReInitFPD() { //mLog::FINFO("========OnReInitFPD"); StatusFeedback(EVT_STATUS_INIT, PANEL_EVENT_START); if (!InitDetector()) { m_pStPanelStatus[m_nCurrentPanelID]->bInitError = true; ErrorFeedback(EVT_ERR_INIT_FAILED, "true"); StatusFeedback(EVT_STATUS_INIT, PANEL_EVENT_END_ERROR); } m_pStPanelStatus[m_nCurrentPanelID]->bConnErrorInInit = false; StatusFeedback(EVT_STATUS_INIT, PANEL_EVENT_END_OK);//OnReInitFPD } DWORD __stdcall PZMedicalCtrl::onCalibrationThread(PVOID pvoid) { PZMedicalCtrl* pOpr = (PZMedicalCtrl*)pvoid; if (pOpr->OnProcessCalibration()) { //mLog::FINFO("Calibration process over"); } else { pOpr->StatusFeedback(EVT_STATUS_CALIBRATIOIN, PANEL_EVENT_END_ERROR); //mLog::FERROR("Quit calibration over(with error)"); } CloseHandle(pOpr->m_hCalibrationThread); pOpr->m_hCalibrationThread = nullptr; //mLog::FINFO("Quit calibration process"); return 0; } /*** ** 校正过程 ** 说明:校正辅助线程,结合校正process的阶段和SDK回调完成校正流程 ** (ActiveCalibration)停止采集,进入idle状态(set prepare event)[CalibINIT process] ** 修改配置 ** == dark == ** 1.(StartCalibration)调用api,进入hst状态(set offset event) ** 2.调用api,开始采集dark图像(image callback) ** 3.保存8张dark图像,停止采集,进入idle状态(set endcalib/aed event)[CalibOFFSET process] ** (上aed图过程目前只在aed同步模式下进行) ** 4.接收10张aed图像,上传数据,停止采集,进入idle状态(set endcalib event)[CalibAED process] ** == flood == ** 1.(PrepareCalibration)调用api,进入hst或aed状态 ** 2.(StartCalibration)调用api,采集flood图像(image callback) ** 3.修改配置,进入hst或aed模式,采集亮场图像 ** 4.重复1、2、3,采集8张flood图像,停止采集,进入idle状态(set endcalib event)[CalibGAIN process] ** (endcalib event)生成校正文件,恢复配置 ***/ bool PZMedicalCtrl::OnProcessCalibration() { //mLog::FINFO("========OnProcessCalibration"); bool bExitThread = false; BOOL nRet = FALSE; while (!bExitThread) { DWORD dwSignal = WaitForMultipleObjects(9, m_hPZMCalibration, FALSE, INFINITE); if (dwSignal == WAIT_OBJECT_0) // 采集前配置 m_hPZMPrepare { // 修改探测器配置 // 参考品臻提供的Demo代码,每次都是先Get再Set TFPUserCfg stUserCfg; memset(&stUserCfg, 0, sizeof(stUserCfg)); //mLog::FINFO("Get [Calibration Prepare] Event, Call GetFPConf"); nRet = API_COM_GetFPConf(&stUserCfg); if (!TestError(nRet, "GetFPConf")) { return false; } stUserCfg.wPreProcessing = 0; // 前校正raw //mLog::FINFO("Call SetFPConf, Set PreProcessing to RAW"); nRet = API_COM_SetFPConf(&stUserCfg); if (!TestError(nRet, "SetFPConf")) { return false; } Sleep(5000); // 5s延迟,保证配置完成 } //暗场校正开始 由于品臻的暗场校正就调一个sdk刷暗场就可以了,不采集暗场图,故此处直接结束 else if (dwSignal == WAIT_OBJECT_0 + 1) //m_hPZMStartOffset { //mLog::FINFO("Start Offset Event"); } // 采集暗场图过程 else if (dwSignal == WAIT_OBJECT_0 + 2) //m_hPZMInOffset { //mLog::FINFO("Start Offset Event more picture"); } // 废弃:开始传10张图 else if (dwSignal == WAIT_OBJECT_0 + 3) //m_hPZMStartAED { } // AED上10张图过程 else if (dwSignal == WAIT_OBJECT_0 + 4) //m_hPZMEndAED { } // 开始采集亮场图 else if (dwSignal == WAIT_OBJECT_0 + 5) //m_hPZMStartGain { } // 是否采够亮场图数量,采集完成就停止采集,否则继续采集 else if (dwSignal == WAIT_OBJECT_0 + 6) //m_hPZMInGain { //mLog::FINFO("gain calibration gather {$} pictures", m_nGainImg); if (m_nGainImg == m_nGainExposureNum) { printf("采集亮场图 集齐 %d 张 \r\n", m_nGainExposureNum); Sleep(1000); // 厂家的建议,使探测器完成上一阶段过程 printf("m_hPZMInGain stop acquisition\n"); //mLog::FINFO("m_hPZMInGain stop acquisition"); if (!StopAcquisition(nullptr)) { return false; } printf("PZ 探测器 IDLE \r\n"); //Sleep(5000); // 厂家的建议20s,使探测器完成上一阶段过程 // 修改探测器配置 参考品臻提供的Demo代码,每次都是先Get再Set TFPUserCfg stUserCfg; memset(&stUserCfg, 0, sizeof(stUserCfg)); //mLog::FINFO("Get [Calibration StartAED] Event, Call GetFPConf"); nRet = API_COM_GetFPConf(&stUserCfg); if (!TestError(nRet, "GetFPConf")) { return false; } stUserCfg.wPreProcessing = 1; // 前校正offset //mLog::FINFO("Call SetFPConf, Set PreProcessing to OFFSET"); nRet = API_COM_SetFPConf(&stUserCfg); if (!TestError(nRet, "SetFPConf")) { return false; } //mLog::FINFO("Sleep 5s.... ensure configuration complete"); Sleep(5000); // 5s延迟,保证配置完成 //结束亮场校正 StatusFeedback(EVT_STATUS_CALIBRATIOIN, PANEL_EVENT_END_OK); } } // 正常结束校正 else if (dwSignal == WAIT_OBJECT_0 + 7) //m_hEndCalibEvent { //mLog::FINFO("Get [end calib] Event"); if (CCOS_CALIBRATION_TYPE_DARK == m_eType) { printf("DARK 校正 结束 \r\n"); //mLog::FINFO("dark calibraion end"); } else { printf("XRAY 校正 结束 \r\n"); //mLog::FINFO("xray calibraion end"); bExitThread = true; GetCalibrationTime(); StatusFeedback(EVT_STATUS_SAVECALIB, PANEL_EVENT_START); StatusFeedback(EVT_STATUS_SAVECALIB, PANEL_EVENT_END); } } // 退出校正,可能是异常退出 else if (dwSignal == WAIT_OBJECT_0 + 8) //m_hPZMEndEvent { //mLog::FINFO("Get [PZ End] Event"); if (m_bCalibrationOver) // 如果是校正结束,则更新校正文件 { if (m_nCalibrationMode)//PZ自己的校正 { if (CCOS_CALIBRATION_TYPE_DARK == m_eType) { //mLog::FINFO("Call GenOffsetTpl"); nRet = API_COM_GenOffsetTpl(); if (!TestError(nRet, "GenOffsetTpl")) { //mLog::FERROR("Save Offset Template Failed"); //return false; } } else { //mLog::FINFO("Call GenGainTpl"); nRet = API_COM_GenGainTpl(); if (!TestError(nRet, "GenGainTpl")) { //mLog::FERROR("Save Gain Template Failed"); //return false; } //mLog::FINFO("Call GenDefectTpl"); nRet = API_COM_GenDefectTpl(); if (!TestError(nRet, "GenDefectTpl")) { //mLog::FERROR("Save Defect Template Failed"); //return false; } } } } // 修改探测器配置 // 参考品臻提供的Demo代码,每次都是先Get再Set TFPUserCfg stUserCfg; memset(&stUserCfg, 0, sizeof(stUserCfg)); //mLog::FINFO("Call GetFPConf"); nRet = API_COM_GetFPConf(&stUserCfg); if (!TestError(nRet, "GetFPConf")) { //return false; } stUserCfg.wPreProcessing = 1; // 前校正offset //mLog::FINFO("Call SetFPConf, Set PreProcessing to OFFSET"); nRet = API_COM_SetFPConf(&stUserCfg); if (!TestError(nRet, "SetFPConf")) { //return false; } Sleep(5000); // 5s延迟,保证配置完成 bExitThread = true; } } return true; } void PZMedicalCtrl::SetPZDPCState(PZDPC_State ePZDPCstate) { string strlog = "Unknown"; switch (ePZDPCstate) { case PZDPC_STATE_INIT: strlog = "INIT"; break; case PZDPC_STATE_STANDBY: strlog = "STANDBY"; break; case PZDPC_STATE_WORK: strlog = "WORK"; break; case PZDPC_STATE_CALIBRATION: strlog = "CALIBRATION"; break; case PZDPC_STATE_EXIT: strlog = "EXIT"; break; case PZDPC_STATE_MAX: break; default: break; } //mLog::FINFO("Set PZ DPC state {$}", strlog.c_str()); m_ePZDPCstate = ePZDPCstate; } PZDPC_State PZMedicalCtrl::GetPZDPCState() { string strlog = "Unknown"; switch (m_ePZDPCstate) { case PZDPC_STATE_INIT: strlog = "INIT"; break; case PZDPC_STATE_STANDBY: strlog = "STANDBY"; break; case PZDPC_STATE_WORK: strlog = "WORK"; break; case PZDPC_STATE_CALIBRATION: strlog = "CALIBRATION"; break; case PZDPC_STATE_EXIT: strlog = "EXIT"; break; case PZDPC_STATE_MAX: break; default: break; } //mLog::FINFO("Get state, {$}", strlog.c_str()); return m_ePZDPCstate; } /*** * 执行失败,记录错误号,返回false;执行成功,返回true * SDK接口(BOOL返回值)成功则返回TRUE, 失败返回FALSE ***/ bool PZMedicalCtrl::TestError(BOOL nRet, const char* szFuncName) { if (nRet) { //mLog::FINFO("{$} returned OK", szFuncName); return true; } else { //mLog::FERROR("{$} returned failed, Error Code: {$}", szFuncName, API_COM_GetErrNo()); return false; } } bool PZMedicalCtrl::WaitRespond(int nTimeOut, const char* szPosition) { //mLog::FINFO("--- {$} WaitRespond, {$}ms ---", szPosition, nTimeOut); DWORD dwRet = WaitForSingleObject(m_hRespond, nTimeOut); if (dwRet == WAIT_TIMEOUT) { //mLog::FERROR("Timeout in wait respond"); return false; } return true; } void PZMedicalCtrl::StopWaiting(const char* szPosition) { //mLog::FINFO("--- Stop waiting respond, {$} ---", szPosition); SetEvent(m_hRespond); } BOOL __stdcall PZMedicalCtrl::FuncLinkUpCallBack(char cEvent) { //mLog::FINFO("[EVENT_LINKUP] EventNum({$}): Detector connected.", (int)cEvent); return g_pDetector->OnProcessLink(cEvent); } BOOL __stdcall PZMedicalCtrl::FuncLinkDownCallBack(char cEvent) { //mLog::FINFO("[EVENT_LINKDOWN] EventNum({$}): Detector disconnected!", (int)cEvent); return g_pDetector->OnProcessBreak(cEvent); } BOOL __stdcall PZMedicalCtrl::FuncImageCallBack(char cEvent) { //mLog::FINFO("[EVENT_IMAGEVALID]"); printf("[EVENT_IMAGEVALID] \n"); return g_pDetector->OnProcessImage(cEvent); } BOOL __stdcall PZMedicalCtrl::FuncHeartBeatCallBack(char cEvent) { // //mLog::FINFO("[EVENT_HEARTBEAT] EventNum(%d): Detector activate", (int)cEvent); return g_pDetector->OnProcessHeartBeat(cEvent); } BOOL __stdcall PZMedicalCtrl::FuncReadyCallBack(char cEvent) { printf("[EVENT_READY] EventNum(%d)\n", cEvent); //mLog::FINFO("[EVENT_READY] EventNum({$})", (int)cEvent); g_pDetector->StatusFeedback(EVT_STATUS_PANEL, PANEL_START_ACQ); g_pDetector->StatusFeedback(EVT_STATUS_PANEL, PANEL_XWINDOW_ON); return TRUE; } BOOL __stdcall PZMedicalCtrl::FuncExposeCallBack(char cEvent) { //此事件只有在A843B探测器工作在AED模式的时候才会回调 printf("PZ FPD Detect Xray comed .....\n"); //mLog::FINFO("[EVENT_EXPOSE] EventNum({$})", (int)cEvent); g_pDetector->StatusFeedback(EVT_STATUS_PANEL, PANEL_XRAY_ON); return TRUE; } BOOL __stdcall PZMedicalCtrl::FuncExposeEndCallBack(char cEvent) { //此事件只有在A843B探测器工作在AED模式的时候才会回调 //mLog::FINFO("[EVENT_EXPEND] EventNum({$})", (int)cEvent); printf("PZ FPD Detect Xray expose end .....\n"); g_pDetector->StatusFeedback(EVT_STATUS_PANEL, PANEL_XRAY_OFF); return TRUE; } BOOL __stdcall PZMedicalCtrl::FuncOffsetDoneCallBack(char cEvent) { //mLog::FINFO("[EVENT_OFFSETDONE] EventNum({$})", (int)cEvent); printf("offset done success.....\n"); return TRUE; } BOOL __stdcall PZMedicalCtrl::FuncAedA1CallBack(char cEvent) { //mLog::FINFO("[EVENT_AED_A1] EventNum({$})", (int)cEvent); printf("detector notify at aed a1 status.....\n"); return TRUE; } BOOL __stdcall PZMedicalCtrl::FuncAedA2CallBack(char cEvent) { //mLog::FINFO("[EVENT_AED_A2] EventNum({$})", (int)cEvent); printf("detector notify at aed a2 status.....\n"); g_pDetector->StatusFeedback(EVT_STATUS_PANEL, PANEL_READY_EXP); return TRUE; } BOOL __stdcall PZMedicalCtrl::FuncImageStartCallBack(char cEvent) { //mLog::FINFO("[EVENT_IMAGESTART] EventNum({$})", (int)cEvent); printf("start to transmit image data......\n"); return TRUE; } BOOL __stdcall PZMedicalCtrl::FuncImageEndCallBack(char cEvent) { //mLog::FINFO("[EVENT_IMAGEEND] EventNum({$})", (int)cEvent); printf("end to transmit image data.....\n"); return TRUE; } BOOL __stdcall PZMedicalCtrl::FuncBattLow1CallBack(char cEvent) { //mLog::FINFO("[EVENT_BATTLOW1] EventNum({$})", (int)cEvent); printf("detector battery low1 event.....\n"); return TRUE; } BOOL __stdcall PZMedicalCtrl::FuncBattLow2CallBack(char cEvent) { //mLog::FINFO("[EVENT_BATTLOW2] EventNum({$})", (int)cEvent); printf("detector battery low2 event.....\n"); return TRUE; } /*** ** 处理SDK LINK回调 ***/ BOOL PZMedicalCtrl::OnProcessLink(char cEvent) { //初始化之前缺省状态是max,收到link之后置为init,超时没收到也会置为init //这个判断是为了只stopwaiting一次 if (PZDPC_STATE_MAX == GetPZDPCState()) { StopWaiting("LINK"); } if (m_pStPanelStatus[m_nCurrentPanelID]->bConnErrorInInit) { //连接探测器时断线,重连后继续执行初始化探测器流程 SetEvent(m_hReInitEvent); } else { printf("Detector Link CallBack Connect Success..\n"); //mLog::FINFO("Detector Link CallBack Connect Success.."); m_pStPanelStatus[m_nCurrentPanelID]->bConnectStatus = true; if (m_bConnectWaiting) { StopWaiting("Open"); } ErrorFeedback(EVT_ERR_COMMUNICATE, "false", m_nCurrentPanelID);//OnProcessLink GetConnectionMode(); } return TRUE; } /*** ** 处理SDK BREAK回调 ***/ BOOL PZMedicalCtrl::OnProcessBreak(char cEvent) { StopWaiting("BREAK"); //暂时只处理退出流程,双板切换流程再完善 m_pStPanelStatus[m_nCurrentPanelID]->bConnectStatus = false; ErrorFeedback(EVT_ERR_COMMUNICATE, "true", m_nCurrentPanelID); return TRUE; } /*** ** 处理SDK IMAGE回调 ***/ BOOL PZMedicalCtrl::OnProcessImage(char cEvent) { SetEvent(m_hProcessImgEvent); return TRUE; } void PZMedicalCtrl::NotifyDetectorInfo() { BOOL nRet; TFPStat objFPStat; // 温度、电量、信号 ////mLog::FINFO("Call GetFPStatus"); nRet = API_COM_GetFPStatus(&objFPStat); if (!TestError(nRet, "GetFPStatus")) { //mLog::FERROR("Get Detector Status Failed"); return; } if (!m_bWired) { // WIFI信号状态 int nSignal_level = (int)objFPStat.tWifiStatus.ucSignal_level; int nWifiValue = 0; //SDK之反馈1~5,自己转换一下 //mLog::FINFO("Wifi signal:{$}", nSignal_level); switch (nSignal_level)// station0-4;ap0-5 { case 5: nWifiValue = 100; break; case 4: nWifiValue = 100; break; case 3: nWifiValue = 80; break; case 2: nWifiValue = 50; break; case 1: nWifiValue = 20; break; case 0: nWifiValue = 0; break; default: break; } if (nWifiValue < 0) //如果发生异常,获取到的wifi值应该是负的 { nWifiValue = 0; } StatusFeedback(EVT_STATUS_WIFI, nWifiValue, "", m_nCurrentPanelID); } // 温度湿度状态 //mLog::FINFO("Temperature:{$}, Humidity:{$}%", (float(objFPStat.tFpTempHum.Temp)) / 10, (float(objFPStat.tFpTempHum.Hum)) / 10); float fTemperature = (float(objFPStat.tFpTempHum.Temp)) / 10; StatusFeedback(EVT_STATUS_TEMPERATURE, 0, "", m_nCurrentPanelID, fTemperature); // 电池电量状态 float fBatRemain = (float)(objFPStat.tBatInfo1.Remain + objFPStat.tBatInfo2.Remain) / (objFPStat.tBatInfo1.full + objFPStat.tBatInfo2.full); //mLog::FINFO("Battery remain:{$}", fBatRemain); int nBattery = (int)(fBatRemain * 100); if (nBattery < 0) { nBattery = 100; //没有电池按满电反馈 } StatusFeedback(EVT_STATUS_BATTERY_VALUE, nBattery, "", m_nCurrentPanelID); } /*** ** 处理SDK 心跳回调 ***/ BOOL PZMedicalCtrl::OnProcessHeartBeat(char cEvent) { // 500ms一次回调 CHAR cFpCurStat = STATUS_NULL; cFpCurStat = API_COM_GetFPCurStatus(); ////mLog::FINFO("Detector current status:{$}", (int)cFpCurStat); if (cFpCurStat != m_cFpCurStat) { printf("now PZ FPD Status is %d, LAST IS %d \n", cFpCurStat, m_cFpCurStat); //mLog::FINFO("[HeartBeat] now PZ FPD Status is {$}, LAST IS {$}", (int)cFpCurStat, (int)m_cFpCurStat); switch (cFpCurStat) { case STATUS_NULL: //mLog::FINFO("Detector current status: STATUS_NULL"); break; case STATUS_IDLE: //mLog::FINFO("Detector current status: STATUS_IDLE"); if (m_eCalState == PZ_CALIBRATION_INIT) //校正准备阶段 { SetEvent(m_hPZMPrepare); } break; case STATUS_HST: //mLog::FINFO("Detector current status: STATUS_HST"); if (m_ePZDPCstate == PZDPC_STATE_WORK) // 曝光使能进hst模式 { StopWaiting("HST"); StatusFeedback(EVT_STATUS_PANEL, PANEL_READY_EXP); } else if (m_eCalState == PZ_CALIBRATION_GAIN) { StopWaiting("HST"); StatusFeedback(EVT_STATUS_PANEL, PANEL_READY_EXP); } break; case STATUS_AED1: //mLog::FINFO("Detector current status: STATUS_AED1"); break; case STATUS_AED2: //mLog::FINFO("Detector current status: STATUS_AED2"); if (m_ePZDPCstate == PZDPC_STATE_WORK) // 曝光使能进aed模式 { StopWaiting("AED2"); StatusFeedback(EVT_STATUS_PANEL, PANEL_READY_EXP); } else if (m_eCalState == PZ_CALIBRATION_GAIN) // aed采集亮场图 { StopWaiting("AED2"); StatusFeedback(EVT_STATUS_PANEL, PANEL_READY_EXP); } else { //mLog::FERROR("Not in work mode or gain calibration process, not send ready to HW"); } break; case STATUS_RECOVER: //探测器在这个状态下刷新offset,结束后自动进入IDLE状态 //mLog::FINFO("Detector current status: STATUS_RECOVER"); break; default: //mLog::FINFO("Detector current status:{$}", (int)cFpCurStat); break; } } m_cFpCurStat = cFpCurStat; //这块以后可做成可配置的 if (m_nHeartCount % 8 == 0)//500ms一次回调 { NotifyDetectorInfo(); } m_nHeartCount++; return TRUE; } /// /// 配置反馈通知 @SDK /// /// /// /// /// /// /// /// void PZMedicalCtrl::ConfFeedback(int nEventID, int nDetectorID, const char* pszMsg, int nParam1, float fParam2, int nPtrParamLen, void* pParam) { if (-1 == nDetectorID) { nDetectorID = m_nCurrentPanelID; } ((FPDDevicePZMedical*)(*m_pPanelID2DPC)[nDetectorID])->OnFPDCallback(nDetectorID, nEventID, EVT_LEVEL_CONFIGURATION, pszMsg, nParam1, fParam2, nPtrParamLen, pParam); } /// /// Info消息反馈通知 @SDK /// /// /// /// /// /// /// /// void PZMedicalCtrl::InfoFeedback(int nEventID, int nDetectorID, int nParam1, float fParam2, const char* pszMsg, int nPtrParamLen, void* pParam) { if (-1 == nDetectorID) { nDetectorID = m_nCurrentPanelID; } ((FPDDevicePZMedical*)(*m_pPanelID2DPC)[nDetectorID])->OnFPDCallback(nDetectorID, nEventID, EVT_LEVEL_INFORMATOION, pszMsg, nParam1, fParam2, nPtrParamLen, pParam); } /// /// 设备状态改变通知 @SDK /// /// 事件ID 属于部件或者子系统 /// 事件状态值,不同事件有不同的取值说明 /// 事件附带文本消息 /// 探测器ID,单板系统 默认值 -1 /// 浮点参数2 /// 附加参数内存长度 /// 附加参数内存地址 void PZMedicalCtrl::StatusFeedback(int nEventID, int nParam1, const char* pszMsg, int nDetectorID, float fParam2, int nPtrParamLen, void* pParam) { if (-1 == nDetectorID) { nDetectorID = m_nCurrentPanelID; } ((FPDDevicePZMedical*)(*m_pPanelID2DPC)[nDetectorID])->OnFPDCallback(nDetectorID, nEventID, EVT_LEVEL_STATUS, pszMsg, nParam1, fParam2, nPtrParamLen, pParam); } /// /// 数据反馈通知 @SDK /// /// 采集数据事件ID /// 图像内存地址 /// 参数1,默认值0 /// 参数2,浮点,默认值0.0 /// 附带文本消息 /// 图像内存长度,默认值0,固定大小 /// 探测器ID,单板模式 默认值-1 void PZMedicalCtrl::DataFeedback(int nEventID, void* pParam, int nParam1, float fParam2, const char* pszMsg, int nPtrParamLen, int nDetectorID) { if (-1 == nDetectorID) { nDetectorID = m_nCurrentPanelID; } ((FPDDevicePZMedical*)(*m_pPanelID2DPC)[nDetectorID])->OnFPDCallback(nDetectorID, nEventID, EVT_LEVEL_DATA, pszMsg, nParam1, fParam2, nPtrParamLen, pParam); } /// /// 告警事件反馈通知 @SDK /// /// /// /// /// /// /// /// void PZMedicalCtrl::WarnFeedback(int nEventID, const char* pszMsg, int nParam1, float fParam2, int nPtrParamLen, void* pParam, int nDetectorID) { if (-1 == nDetectorID) { nDetectorID = m_nCurrentPanelID; } ((FPDDevicePZMedical*)(*m_pPanelID2DPC)[nDetectorID])->OnFPDCallback(nDetectorID, nEventID, EVT_LEVEL_WARNING, pszMsg, nParam1, fParam2, nPtrParamLen, pParam); } /// /// 内部错误通知 @SDK /// /// 事件ID /// 事件消息文本内容 /// 探测器ID,单板模式默认值-1 /// 参数1,整型,默认值0 /// 参数2,浮点数,默认值0.0 /// 附加参数内存长度 /// 附加参数内存地址 void PZMedicalCtrl::ErrorFeedback(int nEventID, const char* pszMsg, int nDetectorID, int nParam1, float fParam2, int nPtrParamLen, void* pParam) { if (-1 == nDetectorID) { nDetectorID = m_nCurrentPanelID; } ((FPDDevicePZMedical*)(*m_pPanelID2DPC)[nDetectorID])->OnFPDCallback(nDetectorID, nEventID, EVT_LEVEL_ERROR, pszMsg, nParam1, fParam2, nPtrParamLen, pParam); } /*** * 设置校正点数 ***/ bool PZMedicalCtrl::SetReferenceNum(int nReferenceNum) { m_nCalibrationRounds = nReferenceNum; //mLog::FINFO("========SetReferenceNum: {$}", m_nCalibrationRounds); return true; } /*** ** 说明:设置当前的曝光模式 ** 参数:nLogicMode,从配置文件读取,与SDK配置application mode对应 ***/ bool PZMedicalCtrl::SetAcqMode(int nLogicMode, FPDDevicePZMedical* pDrvDPC) { //mLog::FINFO("========SetAcqMode nLogicMode:{$}", nLogicMode); if ((*m_pDPC2PanelID)[pDrvDPC] != m_nCurrentPanelID) { //mLog::FINFO("not current DPC, panel id {$} != {$} return... ", (*m_pDPC2PanelID)[pDrvDPC], m_nCurrentPanelID); return false; } if (!m_pStPanelStatus[m_nCurrentPanelID]->bConnectStatus) { //mLog::FINFO("Current detector is not connect, return"); return false; } m_ModeConfig = m_pStPanelStatus[m_nCurrentPanelID]->objPanelConfig; try { int nModeCount = (int)m_ModeConfig["ModeTable"].size(); for (int i = 0; i < nModeCount; i++) { if (nLogicMode == (int)m_ModeConfig["ModeTable"][i]["LogicMode"]) { //由于3025ZF出图的宽高不定,所以宽高不从配置文件读取,上图之前调用接口查询宽高然后再推图 //m_nRawImgHeight = (int)m_ModeConfig["ModeTable"][i]["RawImgHeight"]; //m_nRawImgWidth = (int)m_ModeConfig["ModeTable"][i]["RawImgWidth"]; //m_nImageWidth = (int)m_ModeConfig["ModeTable"][i]["ImageWidth"]; //m_nImageHeight = (int)m_ModeConfig["ModeTable"][i]["ImageHeight"]; m_nWidthOffset = (int)m_ModeConfig["ModeTable"][i]["WidthOffset"]; m_nHeightOffset = (int)m_ModeConfig["ModeTable"][i]["HeightOffset"]; m_nImgBits = (int)m_ModeConfig["ModeTable"][i]["PhySizeInfoBit"]; m_nPixelPitch = (int)m_ModeConfig["ModeTable"][i]["PixelPitch"]; m_nSaveRaw = (int)m_ModeConfig["ModeTable"][i]["IsSaveRaw"]; int m_nSyncType = (int)m_ModeConfig["ModeTable"][i]["SyncType"]; m_pStPanelStatus[m_nCurrentPanelID]->eSyncMode = (SYNC_MODE)m_nSyncType; //mLog::FINFO("Offset({$} {$}), Bits({$}), PixelPitch({$}), SaveRaw({$})", m_nWidthOffset, m_nHeightOffset, m_nImgBits, m_nPixelPitch, m_nSaveRaw); m_nCurrentLogicMode = nLogicMode; break; } } } catch (ResDataObjectExption& exp) { //mLog::FERROR("Get config failed: {$}", exp.what()); return false; } return true; } /*** * 接受曝光图像 ***/ bool PZMedicalCtrl::AcceptCalibration() { //mLog::FINFO("========AcceptCalibration"); if (m_nCalibrationMode)//PZ自己的校正模式 { //不做处理 } else //ZSKK校正 { if (m_nWidthOffset != 0 || m_nHeightOffset != 0) { if (m_nCalibCurrentExposureIndex == 1) { m_pZSKKCalib->AddImageToPixMap(m_pImgBuffer); m_pZSKKCalib->AverageZSKKGainMap(m_pImgBuffer, m_nCalibCurrentCalibrationRound - 1, true); } else { m_pZSKKCalib->AverageZSKKGainMap(m_pImgBuffer, m_nCalibCurrentCalibrationRound - 1, false); //曝光第几轮 } } else { if (m_nCalibCurrentExposureIndex == 1) { m_pZSKKCalib->AddImageToPixMap(m_pRawImgBuffer); m_pZSKKCalib->AverageZSKKGainMap(m_pRawImgBuffer, m_nCalibCurrentCalibrationRound - 1, true); } else { m_pZSKKCalib->AverageZSKKGainMap(m_pRawImgBuffer, m_nCalibCurrentCalibrationRound - 1, false); //曝光第几轮 } } } //mLog::FINFO("Accept calibration exposure over"); return true; } /*** * 拒绝曝光图像 ***/ bool PZMedicalCtrl::RejectCalibration() { //mLog::FINFO("========RejectCalibration"); //不做处理 return true; } bool PZMedicalCtrl::SaveCalibrationFile() { //mLog::FINFO("========SaveCalibrationFile"); if (m_nCalibrationMode)//PZ自己的校正模式 { //不做处理 } else { //mLog::FINFO("Save ZSKK Calibration File"); m_pZSKKCalib->StoreZSKKGainMap(m_strPanelType); m_pZSKKCalib->StoreZSKKPixMap(m_strPanelType); } //更新配置文件中校正日期和时间 SYSTEMTIME stCurrentTime = { 0 }; GetLocalTime(&stCurrentTime); //mLog::FINFO("Current time: {$04d}/{$02d}/{$02d} {$02d}:{$02d}:{$02d}:{$03d}", stCurrentTime.wYear, stCurrentTime.wMonth, stCurrentTime.wDay, stCurrentTime.wHour, stCurrentTime.wMinute, stCurrentTime.wSecond, stCurrentTime.wMilliseconds); //mLog::FINFO("Save Calibration File over"); return true; } bool PZMedicalCtrl::GetCalibrationStep(int nCalibCurrentCalibrationRound, int nCalibrationRounds, int nCalibCurrentExposureIndex, int nExposureNumCurrentRound) { //mLog::FINFO("========GetCalibrationStep"); m_nCalibCurrentCalibrationRound = nCalibCurrentCalibrationRound; m_nCalibrationRounds = nCalibrationRounds; m_nCalibCurrentExposureIndex = nCalibCurrentExposureIndex; m_nExposureNumCurrentRound = nExposureNumCurrentRound; //mLog::FINFO("Calibration Step===Round: {$}/{$}, ExposureNum: {$}/{$}", nCalibCurrentCalibrationRound, nCalibrationRounds, nCalibCurrentExposureIndex, nExposureNumCurrentRound); return true; } /*** ** 说明:结束校正 ** DPC处理完校正报告后调用,此处上传map、报告等文件 ***/ bool PZMedicalCtrl::CompleteCalibration(FPDDevicePZMedical* pDrvDPC) { //mLog::FINFO("========CompleteCalibration calib type:{$}", (int)m_eType); if (m_eType == CCOS_CALIBRATION_TYPE_DARK) { printf("DARK 校正 结束 \r\n"); //mLog::FINFO("DARK Calib over"); m_bCalibrationOver = true; } else if (m_eType == CCOS_CALIBRATION_TYPE_XRAY) { m_bCalibrationOver = true; m_eCalState = PZ_CALIBRATION; SetEvent(m_hEndCalibEvent);//亮场校正结束 } return true; } /*** ** 说明:获取校正时间 ** 连接成功后,校正完成后 获取 ***/ bool PZMedicalCtrl::GetCalibrationTime(int nDetectorID) { if (nDetectorID == -1) { nDetectorID = m_nCurrentPanelID; } else { InfoFeedback(EVT_INFO_CALIBRATIOIN_TIME, nDetectorID, 0, 0, "0"); InfoFeedback(EVT_INFO_CALIBRATIOIN_TIMEL, nDetectorID, 0, 0, "0"); } return true; } /*** ** 说明:终止校正 ***/ RET_STATUS PZMedicalCtrl::AbortCalibration(FPDDevicePZMedical* pDrvDPC) { printf("========AbortCalibration\n"); //mLog::FINFO("======== AbortCalibration"); m_eType = CCOS_CALIBRATION_TYPE_NONE; //恢复初值 m_bConfirmCaliRst = false; //终止校正,恢复初值 m_bAutoContinueCal = false; //终止校正,恢复初值 RET_STATUS Ret = RET_STATUS::RET_FAILED; if (m_nCalibrationMode) //PZ自己的校正模式 { } else { //mLog::FINFO("Abort ZSKK calibration"); m_pZSKKCalib->LoadZSKKGainMap(true, m_strPanelType); //重新加载增益校正文件 m_pZSKKCalib->AbortZSKKPixMap(m_strPanelType); //放弃坏点校正并重新加载原来的坏点校正文件 } //mLog::FINFO("AbortCalibration over"); return RET_STATUS::RET_SUCCEED; } /*** ** 说明:处理dark校正完成流程 ***/ void PZMedicalCtrl::OnProcessDarkEnd() { //mLog::FINFO("========OnProcessDarkEnd"); StatusFeedback(EVT_STATUS_CALIBRATIOIN, PANEL_EVENT_END_OK); } CCOS_CALIBRATION_TYPE PZMedicalCtrl::GetPZMedicalCtrlCalibType() { //mLog::FINFO("========GetPZMedicalCtrlCalibType {$}", (int)m_eType); return m_eType; } //慎重调用,可能会导致板出问题,硬reset需要很长时间 bool PZMedicalCtrl::ResetDetector(FPDDevicePZMedical* pDrvDPC) { //mLog::FINFO("========ResetDetector"); bool nRet = true; /*nRet = API_COM_ResetFP(); if (!TestError(nRet, "ResetFP")) { printf("Reset Detector fail!\n"); //mLog::FERROR("Reset Detector fail!"); return false; }*/ return nRet; }