Loadport.cs 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074
  1. using Aitex.Core.Common;
  2. using Aitex.Core.RT.DataCenter;
  3. using Aitex.Core.RT.Event;
  4. using Aitex.Core.RT.OperationCenter;
  5. using Aitex.Core.RT.SCCore;
  6. using Aitex.Core.Util;
  7. using Aitex.Sorter.Common;
  8. using MECF.Framework.Common.Equipment;
  9. using MECF.Framework.Common.SubstrateTrackings;
  10. using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.LoadPorts;
  11. using System;
  12. using System.Collections;
  13. using System.Collections.Generic;
  14. using System.Diagnostics;
  15. using CyberX8_Core;
  16. using CyberX8_RT.Devices.YASKAWA;
  17. using CyberX8_RT.Modules;
  18. using Aitex.Core.RT.IOCore;
  19. using CyberX8_RT.Dispatch;
  20. namespace CyberX8_RT.Devices.EFEM
  21. {
  22. sealed class Loadport : ILoadport
  23. {
  24. private EfemEntity _controller => Singleton<RouteManager>.Instance.EFEM;
  25. private EfemBase _efemBase;
  26. //---------------------------------Properties------------------------------------
  27. //
  28. public OnlineFlag OnlineFlag { get; set; }
  29. public ModuleName Module { get; set; }
  30. public DeviceState Status { get; set; }
  31. public WaferSize WaferSize { get; set; }
  32. public WaferStatus[] WaferInfo { get; set; }
  33. public bool HasCassette { get; set; }
  34. public bool Protrusion { get; set; }
  35. public bool IsMapped { get; set; }
  36. public bool JobDone { get; set; }
  37. public Stopwatch TimerNotifyJobDone { get; set; }
  38. public IE87CallBack LPCallBack
  39. {
  40. get { return _lpCallBack; }
  41. set { _lpCallBack = value; }
  42. }
  43. private IE87CallBack _lpCallBack;
  44. public bool IsThicknessValid
  45. {
  46. get
  47. {
  48. return !_enableThickness || !string.IsNullOrEmpty(_waferThicknessType);
  49. }
  50. }
  51. public string ThicknessType
  52. {
  53. get
  54. {
  55. return _waferThicknessType;
  56. }
  57. }
  58. public string PortId
  59. {
  60. get; private set;
  61. }
  62. public bool IsClamped { get; set; }
  63. public bool IsLoaded { get; set; }
  64. public bool IsDoorOpened { get; set; }
  65. public bool IsDocked { get; set; }
  66. public string CarrierId { get; set; }
  67. public string SmartTag { get; set; }
  68. public string LotId { get; set; }
  69. public bool IsBusy { get; set; }
  70. public bool IsError { get; set; }
  71. private string[] _slotMap = new string[25];
  72. public string SlotMap
  73. {
  74. get
  75. {
  76. if (_slotMap == null)
  77. {
  78. _slotMap = new string[SC.GetValue<int>("EFEM.LoadPort.SlotNumber")];
  79. }
  80. for (int i = 0; i < _slotMap.Length; i++)
  81. {
  82. _slotMap[i] = ((int)WaferManager.Instance.GetWafer(Module, i).Status).ToString();
  83. }
  84. return string.Join("", _slotMap);
  85. }
  86. }
  87. private string _waferThicknessType;
  88. private bool _enableThickness;
  89. private string AlarmWaferProtrude = "WaferProtrude";
  90. private LoadPortFACallback _faCallback = new LoadPortFACallback();
  91. // Constructor
  92. //
  93. public Loadport(ModuleName mod, EfemBase efem)
  94. {
  95. Module = mod;
  96. PortId = ((int)mod - (int)ModuleName.LP1 + 1).ToString();
  97. TimerNotifyJobDone = new Stopwatch();
  98. _efemBase = efem;
  99. _enableThickness = false;// SC.GetValue<bool>("System.WaferThickness.EnableThickness");
  100. EV.Subscribe(new EventItem("Event", AlarmWaferProtrude, "Wafer protrude", EventLevel.Alarm, EventType.HostNotification));
  101. DATA.Subscribe($"{mod}.WaferSize", () => WaferSize.ToString(),SubscriptionAttribute.FLAG.IgnoreSaveDB);
  102. DATA.Subscribe($"{mod}.CassetteState", () => HasCassette ? LoadportCassetteState.Normal : LoadportCassetteState.Absent, SubscriptionAttribute.FLAG.IgnoreSaveDB);
  103. DATA.Subscribe($"{mod}.CassettePresent", () => HasCassette ? 1 : 0, SubscriptionAttribute.FLAG.IgnoreSaveDB);
  104. DATA.Subscribe($"{mod}.CassettePlaced", () => HasCassette,SubscriptionAttribute.FLAG.IgnoreSaveDB);
  105. DATA.Subscribe($"{mod}.SlotMap", () => SlotMap, SubscriptionAttribute.FLAG.IgnoreSaveDB);
  106. DATA.Subscribe($"{mod}.IsWaferProtrude", () => Protrusion ? 1 : 0,SubscriptionAttribute.FLAG.IgnoreSaveDB);
  107. DATA.Subscribe($"{mod}.IsMapped", () => IsMapped, SubscriptionAttribute.FLAG.IgnoreSaveDB);
  108. DATA.Subscribe($"{mod}.IsLoaded", () => IsLoaded, SubscriptionAttribute.FLAG.IgnoreSaveDB);
  109. DATA.Subscribe($"{mod}.IsClamped", () => IsClamped,SubscriptionAttribute.FLAG.IgnoreSaveDB);
  110. DATA.Subscribe($"{mod}.IsDocked", () => IsDocked, SubscriptionAttribute.FLAG.IgnoreSaveDB);
  111. DATA.Subscribe($"{mod}.IsDoorOpened", () => IsDoorOpened,SubscriptionAttribute.FLAG.IgnoreSaveDB);
  112. DATA.Subscribe($"{mod}.CarrierId", () => CarrierId, SubscriptionAttribute.FLAG.IgnoreSaveDB);
  113. DATA.Subscribe($"{mod}.SmartTag", () => SmartTag,SubscriptionAttribute.FLAG.IgnoreSaveDB);
  114. DATA.Subscribe($"{Module}.WaferThicknessType", () => _waferThicknessType,SubscriptionAttribute.FLAG.IgnoreSaveDB);
  115. OP.Subscribe($"{Module}.SetThick", (cmd, args) => { SetThick(); return true; });
  116. OP.Subscribe($"{Module}.SetThin", (cmd, args) => { SetThin(); return true; });
  117. }
  118. // Methods
  119. //
  120. public void OnError()
  121. {
  122. IsError = true;
  123. IsBusy = false;
  124. }
  125. public void Abort()
  126. {
  127. IsError = false;
  128. IsBusy = false;
  129. }
  130. public void SetThick()
  131. {
  132. _waferThicknessType = "Thick";
  133. SC.SetItemValue($"System.WaferThickness.{Module}WaferThicknessType", _waferThicknessType);
  134. _efemBase.SetThickness(Module, _waferThicknessType);
  135. }
  136. public void SetThin()
  137. {
  138. _waferThicknessType = "Thin";
  139. SC.SetItemValue($"System.WaferThickness.{Module}WaferThicknessType", _waferThicknessType);
  140. _efemBase.SetThickness(Module, _waferThicknessType);
  141. }
  142. #region Home
  143. public void Home()
  144. {
  145. if (IsBusy)
  146. {
  147. EV.PostInfoLog(Module.ToString(), $"{Module} is busy can not home");
  148. return;
  149. }
  150. IsBusy = true;
  151. _efemBase.Home(Module);
  152. }
  153. public void NoteJobStart()
  154. {
  155. JobDone = false;
  156. }
  157. public void NoteJobComplete()
  158. {
  159. TimerNotifyJobDone.Restart();
  160. JobDone = true;
  161. }
  162. public void OnHomeFailed(string data)
  163. {
  164. IsError = true;
  165. IsBusy = false;
  166. }
  167. public void OnHomed()
  168. {
  169. IsError = false;
  170. IsBusy = false;
  171. IsClamped = false;
  172. IsLoaded = false;
  173. IsMapped = false;
  174. IsDocked = false;
  175. WaferManager.Instance.DeleteWafer(Module, 0, 25);
  176. }
  177. #endregion
  178. #region Load
  179. public bool Load()
  180. {
  181. if (IsLoaded)
  182. {
  183. EV.PostWarningLog(Module.ToString(), $"{Module} is loaded, can not load");
  184. return false;
  185. }
  186. if (IsBusy)
  187. {
  188. EV.PostInfoLog(Module.ToString(), $"{Module} is busy, can not load");
  189. return false;
  190. }
  191. if (IsError)
  192. {
  193. EV.PostInfoLog(Module.ToString(), $"{Module} is error, can not load");
  194. return false;
  195. }
  196. IsBusy = true;
  197. _controller.SendEfemAutoCommand(EfemEntity.MSG.Load, Module);
  198. return true;
  199. }
  200. public void LoadStart()
  201. {
  202. if(_lpCallBack!=null)
  203. {
  204. _lpCallBack.LoadStart();
  205. }
  206. }
  207. public void OnLoadFailed(string data)
  208. {
  209. IsError = true;
  210. IsBusy = false;
  211. _faCallback.LoadFailed(this);
  212. }
  213. public void OnLoaded()
  214. {
  215. IsError = false;
  216. IsBusy = false;
  217. IsDocked = true;
  218. IsLoaded = true;
  219. IsMapped = true;
  220. _faCallback.LoadComplete(this);
  221. if(_lpCallBack!=null)
  222. {
  223. _lpCallBack.LoadComplete();
  224. }
  225. }
  226. #endregion
  227. #region unload
  228. public void Unload()
  229. {
  230. if (!IsLoaded)
  231. {
  232. EV.PostWarningLog(Module.ToString(), $"{Module} is not loaded, can not unload");
  233. return;
  234. }
  235. if (IsBusy)
  236. {
  237. EV.PostInfoLog(Module.ToString(), $"{Module} is busy can not unload");
  238. return;
  239. }
  240. if (IsError)
  241. {
  242. EV.PostInfoLog(Module.ToString(), $"{Module} is error can not unload");
  243. return;
  244. }
  245. IsBusy = true;
  246. CycleManager.Instance.InitLpData(Module.ToString());
  247. _controller.SendEfemAutoCommand(EfemEntity.MSG.Unload, Module);
  248. }
  249. public void UnloadStart()
  250. {
  251. if(_lpCallBack!=null)
  252. {
  253. _lpCallBack.UnLoadStart();
  254. }
  255. }
  256. public void OnUnloadFailed(string data)
  257. {
  258. IsError = true;
  259. IsBusy = false;
  260. _faCallback.UnloadFailed(this);
  261. }
  262. public void OnUnloaded()
  263. {
  264. IsBusy = false;
  265. IsError = false;
  266. IsLoaded = false;
  267. IsDocked = false;
  268. IsMapped = false;
  269. WaferManager.Instance.DeleteWafer(Module, 0, 25);
  270. if (SC.GetValue<bool>("EFEM.AutoUnlockAfterUnload"))
  271. {
  272. _faCallback.UnloadComplete(this);
  273. }
  274. else
  275. {
  276. }
  277. }
  278. #endregion
  279. #region Get Wafer Size
  280. /// <summary>
  281. /// 获取Wafer尺寸
  282. /// </summary>
  283. public bool GetWaferSize()
  284. {
  285. if (IsBusy)
  286. {
  287. EV.PostInfoLog(Module.ToString(), $"{Module} is busy can not get wafer size");
  288. return false;
  289. }
  290. if (IsError)
  291. {
  292. EV.PostInfoLog(Module.ToString(), $"{Module} is error can not get wafer size");
  293. return false;
  294. }
  295. IsBusy = true;
  296. return _efemBase.GetWaferSize(Module);
  297. }
  298. public void UpdateWaferSize(WaferSize waferSize)
  299. {
  300. WaferSize = waferSize;
  301. int count = WaferManager.Instance.GetSlotNumber(Module);
  302. for (int i = 0; i < count; i++)
  303. {
  304. WaferManager.Instance.UpdateWaferSize(Module, i, WaferSize);
  305. }
  306. IsBusy = false;
  307. IsError = false;
  308. }
  309. #endregion
  310. #region Dock
  311. public bool Dock()
  312. {
  313. if (IsBusy)
  314. {
  315. EV.PostInfoLog(Module.ToString(), $"{Module} is busy can not dock");
  316. return false;
  317. }
  318. if (IsError)
  319. {
  320. EV.PostInfoLog(Module.ToString(), $"{Module} is error can not dock");
  321. return false;
  322. }
  323. IsBusy = true;
  324. _controller.SendEfemAutoCommand(EfemEntity.MSG.Dock, Module);
  325. return true;
  326. }
  327. public void OnDocked()
  328. {
  329. IsBusy = false;
  330. IsError = false;
  331. }
  332. public void OnDockFailed(string data)
  333. {
  334. IsError = true;
  335. IsBusy = false;
  336. }
  337. #endregion
  338. #region Undock
  339. public void Undock()
  340. {
  341. if (IsBusy)
  342. {
  343. EV.PostInfoLog(Module.ToString(), $"{Module} is busy can not undock");
  344. return;
  345. }
  346. if (IsError)
  347. {
  348. EV.PostInfoLog(Module.ToString(), $"{Module} is error can not undock");
  349. return;
  350. }
  351. IsBusy = true;
  352. _controller.SendEfemAutoCommand(EfemEntity.MSG.Undock, Module);
  353. }
  354. public void OnUndocked()
  355. {
  356. IsBusy = false;
  357. IsError = false;
  358. }
  359. public void OnUndockFailed(string data)
  360. {
  361. IsError = true;
  362. IsBusy = false;
  363. }
  364. #endregion
  365. #region Clamp
  366. public void Clamp(bool isUnloadClamp)
  367. {
  368. if (IsBusy)
  369. {
  370. EV.PostInfoLog(Module.ToString(), $"{Module} is busy can not clamp");
  371. return;
  372. }
  373. if (IsError)
  374. {
  375. EV.PostInfoLog(Module.ToString(), $"{Module} is error can not clamp");
  376. return;
  377. }
  378. IsBusy = true;
  379. _controller.SendEfemAutoCommand(EfemEntity.MSG.Clamp, Module, isUnloadClamp);
  380. }
  381. public void OnClamped(bool isUnloadClamp)
  382. {
  383. IsBusy = false;
  384. IsError = false;
  385. if (isUnloadClamp)
  386. {
  387. _faCallback.UnloadComplete(this);
  388. }
  389. else
  390. {
  391. _faCallback.Clamped(this);
  392. }
  393. }
  394. public void OnClampFailed(string data)
  395. {
  396. IsError = true;
  397. IsBusy = false;
  398. }
  399. #endregion
  400. #region Unclamp
  401. public void Unclamp()
  402. {
  403. if (IsBusy)
  404. {
  405. EV.PostInfoLog(Module.ToString(), $"{Module} is busy can not unclamp");
  406. return;
  407. }
  408. if (IsError)
  409. {
  410. EV.PostInfoLog(Module.ToString(), $"{Module} is error can not unclamp");
  411. return;
  412. }
  413. IsBusy = true;
  414. _controller.SendEfemAutoCommand(EfemEntity.MSG.Unclamp, Module);
  415. }
  416. public void OnUnclamped()
  417. {
  418. IsBusy = false;
  419. IsError = false;
  420. _faCallback.Unclamped(this);
  421. }
  422. public void OnUnclampFailed(string data)
  423. {
  424. }
  425. #endregion
  426. #region map
  427. public void Map()
  428. {
  429. if (IsBusy)
  430. {
  431. EV.PostInfoLog(Module.ToString(), $"{Module} is busy can not unclamp");
  432. return;
  433. }
  434. if (IsError)
  435. {
  436. EV.PostInfoLog(Module.ToString(), $"{Module} is error can not unclamp");
  437. return;
  438. }
  439. IsBusy = true;
  440. _controller.SendEfemAutoCommand(EfemEntity.MSG.Map, Module);
  441. }
  442. public void OnMaped()
  443. {
  444. IsBusy = false;
  445. IsError = false;
  446. }
  447. #endregion
  448. #region carrierID
  449. public void ReadCarrierID()
  450. {
  451. if (IsBusy)
  452. {
  453. EV.PostInfoLog(Module.ToString(), $"{Module} is busy can not read carrier ID");
  454. return;
  455. }
  456. if (IsError)
  457. {
  458. EV.PostInfoLog(Module.ToString(), $"{Module} is error can not read carrier ID");
  459. return;
  460. }
  461. IsBusy = true;
  462. _controller.SendEfemAutoCommand(EfemEntity.MSG.ReadCarrierId, Module);
  463. }
  464. public void OnCarrierIDRead(string data)
  465. {
  466. IsBusy = false;
  467. IsError = false;
  468. //Regex rg = new Regex("(?<=(" + "LOT :" + "))[.\\s\\S]*?(?=(" + "QTY :" + "))", RegexOptions.Multiline | RegexOptions.Singleline);
  469. //string carrierID = rg.Match(data).Value.Replace(":", "").Trim();
  470. //data =
  471. // "CST:C082259 TYPE:CST25_AU LOT:AF2403 QTY:24 FLOW:033000 STATUS:HOLD PRI:3-1 PD:0418A CSRLOT: CLEAN:2021/11/14 19:57:50 EQPGRP:DUMMY STAGE:CP-TEST1 RECIPE:DUMMY EMP:N ";
  472. var items = data.Split(new string[] { " ", "\t", "\r", "\n" }, StringSplitOptions.RemoveEmptyEntries);
  473. CarrierId = "";
  474. foreach (var item in items)
  475. {
  476. if (item.StartsWith("CST:") && item.Length > 4)
  477. CarrierId = item.Substring(4).Trim();
  478. if (item.StartsWith("LOT:") && item.Length > 4)
  479. LotId = item.Substring(4).Trim();
  480. }
  481. if (string.IsNullOrEmpty(CarrierId))
  482. {
  483. CarrierId = data;
  484. }
  485. SmartTag = data;
  486. _faCallback.IDRead(this);
  487. }
  488. public void OnCarrierIDReadFailed(string data)
  489. {
  490. IsError = true;
  491. IsBusy = false;
  492. _faCallback.ReadIDFailed(this);
  493. }
  494. public void WriteCarrierID(string id)
  495. {
  496. if (IsBusy)
  497. {
  498. EV.PostInfoLog(Module.ToString(), $"{Module} is busy can not write carrier ID");
  499. return;
  500. }
  501. if (IsError)
  502. {
  503. EV.PostInfoLog(Module.ToString(), $"{Module} is error can not write carrier ID");
  504. return;
  505. }
  506. IsBusy = true;
  507. _controller.SendEfemAutoCommand(EfemEntity.MSG.WriteCarrierID, Module, id);
  508. }
  509. public void OnCarrierIDWrite(string data)
  510. {
  511. IsBusy = false;
  512. IsError = false;
  513. var items = data.Split(new string[] { " ", "\t", "\r", "\n" }, StringSplitOptions.RemoveEmptyEntries);
  514. CarrierId = "";
  515. foreach (var item in items)
  516. {
  517. if (item.StartsWith("CST:") && item.Length > 4)
  518. CarrierId = item.Substring(4);
  519. }
  520. if (string.IsNullOrEmpty(CarrierId))
  521. {
  522. CarrierId = data;
  523. }
  524. SmartTag = data;
  525. _faCallback.IDWrite(this);
  526. }
  527. public void OnCarrierIDWriteFailed(string data)
  528. {
  529. IsError = true;
  530. IsBusy = false;
  531. _faCallback.WriteIDFailed(this);
  532. }
  533. #endregion
  534. #region event
  535. public void HandleEvent(EfemEventArgs eArg)
  536. {
  537. switch (eArg.CommandType)
  538. {
  539. case EfemOperation.GetWaferInfo:
  540. string sWaferInfo = eArg.DataList[0];
  541. bool resultNormal = true;
  542. for (byte index = 0; index < sWaferInfo.Length; index++)
  543. {
  544. int waferState = int.Parse(sWaferInfo.Substring(index, 1));
  545. //合理的映射到内部支持的叠片/交叉片
  546. if (waferState >= 7) waferState = 7;
  547. else if (waferState >= 2) waferState = 3;
  548. WaferStatus st = (WaferStatus)waferState;
  549. if (st != WaferStatus.Empty)
  550. {
  551. WaferManager.Instance.CreateWafer(this.Module, index, st);
  552. if (st == WaferStatus.Normal)
  553. {
  554. //EV.PostInfoLog(this.Module.ToString(), $"Found Wafer on Slot {index + 1} {WaferSize}");
  555. }
  556. else
  557. {
  558. resultNormal = false;
  559. }
  560. }
  561. }
  562. if (resultNormal)
  563. {
  564. _faCallback.CarrierSlotMapComplete(this);
  565. }
  566. else
  567. {
  568. _faCallback.CarrierSlotMapFailed(this);
  569. }
  570. this.IsMapped = true;
  571. break;
  572. case EfemOperation.SigStatus:
  573. // EVT: SIGSTAT/P2/00000381/00000000;
  574. string sParam = eArg.DataList[0];
  575. ModuleName mod = sParam.ToModule();
  576. if (!ModuleHelper.IsLoadPort(mod))
  577. return;
  578. // DATA1 & DATA2
  579. int nData1 = Convert.ToInt32(eArg.DataList[1], 16);
  580. int nData2 = Convert.ToInt32(eArg.DataList[2], 16);
  581. BitArray baData1 = new BitArray(new int[] { nData1 });
  582. BitArray baData2 = new BitArray(new int[] { nData2 });
  583. // wafer size
  584. this.WaferSize = !baData1[6] ? WaferSize.WS3 :
  585. !baData1[7] ? WaferSize.WS4 :
  586. !baData1[8] ? WaferSize.WS6 : WaferSize.WS0;
  587. // placement & present
  588. bool bPlacement = baData1[0]; // bit 0
  589. bool bPresence = !baData1[1]; // bit 1
  590. bool bArrived = bPlacement && bPresence;
  591. UpdateWaferArrive(bArrived);
  592. this.Protrusion = !baData1[9];
  593. if (Protrusion)
  594. {
  595. //EV.PostAlarmLog(Module.ToString(), "发现 wafer 突出");
  596. //EV.Notify(AlarmWaferProtrude);
  597. //Singleton<RouteManager>.Instance.EFEM.PostMsg(EfemEntity.MSG.Error);
  598. }
  599. // DATA2, loadport上面的LED 灯, 暂时不需要用到
  600. break;
  601. default:
  602. break;
  603. }
  604. }
  605. /// <summary>
  606. /// 更新Wafer到达情况
  607. /// </summary>
  608. /// <param name="bArrived"></param>
  609. public void UpdateWaferArrive(bool bArrived)
  610. {
  611. if (HasCassette)
  612. {
  613. if (!bArrived)
  614. {
  615. this.HasCassette = false;
  616. this.IsMapped = false;
  617. //EV.PostInfoLog(mod.ToString(), "Cassette removed");
  618. //OP.DoOperation("System.CassetteLeave"); //For unload light control off afer job done
  619. CarrierManager.Instance.DeleteCarrier(Module.ToString());
  620. WaferManager.Instance.DeleteWafer(this.Module, 0, 25);
  621. _faCallback.CarrierRemoved(this);
  622. JobDone = false;
  623. _waferThicknessType = "";
  624. }
  625. }
  626. else
  627. {
  628. if (bArrived)
  629. {
  630. this.HasCassette = true;
  631. CarrierManager.Instance.CreateCarrier(Module.ToString());
  632. _faCallback.CarrierArrived(this);
  633. JobDone = false;
  634. _waferThicknessType = "";
  635. }
  636. }
  637. }
  638. #endregion
  639. #region TagData
  640. public void ReadTagData()
  641. {
  642. if (IsBusy)
  643. {
  644. EV.PostInfoLog(Module.ToString(), $"{Module} is busy can not read tag data");
  645. return;
  646. }
  647. if (IsError)
  648. {
  649. EV.PostInfoLog(Module.ToString(), $"{Module} is error can not read tag data");
  650. return;
  651. }
  652. IsBusy = true;
  653. _controller.SendEfemAutoCommand(EfemEntity.MSG.ReadTagData, Module);
  654. }
  655. public void OnTagDataRead(string data)
  656. {
  657. IsBusy = false;
  658. IsError = false;
  659. //Regex rg = new Regex("(?<=(" + "LOT :" + "))[.\\s\\S]*?(?=(" + "QTY :" + "))", RegexOptions.Multiline | RegexOptions.Singleline);
  660. //string carrierID = rg.Match(data).Value.Replace(":", "").Trim();
  661. //data =
  662. // "CST:C082259 TYPE:CST25_AU LOT:AF2403 QTY:24 FLOW:033000 STATUS:HOLD PRI:3-1 PD:0418A CSRLOT: CLEAN:2021/11/14 19:57:50 EQPGRP:DUMMY STAGE:CP-TEST1 RECIPE:DUMMY EMP:N ";
  663. var items = data.Split(new string[] { " ", "\t", "\r", "\n" }, StringSplitOptions.RemoveEmptyEntries);
  664. CarrierId = "";
  665. foreach (var item in items)
  666. {
  667. if (item.StartsWith("CST:") && item.Length > 4)
  668. CarrierId = item.Substring(4);
  669. if (item.StartsWith("LOT:") && item.Length > 4)
  670. LotId = item.Substring(4).Trim();
  671. }
  672. if (string.IsNullOrEmpty(CarrierId))
  673. {
  674. CarrierId = data;
  675. }
  676. SmartTag = data;
  677. _faCallback.TagDataRead(this);
  678. }
  679. public void OnTagDataReadFailed(string data)
  680. {
  681. IsError = true;
  682. IsBusy = false;
  683. _faCallback.ReadTagDataFailed(this);
  684. }
  685. public void WriteTagData(string tagData)
  686. {
  687. if (IsBusy)
  688. {
  689. EV.PostInfoLog(Module.ToString(), $"{Module} is busy can not write tag data");
  690. return;
  691. }
  692. if (IsError)
  693. {
  694. EV.PostInfoLog(Module.ToString(), $"{Module} is error can not write tag data");
  695. return;
  696. }
  697. IsBusy = true;
  698. _controller.SendEfemAutoCommand(EfemEntity.MSG.WriteTagData, Module, tagData);
  699. }
  700. public void OnTagDataWrite(string data)
  701. {
  702. IsBusy = false;
  703. IsError = false;
  704. var items = data.Split(new string[] { " ", "\t", "\r", "\n" }, StringSplitOptions.RemoveEmptyEntries);
  705. CarrierId = "";
  706. foreach (var item in items)
  707. {
  708. if (item.StartsWith("CST:") && item.Length > 4)
  709. CarrierId = item.Substring(4);
  710. }
  711. if (string.IsNullOrEmpty(CarrierId))
  712. {
  713. CarrierId = data;
  714. }
  715. SmartTag = data;
  716. _faCallback.TagDataWrite(this);
  717. }
  718. public void OnTagDataWriteFailed(string data)
  719. {
  720. IsError = true;
  721. IsBusy = false;
  722. _faCallback.WriteTagDataFailed( this);
  723. }
  724. #endregion
  725. public void SetOnline(bool online)
  726. {
  727. OnlineFlag = online ? OnlineFlag.Online : OnlineFlag.Offline;
  728. }
  729. sealed class LoadPortFACallback
  730. {
  731. private string CARRIER_ARRIVED = "CARRIER_ARRIVED";
  732. private string CARRIER_REMOVED = "CARRIER_REMOVED";
  733. private string SLOT_MAP_AVAILABLE = "SLOT_MAP_AVAILABLE";
  734. private string SLOT_MAP_FAILED = "SLOT_MAP_FAILED";
  735. private const string CARRIER_LOADED = "CARRIER_LOADED";
  736. private const string PortLoadFailed = "PortLoadFailed";
  737. private const string CARRIER_UNLOADED = "CARRIER_UNLOADED";
  738. private const string PortUnloadFailed = "PortUnloadFailed";
  739. private const string PortClamped = "PortClamped";
  740. private const string PortUnclamped = "PortUnclamped";
  741. private const string CARRIER_ID_READ = "CARRIER_ID_READ";
  742. private const string PortReadIDFailed = "PortReadIDFailed";
  743. private const string PortIDWrite = "PortIDWrite";
  744. private const string PortWriteIDFailed = "PortWriteIDFailed";
  745. private const string PortTagDataRead = "PortTagDataRead";
  746. private const string PortReadTagDataFailed = "PortReadTagDataFailed";
  747. private const string PortTagDataWrite = "PortTagDataWrite";
  748. private const string PortWriteTagDataFailed = "PortWriteTagDataFailed";
  749. public LoadPortFACallback()
  750. {
  751. EV.Subscribe(new EventItem("Event", CARRIER_ARRIVED, "Carrier Arrived"));
  752. EV.Subscribe(new EventItem("Event", CARRIER_REMOVED, "Carrier Removed"));
  753. EV.Subscribe(new EventItem("Event", SLOT_MAP_AVAILABLE, "Slot map available"));
  754. EV.Subscribe(new EventItem("Event", SLOT_MAP_FAILED, "Slot map failed"));
  755. EV.Subscribe(new EventItem("Event", CARRIER_LOADED, "Carrier Loaded"));
  756. EV.Subscribe(new EventItem("Event", PortLoadFailed, PortLoadFailed));
  757. EV.Subscribe(new EventItem("Event", CARRIER_UNLOADED, "Carrier Unloaded"));
  758. EV.Subscribe(new EventItem("Event", PortUnloadFailed, PortUnloadFailed));
  759. EV.Subscribe(new EventItem("Event", PortClamped, "Port Clamped"));
  760. EV.Subscribe(new EventItem("Event", PortUnclamped, PortUnclamped));
  761. EV.Subscribe(new EventItem("Event", CARRIER_ID_READ, "Carrier Id Read"));
  762. EV.Subscribe(new EventItem("Event", PortReadIDFailed, PortReadIDFailed));
  763. EV.Subscribe(new EventItem("Event", PortIDWrite, PortIDWrite));
  764. EV.Subscribe(new EventItem("Event", PortWriteIDFailed, PortWriteIDFailed));
  765. EV.Subscribe(new EventItem("Event", PortTagDataRead, PortTagDataRead));
  766. EV.Subscribe(new EventItem("Event", PortReadTagDataFailed, PortReadTagDataFailed));
  767. EV.Subscribe(new EventItem("Event", PortTagDataWrite, PortTagDataWrite));
  768. EV.Subscribe(new EventItem("Event", PortWriteTagDataFailed, PortWriteTagDataFailed));
  769. }
  770. public void CarrierArrived(Loadport lp)
  771. {
  772. SerializableDictionary<string, string> dvid = new SerializableDictionary<string, string>();
  773. dvid["PortID"] = lp.PortId;
  774. EV.Notify(CARRIER_ARRIVED, dvid);
  775. }
  776. public void CarrierRemoved(Loadport lp)
  777. {
  778. SerializableDictionary<string, string> dvid = new SerializableDictionary<string, string>();
  779. dvid["PortID"] = lp.PortId;
  780. dvid["CarrierID"] = lp.CarrierId ?? "";
  781. EV.Notify(CARRIER_REMOVED, dvid);
  782. }
  783. public void CarrierSlotMapComplete(Loadport lp)
  784. {
  785. SerializableDictionary<string, string> dvid = new SerializableDictionary<string, string>();
  786. dvid["SlotMap"] = lp.SlotMap;
  787. dvid["PortID"] = lp.PortId;
  788. dvid["CarrierID"] = lp.CarrierId ?? "";
  789. EV.Notify(SLOT_MAP_AVAILABLE, dvid);
  790. }
  791. public void CarrierSlotMapFailed(Loadport lp)
  792. {
  793. }
  794. public void LoadComplete(Loadport lp)
  795. {
  796. ModuleName moduleName = lp.Module;
  797. var dvid = new SerializableDictionary<string, string>
  798. {
  799. ["CarrierID"] = lp.CarrierId ?? "",
  800. ["PortID"] = lp.PortId.ToString()
  801. };
  802. EV.Notify(CARRIER_LOADED, dvid);
  803. }
  804. public void LoadFailed(Loadport lp)
  805. {
  806. }
  807. public void UnloadComplete(Loadport lp)
  808. {
  809. ModuleName moduleName = lp.Module;
  810. var dvid = new SerializableDictionary<string, string>
  811. {
  812. ["CarrierID"] = lp.CarrierId ?? "",
  813. ["PortID"] = lp.PortId.ToString()
  814. };
  815. EV.Notify(CARRIER_UNLOADED, dvid);
  816. }
  817. public void UnloadFailed(Loadport lp)
  818. {
  819. }
  820. public void Clamped(Loadport lp)
  821. {
  822. }
  823. public void Unclamped(Loadport lp)
  824. {
  825. }
  826. public void IDRead(Loadport lp)
  827. {
  828. }
  829. public void ReadIDFailed(Loadport lp)
  830. {
  831. }
  832. public void IDWrite(Loadport lp)
  833. {
  834. }
  835. public void WriteIDFailed(Loadport lp)
  836. {
  837. }
  838. public void TagDataRead(Loadport lp)
  839. {
  840. }
  841. public void ReadTagDataFailed(Loadport lp)
  842. {
  843. }
  844. public void TagDataWrite(Loadport lp)
  845. {
  846. }
  847. public void WriteTagDataFailed(Loadport lp)
  848. {
  849. }
  850. }
  851. }
  852. }