using System; using System.Collections.Generic; using Aitex.Core.RT.Event; using Aitex.Core.RT.Routine; using Aitex.Sorter.Common; using MECF.Framework.Common.Equipment; using MECF.Framework.Common.Schedulers; using MECF.Framework.Common.SubstrateTrackings; using MECF.Framework.RT.ModuleLibrary.SystemModules; using EfemDualSchedulerLib.Schedulers; namespace EfemDualSchedulerLib { internal interface IManualTransferRoutine : IRoutine { } public class MoveItemEx : MoveItem { public int CoolingTime { get; set; } public MoveItemEx(ModuleName sourceModule, int sourceSlot, ModuleName destinationModule, int destinationSlot, int coolingTime) : base(sourceModule, sourceSlot, destinationModule, destinationSlot, Hand.Blade1) { CoolingTime = coolingTime; } } public class ManualTransfer : SchedulerModuleFactory, IRoutine { private Queue _moveTaskQueue = new Queue(); private IRoutine _activeTask; public ManualTransfer(EquipmentManager equipment) { } public Result Start(object[] objs) { _moveTaskQueue.Clear(); ModuleName source = (ModuleName)objs[0]; int ss = (int)objs[1]; ModuleName target = (ModuleName)objs[2]; int ds = (int)objs[3]; //bool autoAlign = (bool)objs[4]; //int alignAngle = (int)objs[5]; bool autoAlign = false; //bool autoCooling = false;//(bool)objs[6]; //int coolingTime = (int)objs[7]; if (!WaferManager.Instance.CheckHasWafer(source, ss)) { EV.PostWarningLog("System", "source no wafer"); return Result.FAIL; } if (!WaferManager.Instance.CheckNoWafer(target, ds)) { EV.PostWarningLog("System", "destination has wafer"); return Result.FAIL; } if (CheckNeedEfemRobot(source, target) && !_efem.Blade1Enable && !_efem.Blade2Enable) { EV.PostWarningLog("System", "EFEM robot both disabled"); return Result.FAIL; } if (CheckNeedEfemRobot(source, target) &&(!ModuleHelper.IsEfemRobot(source)&& !ModuleHelper.IsEfemRobot(target)) && WaferManager.Instance.CheckHasWafer(ModuleName.EfemRobot, 0) && WaferManager.Instance.CheckHasWafer(ModuleName.EfemRobot, 1)) { EV.PostWarningLog("System", "EFEM robot has wafer"); return Result.FAIL; } if (CheckNeedTMRobot(source, target) && !_tmRobot.Blade1Enable && !_tmRobot.Blade2Enable) { EV.PostWarningLog("System", "TM robot both disabled"); return Result.FAIL; } if (CheckNeedTMRobot(source, target) && (!ModuleHelper.IsTMRobot(source) && !ModuleHelper.IsTMRobot(target)) && WaferManager.Instance.CheckHasWafer(ModuleName.TMRobot, 0) && WaferManager.Instance.CheckHasWafer(ModuleName.TMRobot, 1)) { EV.PostWarningLog("System", "TM robot has wafer"); return Result.FAIL; } if (CheckNeedEfemRobot(source, target) && CheckNeedTMRobot(source, target)) { var emptyLoadLockSlot = GetEmptyLoadLockSlot(); if (emptyLoadLockSlot == null) { EV.PostWarningLog("System", "Can not transfer, LoadLock has full wafer"); return Result.FAIL; } if (ModuleHelper.IsPm(source) || ModuleHelper.IsTMRobot(source)) { _moveTaskQueue.Enqueue(new TMRobotMover(new MoveItemEx(source, ss, emptyLoadLockSlot.Item1, emptyLoadLockSlot.Item2, 0))); _moveTaskQueue.Enqueue(new EfemRobotMover(new MoveItemEx(emptyLoadLockSlot.Item1, emptyLoadLockSlot.Item2, target, ds, 0))); } else { _moveTaskQueue.Enqueue(new EfemRobotMover(new MoveItemEx(source, ss, emptyLoadLockSlot.Item1, emptyLoadLockSlot.Item2, 0))); _moveTaskQueue.Enqueue(new TMRobotMover(new MoveItemEx(emptyLoadLockSlot.Item1, emptyLoadLockSlot.Item2, target, ds, 0))); } } else if (CheckNeedEfemRobot(source, target)) { if (autoAlign) { _moveTaskQueue.Enqueue(new EfemRobotMover(new MoveItemEx(source, ss, ModuleName.Aligner, 0, 0))); _moveTaskQueue.Enqueue(new EfemRobotMover(new MoveItemEx(ModuleName.Aligner, 0, target, ds, 0))); } else { _moveTaskQueue.Enqueue(new EfemRobotMover(new MoveItemEx(source, ss, target, ds, 0))); } } else if (CheckNeedTMRobot(source, target)) { _moveTaskQueue.Enqueue(new TMRobotMover(new MoveItemEx(source, ss, target, ds, 0))); } _activeTask = _moveTaskQueue.Dequeue(); return _activeTask.Start(); } public Result Monitor() { System.Diagnostics.Debug.Assert(_activeTask != null, "mover should not be null, call start first"); Result ret = _activeTask.Monitor(); if (ret == Result.FAIL) return ret; if (ret == Result.DONE) { if (_moveTaskQueue.Count > 0) { _activeTask = _moveTaskQueue.Dequeue(); return _activeTask.Start(); } return Result.DONE; } return Result.RUN; } public void Clear() { _moveTaskQueue.Clear(); _activeTask = null; } public void Abort() { } public bool CheckNeedEfemRobot(ModuleName source, ModuleName target) { if (ModuleHelper.IsLoadPort(source) || ModuleHelper.IsLoadPort(target)) { return true; } if (ModuleHelper.IsEfemRobot(source) || ModuleHelper.IsEfemRobot(target)) { return true; } if (ModuleHelper.IsAligner(source) || ModuleHelper.IsAligner(target)) { return true; } if (ModuleHelper.IsLoadLock(source) || ModuleHelper.IsLoadLock(target)) { if (!CheckNeedTMRobot(source, target)) return true; } return false; } public bool CheckNeedTMRobot(ModuleName source, ModuleName target) { if (ModuleHelper.IsPm(source) || ModuleHelper.IsPm(target)) { return true; } if (ModuleHelper.IsTMRobot(source) || ModuleHelper.IsTMRobot(target)) { return true; } return false; } public Tuple GetEmptyLoadLockSlot() { var lla = WaferManager.Instance.GetWafers(ModuleName.LLA); for (int i = 0; i < lla.Length; i++) { if (lla[i].IsEmpty) { return new Tuple(ModuleName.LLA, i); } } var llb = WaferManager.Instance.GetWafers(ModuleName.LLB); for (int i = 0; i < llb.Length; i++) { if (llb[i].IsEmpty) { return new Tuple(ModuleName.LLB, i); } } return null; } } public class EfemRobotMover : SchedulerModuleFactory, IRoutine { private MoveItem _moveTask; private SchedulerModule _source; private SchedulerModule _destination; public EfemRobotMover(MoveItem moveTask) { _moveTask = moveTask; } public Result Start() { _source = GetModule(_moveTask.SourceModule.ToString()); _destination = GetModule(_moveTask.DestinationModule.ToString()); System.Diagnostics.Debug.Assert(_source != null, $"{_moveTask.SourceModule} not valid"); System.Diagnostics.Debug.Assert(_destination != null, $"{_moveTask.DestinationModule} not valid"); if (!_source.HasWafer(_moveTask.SourceSlot)) { EV.PostWarningLog("System", $"Failed transfer, source {_moveTask.SourceModule} slot {_moveTask.SourceSlot + 1} has not wafer"); return Result.FAIL; } if (!_destination.NoWafer(_moveTask.DestinationSlot)) { EV.PostWarningLog("System", $"Failed transfer, destination {_moveTask.DestinationModule} slot {_moveTask.DestinationSlot + 1} has wafer"); return Result.FAIL; } if (!_source.IsOnline) { EV.PostWarningLog("System", $"Failed transfer, source {_moveTask.SourceModule} should be put online"); return Result.FAIL; } if (!_source.IsAvailable) { EV.PostWarningLog("System", $"Failed transfer, source {_moveTask.SourceModule} in busy status"); return Result.FAIL; } if (!_destination.IsOnline) { EV.PostWarningLog("System", $"Failed transfer, Destination {_moveTask.DestinationModule} should be put online"); return Result.FAIL; } if (!_destination.IsAvailable) { EV.PostWarningLog("System", $"Failed transfer, Destination {_moveTask.DestinationModule} in busy status"); return Result.FAIL; } if (!_efem.IsAvailable) { EV.PostWarningLog("System", $"Failed transfer, EFEM Robot is busy"); return Result.FAIL; } if (ModuleHelper.IsEfem(_source.Module)||ModuleHelper.IsEfemRobot(_source.Module)) { _moveTask.RobotHand = (Hand)_moveTask.SourceSlot; } else if (ModuleHelper.IsEfem(_destination.Module) || ModuleHelper.IsEfemRobot(_destination.Module)) { _moveTask.RobotHand = (Hand)_moveTask.DestinationSlot; } else { _moveTask.RobotHand = GetAvailableHand(ModuleName.EfemRobot); } return Result.RUN; } public Result Start(params object[] objs) { return this.Start(); } public Result Monitor() { if (_source.NoWafer(_moveTask.SourceSlot) && _destination.HasWafer(_moveTask.DestinationSlot) && _efem.IsAvailable) { if (_source.IsWaitTransfer(ModuleName.EfemRobot)) _source.StopWaitTransfer(ModuleName.EfemRobot); if (_destination.IsWaitTransfer(ModuleName.EfemRobot)) _destination.StopWaitTransfer(ModuleName.EfemRobot); return Result.DONE; } if (_source.IsError || _destination.IsError || _efem.IsError) return Result.FAIL; if (!_efem.IsAvailable) return Result.RUN; //pick if (_moveTask.SourceModule != ModuleName.EfemRobot) { if (_source.HasWafer(_moveTask.SourceSlot)) { if (!_source.IsAvailable) return Result.RUN; if (!_source.IsReadyForPick(ModuleName.EfemRobot, GetAvailableHand(ModuleName.EfemRobot), _moveTask.SourceSlot)) { if (!_source.PrepareTransfer(ModuleName.EfemRobot, EnumTransferType.Pick, _moveTask.SourceSlot)) return Result.FAIL; } if (!_source.IsAvailable) return Result.RUN; if (!_efem.HasWafer((int)_moveTask.RobotHand)) { if (!_efem.Pick(_moveTask.SourceModule, _moveTask.SourceSlot, _moveTask.RobotHand)) { return Result.FAIL; } _source.WaitTransfer(ModuleName.EfemRobot); } if (!_efem.IsAvailable) return Result.RUN; } else { if (!_efem.IsAvailable) return Result.RUN; if (_source.IsWaitTransfer(ModuleName.EfemRobot)) _source.StopWaitTransfer(ModuleName.EfemRobot); } } //place if (_moveTask.DestinationModule != ModuleName.EfemRobot) { if (!_destination.IsAvailable) return Result.RUN; if (_destination.NoWafer(_moveTask.DestinationSlot)) { if (!_destination.IsReadyForPlace(ModuleName.EfemRobot, GetAvailableHand(ModuleName.EfemRobot), _moveTask.DestinationSlot)) { if (!_destination.PrepareTransfer(ModuleName.EfemRobot, EnumTransferType.Place, _moveTask.DestinationSlot)) return Result.FAIL; } if (!_destination.IsAvailable) return Result.RUN; if (_efem.HasWafer((int)_moveTask.RobotHand)) { if (!_efem.Place(_moveTask.DestinationModule, _moveTask.DestinationSlot, _moveTask.RobotHand)) return Result.FAIL; _destination.WaitTransfer(ModuleName.EfemRobot); } if (!_efem.IsAvailable) return Result.RUN; } else { if (!_efem.IsAvailable) return Result.RUN; if (_destination.IsWaitTransfer(ModuleName.EfemRobot)) _destination.StopWaitTransfer(ModuleName.EfemRobot); } } return Result.RUN; } public void Abort() { Clear(); } public void Clear() { _efem.ResetTask(); _source?.ResetTask(); _destination?.ResetTask(); } public Hand GetAvailableHand(ModuleName module) { var wafers = WaferManager.Instance.GetWafers(module); return _efem.Blade1Enable&&wafers[0].IsEmpty ? Hand.Blade1 : Hand.Blade2; } } public class TMRobotMover : SchedulerModuleFactory, IRoutine { private MoveItem _moveTask; private SchedulerModule _source; private SchedulerModule _destination; public TMRobotMover(MoveItem moveTask) { _moveTask = moveTask; } public Result Start() { _source = GetModule(_moveTask.SourceModule.ToString()); _destination = GetModule(_moveTask.DestinationModule.ToString()); System.Diagnostics.Debug.Assert(_source != null, $"{_moveTask.SourceModule} not valid"); System.Diagnostics.Debug.Assert(_destination != null, $"{_moveTask.DestinationModule} not valid"); if (!_source.HasWafer(_moveTask.SourceSlot)) { EV.PostWarningLog("System", $"Failed transfer, source {_moveTask.SourceModule} slot {_moveTask.SourceSlot + 1} has not wafer"); return Result.FAIL; } if (!_destination.NoWafer(_moveTask.DestinationSlot)) { EV.PostWarningLog("System", $"Failed transfer, destination {_moveTask.DestinationModule} slot {_moveTask.DestinationSlot + 1} has wafer"); return Result.FAIL; } if (!_source.IsOnline) { EV.PostWarningLog("System", $"Failed transfer, source {_moveTask.SourceModule} should be put online"); return Result.FAIL; } if (!_source.IsAvailable) { EV.PostWarningLog("System", $"Failed transfer, source {_moveTask.SourceModule} in busy status"); return Result.FAIL; } if (!_destination.IsOnline) { EV.PostWarningLog("System", $"Failed transfer, Destination {_moveTask.DestinationModule} should be put online"); return Result.FAIL; } if (!_destination.IsAvailable) { EV.PostWarningLog("System", $"Failed transfer, Destination {_moveTask.DestinationModule} in busy status"); return Result.FAIL; } if (!_tmRobot.IsAvailable) { EV.PostWarningLog("System", $"Failed transfer, TM Robot is busy"); return Result.FAIL; } if (ModuleHelper.IsTM(_source.Module)||ModuleHelper.IsTMRobot(_source.Module)) { _moveTask.RobotHand =(Hand) _moveTask.SourceSlot; } else if (ModuleHelper.IsTM(_destination.Module)||ModuleHelper.IsTMRobot(_destination.Module)) { _moveTask.RobotHand = (Hand)_moveTask.DestinationSlot; } else { _moveTask.RobotHand = GetAvailableHand(ModuleName.TMRobot); } return Result.RUN; } public Result Start(params object[] objs) { return this.Start(); } public Result Monitor() { if (_source.NoWafer(_moveTask.SourceSlot) && _destination.HasWafer(_moveTask.DestinationSlot) && _tmRobot.IsAvailable) { if (_source.IsWaitTransfer(ModuleName.TMRobot)) _source.StopWaitTransfer(ModuleName.TMRobot); if (_destination.IsWaitTransfer(ModuleName.TMRobot)) _destination.StopWaitTransfer(ModuleName.TMRobot); if (ModuleHelper.IsPm(_moveTask.SourceModule) || ModuleHelper.IsPm(_moveTask.DestinationModule)) { if (!_pm1.CheckSlitValveClose()) _pm1.CloseSlitValve(); if (!_pm2.CheckSlitValveClose()) _pm2.CloseSlitValve(); } return Result.DONE; } if (_source.IsError || _destination.IsError || _tmRobot.IsError) return Result.FAIL; if (!_tmRobot.IsAvailable) return Result.RUN; //pick if (_moveTask.SourceModule != ModuleName.TMRobot) { if (_source.HasWafer(_moveTask.SourceSlot)) { if (!_source.IsAvailable) return Result.RUN; if (!_source.IsReadyForPick(ModuleName.TMRobot, GetAvailableHand(ModuleName.TMRobot), _moveTask.SourceSlot)) { if (!_source.PrepareTransfer(ModuleName.TMRobot, EnumTransferType.Pick, _moveTask.SourceSlot)) return Result.FAIL; } if (!_source.IsAvailable) return Result.RUN; if (!_tmRobot.HasWafer((int)_moveTask.RobotHand)) { if (!_tmRobot.Pick(_moveTask.SourceModule, _moveTask.SourceSlot, _moveTask.RobotHand, 0, 0, false)) { return Result.FAIL; } _source.WaitTransfer(ModuleName.TMRobot); } if (!_tmRobot.IsAvailable) return Result.RUN; } else { if (!_tmRobot.IsAvailable) return Result.RUN; if (_source.IsWaitTransfer(ModuleName.TMRobot)) _source.StopWaitTransfer(ModuleName.TMRobot); } } //place if (_moveTask.DestinationModule != ModuleName.TMRobot) { if (!_destination.IsAvailable) return Result.RUN; if (_destination.NoWafer(_moveTask.DestinationSlot)) { if (!_destination.IsReadyForPlace(ModuleName.TMRobot, GetAvailableHand(ModuleName.TMRobot), _moveTask.DestinationSlot)) { if (!_destination.PrepareTransfer(ModuleName.TMRobot, EnumTransferType.Place, _moveTask.DestinationSlot)) return Result.FAIL; } if (!_destination.IsAvailable) return Result.RUN; if (_tmRobot.HasWafer((int)_moveTask.RobotHand)) { if (!_tmRobot.Place(_moveTask.DestinationModule, _moveTask.DestinationSlot, _moveTask.RobotHand, 0, 0, false)) return Result.FAIL; _destination.WaitTransfer(ModuleName.TMRobot); } if (!_tmRobot.IsAvailable) return Result.RUN; } else { if (!_tmRobot.IsAvailable) return Result.RUN; if (_destination.IsWaitTransfer(ModuleName.TMRobot)) _destination.StopWaitTransfer(ModuleName.TMRobot); } } return Result.RUN; } public void Abort() { Clear(); } public void Clear() { _tmRobot.ResetTask(); _source?.ResetTask(); _destination?.ResetTask(); } public Hand GetAvailableHand(ModuleName module) { var wafers = WaferManager.Instance.GetWafers(module); return _tmRobot.Blade1Enable && wafers[0].IsEmpty ? Hand.Blade1 : Hand.Blade2; } } }