AutoCycle.cs 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using Aitex.Core.RT.Routine;
  5. using Aitex.Core.RT.SCCore;
  6. using Aitex.Sorter.Common;
  7. using Aitex.Core.RT.Log;
  8. using Aitex.Core.Util;
  9. using Aitex.Core.RT.DataCenter;
  10. using Aitex.Core.RT.Fsm;
  11. using MECF.Framework.Common.Jobs;
  12. using MECF.Framework.Common.Routine;
  13. using MECF.Framework.Common.Equipment;
  14. using MECF.Framework.Common.SubstrateTrackings;
  15. using MECF.Framework.Common.Schedulers;
  16. using Venus_Core;
  17. using Venus_RT.Modules.Schedulers;
  18. using Venus_RT.Scheduler;
  19. namespace Venus_RT.Modules
  20. {
  21. enum ModulePriority
  22. {
  23. High,
  24. Middle,
  25. Low,
  26. Stop,
  27. }
  28. enum MovingStatus
  29. {
  30. Staying,
  31. Waiting,
  32. Moving,
  33. }
  34. class ModuleFlag
  35. {
  36. public ModulePriority Priority { get; set; }
  37. public MovingStatus MovingStatus { get; set; }
  38. public ModuleFlag(ModulePriority _priority)
  39. {
  40. Priority = _priority;
  41. MovingStatus = MovingStatus.Staying;
  42. }
  43. }
  44. class AutoCycle : IRoutine
  45. {
  46. private List<ControlJobInfo> _lstControlJobs = new List<ControlJobInfo>();
  47. private List<ProcessJobInfo> _lstProcessJobs = new List<ProcessJobInfo>();
  48. private RState _cycleState = RState.Init;
  49. Dictionary<ModuleName, SchedulerModule> _atmSchedulers = new Dictionary<ModuleName, SchedulerModule>();
  50. Dictionary<ModuleName, ModuleFlag> _atmModules = new Dictionary<ModuleName, ModuleFlag>();
  51. Dictionary<ModuleName, SchedulerModule> _vacSchedulers = new Dictionary<ModuleName, SchedulerModule>();
  52. Dictionary<ModuleName, ModuleFlag> _vacModules = new Dictionary<ModuleName, ModuleFlag>();
  53. SchedulerTMRobot _tmRobot = new SchedulerTMRobot();
  54. SchedulerEfemRobot _efemRobot = new SchedulerEfemRobot();
  55. List<SlotItem> _vacReadyOutSlots = new List<SlotItem>();
  56. List<SlotItem> _vacReadyInSlots = new List<SlotItem>();
  57. List<SlotItem> _atmReadyOutSlots = new List<SlotItem>();
  58. List<SlotItem> _atmReadyInSlots = new List<SlotItem>();
  59. List<int> _LLAInSlot = new List<int> { 0, 1, 2, 3 };
  60. List<int> _LLAOutSlot = new List<int> { 0, 1, 2, 3 };
  61. List<int> _LLBInSlot = new List<int> { 0, 1, 2, 3 };
  62. List<int> _LLBOutSlot = new List<int> { 0, 1, 2, 3 };
  63. List<MoveItem> _movingItems = new List<MoveItem>();
  64. List<MoveItem> _efemMovingItems = new List<MoveItem>();
  65. Dictionary<SlotItem, Guid> _vacWaferTargets = new Dictionary<SlotItem, Guid>();
  66. Dictionary<SlotItem, Guid> _atmWaferTargets = new Dictionary<SlotItem, Guid>();
  67. private bool _isCycleMode;
  68. private int _cycleSetPoint = 0;
  69. private int _cycledCount = 0;
  70. private int _cycledWafer = 0;
  71. #region public interface
  72. public AutoCycle()
  73. {
  74. InitModules();
  75. DATA.Subscribe("Scheduler.CycledCount", () => _cycledCount);
  76. DATA.Subscribe("Scheduler.CycledWafer", () => _cycledWafer);
  77. DATA.Subscribe("Scheduler.CycleSetPoint", () => _cycleSetPoint);
  78. DATA.Subscribe("Scheduler.PjIdList", () => Array.ConvertAll(_lstProcessJobs.ToArray(), x => x.InnerId.ToString()).ToList());
  79. }
  80. public RState Start(params object[] objs)
  81. {
  82. _isCycleMode = SC.GetValue<bool>("System.IsCycleMode");
  83. _cycleSetPoint = _isCycleMode ? SC.GetValue<int>("System.CycleCount") : 0;
  84. _cycledWafer = 0;
  85. _cycledCount = 0;
  86. return RState.Running;
  87. }
  88. public RState Monitor()
  89. {
  90. prelude();
  91. driveAtmSystem();
  92. driveVacSystem();
  93. epilogue();
  94. return _cycleState;
  95. }
  96. public void Abort()
  97. {
  98. }
  99. public bool CheckAllJobDone()
  100. {
  101. foreach (var cj in _lstControlJobs)
  102. {
  103. if (cj.State == EnumControlJobState.Executing || cj.State == EnumControlJobState.Paused)
  104. return false;
  105. }
  106. return true;
  107. }
  108. public bool CheckJobJustDone(out string sJobName)
  109. {
  110. foreach (var cj in _lstControlJobs)
  111. {
  112. if (cj.State == EnumControlJobState.Completed && !cj.BeenPosted)
  113. {
  114. //LP;WaferSize;Lot;Number;Start;End;
  115. sJobName = $"{cj.Module};{cj.JobWaferSize};{cj.LotName};{cj.LotWafers.Count};{cj.StartTime:T};{cj.EndTime:T}";
  116. cj.BeenPosted = true;
  117. return true;
  118. }
  119. }
  120. sJobName = "NULL";
  121. return false;
  122. }
  123. #endregion
  124. private void InitModules()
  125. {
  126. foreach(var module in new ModuleName[]{ ModuleName.LP1, ModuleName.LP2, ModuleName.LP3,
  127. ModuleName.Aligner1, ModuleName.Aligner2, ModuleName.Cooling1, ModuleName.Cooling2})
  128. {
  129. if(ModuleHelper.IsInstalled(module))
  130. {
  131. if(ModuleHelper.IsLoadPort(module))
  132. {
  133. _atmSchedulers[module] = new SchedulerLoadPort(module);
  134. _atmModules[module] = new ModuleFlag(ModulePriority.Middle);
  135. }
  136. else if(ModuleHelper.IsAligner(module) || ModuleHelper.IsCooling(module))
  137. {
  138. _atmSchedulers[module] = new SchedulerAligner(module);
  139. _atmModules[module] = new ModuleFlag(ModulePriority.Middle);
  140. }
  141. }
  142. }
  143. foreach (var module in new ModuleName[] { ModuleName.PMA, ModuleName.PMB, ModuleName.PMC,
  144. ModuleName.PMD, ModuleName.PME, ModuleName.PMF})
  145. {
  146. if (ModuleHelper.IsInstalled(module))
  147. {
  148. _vacSchedulers[module] = new SchedulerPM(module);
  149. _vacModules[module] = new ModuleFlag(ModulePriority.Middle);
  150. }
  151. }
  152. foreach (var module in new ModuleName[] { ModuleName.LLA, ModuleName.LLB })
  153. {
  154. if (ModuleHelper.IsInstalled(module))
  155. {
  156. var llScheduler = new SchedulerLoadLock(module);
  157. _vacSchedulers[module] = llScheduler;
  158. _vacModules[module] = new ModuleFlag(ModulePriority.Middle);
  159. _atmSchedulers[module] = llScheduler;
  160. _atmModules[module] = new ModuleFlag(ModulePriority.Middle);
  161. }
  162. }
  163. }
  164. private void prelude()
  165. {
  166. }
  167. private void epilogue()
  168. {
  169. foreach(var mod in _vacSchedulers)
  170. {
  171. if(mod.Value.IsAvailable)
  172. {
  173. var tars = _vacWaferTargets.Where(item => item.Key.Module == mod.Key).ToArray();
  174. foreach(var tar in tars)
  175. {
  176. var wafer = WaferManager.Instance.GetWafer(tar.Key.Module, tar.Key.Slot);
  177. if (wafer.IsEmpty)
  178. continue;
  179. if(wafer.InnerId == tar.Value)
  180. {
  181. // wafer arrive
  182. _vacWaferTargets.Remove(tar.Key);
  183. wafer.NextSequenceStep++;
  184. }
  185. }
  186. }
  187. }
  188. foreach(var mod in _atmSchedulers)
  189. {
  190. if (mod.Value.IsAvailable)
  191. {
  192. var tars = _atmWaferTargets.Where(item => item.Key.Module == mod.Key).ToArray();
  193. foreach (var tar in tars)
  194. {
  195. var wafer = WaferManager.Instance.GetWafer(tar.Key.Module, tar.Key.Slot);
  196. if (wafer.IsEmpty)
  197. continue;
  198. if (wafer.InnerId == tar.Value)
  199. {
  200. // wafer arrive
  201. _atmWaferTargets.Remove(tar.Key);
  202. if (!ModuleHelper.IsLoadPort(tar.Key.Module))
  203. wafer.NextSequenceStep++;
  204. }
  205. }
  206. }
  207. }
  208. }
  209. private void driveVacSystem()
  210. {
  211. PumpingTMRobotTask();
  212. ProcessTMRobotTask();
  213. RuningTMRobotTask();
  214. }
  215. #region Vacuum System
  216. private void PumpingTMRobotTask()
  217. {
  218. foreach(var mod in _vacSchedulers)
  219. {
  220. if (mod.Value.IsAvailable && _vacModules[mod.Key].MovingStatus == MovingStatus.Staying)
  221. {
  222. if(ModuleHelper.IsLoadLock(mod.Key))
  223. {
  224. var inSlots = mod.Key == ModuleName.LLA ? _LLAInSlot : _LLBInSlot;
  225. foreach(var slot in inSlots)
  226. {
  227. if(WaferManager.Instance.CheckHasWafer(mod.Key, slot) && IsVacWaferReadyOut(mod.Key, slot))
  228. {
  229. _vacReadyOutSlots.Add(new SlotItem(mod.Key, slot));
  230. _vacModules[mod.Key].MovingStatus = MovingStatus.Waiting;
  231. }
  232. }
  233. var outSlots = mod.Key == ModuleName.LLA ? _LLAOutSlot : _LLBOutSlot;
  234. foreach(var slot in outSlots)
  235. {
  236. if(WaferManager.Instance.CheckNoWafer(mod.Key, slot))
  237. {
  238. _vacReadyInSlots.Add(new SlotItem(mod.Key, slot));
  239. _vacModules[mod.Key].MovingStatus = MovingStatus.Waiting;
  240. }
  241. }
  242. }
  243. else
  244. {
  245. if(WaferManager.Instance.CheckHasWafer(mod.Key, 0) && IsVacWaferReadyOut(mod.Key, 0)) // processed?
  246. {
  247. _vacReadyOutSlots.Add(new SlotItem(mod.Key, 0));
  248. _vacModules[mod.Key].MovingStatus = MovingStatus.Waiting;
  249. }
  250. else
  251. {
  252. _vacReadyInSlots.Add(new SlotItem(mod.Key, 0));
  253. _vacModules[mod.Key].MovingStatus = MovingStatus.Waiting;
  254. }
  255. }
  256. }
  257. }
  258. }
  259. bool SearchWaferDestination(SlotItem outSlot, out SlotItem destSlot)
  260. {
  261. destSlot = new SlotItem(ModuleName.System, -1);
  262. var wafer = WaferManager.Instance.GetWafer(outSlot.Module, outSlot.Slot);
  263. foreach (var next_module in wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepModules)
  264. {
  265. var validSlots = GetModuleValidSlots(next_module);
  266. foreach (var nSlot in validSlots)
  267. {
  268. if (_movingItems.Exists(mItem => mItem.DestinationModule == next_module && mItem.DestinationSlot == nSlot))
  269. continue;
  270. var ready_in = _vacReadyInSlots.Find(item => item.Module == next_module && item.Slot == nSlot);
  271. if (ready_in != null)
  272. {
  273. destSlot.Module = ready_in.Module;
  274. destSlot.Slot = nSlot;
  275. return true;
  276. }
  277. }
  278. }
  279. return false;
  280. }
  281. List<int> GetModuleValidSlots(ModuleName mod)
  282. {
  283. var validSlot = new List<int>();
  284. if(ModuleHelper.IsLoadLock(mod))
  285. {
  286. var inSlots = mod == ModuleName.LLA ? _LLAInSlot : _LLBInSlot;
  287. foreach (var slot in inSlots)
  288. {
  289. if (WaferManager.Instance.CheckNoWafer(mod, slot) && !_movingItems.Exists(item => item.DestinationModule == mod && item.DestinationSlot == slot))
  290. validSlot.Add(slot);
  291. if (WaferManager.Instance.CheckHasWafer(mod, slot) && _movingItems.Exists(item => item.SourceModule == mod && item.SourceSlot == slot))
  292. validSlot.Add(slot);
  293. }
  294. }
  295. else if(ModuleHelper.IsPm(mod))
  296. {
  297. if (WaferManager.Instance.CheckNoWafer(mod, 0) && !_movingItems.Exists(item => item.DestinationModule == mod))
  298. validSlot.Add(0);
  299. if (WaferManager.Instance.CheckHasWafer(mod, 0) && _movingItems.Exists(item => item.SourceModule == mod))
  300. validSlot.Add(0);
  301. }
  302. return validSlot.Distinct().ToList();
  303. }
  304. List<MoveItem> SearchWaitInSlots(ModuleName inModule)
  305. {
  306. List<MoveItem> inSlots = new List<MoveItem>();
  307. var validSlots = GetModuleValidSlots(inModule);
  308. foreach(var slot in _vacReadyOutSlots)
  309. {
  310. if (slot.Module == inModule)
  311. continue;
  312. var wafer = WaferManager.Instance.GetWafer(slot.Module, slot.Slot);
  313. foreach (var next_module in wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepModules)
  314. {
  315. if(next_module == inModule && validSlots.Count > 0)
  316. {
  317. inSlots.Add(new MoveItem(slot.Module, slot.Slot, inModule, validSlots.First(), Hand.None) );
  318. validSlots.RemoveAt(0);
  319. }
  320. }
  321. }
  322. return inSlots;
  323. }
  324. private void ProcessTMRobotTask()
  325. {
  326. if(_tmRobot.IsAvailable)
  327. {
  328. if(WaferManager.Instance.CheckHasWafer(ModuleName.TMRobot, 0) || WaferManager.Instance.CheckHasWafer(ModuleName.TMRobot, 1))
  329. {
  330. return;
  331. }
  332. foreach(var slot in _vacReadyOutSlots)
  333. {
  334. if(ModuleHelper.IsLoadLock(slot.Module))
  335. {
  336. if(SearchWaferDestination(slot, out SlotItem destSlot))
  337. {
  338. _movingItems.Add(new MoveItem(slot.Module, slot.Slot, destSlot.Module, destSlot.Slot, Hand.None));
  339. // check whether match double pick pattern
  340. var out_slot_2 = _vacReadyOutSlots.Find(item => item.Module == slot.Module && item.Slot != slot.Slot);
  341. if (out_slot_2 != null)
  342. {
  343. if(SearchWaferDestination(out_slot_2, out SlotItem destSlot_2))
  344. {
  345. _movingItems.Add(new MoveItem(out_slot_2.Module, out_slot_2.Slot, destSlot_2.Module, destSlot_2.Slot, Hand.None));
  346. }
  347. }
  348. // check whether match swap pattern
  349. var in_slots = SearchWaitInSlots(slot.Module);
  350. foreach(var in_slot in in_slots)
  351. {
  352. _movingItems.Add(in_slot);
  353. }
  354. return;
  355. }
  356. }
  357. else // PM
  358. {
  359. if(SearchWaferDestination(slot, out SlotItem destSlot))
  360. {
  361. _movingItems.Add(new MoveItem(slot.Module, slot.Slot, destSlot.Module, destSlot.Slot, Hand.None));
  362. // check whether match swap pattern
  363. var in_slots = SearchWaitInSlots(slot.Module);
  364. if(in_slots.Count >= 1)
  365. {
  366. _movingItems.Add(in_slots.First());
  367. }
  368. else
  369. {
  370. // check whether match double move pattern
  371. var same_dest = SearchWaitInSlots(destSlot.Module);
  372. foreach (var item in same_dest)
  373. {
  374. _movingItems.Add(item);
  375. }
  376. }
  377. return;
  378. }
  379. }
  380. }
  381. }
  382. }
  383. private void RuningTMRobotTask()
  384. {
  385. if(_tmRobot.IsAvailable)
  386. {
  387. if(_tmRobot.PostMoveItems(_movingItems.ToArray()))
  388. {
  389. foreach(var item in _movingItems)
  390. {
  391. var wafer = WaferManager.Instance.GetWafer(item.SourceModule, item.SourceSlot);
  392. if (wafer.IsEmpty)
  393. {
  394. // post alarm
  395. LOG.Write(eEvent.ERR_ROUTER, ModuleName.System, $"Cannot run TM moving task as Get {item.SourceModule}{item.SourceModule} Wafer Info failed");
  396. return;
  397. }
  398. var slot = new SlotItem(item.DestinationModule, item.DestinationSlot);
  399. _vacWaferTargets[slot] = wafer.InnerId;
  400. }
  401. _movingItems.Clear();
  402. }
  403. }
  404. }
  405. private Hand GetTMRobotFreeHand()
  406. {
  407. var blade1HasWafer = WaferManager.Instance.CheckHasWafer(ModuleName.TMRobot, 0);
  408. var blade2HasWafer = WaferManager.Instance.CheckHasWafer(ModuleName.TMRobot, 1);
  409. if (blade1HasWafer && blade2HasWafer)
  410. return Hand.None;
  411. else if (!blade1HasWafer && !blade2HasWafer)
  412. return Hand.Both;
  413. else if (blade1HasWafer)
  414. return Hand.Blade2;
  415. else
  416. return Hand.Blade1;
  417. }
  418. private bool IsVacWaferReadyOut(ModuleName mod, int slot)
  419. {
  420. var wafer = WaferManager.Instance.GetWafer(mod, slot);
  421. if (wafer.IsEmpty)
  422. return false;
  423. if (wafer.ProcessJob == null || wafer.ProcessJob.Sequence == null)
  424. return false;
  425. if (wafer.NextSequenceStep >= wafer.ProcessJob.Sequence.Steps.Count)
  426. {
  427. // should not go here
  428. LOG.Write(eEvent.ERR_ROUTER, ModuleName.System, $"Wafer:{wafer.WaferOrigin} NextSequenceStep {wafer.NextSequenceStep} exceeds {wafer.ProcessJob.Sequence.Name} max steps number");
  429. return false;
  430. }
  431. if (wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepModules.Contains(mod))
  432. return false;
  433. foreach(var module in wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepModules)
  434. {
  435. if (ModuleHelper.IsLoadLock(module) || ModuleHelper.IsPm(module))
  436. return true;
  437. }
  438. return false;
  439. }
  440. #endregion Vacuum System
  441. #region Atm System
  442. private void driveAtmSystem()
  443. {
  444. PumpingEFEMRobotTask();
  445. RuningEFEMRobotTask();
  446. }
  447. private void PumpingEFEMRobotTask()
  448. {
  449. if (!_efemRobot.IsAvailable)
  450. return;
  451. foreach(var scheduler in _atmSchedulers)
  452. {
  453. if (!scheduler.Value.IsAvailable)
  454. continue;
  455. if(ModuleHelper.IsLoadLock(scheduler.Key))
  456. {
  457. if (ProcessLLEFEMRobotTask(scheduler.Key))
  458. return;
  459. }
  460. else if(ModuleHelper.IsLoadPort(scheduler.Key))
  461. {
  462. if (ProcessLPEFEMRobotTask(scheduler.Key))
  463. return;
  464. }
  465. else if(ModuleHelper.IsAligner(scheduler.Key))
  466. {
  467. if (ProcessAlignerEFEMRobotTask(scheduler.Key))
  468. return;
  469. }
  470. else if(ModuleHelper.IsCooling(scheduler.Key))
  471. {
  472. if (ProcessCoolingEFEMRobotTask(scheduler.Key))
  473. return;
  474. }
  475. else
  476. {
  477. // should not go here
  478. LOG.Write(eEvent.ERR_ROUTER, $"Wrong Module: {scheduler.Key} in ATM System");
  479. }
  480. }
  481. }
  482. List<int> GetEfemRobotWaferReadyInHands(ModuleName mod)
  483. {
  484. var slots = new List<int>();
  485. for(int i = 0; i < 2; i++)
  486. {
  487. var wafer = WaferManager.Instance.GetWafer(ModuleName.EfemRobot, i);
  488. if (wafer.IsEmpty)
  489. continue;
  490. if (wafer.ProcessJob == null || wafer.ProcessJob.Sequence == null)
  491. continue;
  492. if (wafer.NextSequenceStep >= wafer.ProcessJob.Sequence.Steps.Count)
  493. {
  494. // should not go here
  495. LOG.Write(eEvent.ERR_ROUTER, ModuleName.System, $"Wafer:{wafer.WaferOrigin} NextSequenceStep {wafer.NextSequenceStep} exceeds {wafer.ProcessJob.Sequence.Name} max steps number");
  496. continue;
  497. }
  498. if (wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepModules.Contains(mod))
  499. {
  500. slots.Add(i);
  501. }
  502. }
  503. return slots;
  504. }
  505. bool IsAtmWaferReadyOut(ModuleName mod, int slot)
  506. {
  507. var wafer = WaferManager.Instance.GetWafer(mod, slot);
  508. if (wafer.IsEmpty)
  509. return false;
  510. if (wafer.ProcessJob == null || wafer.ProcessJob.Sequence == null)
  511. return false;
  512. if (wafer.NextSequenceStep >= wafer.ProcessJob.Sequence.Steps.Count)
  513. {
  514. // should not go here
  515. LOG.Write(eEvent.ERR_ROUTER, ModuleName.System, $"Wafer:{wafer.WaferOrigin} NextSequenceStep {wafer.NextSequenceStep} exceeds {wafer.ProcessJob.Sequence.Name} max steps number");
  516. return false;
  517. }
  518. if (wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepModules.Contains(mod))
  519. return false;
  520. if(ModuleHelper.IsLoadLock(mod))
  521. {
  522. foreach (var module in wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepModules)
  523. {
  524. if (ModuleHelper.IsPm(module))
  525. return false;
  526. }
  527. }
  528. return true;
  529. }
  530. private bool ProcessLLEFEMRobotTask(ModuleName ll)
  531. {
  532. var robotSlots = GetEfemRobotWaferReadyInHands(ll);
  533. var inSlots = ll == ModuleName.LLA ? _LLAInSlot : _LLBInSlot;
  534. foreach(var slot in inSlots)
  535. {
  536. if(robotSlots.Count >= 1)
  537. {
  538. if(WaferManager.Instance.CheckNoWafer(ll, slot))
  539. {
  540. _efemMovingItems.Add(new MoveItem(ModuleName.EfemRobot, robotSlots.First(), ll, slot, (Hand)robotSlots.First()));
  541. robotSlots.RemoveAt(0);
  542. }
  543. }
  544. }
  545. var outSlots = ll == ModuleName.LLA ? _LLAOutSlot : _LLBOutSlot;
  546. foreach(var slot in outSlots)
  547. {
  548. if(IsAtmWaferReadyOut(ll, slot))
  549. {
  550. var robotHand = GetEFEMRobotFreeHand();
  551. if(robotHand != Hand.None)
  552. {
  553. _efemMovingItems.Add(new MoveItem(ll, slot, ModuleName.EfemRobot, (int)robotHand, robotHand));
  554. }
  555. }
  556. }
  557. return _efemMovingItems.Count > 0;
  558. }
  559. private bool ProcessLPEFEMRobotTask(ModuleName lp)
  560. {
  561. // check return
  562. for(int i = 0; i < 2; i++)
  563. {
  564. if(WaferManager.Instance.CheckHasWafer(ModuleName.EfemRobot, i))
  565. {
  566. var returnWafer = WaferManager.Instance.GetWafer(ModuleName.EfemRobot, i);
  567. if (returnWafer.IsEmpty)
  568. continue;
  569. if (returnWafer.ProcessJob == null || returnWafer.ProcessJob.Sequence == null)
  570. continue;
  571. if (returnWafer.NextSequenceStep >= returnWafer.ProcessJob.Sequence.Steps.Count && lp == (ModuleName)returnWafer.OriginStation) // need return
  572. {
  573. _efemMovingItems.Add(new MoveItem(ModuleName.EfemRobot, i, lp, returnWafer.OriginSlot, (Hand)i));
  574. }
  575. }
  576. }
  577. if (_efemMovingItems.Count > 0)
  578. return true;
  579. var outSlots = GetNextWaferInJobQueue(lp);
  580. foreach(var slot in outSlots)
  581. {
  582. var hand = GetEFEMRobotFreeHand();
  583. if(hand != Hand.None)
  584. {
  585. _efemMovingItems.Add(new MoveItem(lp, slot, ModuleName.EfemRobot, (int)hand, hand));
  586. }
  587. }
  588. return _efemMovingItems.Count > 0;
  589. }
  590. private List<int> GetNextWaferInJobQueue(ModuleName lp)
  591. {
  592. var inSlots = new List<int>();
  593. return inSlots;
  594. //if (GetSystemInnerWaferCount() >= SystemInternalWaferCount || GetBufferWaferCount() > _maxBufferWaferCount)
  595. // return new SlotItem(ModuleName.System, -1);
  596. //foreach (var cj in _lstControlJobs)
  597. //{
  598. // if (lpModule != ModuleName.System && (cj.Module != lpModule.ToString()))
  599. // continue;
  600. // if (cj.State == EnumControlJobState.Executing)
  601. // {
  602. // foreach (var pj in _lstProcessJobs)
  603. // {
  604. // if (pj.ControlJobName == cj.Name && pj.State == EnumProcessJobState.Processing)
  605. // {
  606. // foreach (var pjSlotWafer in pj.SlotWafers)
  607. // {
  608. // if (CheckWaferNeedProcessAndPMAvailable(pjSlotWafer.Item1, pjSlotWafer.Item2))
  609. // {
  610. // return new SlotItem(pjSlotWafer.Item1, pjSlotWafer.Item2);
  611. // }
  612. // }
  613. // }
  614. // }
  615. // }
  616. //}
  617. //return new SlotItem(ModuleName.System, -1);
  618. }
  619. private bool ProcessAlignerEFEMRobotTask(ModuleName aligner)
  620. {
  621. if(WaferManager.Instance.CheckHasWafer(aligner, 0) && IsAtmWaferReadyOut(aligner, 0))
  622. {
  623. var hand = GetEFEMRobotFreeHand();
  624. if(hand != Hand.None)
  625. {
  626. _efemMovingItems.Add(new MoveItem(aligner, 0, ModuleName.EfemRobot, (int)hand, hand));
  627. }
  628. }
  629. else
  630. {
  631. var robotSlots = GetEfemRobotWaferReadyInHands(aligner);
  632. if(robotSlots.Count > 0)
  633. {
  634. _efemMovingItems.Add(new MoveItem(aligner, 0, ModuleName.EfemRobot, robotSlots.First(), (Hand)robotSlots.First()));
  635. }
  636. }
  637. return _efemMovingItems.Count > 0;
  638. }
  639. private bool ProcessCoolingEFEMRobotTask(ModuleName cooling)
  640. {
  641. if (WaferManager.Instance.CheckHasWafer(cooling, 0) && IsAtmWaferReadyOut(cooling, 0))
  642. {
  643. var hand = GetEFEMRobotFreeHand();
  644. if (hand != Hand.None)
  645. {
  646. _efemMovingItems.Add(new MoveItem(cooling, 0, ModuleName.EfemRobot, (int)hand, hand));
  647. }
  648. }
  649. else
  650. {
  651. var robotSlots = GetEfemRobotWaferReadyInHands(cooling);
  652. if (robotSlots.Count > 0)
  653. {
  654. _efemMovingItems.Add(new MoveItem(cooling, 0, ModuleName.EfemRobot, robotSlots.First(), (Hand)robotSlots.First()));
  655. }
  656. }
  657. return _efemMovingItems.Count > 0;
  658. }
  659. private void RuningEFEMRobotTask()
  660. {
  661. if (_efemRobot.IsAvailable)
  662. {
  663. if (_efemRobot.PostMoveItems(_efemMovingItems.ToArray()))
  664. {
  665. foreach (var item in _efemMovingItems)
  666. {
  667. var wafer = WaferManager.Instance.GetWafer(item.SourceModule, item.SourceSlot);
  668. if (wafer.IsEmpty)
  669. {
  670. // post alarm
  671. LOG.Write(eEvent.ERR_ROUTER, ModuleName.System, $"Cannot run EFEM moving task as Get {item.SourceModule}{item.SourceModule} Wafer Info failed");
  672. return;
  673. }
  674. var slot = new SlotItem(item.DestinationModule, item.DestinationSlot);
  675. _atmWaferTargets[slot] = wafer.InnerId;
  676. }
  677. _efemMovingItems.Clear();
  678. }
  679. }
  680. }
  681. private Hand GetEFEMRobotFreeHand()
  682. {
  683. for(int i = 0; i < 2; i++)
  684. {
  685. if ((WaferManager.Instance.CheckNoWafer(ModuleName.EfemRobot, i) && !_efemMovingItems.Exists(item => item.DestinationModule == ModuleName.EfemRobot && item.DestinationSlot == i)) ||
  686. (WaferManager.Instance.CheckHasWafer(ModuleName.EfemRobot, i) && _efemMovingItems.Exists(item => item.SourceModule == ModuleName.EfemRobot && item.SourceSlot == i)))
  687. return (Hand)i;
  688. }
  689. return Hand.None;
  690. }
  691. #endregion Atm System
  692. }
  693. }