CMsrThread.cs 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543
  1. using System.Collections.Generic;
  2. using OTSDataType;
  3. using System;
  4. using System.Drawing;
  5. using static OTSDataType.otsdataconst;
  6. using OTSModelSharp.ImageProcess;
  7. using OTSModelSharp.ServiceInterface;
  8. namespace OTSModelSharp
  9. {
  10. // enum and struct used for send message to App
  11. public enum ENUM_MSG_TYPE
  12. {
  13. MTHREADSTATUS = 1001,
  14. MSAMPLESTATUS = 1002,
  15. MSAMPLERESULT = 1003
  16. };
  17. public enum MSAMPLE_RET
  18. {
  19. BSE_DATA = 0,
  20. FIELD_DATA = 1,
  21. START_MSR_FIELD = 2
  22. };
  23. public struct SMSR_COMPLETE_DATA
  24. {
  25. public OTS_MSR_THREAD_STATUS MsrStatus;
  26. public string csMsrStartTime;
  27. public int iMsrCompleteSampleCount;
  28. public int iMsrCompleteFieldCount;
  29. public int iParticleCount;
  30. public TimeSpan MsrUsedTime;
  31. public string csMsrEndTime;
  32. };
  33. public struct STMThreadStatus
  34. {
  35. public OTS_MSR_THREAD_STATUS iMsrStatu; //OTS_MSR_THREAD_STATUS
  36. public string csMsrStartTime; //MSR_START_TIME
  37. public string csMsrEndTime; //MSR_END_TIME
  38. public SMSR_COMPLETE_DATA SMsrCompleteData;
  39. };
  40. public struct STMSampleStatus
  41. {
  42. public OTS_MSR_SAMPLE_STATUS iMsrSampleStatu; //OTS_MSR_SAMPLE_STATUS
  43. public string cSampleName;
  44. public string csSampleMsrStartTime;
  45. public List<Point> BCompleteFieldList;
  46. };
  47. public struct STMSampleResultData
  48. {
  49. public MSAMPLE_RET iRetDataType; //ENUM_MEASURE_SAMPLE_RESULT
  50. public struct RBSEDATA
  51. {
  52. public System.Drawing.Point pos;
  53. public int iBSEDataHeight;
  54. public int iBSEDataWidth;
  55. public byte[] lpBSEData;
  56. };
  57. public struct SAMPLEFIELDDATA
  58. {
  59. public System.Drawing.Point FieldPos;
  60. public int iMeasureFieldCount;
  61. public int iCompleteFieldCount;
  62. public int iSParticleCount; // Field particle count
  63. public TimeSpan TUsedTime;
  64. };
  65. public struct StartToMsrField
  66. {
  67. public System.Drawing.Point FieldPos;
  68. };
  69. public RBSEDATA BSEData;
  70. public SAMPLEFIELDDATA SFieldData;
  71. public StartToMsrField SMsrField;
  72. };
  73. public struct ST_MSTMsg
  74. {
  75. public ENUM_MSG_TYPE iMsgType;
  76. public STMThreadStatus STMThreadStu;
  77. public STMSampleStatus STMSampleStu;
  78. public STMSampleResultData STMSampleRetData;
  79. };
  80. public class CMsrThread
  81. {
  82. private const string UNTITLED_FILE_NAME = "Untitled";
  83. public delegate void ProgressEventHandler(ST_MSTMsg msg);
  84. public event ProgressEventHandler ProgressEvent;
  85. COTSMsrPrjResultData m_pProjData;
  86. List< COTSSample> m_listMeasurableSamples;
  87. string m_strWorkingFolder;
  88. CMsrThreadStatus m_ThreadStatus;
  89. SemController m_SemController;// there is no correspondense clr,so use this instead temporarilly
  90. protected static NLog.Logger loger = NLog.LogManager.GetCurrentClassLogger();
  91. public CMsrThread()
  92. {
  93. m_strWorkingFolder = "";
  94. m_ThreadStatus = new CMsrThreadStatus();
  95. m_SemController = new SemController();
  96. }
  97. public COTSMsrPrjResultData GetProjResultData()
  98. {
  99. return m_pProjData;
  100. }
  101. public ISemController GetSEMController()
  102. {
  103. // get SEM, scanner and x-ray controller via hardware manager
  104. return m_SemController;
  105. }
  106. public CMsrThreadStatus GetMsrThreadStatus() { return m_ThreadStatus; }
  107. public void Init(COTSMsrPrjResultData a_pProjMgrFile)
  108. {
  109. m_pProjData = a_pProjMgrFile;
  110. m_listMeasurableSamples = a_pProjMgrFile.GetSampleList() ;
  111. return ;
  112. }
  113. void ThreadOver()
  114. {
  115. loger.Info("Disconnect SEM!");
  116. m_SemController.DisConnect();
  117. DateTime timeEnd = m_ThreadStatus.GetEndTime();
  118. ST_MSTMsg MsrMsg = new ST_MSTMsg();
  119. MsrMsg.iMsgType = ENUM_MSG_TYPE.MTHREADSTATUS;
  120. MsrMsg.STMThreadStu.iMsrStatu = m_ThreadStatus.GetStatus();
  121. MsrMsg.STMThreadStu.csMsrEndTime = timeEnd.ToShortDateString();
  122. ProgressEvent(MsrMsg);
  123. }
  124. void SetWorkingFolderStr()
  125. {
  126. // get project file pathname
  127. string strSettingFilePathName = m_pProjData.GetPathName();
  128. strSettingFilePathName.Trim();
  129. if (strSettingFilePathName == "")
  130. {
  131. loger .Error("SetWorkingFolderStr: project file pathname is an empty string");
  132. return ;
  133. }
  134. else if (strSettingFilePathName==UNTITLED_FILE_NAME)
  135. {
  136. loger .Error ("SetWorkingFolderStr: project file pathname is an invalid string");
  137. return ;
  138. }
  139. // working folder string
  140. string strWorkingFolder =FileHelper.GetFolderName(strSettingFilePathName);
  141. // set working folder string
  142. m_strWorkingFolder = strWorkingFolder;
  143. // ok, return TRUE
  144. return ;
  145. }
  146. public void SendMessageToMeasureApp(ST_MSTMsg msg)
  147. {
  148. ProgressEvent(msg);
  149. }
  150. public bool IsMeasureStopped()
  151. {
  152. return m_ThreadStatus.GetStatus() == OTS_MSR_THREAD_STATUS.STOPPED;
  153. }
  154. public bool IsMeasureRunning() { return m_ThreadStatus.GetStatus() == OTS_MSR_THREAD_STATUS.INPROCESS; }
  155. public bool IsMeasureFailed() { return m_ThreadStatus.GetStatus() == OTS_MSR_THREAD_STATUS.FAILED; }
  156. public bool IsMeasureCompleted() { return m_ThreadStatus.GetStatus() == OTS_MSR_THREAD_STATUS.COMPLETED; }
  157. public void DoMeasure()
  158. {
  159. // start measurement, creat thread measure status class, let the main thread know that measurement started
  160. SortedDictionary<string , CSmplMeasure> mapSmplMsr=new SortedDictionary<string, CSmplMeasure>();//use this map to hold all the smplMeasure object
  161. m_ThreadStatus.SetStartTime(System.DateTime.Now);
  162. DateTime timeStart = m_ThreadStatus.GetStartTime();
  163. ST_MSTMsg MsgMsrStart=new ST_MSTMsg();
  164. MsgMsrStart.iMsgType = ENUM_MSG_TYPE.MTHREADSTATUS;
  165. MsgMsrStart.STMThreadStu.iMsrStatu = OTS_MSR_THREAD_STATUS.INPROCESS;
  166. MsgMsrStart.STMThreadStu.csMsrStartTime = timeStart.ToShortDateString();
  167. ProgressEvent (MsgMsrStart);
  168. loger.Info("Measurement started!");
  169. // connect hardware
  170. loger.Info("Connect SEM!");
  171. if (!m_SemController.Connect())
  172. {
  173. loger .Error("DoMeasure: failed to connect hardware.");
  174. m_ThreadStatus.SetStatus(OTS_MSR_THREAD_STATUS.FAILED);
  175. m_ThreadStatus.ComputeTime(OTS_THREAD_TIME_TYPE.STOPPED);
  176. ThreadOver();
  177. return;
  178. }
  179. // set working directory which is the same directory of the setting file
  180. SetWorkingFolderStr();
  181. List <string > listMeasuredSamples = m_ThreadStatus.GetCompletedSamples();
  182. // got through measure list
  183. foreach (var pSample in m_listMeasurableSamples)
  184. {// check and break if stop button is clicked
  185. if (m_ThreadStatus.GetStatus()== OTS_MSR_THREAD_STATUS.STOPPED )
  186. {
  187. // stop button clicked
  188. loger .Info("DoMeasure: stop button is clicked.");
  189. // record end time
  190. m_ThreadStatus.ComputeTime(OTS_THREAD_TIME_TYPE.STOPPED);
  191. ThreadOver();
  192. return;
  193. }
  194. if (!pSample.GetSwitch())
  195. {
  196. continue;
  197. }
  198. CSmplMeasure pSmplMeasure;
  199. if (!mapSmplMsr.ContainsKey(pSample.GetName()))
  200. {// create a sample measure object for the sample
  201. switch (m_pProjData.m_nPackId)
  202. {
  203. case OTS_SysType_ID.IncA:
  204. pSmplMeasure = new CSmplMeasureInclution(m_strWorkingFolder, pSample);
  205. break;
  206. case OTS_SysType_ID.CleanlinessA:
  207. pSmplMeasure = new CSmplMeasureCleanliness(m_strWorkingFolder, pSample);
  208. break;
  209. default:
  210. pSmplMeasure = new CSmplMeasureInclution(m_strWorkingFolder, pSample);
  211. break;
  212. }
  213. // set measure thread
  214. pSmplMeasure.SetMsrThread(this);
  215. mapSmplMsr[pSample.GetName()] = pSmplMeasure;
  216. }
  217. else
  218. {
  219. pSmplMeasure = mapSmplMsr[pSample.GetName()];
  220. pSample.GetMsrStatus().SetStatus(OTS_MSR_SAMPLE_STATUS.INPROCESS);
  221. m_ThreadStatus.SetStatus(OTS_MSR_THREAD_STATUS.INPROCESS);
  222. }
  223. pSmplMeasure.DoMeasureForOneSample();
  224. // check if measurement is successful
  225. if (pSample.GetMsrStatus().GetStatus() == OTS_MSR_SAMPLE_STATUS.STOPPED)
  226. {// record end time
  227. m_ThreadStatus.SetStatus(OTS_MSR_THREAD_STATUS.STOPPED);
  228. m_ThreadStatus.ComputeTime(OTS_THREAD_TIME_TYPE.STOPPED);
  229. // update thread measure status class, let the main thread know that this sample measurement stopped
  230. ST_MSTMsg MsgSmpStop = new ST_MSTMsg();
  231. MsgSmpStop.iMsgType = ENUM_MSG_TYPE.MSAMPLESTATUS;
  232. MsgSmpStop.STMThreadStu.iMsrStatu= OTS_MSR_THREAD_STATUS.STOPPED;
  233. MsgSmpStop.STMSampleStu.iMsrSampleStatu = OTS_MSR_SAMPLE_STATUS.STOPPED;
  234. MsgSmpStop.STMThreadStu.csMsrEndTime = DateTime .Now .ToShortDateString();
  235. MsgSmpStop.STMThreadStu.iMsrStatu= OTS_MSR_THREAD_STATUS.STOPPED;
  236. ProgressEvent(MsgSmpStop);
  237. ThreadOver();
  238. return;
  239. }
  240. else if (pSample.GetMsrStatus().GetStatus() == OTS_MSR_SAMPLE_STATUS.FAILED)
  241. {
  242. // measurement failed
  243. m_ThreadStatus.SetStatus(OTS_MSR_THREAD_STATUS.FAILED);
  244. // record end time
  245. m_ThreadStatus.ComputeTime(OTS_THREAD_TIME_TYPE.STOPPED);
  246. // update thread measure status class, let the main thread know that this sample measurement failed
  247. ST_MSTMsg MsgSmpFailed=new ST_MSTMsg();
  248. MsgSmpFailed.iMsgType = ENUM_MSG_TYPE.MSAMPLESTATUS;
  249. MsgSmpFailed.STMSampleStu.iMsrSampleStatu = OTS_MSR_SAMPLE_STATUS.FAILED;
  250. ProgressEvent(MsgSmpFailed);
  251. ThreadOver();
  252. return;
  253. }
  254. // record end time
  255. m_ThreadStatus.ComputeTime(OTS_THREAD_TIME_TYPE.STOPPED);
  256. // update thread measure status class, let the main thread know that this sample measurement successes
  257. ST_MSTMsg MsgSmpSuccess=new ST_MSTMsg();
  258. MsgSmpSuccess.iMsgType = ENUM_MSG_TYPE.MSAMPLESTATUS;
  259. MsgSmpSuccess.STMSampleStu.iMsrSampleStatu = OTS_MSR_SAMPLE_STATUS.SUCCESSED;
  260. ProgressEvent(MsgSmpSuccess);
  261. // continue to the next sample
  262. listMeasuredSamples.Add (pSample.GetName());
  263. }
  264. // measurement completed
  265. m_ThreadStatus.SetStatus(OTS_MSR_THREAD_STATUS.COMPLETED);
  266. // record end time
  267. m_ThreadStatus.ComputeTime(OTS_THREAD_TIME_TYPE.STOPPED);
  268. ThreadOver();
  269. }
  270. // hole preview
  271. public void DoHolePreview(int a_nHoleID, CDomain a_pMeasureArea)
  272. {
  273. // start measurement, creat thread measure status class, let the main thread know that measurement started
  274. // set measure status to in-process
  275. //record time
  276. m_ThreadStatus.ComputeTime(OTS_THREAD_TIME_TYPE.START);
  277. DateTime timeStart = m_ThreadStatus.GetStartTime();
  278. int iYear = timeStart.DayOfYear;
  279. int imonth = timeStart.Month;
  280. int iDay = timeStart.Day;
  281. int iHour = timeStart.Hour;
  282. int iMin = timeStart.Minute;
  283. int iSec = timeStart.Second;
  284. String csTime;
  285. string.Format("%04d-%02d-%02d %02d:%02d:%02d", iYear, imonth, iDay, iHour, iMin, iSec);
  286. ST_MSTMsg MsgMsrStart = new ST_MSTMsg();
  287. /// memset(&MsgMsrStart, 0, sizeof(ST_MSTMsg));
  288. MsgMsrStart.iMsgType = ENUM_MSG_TYPE.MTHREADSTATUS;
  289. MsgMsrStart.STMThreadStu.iMsrStatu =OTS_MSR_THREAD_STATUS.INPROCESS;
  290. // strcpy(MsgMsrStart.STMThreadStu.cMsrStartTime, csTime);
  291. SendMessageToMeasureApp(MsgMsrStart);
  292. // connect hardware
  293. if (!m_SemController.Connect())
  294. {
  295. // failed to connect hardware
  296. SetMsrLoopStatus(otsdataconst.OTS_MSR_THREAD_STATUS.FAILED);
  297. m_ThreadStatus.ComputeTime(OTS_THREAD_TIME_TYPE.STOPPED);
  298. ThreadOver();
  299. }
  300. COTSSample pSampleHole = CreateHoleSample(a_pMeasureArea);
  301. // create a sample measure object for the sample
  302. CSmplMeasure pSmplMeasure = new CSmplMeasureCleanliness(m_strWorkingFolder,pSampleHole);
  303. // set measure thread
  304. pSmplMeasure.SetMsrThread(this);
  305. // update thread measure status class, let the main thread know that this sample measurement starts
  306. // set working folder string
  307. pSmplMeasure.SetSample(pSampleHole);
  308. pSmplMeasure.SetWorkingFolder(m_strWorkingFolder);
  309. // do measure
  310. pSmplMeasure.DoHolePreview(a_nHoleID);
  311. // check if measurement is successful
  312. if (pSampleHole.GetMsrStatus().GetStatus() == OTS_MSR_SAMPLE_STATUS.STOPPED)
  313. {
  314. // record end time
  315. m_ThreadStatus.ComputeTime(OTS_THREAD_TIME_TYPE.STOPPED);
  316. // measurement stopped
  317. SetMsrLoopStatus(otsdataconst.OTS_MSR_THREAD_STATUS.STOPPED);
  318. // update thread measure status class, let the main thread know that this sample measurement stopped
  319. ST_MSTMsg MsgSmpStop = new ST_MSTMsg();
  320. MsgSmpStop.iMsgType = ENUM_MSG_TYPE.MSAMPLESTATUS;
  321. MsgSmpStop.STMSampleStu.iMsrSampleStatu = OTS_MSR_SAMPLE_STATUS.STOPPED;
  322. SendMessageToMeasureApp(MsgSmpStop);
  323. ThreadOver();
  324. return;
  325. }
  326. else if (pSampleHole.GetMsrStatus().GetStatus() == OTS_MSR_SAMPLE_STATUS.FAILED)
  327. {
  328. // measurement failed
  329. SetMsrLoopStatus(otsdataconst.OTS_MSR_THREAD_STATUS.FAILED);
  330. // record end time
  331. m_ThreadStatus.ComputeTime(OTS_THREAD_TIME_TYPE.STOPPED);
  332. // update thread measure status class, let the main thread know that this sample measurement failed
  333. ST_MSTMsg MsgSmpFailed = new ST_MSTMsg();
  334. MsgSmpFailed.iMsgType = ENUM_MSG_TYPE.MSAMPLESTATUS;
  335. MsgSmpFailed.STMSampleStu.iMsrSampleStatu = OTS_MSR_SAMPLE_STATUS.FAILED;
  336. SendMessageToMeasureApp(MsgSmpFailed);
  337. ThreadOver();
  338. return;
  339. }
  340. // record end time
  341. m_ThreadStatus.ComputeTime(OTS_THREAD_TIME_TYPE.STOPPED);
  342. // update thread measure status class, let the main thread know that this sample measurement successes
  343. ST_MSTMsg MsgSmpSuccess = new ST_MSTMsg();
  344. MsgSmpSuccess.iMsgType = ENUM_MSG_TYPE.MSAMPLESTATUS;
  345. MsgSmpSuccess.STMSampleStu.iMsrSampleStatu = OTS_MSR_SAMPLE_STATUS.SUCCESSED;
  346. SendMessageToMeasureApp(MsgSmpSuccess);
  347. // measurement completed
  348. SetMsrLoopStatus(otsdataconst.OTS_MSR_THREAD_STATUS.COMPLETED);
  349. // record end time
  350. m_ThreadStatus.ComputeTime(OTS_THREAD_TIME_TYPE.STOPPED);
  351. ThreadOver();
  352. }
  353. public COTSSample CreateHoleSample(CDomain a_pMsrArea)
  354. {
  355. COTSSample pHoleSample = new COTSSample();
  356. pHoleSample.SetMsrArea(a_pMsrArea);
  357. // get min magnification
  358. CSEMStageData pSEMStageData = m_pProjData.GetSEMStageData();
  359. double dMinMag = pSEMStageData.GetMinMag();
  360. // get scan field size 100
  361. int nScanFieldSize100 = pSEMStageData.GetScanFieldSize100();
  362. // get working distance
  363. double dWorkingDistance = 0.0;
  364. if (!GetSEMWorkingDistanceFromHW(ref dWorkingDistance))
  365. {
  366. return null;
  367. }
  368. CSEMDataMsr poSEMDataMsr = new CSEMDataMsr();
  369. poSEMDataMsr.SetScanFieldSize100(nScanFieldSize100);
  370. poSEMDataMsr.SetWorkingDistance(dWorkingDistance);
  371. poSEMDataMsr.SetMagnification(dMinMag);
  372. pHoleSample.SetSEMDataMsr(poSEMDataMsr);
  373. // Set image scan param
  374. COTSImgScanPrm poImageScanParam = new COTSImgScanPrm();
  375. poImageScanParam.SetStopMode(OTS_MEASURE_STOP_MODE.CoverMode);
  376. poImageScanParam.SetStartImageMode(OTS_GET_IMAGE_MODE.FROM_CENTER);
  377. poImageScanParam.SetScanImageSpeed(OTS_THREE_TIES_OPTIONS.TIE1);
  378. poImageScanParam.SetImagePixelSize(OTS_FIVE_TIES_OPTIONS.TIE1);
  379. CSampleParam poMsrParams = pHoleSample.GetMsrParams();
  380. poMsrParams.SetImageScanParam(poImageScanParam);
  381. pHoleSample.SetMsrParams(poMsrParams);
  382. return pHoleSample;
  383. }
  384. public bool GetSEMWorkingDistanceFromHW(ref double a_dWorkingDistance)
  385. {
  386. m_SemController.GetWorkingDistance(ref a_dWorkingDistance);
  387. return true;
  388. }
  389. // measure status
  390. public void SetMsrLoopStatus(otsdataconst.OTS_MSR_THREAD_STATUS a_nMsrLoopStatus)
  391. {
  392. if (a_nMsrLoopStatus >= otsdataconst.OTS_MSR_THREAD_STATUS.MIN && a_nMsrLoopStatus <= otsdataconst.OTS_MSR_THREAD_STATUS.MAX)
  393. {
  394. m_ThreadStatus.SetStatus( a_nMsrLoopStatus);
  395. }
  396. }
  397. }
  398. }