Loadport.cs 34 KB

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