ManualTransfer.cs 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780
  1. using System;
  2. using System.Collections.Generic;
  3. using Aitex.Core.RT.Event;
  4. using Aitex.Core.RT.Routine;
  5. using Aitex.Sorter.Common;
  6. using MECF.Framework.Common.Equipment;
  7. using MECF.Framework.Common.Schedulers;
  8. using MECF.Framework.Common.SubstrateTrackings;
  9. using MECF.Framework.RT.ModuleLibrary.SystemModules;
  10. using EfemDualSchedulerLib.Schedulers;
  11. using Aitex.Core.RT.SCCore;
  12. using System.Linq;
  13. using Aitex.Core.Util;
  14. namespace EfemDualSchedulerLib
  15. {
  16. internal interface IManualTransferRoutine : IRoutine
  17. {
  18. }
  19. public class MoveItemEx : MoveItem
  20. {
  21. public int CoolingTime { get; set; }
  22. public MoveItemEx(ModuleName sourceModule, int sourceSlot, ModuleName destinationModule, int destinationSlot, int coolingTime)
  23. : base(sourceModule, sourceSlot, destinationModule, destinationSlot, Hand.Blade1)
  24. {
  25. CoolingTime = coolingTime;
  26. }
  27. }
  28. public class ManualTransfer : SchedulerModuleFactory, IRoutine
  29. {
  30. private ModuleName[] _llBuffers = null;
  31. private Queue<IRoutine> _moveTaskQueue = new Queue<IRoutine>();
  32. private IRoutine _activeTask;
  33. public ManualTransfer(EquipmentManager equipment)
  34. {
  35. _llBuffers = new ModuleName[] { ModuleName.LLA, ModuleName.LLB }.Where(p=>ModuleHelper.IsInstalled(p)).ToArray();
  36. }
  37. public Result Start(object[] objs)
  38. {
  39. _moveTaskQueue.Clear();
  40. ModuleName source = (ModuleName)objs[0];
  41. int ss = (int)objs[1];
  42. ModuleName target = (ModuleName)objs[2];
  43. int ds = (int)objs[3];
  44. //bool autoAlign = (bool)objs[4];
  45. //int alignAngle = (int)objs[5];
  46. bool autoAlign = false;
  47. bool autoCooling = (bool)objs[6];
  48. int coolingTime = (int)objs[7];
  49. if (!WaferManager.Instance.CheckHasWafer(source, ss))
  50. {
  51. EV.PostWarningLog("System", "source no wafer");
  52. return Result.FAIL;
  53. }
  54. if (ModuleHelper.IsTMRobot(target))
  55. {
  56. if (!Converter.MapBladeToSlots(Converter.MapSlotToHand(ds)).All(p=> WaferManager.Instance.CheckNoWafer(target,p)))
  57. {
  58. EV.PostWarningLog("System", "destination has wafer");
  59. return Result.FAIL;
  60. }
  61. }
  62. else
  63. {
  64. if (!WaferManager.Instance.CheckNoWafer(target, ds))
  65. {
  66. EV.PostWarningLog("System", "destination has wafer");
  67. return Result.FAIL;
  68. }
  69. }
  70. if (CheckNeedEfemRobot(source, target) && !_efem.Blade1Enable && !_efem.Blade2Enable)
  71. {
  72. EV.PostWarningLog("System", "EFEM robot both disabled");
  73. return Result.FAIL;
  74. }
  75. if (CheckNeedEfemRobot(source, target)
  76. && (!ModuleHelper.IsEfemRobot(source) && !ModuleHelper.IsEfemRobot(target))
  77. && WaferManager.Instance.CheckHasWafer(ModuleName.EfemRobot, 0)
  78. && WaferManager.Instance.CheckHasWafer(ModuleName.EfemRobot, 1))
  79. {
  80. EV.PostWarningLog("System", "EFEM robot has wafer");
  81. return Result.FAIL;
  82. }
  83. if (CheckNeedTMRobot(source, target) && !_tmRobot.Blade1Enable && !_tmRobot.Blade2Enable)
  84. {
  85. EV.PostWarningLog("System", "TM robot both disabled");
  86. return Result.FAIL;
  87. }
  88. if (CheckNeedTMRobot(source, target)
  89. && (!ModuleHelper.IsTMRobot(source) && !ModuleHelper.IsTMRobot(target))
  90. && Converter.MapBladeToSlots(Hand.Blade1).Any(p=>WaferManager.Instance.CheckHasWafer(ModuleName.TMRobot, p))
  91. && Converter.MapBladeToSlots(Hand.Blade2).Any(p=>WaferManager.Instance.CheckHasWafer(ModuleName.TMRobot, p)))
  92. {
  93. EV.PostWarningLog("System", "TM robot has wafer");
  94. return Result.FAIL;
  95. }
  96. if (CheckNeedEfemRobot(source, target) && CheckNeedTMRobot(source, target))
  97. {
  98. var emptyLoadLockSlot = GetEmptyLoadLockSlot(source, ss, target, ds);
  99. if (emptyLoadLockSlot == null)
  100. {
  101. EV.PostWarningLog("System", "Can not transfer, LoadLock has full wafer");
  102. return Result.FAIL;
  103. }
  104. if (!GetEmptyCooling())
  105. {
  106. EV.PostWarningLog("System", "Can not transfer, Cooling is busy");
  107. return Result.FAIL;
  108. }
  109. if (ModuleHelper.IsPm(source) || ModuleHelper.IsTMRobot(source))
  110. {
  111. _moveTaskQueue.Enqueue(new TMRobotMover(new MoveItemEx(source, ss, emptyLoadLockSlot.Item1, emptyLoadLockSlot.Item2, 0)));
  112. if (autoCooling)
  113. {
  114. _moveTaskQueue.Enqueue(new EfemRobotMover(new MoveItemEx(emptyLoadLockSlot.Item1, emptyLoadLockSlot.Item2, ModuleName.Cooling1, 0, 0)));
  115. _moveTaskQueue.Enqueue(new EfemRobotMover(new MoveItemEx(ModuleName.Cooling1, 0, target, ds, coolingTime)));
  116. }
  117. else
  118. {
  119. _moveTaskQueue.Enqueue(new EfemRobotMover(new MoveItemEx(emptyLoadLockSlot.Item1, emptyLoadLockSlot.Item2, target, ds, 0)));
  120. }
  121. }
  122. else
  123. {
  124. _moveTaskQueue.Enqueue(new EfemRobotMover(new MoveItemEx(source, ss, emptyLoadLockSlot.Item1, emptyLoadLockSlot.Item2, 0)));
  125. _moveTaskQueue.Enqueue(new TMRobotMover(new MoveItemEx(emptyLoadLockSlot.Item1, emptyLoadLockSlot.Item2, target, ds, 0)));
  126. }
  127. }
  128. else if (CheckNeedEfemRobot(source, target))
  129. {
  130. if (autoAlign)
  131. {
  132. _moveTaskQueue.Enqueue(new EfemRobotMover(new MoveItemEx(source, ss, ModuleName.Aligner, 0, 0)));
  133. _moveTaskQueue.Enqueue(new EfemRobotMover(new MoveItemEx(ModuleName.Aligner, 0, target, ds, 0)));
  134. }
  135. else
  136. {
  137. _moveTaskQueue.Enqueue(new EfemRobotMover(new MoveItemEx(source, ss, target, ds, 0)));
  138. }
  139. }
  140. else if (CheckNeedTMRobot(source, target))
  141. {
  142. _moveTaskQueue.Enqueue(new TMRobotMover(new MoveItemEx(source, ss, target, ds, 0)));
  143. }
  144. _activeTask = _moveTaskQueue.Dequeue();
  145. return _activeTask.Start();
  146. }
  147. public Result Monitor()
  148. {
  149. System.Diagnostics.Debug.Assert(_activeTask != null, "mover should not be null, call start first");
  150. Result ret = _activeTask.Monitor();
  151. if (ret == Result.FAIL)
  152. return ret;
  153. if (ret == Result.DONE)
  154. {
  155. if (_moveTaskQueue.Count > 0)
  156. {
  157. _activeTask = _moveTaskQueue.Dequeue();
  158. return _activeTask.Start();
  159. }
  160. return Result.DONE;
  161. }
  162. return Result.RUN;
  163. }
  164. public void Clear()
  165. {
  166. _moveTaskQueue.Clear();
  167. _activeTask = null;
  168. }
  169. public void Abort()
  170. {
  171. }
  172. public bool CheckNeedEfemRobot(ModuleName source, ModuleName target)
  173. {
  174. if (ModuleHelper.IsLoadPort(source) || ModuleHelper.IsLoadPort(target))
  175. {
  176. return true;
  177. }
  178. if (ModuleHelper.IsEfemRobot(source) || ModuleHelper.IsEfemRobot(target))
  179. {
  180. return true;
  181. }
  182. if (ModuleHelper.IsAligner(source) || ModuleHelper.IsAligner(target))
  183. {
  184. return true;
  185. }
  186. if (ModuleHelper.IsCooling(source) || ModuleHelper.IsCooling(target))
  187. {
  188. return true;
  189. }
  190. if (ModuleHelper.IsLoadLock(source) || ModuleHelper.IsLoadLock(target))
  191. {
  192. if (!CheckNeedTMRobot(source, target))
  193. return true;
  194. }
  195. return false;
  196. }
  197. public bool CheckNeedTMRobot(ModuleName source, ModuleName target)
  198. {
  199. if (ModuleHelper.IsPm(source) || ModuleHelper.IsPm(target))
  200. {
  201. return true;
  202. }
  203. if (ModuleHelper.IsTMRobot(source) || ModuleHelper.IsTMRobot(target))
  204. {
  205. return true;
  206. }
  207. return false;
  208. }
  209. public Tuple<ModuleName, int> GetEmptyLoadLockSlot(ModuleName source, int sourceSlot, ModuleName target, int targetSlot )
  210. {
  211. Tuple<ModuleName, int> targetModule = null;
  212. Array.ForEach(_llBuffers, p =>
  213. {
  214. var wafers = WaferManager.Instance.GetWafers(p);
  215. for (int i = 0; i < wafers.Length; i++)
  216. {
  217. if (!wafers[i].IsEmpty) continue;
  218. if (!SC.IsDoubleFork ||
  219. (ModuleHelper.IsPm(target) && ((targetSlot % 2 > 0 && i % 2 > 0) || (targetSlot % 2 == 0 && i % 2 == 0))) ||
  220. (ModuleHelper.IsPm(source) && ((sourceSlot % 2 > 0 && i % 2 > 0) || (sourceSlot % 2 == 0 && i % 2 == 0))) ||
  221. (ModuleHelper.IsTMRobot(source) && ((sourceSlot > 1 && i % 2 > 0) || (sourceSlot <= 1 && i % 2 == 0))) ||
  222. (ModuleHelper.IsTMRobot(target) && ((targetSlot > 1 && i % 2 > 0) || (targetSlot <= 1 && i % 2 == 0)))
  223. )
  224. {
  225. targetModule = new Tuple<ModuleName, int>(p, i);
  226. break;
  227. }
  228. }
  229. if (targetModule != null) return;
  230. });
  231. return targetModule;
  232. }
  233. public bool GetEmptyCooling()
  234. {
  235. var coolingList = new ModuleName[] { ModuleName.Cooling1, ModuleName.Cooling2 }.Where(p => SC.GetValueOrDefault<bool>($"System.SetUp.{p.ToString()}.IsInstalled")).ToArray();
  236. if (coolingList == null || coolingList.Length == 0 || coolingList.Any(p => WaferManager.Instance.CheckNoWafer(p, 0))) return true;
  237. return false;
  238. }
  239. }
  240. public class EfemRobotMover : SchedulerModuleFactory, IRoutine
  241. {
  242. private MoveItemEx _moveTask;
  243. private SchedulerModule _source;
  244. private SchedulerModule _destination;
  245. public EfemRobotMover(MoveItemEx moveTask)
  246. {
  247. _moveTask = moveTask;
  248. }
  249. public Result Start()
  250. {
  251. _source = GetModule(_moveTask.SourceModule.ToString());
  252. _destination = GetModule(_moveTask.DestinationModule.ToString());
  253. System.Diagnostics.Debug.Assert(_source != null, $"{_moveTask.SourceModule} not valid");
  254. System.Diagnostics.Debug.Assert(_destination != null, $"{_moveTask.DestinationModule} not valid");
  255. if (!_source.HasWafer(_moveTask.SourceSlot))
  256. {
  257. EV.PostWarningLog("System", $"Failed transfer, source {_moveTask.SourceModule} slot {_moveTask.SourceSlot + 1} has not wafer");
  258. return Result.FAIL;
  259. }
  260. if (!_destination.NoWafer(_moveTask.DestinationSlot))
  261. {
  262. EV.PostWarningLog("System", $"Failed transfer, destination {_moveTask.DestinationModule} slot {_moveTask.DestinationSlot + 1} has wafer");
  263. return Result.FAIL;
  264. }
  265. if (!_source.IsOnline)
  266. {
  267. EV.PostWarningLog("System", $"Failed transfer, source {_moveTask.SourceModule} should be put online");
  268. return Result.FAIL;
  269. }
  270. if (!_source.IsAvailable)
  271. {
  272. EV.PostWarningLog("System", $"Failed transfer, source {_moveTask.SourceModule} in busy status");
  273. return Result.FAIL;
  274. }
  275. if (!_destination.IsOnline)
  276. {
  277. EV.PostWarningLog("System", $"Failed transfer, Destination {_moveTask.DestinationModule} should be put online");
  278. return Result.FAIL;
  279. }
  280. if (!_destination.IsAvailable)
  281. {
  282. EV.PostWarningLog("System", $"Failed transfer, Destination {_moveTask.DestinationModule} in busy status");
  283. return Result.FAIL;
  284. }
  285. if (!_efem.IsAvailable)
  286. {
  287. EV.PostWarningLog("System", $"Failed transfer, EFEM Robot is busy");
  288. return Result.FAIL;
  289. }
  290. if (ModuleHelper.IsCooling(_source.Module))
  291. _source.Cooling(_moveTask.CoolingTime);
  292. if (ModuleHelper.IsEfem(_source.Module) || ModuleHelper.IsEfemRobot(_source.Module))
  293. {
  294. _moveTask.RobotHand = (Hand)_moveTask.SourceSlot;
  295. }
  296. else if (ModuleHelper.IsEfem(_destination.Module) || ModuleHelper.IsEfemRobot(_destination.Module))
  297. {
  298. _moveTask.RobotHand = (Hand)_moveTask.DestinationSlot;
  299. }
  300. else
  301. {
  302. _moveTask.RobotHand = GetAvailableHand(ModuleName.EfemRobot);
  303. }
  304. return Result.RUN;
  305. }
  306. public Result Start(params object[] objs)
  307. {
  308. return this.Start();
  309. }
  310. public Result Monitor()
  311. {
  312. if (_source.NoWafer(_moveTask.SourceSlot) && _destination.HasWafer(_moveTask.DestinationSlot) &&
  313. _efem.IsAvailable)
  314. {
  315. if (_source.IsWaitTransfer(ModuleName.EfemRobot))
  316. _source.StopWaitTransfer(ModuleName.EfemRobot);
  317. if (_destination.IsWaitTransfer(ModuleName.EfemRobot))
  318. _destination.StopWaitTransfer(ModuleName.EfemRobot);
  319. return Result.DONE;
  320. }
  321. if (_source.IsError || _destination.IsError || _efem.IsError)
  322. return Result.FAIL;
  323. if (!_efem.IsAvailable)
  324. return Result.RUN;
  325. //pick
  326. if (_moveTask.SourceModule != ModuleName.EfemRobot)
  327. {
  328. if (_source.HasWafer(_moveTask.SourceSlot))
  329. {
  330. if (!_source.IsAvailable)
  331. return Result.RUN;
  332. if (!_source.IsReadyForPick(ModuleName.EfemRobot, GetAvailableHand(ModuleName.EfemRobot), _moveTask.SourceSlot))
  333. {
  334. if (!_source.PrepareTransfer(ModuleName.EfemRobot, EnumTransferType.Pick, new int[] { _moveTask.SourceSlot }))
  335. return Result.FAIL;
  336. }
  337. if (!_source.IsAvailable)
  338. return Result.RUN;
  339. if (!_efem.HasWafer((int)_moveTask.RobotHand))
  340. {
  341. if (!_efem.Pick(_moveTask.SourceModule, _moveTask.SourceSlot, _moveTask.RobotHand))
  342. {
  343. return Result.FAIL;
  344. }
  345. _source.WaitTransfer(ModuleName.EfemRobot);
  346. }
  347. if (!_efem.IsAvailable)
  348. return Result.RUN;
  349. }
  350. else
  351. {
  352. if (!_efem.IsAvailable)
  353. return Result.RUN;
  354. if (_source.IsWaitTransfer(ModuleName.EfemRobot))
  355. _source.StopWaitTransfer(ModuleName.EfemRobot);
  356. }
  357. }
  358. //place
  359. if (_moveTask.DestinationModule != ModuleName.EfemRobot)
  360. {
  361. if (!_destination.IsAvailable)
  362. return Result.RUN;
  363. if (_destination.NoWafer(_moveTask.DestinationSlot))
  364. {
  365. if (!_destination.IsReadyForPlace(ModuleName.EfemRobot, _moveTask.RobotHand, _moveTask.DestinationSlot))
  366. {
  367. if (!_destination.PrepareTransfer(ModuleName.EfemRobot, EnumTransferType.Place,
  368. new int[] { _moveTask.DestinationSlot }))
  369. return Result.FAIL;
  370. }
  371. if (!_destination.IsAvailable)
  372. return Result.RUN;
  373. if (_efem.HasWafer((int)_moveTask.RobotHand))
  374. {
  375. if (!_efem.Place(_moveTask.DestinationModule, _moveTask.DestinationSlot, _moveTask.RobotHand))
  376. return Result.FAIL;
  377. _destination.WaitTransfer(ModuleName.EfemRobot);
  378. }
  379. if (!_efem.IsAvailable)
  380. return Result.RUN;
  381. }
  382. else
  383. {
  384. if (!_efem.IsAvailable)
  385. return Result.RUN;
  386. if (_destination.IsWaitTransfer(ModuleName.EfemRobot))
  387. _destination.StopWaitTransfer(ModuleName.EfemRobot);
  388. }
  389. }
  390. return Result.RUN;
  391. }
  392. public void Abort()
  393. {
  394. Clear();
  395. }
  396. public void Clear()
  397. {
  398. _efem.ResetTask();
  399. _source?.ResetTask();
  400. _destination?.ResetTask();
  401. }
  402. public Hand GetAvailableHand(ModuleName module)
  403. {
  404. var wafers = WaferManager.Instance.GetWafers(module);
  405. return _efem.Blade1Enable && wafers[0].IsEmpty ? Hand.Blade1 : Hand.Blade2;
  406. }
  407. }
  408. public class TMRobotMover : SchedulerModuleFactory, IRoutine
  409. {
  410. private MoveItem _moveTask;
  411. private SchedulerModule _source;
  412. private SchedulerModule _destination;
  413. private bool _pmaIsInstalled;
  414. private bool _pmbIsInstalled;
  415. private Dictionary<int, Hand> _slotMapToHand = new Dictionary<int, Hand>()
  416. {
  417. {(int)ArmBlade.ArmAFork0, Hand.Blade1},
  418. {(int)ArmBlade.ArmBFork1,Hand.Blade2 },
  419. {(int)ArmBlade.ArmAFork2, Hand.Blade1},
  420. {(int)ArmBlade.ArmBFork3,Hand.Blade2}
  421. };
  422. public TMRobotMover(MoveItem moveTask)
  423. {
  424. _moveTask = moveTask;
  425. _pmaIsInstalled = SC.GetValueOrDefault<bool>($"System.SetUp.{ModuleName.PMA}.IsInstalled");
  426. _pmbIsInstalled = SC.GetValueOrDefault<bool>($"System.SetUp.{ModuleName.PMB}.IsInstalled");
  427. }
  428. public Result Start()
  429. {
  430. _source = GetModule(_moveTask.SourceModule.ToString());
  431. _destination = GetModule(_moveTask.DestinationModule.ToString());
  432. System.Diagnostics.Debug.Assert(_source != null, $"{_moveTask.SourceModule} not valid");
  433. System.Diagnostics.Debug.Assert(_destination != null, $"{_moveTask.DestinationModule} not valid");
  434. if(SC.IsDoubleFork)
  435. {
  436. if(ModuleHelper.IsTM(_source.Module) && ModuleHelper.IsTM(_destination.Module))
  437. {
  438. EV.PostWarningLog("System", $"Failed transfer, source slot wafer can't move to target slot ");
  439. return Result.FAIL;
  440. }
  441. if(ModuleHelper.IsTM(_source.Module) || ModuleHelper.IsTM(_destination.Module))
  442. {
  443. var tmSlot = ModuleHelper.IsTM(_source.Module) ? _moveTask.SourceSlot : _moveTask.DestinationSlot;
  444. var sourceOrTarget = ModuleHelper.IsTM(_source.Module) ? _moveTask.DestinationSlot : _moveTask.SourceSlot;
  445. if ((tmSlot < 2 && (sourceOrTarget % 2) > 0) || (tmSlot > 1 && (sourceOrTarget % 2) == 0))
  446. {
  447. EV.PostWarningLog("System", $"Failed transfer, source slot wafer can't move to target slot ");
  448. return Result.FAIL;
  449. }
  450. }
  451. else
  452. {
  453. if ((((_moveTask.SourceSlot % 2) == 0 && (_moveTask.DestinationSlot % 2) > 0)
  454. || ((_moveTask.SourceSlot % 2) > 0 && (_moveTask.DestinationSlot % 2) == 0)))
  455. {
  456. EV.PostWarningLog("System", $"Failed transfer, source slot wafer can't move to target slot ");
  457. return Result.FAIL;
  458. }
  459. }
  460. }
  461. if (!_source.HasWafer(_moveTask.SourceSlot))
  462. {
  463. EV.PostWarningLog("System", $"Failed transfer, source {_moveTask.SourceModule} slot {_moveTask.SourceSlot + 1} has not wafer");
  464. return Result.FAIL;
  465. }
  466. if (!_destination.NoWafer(_moveTask.DestinationSlot))
  467. {
  468. EV.PostWarningLog("System", $"Failed transfer, destination {_moveTask.DestinationModule} slot {_moveTask.DestinationSlot + 1} has wafer");
  469. return Result.FAIL;
  470. }
  471. if(SC.IsDoubleFork && _moveTask.DestinationModule != ModuleName.TMRobot )
  472. {
  473. var leftOrRightSlot = (_moveTask.DestinationSlot % 2 > 0) ? _moveTask.DestinationSlot-1 : _moveTask.DestinationSlot+1;
  474. if (!_destination.NoWafer(leftOrRightSlot))
  475. {
  476. EV.PostWarningLog("System", $"Failed transfer, destination {_moveTask.DestinationModule} slot {leftOrRightSlot + 1} has wafer");
  477. return Result.FAIL;
  478. }
  479. }
  480. if (!_source.IsOnline)
  481. {
  482. EV.PostWarningLog("System", $"Failed transfer, source {_moveTask.SourceModule} should be put online");
  483. return Result.FAIL;
  484. }
  485. if (!_source.IsAvailable)
  486. {
  487. EV.PostWarningLog("System", $"Failed transfer, source {_moveTask.SourceModule} in busy status");
  488. return Result.FAIL;
  489. }
  490. if (!_destination.IsOnline)
  491. {
  492. EV.PostWarningLog("System", $"Failed transfer, Destination {_moveTask.DestinationModule} should be put online");
  493. return Result.FAIL;
  494. }
  495. if (!_destination.IsAvailable)
  496. {
  497. EV.PostWarningLog("System", $"Failed transfer, Destination {_moveTask.DestinationModule} in busy status");
  498. return Result.FAIL;
  499. }
  500. if (!_tmRobot.IsAvailable)
  501. {
  502. EV.PostWarningLog("System", $"Failed transfer, TM Robot is busy");
  503. return Result.FAIL;
  504. }
  505. if (ModuleHelper.IsTM(_source.Module) || ModuleHelper.IsTMRobot(_source.Module))
  506. {
  507. _moveTask.RobotHand = _slotMapToHand[_moveTask.SourceSlot];
  508. }
  509. else if (ModuleHelper.IsTM(_destination.Module) || ModuleHelper.IsTMRobot(_destination.Module))
  510. {
  511. _moveTask.RobotHand = _slotMapToHand[_moveTask.DestinationSlot];
  512. }
  513. else
  514. {
  515. _moveTask.RobotHand = GetAvailableHand(ModuleName.TMRobot);
  516. }
  517. return Result.RUN;
  518. }
  519. public Result Start(params object[] objs)
  520. {
  521. return this.Start();
  522. }
  523. public Result Monitor()
  524. {
  525. if (_source.NoWafer(_moveTask.SourceSlot) && _destination.HasWafer(_moveTask.DestinationSlot) &&
  526. _tmRobot.IsAvailable)
  527. {
  528. if (_source.IsWaitTransfer(ModuleName.TMRobot))
  529. _source.StopWaitTransfer(ModuleName.TMRobot);
  530. if (_destination.IsWaitTransfer(ModuleName.TMRobot))
  531. _destination.StopWaitTransfer(ModuleName.TMRobot);
  532. if (ModuleHelper.IsPm(_moveTask.SourceModule) || ModuleHelper.IsPm(_moveTask.DestinationModule))
  533. {
  534. if (_pmaIsInstalled && !_pm1.CheckSlitValveClose())
  535. _pm1.CloseSlitValve();
  536. if (_pmbIsInstalled && !_pm2.CheckSlitValveClose())
  537. _pm2.CloseSlitValve();
  538. }
  539. return Result.DONE;
  540. }
  541. if (_source.IsError || _destination.IsError || _tmRobot.IsError)
  542. return Result.FAIL;
  543. if (!_tmRobot.IsAvailable)
  544. return Result.RUN;
  545. //pick
  546. if (_moveTask.SourceModule != ModuleName.TMRobot)
  547. {
  548. if (_source.HasWafer(_moveTask.SourceSlot))
  549. {
  550. if (!_source.IsAvailable)
  551. return Result.RUN;
  552. List<int> sourceSlots = new List<int>() { _moveTask.SourceSlot };
  553. if(SC.IsDoubleFork)
  554. {
  555. var nextPickSlot = (_moveTask.SourceSlot % 2) > 0 ? _moveTask.SourceSlot - 1 : _moveTask.SourceSlot + 1;
  556. if (_source.HasWafer(nextPickSlot))
  557. {
  558. sourceSlots.Add(nextPickSlot);
  559. }
  560. }
  561. var isReadyForPick = sourceSlots.All(p => _source.IsReadyForPick(ModuleName.TMRobot, _moveTask.RobotHand, p));
  562. if(!isReadyForPick && !_source.PrepareTransfer(ModuleName.TMRobot, EnumTransferType.Pick, sourceSlots.ToArray()))
  563. return Result.FAIL;
  564. if (!_source.IsAvailable)
  565. return Result.RUN;
  566. if (!_tmRobot.HasWafer((int)_moveTask.RobotHand))
  567. {
  568. if (!_tmRobot.Pick(_moveTask.SourceModule, sourceSlots.ToArray(), _moveTask.RobotHand, Converter.GetPanAndSlotFromPick(_moveTask.RobotHand, sourceSlots.ToArray()).Item1, 0, 0, true))
  569. {
  570. return Result.FAIL;
  571. }
  572. _source.WaitTransfer(ModuleName.TMRobot);
  573. }
  574. if (!_tmRobot.IsAvailable)
  575. return Result.RUN;
  576. }
  577. else
  578. {
  579. if (!_tmRobot.IsAvailable)
  580. return Result.RUN;
  581. if (_source.IsWaitTransfer(ModuleName.TMRobot))
  582. _source.StopWaitTransfer(ModuleName.TMRobot);
  583. }
  584. }
  585. //place
  586. if (_moveTask.DestinationModule != ModuleName.TMRobot)
  587. {
  588. if (!_destination.IsAvailable)
  589. return Result.RUN;
  590. if (_destination.NoWafer(_moveTask.DestinationSlot))
  591. {
  592. var sourceSlots = GetHandSlotsByWafer(_moveTask.RobotHand);
  593. List<int> targetSlots = new List<int>() { _moveTask.DestinationSlot };
  594. if (SC.IsDoubleFork)
  595. {
  596. var nextPlacekSlot = (_moveTask.DestinationSlot % 2) > 0 ? _moveTask.DestinationSlot - 1 : _moveTask.DestinationSlot + 1;
  597. if (_destination.HasWafer(nextPlacekSlot))
  598. {
  599. return Result.FAIL;
  600. }
  601. if (sourceSlots.Length > 1) targetSlots.Add(nextPlacekSlot);
  602. }
  603. var isReadyForPlace = targetSlots.All(p => _destination.IsReadyForPlace(ModuleName.TMRobot, _moveTask.RobotHand, p));
  604. if (!isReadyForPlace && !_destination.PrepareTransfer(ModuleName.TMRobot, EnumTransferType.Place, targetSlots.ToArray()))
  605. return Result.FAIL;
  606. if (!_destination.IsAvailable)
  607. return Result.RUN;
  608. if (sourceSlots.Length > 0 && targetSlots.Count>0)
  609. {
  610. if (!_tmRobot.Place(_moveTask.DestinationModule, targetSlots.ToArray(), _moveTask.RobotHand, Converter.GetPanAndSlotFromPlace(_moveTask.RobotHand).Item1, 0, 0, true))
  611. return Result.FAIL;
  612. _destination.WaitTransfer(ModuleName.TMRobot);
  613. }
  614. if (!_tmRobot.IsAvailable)
  615. return Result.RUN;
  616. }
  617. else
  618. {
  619. if (!_tmRobot.IsAvailable)
  620. return Result.RUN;
  621. if (_destination.IsWaitTransfer(ModuleName.TMRobot))
  622. _destination.StopWaitTransfer(ModuleName.TMRobot);
  623. }
  624. }
  625. return Result.RUN;
  626. }
  627. private int[] GetHandSlotsByWafer(Hand hand)
  628. {
  629. var forkSlots = new int[] { (int)hand, ((int)hand) + 2 };
  630. var sourceSlots = new List<int>();
  631. foreach (var forkSlot in forkSlots)
  632. {
  633. var wafer = WaferManager.Instance.GetWafer(ModuleName.TMRobot, forkSlot);
  634. if (wafer != null && !wafer.IsEmpty) sourceSlots.Add(forkSlot);
  635. }
  636. return sourceSlots.ToArray();
  637. }
  638. public void Abort()
  639. {
  640. Clear();
  641. }
  642. public void Clear()
  643. {
  644. _tmRobot.ResetTask();
  645. _source?.ResetTask();
  646. _destination?.ResetTask();
  647. }
  648. public Hand GetAvailableHand(ModuleName module)
  649. {
  650. if (_tmRobot.Blade1Enable && Converter.MapBladeToSlots(Hand.Blade1).All(p=> WaferManager.Instance.CheckNoWafer(module, p))) return Hand.Blade1;
  651. return Hand.Blade2;
  652. }
  653. }
  654. }