Detector_TeledyneDalsa.cpp 46 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710
  1. #include "stdafx.h"
  2. #include "Detector_TeledyneDalsa.h"
  3. #include "CCOS.Dev.FPD.TeledyneDalsa.h"
  4. extern Log4CPP::Logger* gLogger;
  5. Detector_TeledyneDalsa* g_pTeledyneDalsaInstance = nullptr;
  6. constexpr auto FRAME_NUMBER = 10;
  7. constexpr auto RAD_HEADER_SIZE = 65536; //SDK Rad模式图像头
  8. inline int GetReturnCode(int nCode) { return nCode / 100000; }
  9. Detector_TeledyneDalsa* g_pDetector = nullptr;
  10. #define LOAD_PROC_ADDRESS(handle,func) \
  11. if ((func = (CB_##func)GetProcAddress(handle, #func)) == NULL) { printf("Error occurs while loading entry point!!! \n'%s'\n", #func); }\
  12. void CALLBACK G_Teledyne_OnEvent(int nIndex, void* context)
  13. {
  14. g_pTeledyneDalsaInstance->CallbackProcess(nIndex, context);
  15. }
  16. void CALLBACK Dark_Teledyne_OnEvent(int nIndex, void* context)
  17. {
  18. g_pTeledyneDalsaInstance->DarkCallbackProcess(nIndex, context);
  19. }
  20. void CALLBACK Gain_Teledyne_OnEvent(int nIndex, void* context)
  21. {
  22. g_pTeledyneDalsaInstance->GainCallbackProcess(nIndex, context);
  23. }
  24. Detector_TeledyneDalsa::Detector_TeledyneDalsa()
  25. {
  26. g_pTeledyneDalsaInstance = this;
  27. m_pDPC2PanelID = new map<void*, int>();
  28. m_pPanelID2DPC = new map<int, void*>();
  29. m_nPanelCount = 0;
  30. m_hTeledyneDalsaModule = nullptr;
  31. m_nCurrentPanelID = 0;
  32. m_nLastLogicMode = -1;
  33. m_nCurrentLogicMode = -1;
  34. m_pImageBuffer = nullptr;
  35. m_pRawImgBuffer = nullptr;
  36. m_pFullImgBuffer = nullptr;
  37. m_bSaveRaw = false;
  38. m_strWorkPath = "";
  39. m_eCaliType = CCOS_CALIBRATION_TYPE_NONE;
  40. m_eStatus = eDetStatus::DetStatus_NotIni;
  41. m_nImageHeight = 0;
  42. m_nImageWidth = 0;
  43. m_nCropLeft = 0;
  44. m_nCropRight = 0;
  45. m_nCropTop = 0;
  46. m_nCropBottom = 0;
  47. m_nRawImgHeight = 0;
  48. m_nRawImgWidth = 0;
  49. m_nImgIndex = 0;
  50. m_nAcqReadyTimeout = 20;
  51. m_nGainReadyTimeout = 20;
  52. m_nOftRefreshTimer = 20;
  53. m_bIsRadMode = false;
  54. m_bSendImgToUpper = true;
  55. m_nDropImgNum = 0;
  56. m_nDropImgCount = 0;
  57. m_nExamMode = APP_STATUS_MAX;
  58. m_bAbortRefreshOft = false;
  59. m_hFPDScanThread = nullptr;
  60. m_hRefreshOftThread = nullptr;
  61. //m_bFramePrep = false;
  62. m_fFrameRate = 1; //缺省值,1帧每秒
  63. m_nDelayTime = 0;
  64. m_bStartGrab = false;
  65. //m_nXrayOnNum = 0;
  66. m_nValidImgNum = 0;
  67. m_nExposureCount = -1;
  68. m_nExiThreshold = 200;//新增配置
  69. m_bFirstImage = true;
  70. InitializeCriticalSection(&m_cs);
  71. m_hStopScanEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  72. m_hAcqEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  73. m_hGainEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  74. m_hDarkEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  75. m_hProcessImgEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  76. m_hArrayEvent[0] = m_hStopScanEvent;
  77. m_hArrayEvent[1] = m_hAcqEvent;
  78. m_hArrayEvent[2] = m_hGainEvent;
  79. m_hArrayEvent[3] = m_hDarkEvent;
  80. m_hArrayEvent[4] = m_hProcessImgEvent;
  81. m_hAcqReadyEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  82. m_hGainReadyEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  83. m_hOftEndEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  84. m_hImageEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  85. }
  86. Detector_TeledyneDalsa::~Detector_TeledyneDalsa()
  87. {
  88. if (m_hStopScanEvent)
  89. {
  90. CloseHandle(m_hStopScanEvent);
  91. m_hStopScanEvent = nullptr;
  92. }
  93. if (m_hAcqEvent)
  94. {
  95. CloseHandle(m_hAcqEvent);
  96. m_hAcqEvent = nullptr;
  97. }
  98. if (m_hAcqReadyEvent)
  99. {
  100. CloseHandle(m_hAcqReadyEvent);
  101. m_hAcqReadyEvent = nullptr;
  102. }
  103. if (m_hGainEvent)
  104. {
  105. CloseHandle(m_hGainEvent);
  106. m_hGainEvent = nullptr;
  107. }
  108. if (m_hGainReadyEvent)
  109. {
  110. CloseHandle(m_hGainReadyEvent);
  111. m_hGainReadyEvent = nullptr;
  112. }
  113. if (m_hDarkEvent)
  114. {
  115. CloseHandle(m_hDarkEvent);
  116. m_hDarkEvent = nullptr;
  117. }
  118. if (m_hProcessImgEvent)
  119. {
  120. CloseHandle(m_hProcessImgEvent);
  121. m_hProcessImgEvent = nullptr;
  122. }
  123. if (m_hOftEndEvent)
  124. {
  125. CloseHandle(m_hOftEndEvent);
  126. m_hOftEndEvent = nullptr;
  127. }
  128. if (m_hImageEvent)
  129. {
  130. CloseHandle(m_hImageEvent);
  131. m_hImageEvent = nullptr;
  132. }
  133. if (m_pImageBuffer)
  134. {
  135. delete[]m_pImageBuffer;
  136. m_pImageBuffer = nullptr;
  137. }
  138. if (m_pRawImgBuffer)
  139. {
  140. delete[]m_pRawImgBuffer;
  141. m_pRawImgBuffer = nullptr;
  142. }
  143. if (m_pFullImgBuffer != nullptr)
  144. {
  145. delete[]m_pFullImgBuffer;
  146. m_pFullImgBuffer = nullptr;
  147. }
  148. }
  149. bool Detector_TeledyneDalsa::DriverEntry(void* pDrvDPC, ResDataObject& Configuration)
  150. {
  151. printf("--Func-- DriverEntry %p\n", pDrvDPC);
  152. Info("--Func-- DriverEntry {$}", pDrvDPC);
  153. map<void*, int>::iterator DPCsIter = m_pDPC2PanelID->find(pDrvDPC);
  154. if (DPCsIter != m_pDPC2PanelID->end())
  155. {
  156. //printf("This DPC already exist\n");
  157. Error("This DPC already exist");
  158. return false;
  159. }
  160. m_pDPC2PanelID->insert(pair<void*, int>(pDrvDPC, m_nPanelCount));
  161. m_pPanelID2DPC->insert(pair<int, void*>(m_nPanelCount, pDrvDPC));
  162. m_nPanelCount++;
  163. m_ModeConfig = Configuration; //记录配置 --目前只有一个平板,多板时应该分别存储
  164. return true;
  165. }
  166. bool Detector_TeledyneDalsa::Connect(void* pDrvDPC, const char* szWorkPath)
  167. {
  168. printf("Connect detector begin \r\n");
  169. Info("Connect detector begin \n");
  170. if ((*m_pDPC2PanelID)[pDrvDPC] != m_nCurrentPanelID)
  171. {
  172. Debug("Not current DPC, return true");
  173. //printf("Not current DPC, return true \n");
  174. return true;
  175. }
  176. m_strWorkPath = szWorkPath;
  177. try
  178. {
  179. int nModeCount = (int)m_ModeConfig["ModeTable"].GetKeyCount("DetectorMode");
  180. for (int i = 0; i < nModeCount; i++)
  181. {
  182. Info("mode count:{$}",i);
  183. int nAppModeID = (int)m_ModeConfig["ModeTable"][i]["LogicMode"];//Connect
  184. int nModeID = (int)m_ModeConfig["ModeTable"][i]["OperationMode"];
  185. int nGainID = (int)m_ModeConfig["ModeTable"][i]["GainValue"];
  186. string strFrameRate = (string)m_ModeConfig["ModeTable"][i]["Frequency"];
  187. float fFrameRate = stof(strFrameRate.c_str());
  188. int nExpTime = (int)m_ModeConfig["ModeTable"][i]["ExpTime"];
  189. int nTrigType = (int)m_ModeConfig["ModeTable"][i]["ExamType"];
  190. m_nDelayTime = (int)m_ModeConfig["ModeTable"][i]["DelayTime"];
  191. Info("config m_nDelayTime:{$}", m_nDelayTime);
  192. }
  193. m_nExiThreshold = (int)m_ModeConfig["ExiThreshold"];
  194. Info("image exi threshold:{$}", m_nExiThreshold);
  195. m_nAcqReadyTimeout = (int)m_ModeConfig["WorkReadyTimeout"];
  196. m_nGainReadyTimeout = (int)m_ModeConfig["GainReadyTimeout"];
  197. //在Ccos_DROC中进入检查界面后没有停止刷新offset的按钮故此处配置为0,表示不刷新offset
  198. m_nOftRefreshTimer = (int)m_ModeConfig["OffsetRefreshTimeout"];
  199. m_strSerialNum = (std::string)m_ModeConfig["SerialNum"];
  200. Info("Acq timeout({$}), Gain timeout({$}), OftRefresh timeout({$}), Serial Num({$})", m_nAcqReadyTimeout, m_nGainReadyTimeout, m_nOftRefreshTimer, m_strSerialNum);
  201. }
  202. catch (ResDataObjectExption &e)
  203. {
  204. Error("Get config error: {$}", e.what());
  205. return false;
  206. }
  207. if (!OpenDetector())
  208. {
  209. Error("Open detector failed, Connect failed \n");
  210. return false;
  211. }
  212. if (m_nOftRefreshTimer != 0) //0表示不刷新
  213. {
  214. RefreshAllOffset();
  215. m_bAbortRefreshOft = false;
  216. DWORD dwThreadId;
  217. if (nullptr == m_hRefreshOftThread)
  218. {
  219. m_hRefreshOftThread = CreateThread(NULL, 0, RefreshOffsetThread, this, 0, &dwThreadId);
  220. }
  221. }
  222. if (nullptr == m_hFPDScanThread)
  223. {
  224. unsigned uThreadId;
  225. _beginthreadex(NULL, 0, onFPDScanThread, this, 0, &uThreadId);
  226. m_hFPDScanThread = OpenThread(THREAD_ALL_ACCESS, TRUE, uThreadId);
  227. }
  228. Info("Connect over");
  229. printf("Connect over \n");
  230. return true;
  231. }
  232. void Detector_TeledyneDalsa::DisConnect()
  233. {
  234. printf("DisConnect with detector \n");
  235. if (eDetStatus::DetStatus_XrayCalibration == GetTeledyneDalsaDPCStatus() || eDetStatus::DetStatus_Offset == GetTeledyneDalsaDPCStatus())
  236. {
  237. Info("DisConnect Calling StopCalibration");
  238. if (!m_cGigeDevice.Stop())
  239. {
  240. Error("StopAcquisition failed, reason:({$})", m_cGigeDevice.GetLastStatus());
  241. }
  242. m_bAbortRefreshOft = true; //退出时停止offset线程
  243. }
  244. if (m_pImageBuffer)
  245. {
  246. delete[]m_pImageBuffer;
  247. m_pImageBuffer = nullptr;
  248. }
  249. if (m_pRawImgBuffer)
  250. {
  251. delete[]m_pRawImgBuffer;
  252. m_pRawImgBuffer = nullptr;
  253. }
  254. Info("Calling Disconnect");
  255. m_cGigeDevice.Disconnect();
  256. Info("Disconnect Detector Over");
  257. }
  258. void Detector_TeledyneDalsa::EnterExamMode(int nExamMode)
  259. {
  260. switch (nExamMode)
  261. {
  262. case APP_STATUS_WORK_BEGIN:
  263. Info("Enter into Exam Windows");
  264. m_nExamMode = APP_STATUS_WORK_BEGIN;
  265. break;
  266. case APP_STATUS_WORK_END:
  267. Info("Quit Exam Windows");
  268. m_nExamMode = APP_STATUS_WORK_END;
  269. break;
  270. case APP_STATUS_DETSHARE_BEGIN:
  271. Info("Enter into Detector Share Windows");
  272. m_nExamMode = APP_STATUS_DETSHARE_BEGIN;
  273. break;
  274. case APP_STATUS_DETSHAR_END:
  275. m_nExamMode = APP_STATUS_IDLE;
  276. Info("Quit Detector Share Windows");
  277. m_nExamMode = APP_STATUS_DETSHAR_END;
  278. break;
  279. case APP_STATUS_CAL_BEGIN:
  280. Info("Enter into Calibration Windows");
  281. m_nExamMode = APP_STATUS_CAL_BEGIN;
  282. break;
  283. case APP_STATUS_CAL_END:
  284. Info("Quit Calibration Windows");
  285. m_nExamMode = APP_STATUS_CAL_END;
  286. break;
  287. case APP_STATUS_WORK_IN_SENSITIVITY:
  288. Info("Enter into sensitivity test interface");
  289. m_nExamMode = APP_STATUS_WORK_IN_SENSITIVITY;
  290. break;
  291. default:
  292. break;
  293. }
  294. if (APP_STATUS_WORK_END == m_nExamMode)
  295. {
  296. if (eDetStatus::DetStatus_Acquire == GetTeledyneDalsaDPCStatus())
  297. {
  298. StopAcquisitionInside();
  299. }
  300. }
  301. }
  302. bool Detector_TeledyneDalsa::SetAcqMode(int nMode)
  303. {
  304. printf("SetAcqMode nMode:%d \n", nMode);
  305. Info("SetAcqMode nMode:{$}",nMode);
  306. if (m_nCurrentLogicMode == nMode)
  307. {
  308. Info("Same mode, return");
  309. return true;
  310. }
  311. m_nCurrentLogicMode = -1; //恢复初值
  312. if (eDetStatus::DetStatus_Acquire == GetTeledyneDalsaDPCStatus())
  313. {
  314. StopAcquisitionInside();
  315. }
  316. try
  317. {
  318. int nModeCount = (int)m_ModeConfig["ModeTable"].GetKeyCount("DetectorMode");
  319. for (int i = 0; i < nModeCount; i++)
  320. {
  321. int nAppModeID = (int)m_ModeConfig["ModeTable"][i]["LogicMode"];//SetAcqMode
  322. if (nAppModeID == nMode)
  323. {
  324. printf("find LogicMode == nMode \n");
  325. Info("find LogicMode == nMode");
  326. m_nImageWidth = (int)m_ModeConfig["ModeTable"][i]["ImageWidth"];
  327. m_nImageHeight = (int)m_ModeConfig["ModeTable"][i]["ImageHeight"];
  328. m_nCropLeft = (int)m_ModeConfig["ModeTable"][i]["DeadLineLeft"];
  329. m_nCropRight = (int)m_ModeConfig["ModeTable"][i]["DeadLineRight"];
  330. m_nCropTop = (int)m_ModeConfig["ModeTable"][i]["DeadLineTop"];
  331. m_nCropBottom = (int)m_ModeConfig["ModeTable"][i]["DeadLineBottom"];
  332. m_nRawImgHeight = (int)m_ModeConfig["ModeTable"][i]["RawImgWidth"];
  333. m_nRawImgWidth = (int)m_ModeConfig["ModeTable"][i]["RawImgHeight"];
  334. //m_nImgBits = (int)m_ModeConfig["ModeTable"][i]["PhySizeInfoBit"];
  335. m_strCurrentExamType = (std::string)m_ModeConfig["ModeTable"][i]["ExamType"];
  336. m_nDropImgCount = (int)m_ModeConfig["ModeTable"][i]["DropImgCount"];
  337. m_bSaveRaw = (int)m_ModeConfig["ModeTable"][i]["IsSaveRaw"];
  338. Info("ImgX: {$}, ImgY: {$}, Crop left: {$}, top: {$}, right: {$}, bottom: {$}",
  339. m_nImageWidth, m_nImageHeight, m_nCropLeft, m_nCropTop, m_nCropRight, m_nCropBottom);
  340. Info("RawImgX: {$}, RawImgY: {$}, ExamType: {$}, DropImgCount: {$}, SaveRaw: {$}",
  341. m_nRawImgWidth, m_nRawImgHeight, m_strCurrentExamType, m_nDropImgCount, m_bSaveRaw);
  342. if (nullptr != m_pRawImgBuffer)
  343. {
  344. delete[]m_pRawImgBuffer;
  345. m_pRawImgBuffer = nullptr;
  346. }
  347. m_pRawImgBuffer = new WORD[(size_t)m_nRawImgWidth * (size_t)m_nRawImgHeight];
  348. if (nullptr != m_pFullImgBuffer)
  349. {
  350. delete[]m_pFullImgBuffer;
  351. m_pFullImgBuffer = nullptr;
  352. }
  353. m_pFullImgBuffer = new WORD[(size_t)m_nRawImgWidth * (size_t)m_nImageHeight];
  354. m_nCurrentLogicMode = nMode;
  355. //临时写死
  356. /*if (1 == nMode)
  357. {
  358. m_bIsRadMode = true;
  359. }
  360. else
  361. {
  362. m_bIsRadMode = false;
  363. }*/
  364. break;
  365. }
  366. }
  367. }
  368. catch (ResDataObjectExption& e)
  369. {
  370. Error("Read configuration failed, Error code: {$}", e.what());
  371. return false;
  372. }
  373. //m_nXrayOnNum = 0; //选择模式,恢复初值
  374. m_nValidImgNum = 0; //选择模式,恢复初值
  375. return true;
  376. }
  377. /***
  378. ** 说明:曝光开始时调用
  379. ***/
  380. bool Detector_TeledyneDalsa::SetXrayOnNum()
  381. {
  382. Info("--Func-- SetXrayOnNum");
  383. printf("--Func-- SetXrayOnNum \n");
  384. m_bStartGrab = true; //曝光第一次,表示开始采集
  385. m_dwBeginTime = GetTickCount64();
  386. Info("SetXrayOnNum m_dwBeginTime:{$}", m_dwBeginTime);
  387. return true;
  388. }
  389. /***
  390. ** 说明:设置曝光总数
  391. ** TOMO模式根据这个值自动停止采集
  392. ** 参数:nTimes,曝光总数,如果小于0,则不用这个逻辑来停止采集
  393. ***/
  394. bool Detector_TeledyneDalsa::SetExposureTimes(int nTimes)
  395. {
  396. Info("--Func-- SetExposureTimes({$})", nTimes);
  397. //printf("--Func-- SetExposureTimes(%d) \n", nTimes);
  398. m_nExposureCount = nTimes;
  399. return true;
  400. }
  401. bool Detector_TeledyneDalsa::PrepareAcquisition(void* pDrvDPC)
  402. {
  403. printf("PrepareAcquisition \n");
  404. Info("PrepareAcquisition ");
  405. bool bRet = false;
  406. if ((*m_pDPC2PanelID)[pDrvDPC] != m_nCurrentPanelID)
  407. {
  408. //printf("Not current DPC, return\n");
  409. Error("Not current DPC, return");
  410. return bRet;
  411. }
  412. Info("PrepareAcquisition m_nLastLogicMode:{$},m_nCurrentLogicMode:{$}", m_nLastLogicMode, m_nCurrentLogicMode);
  413. //模式发生变化,重新加载校正文件
  414. if (m_nLastLogicMode != m_nCurrentLogicMode)
  415. {
  416. LoadCalibrationFiles();
  417. }
  418. //模式发生变化,或还没激活采集,则激活一次
  419. if (m_nLastLogicMode != m_nCurrentLogicMode || GetTeledyneDalsaDPCStatus() != eDetStatus::DetStatus_Acquire)
  420. {
  421. if (m_strCurrentExamType == "RAD")//PrepareAcquisition
  422. {
  423. SetEvent(m_hAcqEvent);
  424. DWORD dwRet = WaitForSingleObject(m_hAcqReadyEvent, m_nAcqReadyTimeout * 1000);
  425. if (dwRet != WAIT_OBJECT_0)
  426. {
  427. Error("Prepare acquisition failed({$}), cancle it", dwRet);
  428. }
  429. else
  430. {
  431. SetTeledyneDalsaDPCStatus(eDetStatus::DetStatus_Acquire); //静态模式激活采集,设置状态
  432. bRet = true;
  433. }
  434. }
  435. else if(m_strCurrentExamType == "PF")
  436. {
  437. if (!m_cGigeDevice.SetFeature("ReadOutMode", 3))
  438. {
  439. Info("Failed to SetFeature ReadOutMode, Reason:({$})", m_cGigeDevice.GetLastStatus());
  440. return false;
  441. }
  442. if (!m_cGigeDevice.SetFeature("TriggerMode", 1))
  443. {
  444. Info("Failed to SetFeature TriggerMode, Reason:({$})", m_cGigeDevice.GetLastStatus());
  445. return false;
  446. }
  447. if (!m_cGigeDevice.SetFeature("FullWell", 0))
  448. {
  449. Info("Failed to SetFeature Fullwell, Reason:({$})", m_cGigeDevice.GetLastStatus());
  450. return false;
  451. }
  452. Info("Calling StartAcquisition ExamType:{$}", m_strCurrentExamType);
  453. Sleep(300);
  454. if (!(m_cGigeDevice.GrabAsync(15, G_Teledyne_OnEvent, nullptr)))
  455. {
  456. Info("Failed to StartAcquisition, Reason:({$})", m_cGigeDevice.GetLastStatus());
  457. return false;
  458. }
  459. else
  460. {
  461. SetTeledyneDalsaDPCStatus(eDetStatus::DetStatus_Acquire); //动态模式激活采集,设置状态
  462. }
  463. }
  464. else if (m_strCurrentExamType == "CF")
  465. {
  466. if (!m_cGigeDevice.SetFeature("ReadOutMode", 3))
  467. {
  468. Info("Failed to SetFeature ReadOutMode, Reason:({$})", m_cGigeDevice.GetLastStatus());
  469. return false;
  470. }
  471. if (!m_cGigeDevice.SetFeature("TriggerMode", 0))
  472. {
  473. Info("Failed to SetFeature TriggerMode, Reason:({$})", m_cGigeDevice.GetLastStatus());
  474. return false;
  475. }
  476. if (!m_cGigeDevice.SetFeature("FullWell", 0))
  477. {
  478. Info("Failed to SetFeature Fullwell, Reason:({$})", m_cGigeDevice.GetLastStatus());
  479. return false;
  480. }
  481. Info("Calling StartAcquisition ExamType:{$}", m_strCurrentExamType);
  482. Sleep(300);
  483. if (!(m_cGigeDevice.GrabAsync(5, G_Teledyne_OnEvent, nullptr)))
  484. {
  485. Info("Failed to StartAcquisition, Reason:({$})", m_cGigeDevice.GetLastStatus());
  486. return false;
  487. }
  488. else
  489. {
  490. SetTeledyneDalsaDPCStatus(eDetStatus::DetStatus_Acquire); //动态模式激活采集,设置状态
  491. }
  492. }
  493. }
  494. //FramePrep执行成功,修改记录
  495. if (bRet)
  496. {
  497. m_nLastLogicMode = m_nCurrentLogicMode;
  498. }
  499. return true;
  500. }
  501. bool Detector_TeledyneDalsa::StartAcquisition(void* pDrvDPC)
  502. {
  503. printf("StartAcquisition \n");
  504. Info("StartAcquisition ");
  505. bool bRet = false;
  506. if ((*m_pDPC2PanelID)[pDrvDPC] != m_nCurrentPanelID)
  507. {
  508. //printf("Not current DPC, return\n");
  509. Error("Not current DPC, return");
  510. return bRet;
  511. }
  512. if (-1 == m_nCurrentLogicMode)
  513. {
  514. Error("Illegal exam mode");
  515. }
  516. else
  517. {
  518. m_bSendImgToUpper = true; //开始采集,恢复初值
  519. m_bValidImage = false; //开始采集,恢复初值
  520. m_nDropImgNum = 0; //开始采集,恢复初值
  521. bRet = true;
  522. m_bFirstImage = true;
  523. }
  524. //StatusFeedback(EVT_STATUS_PANEL, PANEL_XWINDOW_ON);
  525. return bRet;
  526. }
  527. bool Detector_TeledyneDalsa::StopAcquisition(void* pDrvDPC)
  528. {
  529. printf("StopAcquisition \n");
  530. Info("StopAcquisition ");
  531. bool bRet = false;
  532. if ((*m_pDPC2PanelID)[pDrvDPC] != m_nCurrentPanelID)
  533. {
  534. //printf("Not current DPC, return\n");
  535. Error("Not current DPC, return");
  536. return bRet;
  537. }
  538. if (eDetStatus::DetStatus_Acquire == GetTeledyneDalsaDPCStatus())
  539. {
  540. if (m_nExposureCount > 0 && m_bStartGrab)
  541. {
  542. //TOMO模式等图
  543. //1.窗口最大1000ms,所以每次等1000ms
  544. int nLoop = 0;
  545. int nLoopCount = m_nExposureCount - m_nValidImgNum + 2;
  546. Info("Exposure count: {$}, valid image count: {$}", m_nExposureCount, m_nValidImgNum);
  547. while (m_bStartGrab && (m_nValidImgNum < m_nExposureCount) &&
  548. (nLoop < nLoopCount))
  549. {
  550. DWORD dwRet = WaitForSingleObject(m_hImageEvent, 1000);
  551. if (WAIT_TIMEOUT == dwRet)
  552. {
  553. Info("Waited 1000ms ({$}/{$})", nLoop, nLoopCount);
  554. }
  555. nLoop++;
  556. }
  557. }
  558. //else
  559. //{
  560. // //增加序列模式等图处理
  561. // //1.窗口最大1000ms,所以每次等1000ms
  562. // int nLoop = 0;
  563. // int nLoopCount = m_nXrayOnNum - m_nValidImgNum + 2;
  564. // Info("XrayOn count: %d, valid image count: %d",
  565. // m_nXrayOnNum, m_nValidImgNum);
  566. // DWORD dwWaitTime = 1000;
  567. // while (m_bStartGrab && (m_nValidImgNum < m_nXrayOnNum) &&
  568. // (nLoop < nLoopCount))
  569. // {
  570. // DWORD dwRet = WaitForSingleObject(m_hImageEvent, dwWaitTime);
  571. // if (WAIT_TIMEOUT == dwRet)
  572. // {
  573. // Info("Waited 1000ms(%d/%d)", nLoop, nLoopCount);
  574. // }
  575. // nLoop++;
  576. // }
  577. //}
  578. Info("Calling StopAcquisition");
  579. if (!m_cGigeDevice.Stop())
  580. {
  581. Info("StopAcquisition failed, reason:({$})", m_cGigeDevice.GetLastStatus());
  582. }
  583. else
  584. {
  585. bRet = true;
  586. }
  587. m_nImgIndex = 0;
  588. m_bStartGrab = false; //停止采集,恢复初值
  589. m_nValidImgNum = 0; //停止采集,恢复初值
  590. m_nExposureCount = -1; //停止采集,恢复初值
  591. //m_nXrayOnNum = 0; //停止采集,恢复初值
  592. SetTeledyneDalsaDPCStatus(eDetStatus::DetStatus_Standby); //停止采集,设置状态
  593. }
  594. else
  595. {
  596. Info("Not in acquire status");
  597. //切换到静态采集后,进入了ready状态。但此时可以不开始采集,切换到别的模式,
  598. bRet = true;
  599. }
  600. return bRet;
  601. }
  602. bool Detector_TeledyneDalsa::StopAcquisitionInside()
  603. {
  604. printf("StopAcquisitionInside \n");
  605. Info("StopAcquisitionInside ");
  606. bool bRet = false;
  607. if (eDetStatus::DetStatus_Acquire == GetTeledyneDalsaDPCStatus())
  608. {
  609. if (m_nExposureCount > 0 && m_bStartGrab)
  610. {
  611. //TOMO模式等图
  612. //1.窗口最大1000ms,所以每次等1000ms
  613. int nLoop = 0;
  614. int nLoopCount = m_nExposureCount - m_nValidImgNum + 2;
  615. Info("Exposure count: {$}, valid image count: {$}", m_nExposureCount, m_nValidImgNum);
  616. while (m_bStartGrab && (m_nValidImgNum < m_nExposureCount) && (nLoop < nLoopCount))
  617. {
  618. DWORD dwRet = WaitForSingleObject(m_hImageEvent, 1000);
  619. if (WAIT_TIMEOUT == dwRet)
  620. {
  621. Info("Waited 1000ms ({$}/{$})", nLoop, nLoopCount);
  622. }
  623. nLoop++;
  624. }
  625. }
  626. //else
  627. //{
  628. // //增加序列模式等图处理
  629. // //1.窗口最大1000ms,所以每次等1000ms
  630. // int nLoop = 0;
  631. // int nLoopCount = m_nXrayOnNum - m_nValidImgNum + 2;
  632. // Info("XrayOn count: %d, valid image count: %d",
  633. // m_nXrayOnNum, m_nValidImgNum);
  634. // DWORD dwWaitTime = 1000;
  635. // while (m_bStartGrab && (m_nValidImgNum < m_nXrayOnNum) &&
  636. // (nLoop < nLoopCount))
  637. // {
  638. // DWORD dwRet = WaitForSingleObject(m_hImageEvent, dwWaitTime);
  639. // if (WAIT_TIMEOUT == dwRet)
  640. // {
  641. // Info("Waited 1000ms(%d/%d)", nLoop, nLoopCount);
  642. // }
  643. // nLoop++;
  644. // }
  645. //}
  646. Info("Calling StopAcquisition");
  647. if (!m_cGigeDevice.Stop())
  648. {
  649. Info("StopAcquisition failed, reason:({$})", m_cGigeDevice.GetLastStatus());
  650. }
  651. else
  652. {
  653. bRet = true;
  654. }
  655. m_bStartGrab = false; //停止采集,恢复初值
  656. m_nValidImgNum = 0; //停止采集,恢复初值
  657. m_nExposureCount = -1; //停止采集,恢复初值
  658. //m_nXrayOnNum = 0; //停止采集,恢复初值
  659. SetTeledyneDalsaDPCStatus(eDetStatus::DetStatus_Standby); //停止采集,设置状态
  660. }
  661. else
  662. {
  663. Info("Not in acquire status");
  664. //切换到静态采集后,进入了ready状态。但此时可以不开始采集,切换到别的模式,
  665. bRet = true;
  666. }
  667. return bRet;
  668. }
  669. bool Detector_TeledyneDalsa::ActiveCalibration(void* pDrvDPC, CCOS_CALIBRATION_TYPE eType)
  670. {
  671. printf("ActiveCalibration \n");
  672. Info("ActiveCalibration ");
  673. if ((*m_pDPC2PanelID)[pDrvDPC] != m_nCurrentPanelID)
  674. {
  675. //printf("Not current DPC, return\n");
  676. Error("Not current DPC, return");
  677. return false;
  678. }
  679. if (-1 == m_nCurrentLogicMode)
  680. {
  681. Error("Illegal exam mode");
  682. return false;
  683. }
  684. if (CCOS_CALIBRATION_TYPE_XRAY == eType)
  685. {
  686. SetTeledyneDalsaDPCStatus(eDetStatus::DetStatus_XrayCalibration);
  687. }
  688. m_eCaliType = eType;
  689. return true;
  690. }
  691. /***
  692. ** 校正时响应上层调用的FramePrep
  693. ***/
  694. bool Detector_TeledyneDalsa::PrepareCalibration(void* pDrvDPC)
  695. {
  696. printf("PrepareCalibration \n");
  697. Info("PrepareCalibration ");
  698. bool bRet = false;
  699. if ((*m_pDPC2PanelID)[pDrvDPC] != m_nCurrentPanelID)
  700. {
  701. //printf("Not current DPC, return\n");
  702. Error("Not current DPC, return");
  703. return bRet;
  704. }
  705. if (GetTeledyneDalsaDPCStatus() != eDetStatus::DetStatus_XrayCalibration)
  706. {
  707. Info("Current status is not XrayCalibration, return succeed");
  708. return true;
  709. }
  710. if (m_strCurrentExamType == "CF")//PrepareCalibration
  711. {
  712. //这里应该只在第一次prepare时setevent,但第一次setevent之后,线程一直被占用着,
  713. //所以每次setevent也无所谓了,线程执行完毕后resetevent
  714. SetEvent(m_hGainEvent);
  715. DWORD dwRet = WaitForSingleObject(m_hGainReadyEvent, m_nGainReadyTimeout * 1000);
  716. if (dwRet != WAIT_OBJECT_0)
  717. {
  718. Error("Prepare calibration failed({$}), cancle it", dwRet);
  719. }
  720. else
  721. {
  722. bRet = true;
  723. }
  724. }
  725. else
  726. {
  727. bRet = true;
  728. }
  729. return bRet;
  730. }
  731. bool Detector_TeledyneDalsa::StartCalibration(void* pDrvDPC)
  732. {
  733. printf("StartCalibration \n");
  734. Info("StartCalibration ");
  735. bool bRet = false;
  736. if ((*m_pDPC2PanelID)[pDrvDPC] != m_nCurrentPanelID)
  737. {
  738. //printf("Not current DPC, return\n");
  739. Error("Not current DPC, return");
  740. return bRet;
  741. }
  742. if (CCOS_CALIBRATION_TYPE_DARK == m_eCaliType)
  743. {
  744. SetEvent(m_hDarkEvent);
  745. bRet = true;
  746. }
  747. else if (CCOS_CALIBRATION_TYPE_XRAY == m_eCaliType)
  748. {
  749. bRet = StartGainCalibration();
  750. }
  751. return bRet;
  752. }
  753. bool Detector_TeledyneDalsa::StopCalibration(void* pDrvDPC)
  754. {
  755. printf("StopCalibration \n");
  756. Info("StopCalibration ");
  757. bool bRet = false;
  758. int nRet = 0;
  759. if ((*m_pDPC2PanelID)[pDrvDPC] != m_nCurrentPanelID)
  760. {
  761. //printf("Not current DPC, return\n");
  762. Error("Not current DPC, return");
  763. return bRet;
  764. }
  765. Info("StopCalibration Calling StopCalibration");
  766. if (!m_cGigeDevice.Stop())
  767. {
  768. Info("StopAcquisition failed, reason:({$})", m_cGigeDevice.GetLastStatus());
  769. }
  770. else
  771. {
  772. bRet = true;
  773. }
  774. return bRet;
  775. }
  776. bool Detector_TeledyneDalsa::OpenDetector()
  777. {
  778. Info("OpenDetector ");
  779. bool res;
  780. int nDetrNum = 0;
  781. if (!m_cGigeDevice.Connect(m_strSerialNum.c_str()))
  782. {
  783. Info("Detector Connect Failed");
  784. return false;
  785. }
  786. else
  787. {
  788. Info("Detector is Connected");
  789. m_eStatus = eDetStatus::DetStatus_Standby;
  790. }
  791. Info("Open Detector Success--->");
  792. return true;
  793. }
  794. bool Detector_TeledyneDalsa::CalculateEXI(WORD* pImgData, int nImgWidth, int nImgHeight, int nImageBit, int nThreshold)
  795. {
  796. int nROIXL = static_cast<int>(0.3 * nImgWidth);
  797. int nROIXR = static_cast<int>(0.7 * nImgWidth);
  798. int nROIYL = static_cast<int>(0.3 * nImgHeight);
  799. int nROIYR = static_cast<int>(0.7 * nImgHeight);
  800. WORD* pSrc = NULL;
  801. long nCount = 0;
  802. DWORD64 nSum = 0;
  803. int nEXI = 0;
  804. try
  805. {
  806. for (int i = nROIYL; i < nROIYR; i++)
  807. {
  808. pSrc = pImgData + (i * nImgWidth);
  809. for (int j = nROIXL; j < nROIXR; j++)
  810. {
  811. nSum += *(pSrc + j);
  812. nCount++;
  813. }
  814. }
  815. nEXI = (int)(nSum / nCount);
  816. }
  817. catch (...)
  818. {
  819. return false;
  820. }
  821. Info("Image EXI:{$}, Threshold:{$}", nEXI, nThreshold);
  822. if (nEXI >= nThreshold)
  823. {
  824. Info("Image has xray!");
  825. return true;//有x射线
  826. }
  827. return false;
  828. }
  829. bool Detector_TeledyneDalsa::CheckImageExi(WORD* pImgData, int nImgWidth, int nImgHeight, WORD dwExiThrethold)
  830. {
  831. if (dwExiThrethold <= 0)
  832. {
  833. return true;
  834. }
  835. Info("Check image exi...");
  836. bool bResult = CalculateEXI(pImgData, nImgWidth, nImgHeight, 16, dwExiThrethold);
  837. if (bResult)
  838. {
  839. return true;
  840. }
  841. Info("Check image exi---black Image");
  842. return false;
  843. }
  844. //nIndex 缺省-1,当使用缺省值时代表是静态模式,图像名不记录序号
  845. void Detector_TeledyneDalsa::OnProcessImage(int nIndex)
  846. {
  847. printf("OnProcessImage \n");
  848. Info("OnProcessImage ");
  849. CropImageMargin(m_pFullImgBuffer, m_nImageWidth, m_nImageHeight,
  850. image.pixels.data(), m_nRawImgWidth, m_nRawImgHeight, 16,
  851. m_nCropLeft, m_nCropTop, m_nCropRight, m_nCropBottom);
  852. if (!m_bValidImage && m_nDelayTime > 0)
  853. {
  854. m_dwEndTime = GetTickCount64();
  855. }
  856. /***
  857. ** 1.第一个trigIn信号触发trigOut升高,此时代表读图,所以基本需要丢掉第一帧图像
  858. ** 此处灵活应用,可配置丢图张数
  859. ** 2.由于先采集,后曝光,此处还需要根据曝光和拿图时间间隔来判断是否为曝光图像
  860. ****/
  861. Info("OnProcessImage m_nDropImgNum:{$} m_nDropImgCount:{$}", m_nDropImgNum, m_nDropImgCount);
  862. if (m_nDropImgNum < m_nDropImgCount)//配置为0时表示不丢图
  863. {
  864. m_nDropImgNum++;
  865. Info("Drop {$} image", m_nDropImgNum);
  866. }
  867. else if (!CheckTimeLimit(m_dwBeginTime, m_dwEndTime))//m_nDelayTime 配置为0时表示不延时
  868. {
  869. m_nDropImgNum++;
  870. Warn("CheckTimeLimit Drop {$} image", m_nDropImgNum);
  871. }
  872. else
  873. {
  874. if (m_bIsRadMode)//setacqmode时进行设置 默认logicmode为1时是RAD
  875. {
  876. Info("OnProcessImage rad mode");
  877. if (m_bSendImgToUpper)
  878. {
  879. CheckImageExi(m_pFullImgBuffer, m_nImageWidth, m_nImageHeight, m_nExiThreshold);//true 有射线 false 没射线
  880. Info("rad mode send image to upper!");
  881. m_nValidImgNum++;
  882. m_bSendImgToUpper = false; //单帧点片,发送一张图像后不再发送图像
  883. DataFeedback(EVT_DATA_RAW_IMAGE, m_pFullImgBuffer);
  884. //自动停止采集(发送standby,触发上层流程)
  885. StatusFeedback(EVT_STATUS_PANEL, PANEL_END_ACQ);
  886. }
  887. else
  888. {
  889. Info("Already send image");
  890. }
  891. }
  892. else
  893. {
  894. if (m_bFirstImage)
  895. {
  896. Info("m_bFirstImage is true");
  897. StatusFeedback(EVT_STATUS_PANEL, PANEL_XWINDOW_ON);
  898. m_bFirstImage = false;
  899. }
  900. Info("OnProcessImage flu mode,m_strCurrentExamType:{$},m_nCurrentLogicMode:{$}", m_strCurrentExamType, m_nCurrentLogicMode);
  901. //动态触发模式,但是SetAcqMode的参数是1
  902. if (m_strCurrentExamType != "RAD" && m_nCurrentLogicMode == 1)
  903. {
  904. Info("m_nCurrentExamType == 8, m_nCurrentLogicMode == 1");
  905. //计算图像EXI 不满足的不往上推
  906. if (!CheckImageExi(m_pFullImgBuffer, m_nImageWidth, m_nImageHeight, m_nExiThreshold)) //true 有射线 false 没射线
  907. {
  908. return;
  909. }
  910. if (m_bValidImage)
  911. {
  912. //RAD模式已经推过图了就不在推图了
  913. Info("RAD has send image! return");
  914. return;
  915. }
  916. }
  917. m_bValidImage = true; //合法图像,不再判断时间间隔
  918. if (m_nExposureCount > 0 /*&& m_nValidImgNum < m_nExposureCount*/)//3DDR tomo m_nExposureCount消息比图像晚到,影响上图。
  919. {
  920. m_nValidImgNum++;
  921. ResetEvent(m_hImageEvent);
  922. SetEvent(m_hImageEvent);
  923. Info("flu mode m_nExposureCount > 0, send image to upper!");
  924. DataFeedback(EVT_DATA_RAW_IMAGE, m_pFullImgBuffer);
  925. //TOMO模式根据上层设置的采集总数,自动停止采集(发送standby,触发上层流程)
  926. /*if (m_nValidImgNum == m_nExposureCount)
  927. {
  928. StatusFeedback(EVT_STATUS_PANEL, PANEL_END_ACQ);
  929. }*/
  930. }
  931. else if(m_nExposureCount == 0) //PF逻辑,不知道曝光次数
  932. {
  933. m_nValidImgNum++;
  934. ResetEvent(m_hImageEvent);
  935. SetEvent(m_hImageEvent);
  936. Info("flu mode m_nExposureCount == 0, send image to upper!");
  937. DataFeedback(EVT_DATA_RAW_IMAGE, m_pFullImgBuffer);
  938. }
  939. }
  940. }
  941. if (m_bSaveRaw)
  942. {
  943. Info("Begin save image");
  944. char szTemp[30] = { 0 };
  945. FILE* fp;
  946. string strFileName = m_strWorkPath + "\\Image";
  947. if (-1 == nIndex)
  948. {
  949. strFileName += "\\Image_Rad.raw";
  950. }
  951. else
  952. {
  953. sprintf_s(szTemp, "\\Image_%d.raw", nIndex);
  954. strFileName += szTemp;
  955. }
  956. if ((fp = fopen(strFileName.c_str(), "wb+")) == nullptr)
  957. {
  958. DWORD dw = GetLastError();
  959. Error("fopen {$} failed, {$}", strFileName.c_str(), dw);
  960. return;
  961. }
  962. fwrite(m_pFullImgBuffer, sizeof(WORD), (ULONGLONG)m_nImageWidth * m_nImageHeight, fp);
  963. fclose(fp);
  964. Info("Save image over");
  965. }
  966. }
  967. /***
  968. ** 说明:调用SDK接口,执行offset校正流程
  969. ** dark校正、闲时offset刷新都会调用这个函数
  970. ***/
  971. bool Detector_TeledyneDalsa::StartDarkCalibration(int nLogicMode)
  972. {
  973. Info("StartDarkCalibration ");
  974. bool bRet = false;
  975. int nRet = 0, nCurrFrmNum = 0, nPrevFrmNum = nCurrFrmNum - 1;
  976. Info("Calling StartDarkCalibration, Logic mode({$})", nLogicMode);
  977. if (!m_cGigeDevice.SetFeature("ReadOutMode", 3))
  978. {
  979. Info("Failed to SetFeature ReadOutMode, Reason:({$})", m_cGigeDevice.GetLastStatus());
  980. return false;
  981. }
  982. if (!m_cGigeDevice.SetFeature("TriggerMode", 0))
  983. {
  984. Info("Failed to SetFeature TriggerMode, Reason:({$})", m_cGigeDevice.GetLastStatus());
  985. return false;
  986. }
  987. if (!m_cGigeDevice.SetFeature("FullWell", 0))
  988. {
  989. Info("Failed to SetFeature Fullwell, Reason:({$})", m_cGigeDevice.GetLastStatus());
  990. return false;
  991. }
  992. Info("Calling StartAcquisition ExamType:{$}", m_strCurrentExamType);
  993. Sleep(300);
  994. if (!(m_cGigeDevice.GrabAsync(5, Dark_Teledyne_OnEvent, nullptr)))
  995. {
  996. Info("Failed to StartAcquisition, Reason:({$})", m_cGigeDevice.GetLastStatus());
  997. return false;
  998. }
  999. return true;
  1000. }
  1001. bool Detector_TeledyneDalsa::StartGainCalibration()
  1002. {
  1003. printf("StartGainCalibration \n");
  1004. Info("StartGainCalibration ");
  1005. if (-1 == m_nCurrentLogicMode)
  1006. {
  1007. Error("Illegal exam mode");
  1008. return false;
  1009. }
  1010. int nCurrFrmNum = 0, nPrevFrmNum = 0;
  1011. //改为先发状态,再调用SDK接口
  1012. //如果后发,SDK接口执行失败会导致不发送这个状态,进而导致停止校正流程不能正确执行
  1013. //m_pDrvDPC->SetDetectorStatus(DETECTOR_STATUS_ACQ); //设置状态,准备开始亮场 --ys
  1014. //m_pCali->SetCalibrationStatus(CCOS_CALIBRATION_STATUS_RUNNING); --ys
  1015. //静态点片模式的增益校正流程还需要考虑
  1016. Info("Calling StartGainCalibration");
  1017. if (!m_cGigeDevice.SetFeature("ReadOutMode", 3))
  1018. {
  1019. Info("Failed to SetFeature ReadOutMode, Reason:({$})", m_cGigeDevice.GetLastStatus());
  1020. return false;
  1021. }
  1022. if (!m_cGigeDevice.SetFeature("TriggerMode", 0))
  1023. {
  1024. Info("Failed to SetFeature TriggerMode, Reason:({$})", m_cGigeDevice.GetLastStatus());
  1025. return false;
  1026. }
  1027. if (!m_cGigeDevice.SetFeature("FullWell", 0))
  1028. {
  1029. Info("Failed to SetFeature Fullwell, Reason:({$})", m_cGigeDevice.GetLastStatus());
  1030. return false;
  1031. }
  1032. Info("Calling StartAcquisition ExamType:{$}", m_strCurrentExamType);
  1033. Sleep(300);
  1034. if (!(m_cGigeDevice.GrabAsync(5, Gain_Teledyne_OnEvent, nullptr)))
  1035. {
  1036. Info("Failed to StartAcquisition, Reason:({$})", m_cGigeDevice.GetLastStatus());
  1037. SetTeledyneDalsaDPCStatus(eDetStatus::DetStatus_Standby);
  1038. StatusFeedback(EVT_STATUS_CALIBRATIOIN, PANEL_EVENT_END_ERROR);
  1039. return false;
  1040. }
  1041. return true;
  1042. }
  1043. unsigned __stdcall Detector_TeledyneDalsa::onFPDScanThread(PVOID pvoid)
  1044. {
  1045. Detector_TeledyneDalsa* pOpr = (Detector_TeledyneDalsa*)pvoid;
  1046. Info("Enter scan thread");
  1047. //printf("Enter scan thread \r\n");
  1048. bool bExit = false;
  1049. DWORD dwTimeOut = INFINITE;
  1050. while (!bExit)
  1051. {
  1052. DWORD dwRet = WaitForMultipleObjects(SCAN_EVENT_COUNT, pOpr->m_hArrayEvent, FALSE, dwTimeOut);
  1053. if (WAIT_OBJECT_0 == dwRet) //m_hStopScanEvent
  1054. {
  1055. bExit = true;
  1056. }
  1057. else if (WAIT_OBJECT_0 + 1 == dwRet) //m_hAcqEvent
  1058. {
  1059. pOpr->OnAcquireImage();
  1060. }
  1061. else if (WAIT_OBJECT_0 + 2 == dwRet) //m_hGainEvent
  1062. {
  1063. pOpr->OnAcquireGainImage();
  1064. }
  1065. else if (WAIT_OBJECT_0 + 3 == dwRet) //m_hDarkEvent
  1066. {
  1067. pOpr->OnStartDarkCalibration();
  1068. }
  1069. else if (WAIT_OBJECT_0 + 4 == dwRet) //m_hProcessImgEvent
  1070. {
  1071. pOpr->OnProcessImage(pOpr->m_nImgIndex);
  1072. }
  1073. }
  1074. Info("Level scan thread");
  1075. //printf("Level scan thread \r\n");
  1076. return 0;
  1077. }
  1078. void Detector_TeledyneDalsa::OnAcquireImage()
  1079. {
  1080. }
  1081. void Detector_TeledyneDalsa::OnAcquireGainImage()
  1082. {
  1083. }
  1084. /***
  1085. ** 说明:开始暗场校正
  1086. ***/
  1087. void Detector_TeledyneDalsa::OnStartDarkCalibration()
  1088. {
  1089. printf("OnStartDarkCalibration \n");
  1090. Info("OnStartDarkCalibration ");
  1091. SetTeledyneDalsaDPCStatus(eDetStatus::DetStatus_Offset); //开始offset校正
  1092. if (StartDarkCalibration(m_nCurrentLogicMode))
  1093. {
  1094. StatusFeedback(EVT_STATUS_CALIBRATIOIN, PANEL_EVENT_END_OK);
  1095. }
  1096. else
  1097. {
  1098. StatusFeedback(EVT_STATUS_CALIBRATIOIN, PANEL_EVENT_END_ERROR);
  1099. }
  1100. SetTeledyneDalsaDPCStatus(eDetStatus::DetStatus_Standby); //offset校正完成,置回Standby
  1101. }
  1102. //获取只用于本DPC记录的探测器状态
  1103. eDetStatus Detector_TeledyneDalsa::GetTeledyneDalsaDPCStatus()
  1104. {
  1105. string strStatus = "Unknown";
  1106. switch (m_eStatus)
  1107. {
  1108. case eDetStatus::DetStatus_NotIni:
  1109. strStatus = "NotIni";
  1110. break;
  1111. case eDetStatus::DetStatus_NotConn:
  1112. strStatus = "NotConn";
  1113. break;
  1114. case eDetStatus::DetStatus_Sleep:
  1115. strStatus = "Sleep";
  1116. break;
  1117. case eDetStatus::DetStatus_Standby:
  1118. strStatus = "Standby";
  1119. break;
  1120. case eDetStatus::DetStatus_Work:
  1121. strStatus = "Work";
  1122. break;
  1123. case eDetStatus::DetStatus_Acquire:
  1124. strStatus = "Acquire";
  1125. break;
  1126. case eDetStatus::DetStatus_Offset:
  1127. strStatus = "Offset";
  1128. break;
  1129. case eDetStatus::DetStatus_XrayCalibration:
  1130. strStatus = "XrayCalibration";
  1131. break;
  1132. default:
  1133. break;
  1134. }
  1135. Info("Driver status: {$}", strStatus.c_str());
  1136. return m_eStatus;
  1137. }
  1138. //设置只用于本DPC的探测器状态
  1139. bool Detector_TeledyneDalsa::SetTeledyneDalsaDPCStatus(eDetStatus status)
  1140. {
  1141. string strStatus = "Unknown";
  1142. bool bSetStatus = true;
  1143. switch (status)
  1144. {
  1145. case eDetStatus::DetStatus_NotIni:
  1146. strStatus = "NotIni";
  1147. break;
  1148. case eDetStatus::DetStatus_NotConn:
  1149. strStatus = "NotConn";
  1150. break;
  1151. case eDetStatus::DetStatus_Sleep:
  1152. strStatus = "Sleep";
  1153. break;
  1154. case eDetStatus::DetStatus_Standby:
  1155. strStatus = "Standby";
  1156. break;
  1157. case eDetStatus::DetStatus_Work:
  1158. strStatus = "Work";
  1159. break;
  1160. case eDetStatus::DetStatus_Acquire:
  1161. strStatus = "Acquire";
  1162. break;
  1163. case eDetStatus::DetStatus_Offset:
  1164. strStatus = "Offset";
  1165. break;
  1166. case eDetStatus::DetStatus_XrayCalibration:
  1167. strStatus = "XrayCalibration";
  1168. break;
  1169. default:
  1170. bSetStatus = false;
  1171. break;
  1172. }
  1173. if (bSetStatus)
  1174. {
  1175. m_eStatus = status;
  1176. Info("Set driver status: {$}", strStatus.c_str());
  1177. }
  1178. else
  1179. {
  1180. Warn("{$} {$} is a illegal status", strStatus.c_str(), (int)status);
  1181. }
  1182. return bSetStatus;
  1183. }
  1184. bool Detector_TeledyneDalsa::LoadCalibrationFiles()
  1185. {
  1186. Info("Calling LoadReference m_nCurrentLogicMode:{$}", m_nCurrentLogicMode);
  1187. Info("LoadReference command succeed");
  1188. return true;
  1189. }
  1190. //参照RFOC动态代码整理的图像裁剪功能
  1191. int Detector_TeledyneDalsa::CropImageMargin(LPVOID pDstData, int& nDstWidth, int& nDstHeight,
  1192. LPVOID pScrData, int nSrcWidth, int nSrcHeight, int nBits,
  1193. int nLeftMargin, int nTopMargin, int nRightMargin, int nBottomMargin)
  1194. {
  1195. printf("CropImageMargin \n");
  1196. Info("CropImageMargin ");
  1197. if ((pDstData == NULL) || (pScrData == NULL) || (nSrcWidth <= 0) || (nSrcHeight <= 0) || (nBits <= 0))
  1198. return -1;
  1199. if ((nLeftMargin >= nSrcWidth) || (nTopMargin >= nSrcHeight))
  1200. return -1;
  1201. int nBitsToBYTE = (int)((nBits + 7) * 0.125);
  1202. if (nBitsToBYTE < 1)
  1203. return -1;
  1204. int nXL, nXR, nYL, nYR;
  1205. nXL = nLeftMargin;//32
  1206. nYL = nTopMargin;
  1207. if (nSrcWidth - nRightMargin < 0)
  1208. return -1;
  1209. nXR = nSrcWidth - nRightMargin - 1; //2783
  1210. if (nXR < nXL)
  1211. return -1;
  1212. if (nSrcHeight - nBottomMargin < 0)
  1213. return -1;
  1214. nYR = nSrcHeight - nBottomMargin - 1;
  1215. if (nYR < nYL)
  1216. return -1;
  1217. nDstWidth = nXR - nXL + 1;
  1218. nDstHeight = nYR - nYL + 1;
  1219. Info("TopCrop:{$};Bottom:{$},nDstWidth:{$},nDstHeight:{$},Bits:{$}", nYL, nYR, nDstWidth, nDstHeight, nBitsToBYTE);
  1220. int i = 0;
  1221. #pragma omp parallel private(i)
  1222. {
  1223. #pragma omp for
  1224. for (i = nYL; i <= nYR; i++)
  1225. {
  1226. ::memcpy((WORD*)pDstData + (i - nYL) * nDstWidth, (WORD*)pScrData + (i * nSrcWidth + nXL), nDstWidth * nBitsToBYTE);
  1227. }
  1228. }
  1229. return 0;
  1230. }
  1231. /***
  1232. ** 说明:非检查界面定时刷新offset的辅助线程
  1233. ***/
  1234. DWORD __stdcall Detector_TeledyneDalsa::RefreshOffsetThread(PVOID pvoid)
  1235. {
  1236. Detector_TeledyneDalsa* pOpr = (Detector_TeledyneDalsa*)pvoid;
  1237. pOpr->OnRefreshOffset();
  1238. return 0;
  1239. }
  1240. /***
  1241. ** 说明:初始化时刷新所有模式的offset
  1242. ***/
  1243. bool Detector_TeledyneDalsa::RefreshAllOffset()
  1244. {
  1245. printf("Refresh all mode offset begin \n");
  1246. Info("Refresh all mode offset begin");
  1247. //printf("Refresh all mode offset begin... \n");
  1248. int nLogicMode; //nLogicMode:配置文件中LogicMode
  1249. string strFrameRate;
  1250. int nModeCount = (int)m_ModeConfig["ModeTable"].GetKeyCount("DetectorMode");
  1251. SetTeledyneDalsaDPCStatus(eDetStatus::DetStatus_Offset); //开始全模式offset刷新
  1252. for (int i = 0; i < nModeCount; i++)
  1253. {
  1254. try
  1255. {
  1256. //初始化阶段的offset刷新流程不在整个软件的控制之内,所以不会给探测器外触发信号,
  1257. //因此刷新之前将模式改成内触发重新注册,SDK可同时生成外触发的校正文件
  1258. nLogicMode = (int)m_ModeConfig["ModeTable"][i]["LogicMode"];//RefreshAllOffset
  1259. StartDarkCalibration(nLogicMode); //当前mode失败,仍可以进行下一个mode的刷新
  1260. }
  1261. catch (...)
  1262. {
  1263. Fatal("Get configuration crashed!!! OnRefreshOffset over");
  1264. SetTeledyneDalsaDPCStatus(eDetStatus::DetStatus_Standby); //offset读取配置失败,置回Standby
  1265. return false;
  1266. }
  1267. }
  1268. SetTeledyneDalsaDPCStatus(eDetStatus::DetStatus_Standby); //全模式offset刷新结束,置回Standby
  1269. Info("Refresh all mode offset over");
  1270. //printf("Refresh all mode offset over \n");
  1271. return true;
  1272. }
  1273. /***
  1274. ** 说明:非检查界面定时刷新offset
  1275. ***/
  1276. void Detector_TeledyneDalsa::OnRefreshOffset()
  1277. {
  1278. printf("OnRefreshOffset begin \n");
  1279. Info("OnRefreshOffset begin");
  1280. bool bRefresh = false, bReckonTime = true;
  1281. ULONGLONG fBeginTime, fEndTime;
  1282. int nAppMode;
  1283. int nModeCount = 0; // (int)m_ModeConfig["ModeTable"].GetKeyCount("DetectorMode");
  1284. int nOftRefreshNum = 1;
  1285. int nRet = 0, nCurrFrmNum = 0, nPrevFrmNum = nCurrFrmNum - 1;
  1286. while (!m_bAbortRefreshOft)
  1287. {
  1288. if (bReckonTime) //一轮计时完毕,如果仍在检查界面,不会重新计时
  1289. {
  1290. //先计时,超时后刷新offset
  1291. fBeginTime = GetTickCount64();
  1292. fEndTime = fBeginTime;
  1293. while (!m_bAbortRefreshOft && (fEndTime - fBeginTime) < (ULONGLONG)m_nOftRefreshTimer * 60 * 1000)
  1294. {
  1295. fEndTime = GetTickCount64();
  1296. Sleep(10); //停10ms再循环,避免CPU占用太高
  1297. }
  1298. Info("offset timmer({$} min)", m_nOftRefreshTimer);
  1299. bReckonTime = false; //一轮计时完毕,置为false
  1300. }
  1301. if (!m_bAbortRefreshOft)
  1302. {
  1303. break;
  1304. }
  1305. EnterCriticalSection(&m_cs);
  1306. if (APP_STATUS_WORK_BEGIN == m_nExamMode)
  1307. {
  1308. LeaveCriticalSection(&m_cs);
  1309. bRefresh = false;
  1310. Sleep(10); //如果当前在检查界面,停10ms再循环,避免CPU占用太高
  1311. }
  1312. else
  1313. {
  1314. LeaveCriticalSection(&m_cs);
  1315. bRefresh = true;
  1316. }
  1317. if (bRefresh)
  1318. {
  1319. Info("Begin refresh offset {$} time", nOftRefreshNum);
  1320. //m_pCali->UpdateAutoDarkCalibrationStatus(CCOS_AUTODARKCALIBRATION_STATUS_START); //通知UI开始刷offset
  1321. SetTeledyneDalsaDPCStatus(eDetStatus::DetStatus_Offset); //开始非检查界面offset刷新
  1322. try
  1323. {
  1324. nModeCount = (int)m_ModeConfig["ModeTable"].GetKeyCount("DetectorMode");
  1325. for (int i = 0; i < nModeCount; i++)
  1326. {
  1327. if (!m_bAbortRefreshOft)
  1328. {
  1329. break;
  1330. }
  1331. EnterCriticalSection(&m_cs);
  1332. if (APP_STATUS_WORK_BEGIN == m_nExamMode)
  1333. {
  1334. LeaveCriticalSection(&m_cs);
  1335. break;
  1336. }
  1337. else
  1338. {
  1339. LeaveCriticalSection(&m_cs);
  1340. }
  1341. //非检查界面的offset刷新流程不在整个软件的控制之内,所以不会给探测器外触发信号,
  1342. //因此刷新之前将模式改成内触发重新注册,SDK可同时生成外触发的校正文件
  1343. nAppMode = (int)m_ModeConfig["ModeTable"][i]["LogicMode"];//OnRefreshOffset
  1344. StartDarkCalibration(nAppMode);
  1345. }
  1346. }
  1347. catch (...)
  1348. {
  1349. Fatal("Get configuration crashed!!! OnRefreshOffset over");
  1350. SetTeledyneDalsaDPCStatus(eDetStatus::DetStatus_Standby); //offset读取配置失败,置回Standby
  1351. //m_pCali->UpdateAutoDarkCalibrationStatus(CCOS_AUTODARKCALIBRATION_STATUS_END); //通知UI刷offset结束
  1352. return;
  1353. }
  1354. bRefresh = false;
  1355. bReckonTime = true; //offset结束,重新计时
  1356. SetTeledyneDalsaDPCStatus(eDetStatus::DetStatus_Standby); //非检查界面offset刷新结束,置回Standby
  1357. //m_pCali->UpdateAutoDarkCalibrationStatus(CCOS_AUTODARKCALIBRATION_STATUS_END); //通知UI刷offset结束
  1358. SetEvent(m_hOftEndEvent); //进入检查后,终止闲时offset刷新流程
  1359. Info("Refresh offset {$} time over", nOftRefreshNum);
  1360. nOftRefreshNum++;
  1361. }
  1362. }
  1363. Info("OnRefreshOffset over");
  1364. }
  1365. bool Detector_TeledyneDalsa::CheckTimeLimit(ULONGLONG dwBeginTime, ULONGLONG dwEndTime)
  1366. {
  1367. if (m_bValidImage) //合法图像,不再判断时间间隔,直接返回true
  1368. {
  1369. Info("CheckTimeLimit m_bValidImage is true!");
  1370. return true;
  1371. }
  1372. if (m_nDelayTime == 0) //没有开启延时机制
  1373. {
  1374. Info("The delay time is invalid, return");
  1375. return true;
  1376. }
  1377. if ((int)(dwEndTime - dwBeginTime) > m_nDelayTime)
  1378. {
  1379. Info("The interval({$}) is ok", dwEndTime - dwBeginTime);
  1380. return true;
  1381. }
  1382. Warn("The interval({$}) is shorter than the delay({$})",dwEndTime - dwBeginTime, m_nDelayTime);
  1383. return false;
  1384. }
  1385. bool Detector_TeledyneDalsa::GetModeMatchInfo()
  1386. {
  1387. return true;
  1388. }
  1389. bool Detector_TeledyneDalsa::CallbackProcess(int nEventID, void* context)
  1390. {
  1391. Info("CallbackProcess event id:{$}",nEventID);
  1392. int width, height;
  1393. unsigned int timestamp;
  1394. unsigned short* dataptr;
  1395. switch (nEventID)
  1396. {
  1397. case -1:
  1398. Info("*** Transfer Complete ***");
  1399. break;
  1400. case -2:
  1401. Error("*** Frame lost in transmission ***");
  1402. break;
  1403. case -3:
  1404. Error("*** Frame lost in trash buffer ***");
  1405. break;
  1406. case -4:
  1407. Error("*** Frame Empty ***");
  1408. break;
  1409. default:
  1410. if (!m_cGigeDevice.GetBufferInfo(nEventID, &dataptr, &width, &height, &timestamp))
  1411. {
  1412. Error("Frame ({$}) receive, Failed to retreive buffer info: ({$})", nEventID, m_cGigeDevice.GetLastStatus());
  1413. break;
  1414. }
  1415. if (!TXP_FlatfieldCorrection(dataptr, gain.pixels.data(), dark.pixels.data(), raw.pixels.data(), m_dgainAverage, m_nblackOffset, 65536 - 40, width, height))
  1416. {
  1417. Error("FlatfieldCorrection Calibration Failed");
  1418. }
  1419. else
  1420. {
  1421. Info("FlatfieldCorrection Calibration Success");
  1422. }
  1423. if (!TXP_DefectCorrection(raw.pixels.data(), defect.pixels.data(), image.pixels.data(), 1416, 1420))
  1424. {
  1425. Error("Defect Calibration Failed");
  1426. }
  1427. else
  1428. {
  1429. Info("Defect Calibration Success");
  1430. }
  1431. ResetEvent(m_hProcessImgEvent);
  1432. SetEvent(m_hProcessImgEvent);
  1433. m_nImgIndex++;
  1434. }
  1435. return true;
  1436. }
  1437. bool Detector_TeledyneDalsa::DarkCallbackProcess(int nEventID, void* context)
  1438. {
  1439. Info("DrakCallbackProcess EventID:({$})", nEventID);
  1440. int width, height;
  1441. unsigned int timestamp;
  1442. unsigned short* dataptr;
  1443. switch (nEventID)
  1444. {
  1445. case -1:
  1446. Info("*** Transfer Complete ***");
  1447. break;
  1448. case -2:
  1449. Error("*** Frame lost in transmission ***");
  1450. break;
  1451. case -3:
  1452. Error("*** Frame lost in trash buffer ***");
  1453. break;
  1454. case -4:
  1455. Error("*** Frame Empty ***");
  1456. break;
  1457. default:
  1458. if (!m_cGigeDevice.GetBufferInfo(nEventID, &dataptr, &width, &height, &timestamp))
  1459. {
  1460. Error("Frame ({$}) receive, Failed to retreive buffer info: ({$})", nEventID, m_cGigeDevice.GetLastStatus());
  1461. break;
  1462. }
  1463. }
  1464. return true;
  1465. }
  1466. bool Detector_TeledyneDalsa::GainCallbackProcess(int nEventID, void* context)
  1467. {
  1468. return false;
  1469. }
  1470. void Detector_TeledyneDalsa::ConfFeedback(int nEventID, int nDetectorID, const char* pszMsg, int nParam1, float fParam2, int nPtrParamLen, void* pParam)
  1471. {
  1472. if (-1 == nDetectorID)
  1473. {
  1474. nDetectorID = m_nCurrentPanelID;
  1475. }
  1476. ((FPDDeviceTeledyneDalsa*)(*m_pPanelID2DPC)[nDetectorID])->OnFPDCallback(nDetectorID,
  1477. nEventID, EVT_LEVEL_CONFIGURATION, pszMsg, nParam1, fParam2, nPtrParamLen, pParam);
  1478. }
  1479. void Detector_TeledyneDalsa::InfoFeedback(int nEventID, int nDetectorID, int nParam1, float fParam2, const char* pszMsg, int nPtrParamLen, void* pParam)
  1480. {
  1481. if (-1 == nDetectorID)
  1482. {
  1483. nDetectorID = m_nCurrentPanelID;
  1484. }
  1485. ((FPDDeviceTeledyneDalsa*)(*m_pPanelID2DPC)[nDetectorID])->OnFPDCallback(nDetectorID,
  1486. nEventID, EVT_LEVEL_INFORMATOION, pszMsg, nParam1, fParam2, nPtrParamLen, pParam);
  1487. }
  1488. void Detector_TeledyneDalsa::StatusFeedback(int nEventID, int nParam1, const char* pszMsg, int nDetectorID, float fParam2, int nPtrParamLen, void* pParam)
  1489. {
  1490. if (-1 == nDetectorID)
  1491. {
  1492. nDetectorID = m_nCurrentPanelID;
  1493. }
  1494. ((FPDDeviceTeledyneDalsa*)(*m_pPanelID2DPC)[nDetectorID])->OnFPDCallback(nDetectorID,
  1495. nEventID, EVT_LEVEL_STATUS, pszMsg, nParam1, fParam2, nPtrParamLen, pParam);
  1496. }
  1497. void Detector_TeledyneDalsa::DataFeedback(int nEventID, void* pParam, int nParam1, float fParam2, const char* pszMsg, int nPtrParamLen, int nDetectorID)
  1498. {
  1499. if (-1 == nDetectorID)
  1500. {
  1501. nDetectorID = m_nCurrentPanelID;
  1502. }
  1503. ((FPDDeviceTeledyneDalsa*)(*m_pPanelID2DPC)[nDetectorID])->OnFPDCallback(nDetectorID,
  1504. nEventID, EVT_LEVEL_DATA, pszMsg, nParam1, fParam2, nPtrParamLen, pParam);
  1505. }
  1506. void Detector_TeledyneDalsa::WarnFeedback(int nEventID, const char* pszMsg, int nParam1, float fParam2, int nPtrParamLen, void* pParam, int nDetectorID)
  1507. {
  1508. if (-1 == nDetectorID)
  1509. {
  1510. nDetectorID = m_nCurrentPanelID;
  1511. }
  1512. ((FPDDeviceTeledyneDalsa*)(*m_pPanelID2DPC)[nDetectorID])->OnFPDCallback(nDetectorID,
  1513. nEventID, EVT_LEVEL_WARNING, pszMsg, nParam1, fParam2, nPtrParamLen, pParam);
  1514. }
  1515. void Detector_TeledyneDalsa::ErrorFeedback(int nEventID, const char* pszMsg, int nDetectorID, int nParam1, float fParam2, int nPtrParamLen, void* pParam)
  1516. {
  1517. if (-1 == nDetectorID)
  1518. {
  1519. nDetectorID = m_nCurrentPanelID;
  1520. }
  1521. ((FPDDeviceTeledyneDalsa*)(*m_pPanelID2DPC)[nDetectorID])->OnFPDCallback(nDetectorID,
  1522. nEventID, EVT_LEVEL_ERROR, pszMsg, nParam1, fParam2, nPtrParamLen, pParam);
  1523. }