Loadport.cs 37 KB

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