using System.Collections.Generic; using Aitex.Core.Common; using Aitex.Core.RT.Routine; using Aitex.Core.RT.SCCore; using Aitex.Sorter.Common; using SicRT.Modules.Schedulers; using SicRT.Scheduler; using MECF.Framework.Common.Schedulers; using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Buffers; namespace SicRT.Modules { public class ReturnAllWafer : SchedulerModuleFactory { //private bool needAligner = false; Dictionary _checkPosition = new Dictionary() { {ModuleName.PM1, 1}, {ModuleName.PM2, 1}, {ModuleName.LoadLock, 1}, {ModuleName.UnLoad, 1}, {ModuleName.WaferRobot, 1}, {ModuleName.TrayRobot, 1}, {ModuleName.TMRobot, 1}, {ModuleName.Aligner, 1}, }; public ReturnAllWafer() { } public Result Start() { if (!_tmRobot.IsAvailable) { EV.PostWarningLog("Scheduler", "can not return wafer, TmRobort is not available!"); return Result.FAIL; } if (!_trayRobot.IsAvailable) { EV.PostWarningLog("Scheduler", "can not return wafer, TrayRobort is not available!"); return Result.FAIL; } if (!_waferRobot.IsAvailable) { EV.PostWarningLog("Scheduler", "can not return wafer, WaferRobort is not available!"); return Result.FAIL; } if (!_load.IsAvailable) { EV.PostWarningLog("Scheduler", "can not return wafer, Load is not available!"); return Result.FAIL; } if (!_unload.IsAvailable) { EV.PostWarningLog("Scheduler", "can not return wafer, UnLoad is not available!"); return Result.FAIL; } if (!_buffer.IsAvailable) { EV.PostWarningLog("Scheduler", "can not return wafer, Buffer is not available!"); return Result.FAIL; } return Result.RUN; } public Result Monitor() { MonitorModuleTasks(); if (MonitorTaskDone()) { return Result.DONE; } return Result.RUN; } public Result MonitorModuleTasks() { MonitorPMTask(); MonitorLoadTask(); MonitorUnLoadTask(); MonitorBufferTask(); MonitorAlignerTask(); MonitorTmRobotTask(); MonitorWaferRobotTask(); MonitorTrayRobotTask(); return Result.RUN; } private bool MonitorTaskDone() { foreach (var positions in _checkPosition) { for (int i = 0; i < positions.Value; i++) { if (CheckWaferCouldBeReturn(positions.Key, i)) { return false; } } } if (_buffer.HasWafer(0) || _buffer.HasWafer(1) || _buffer.HasWafer(2)) { return false; } if (_buffer.HasTrayAndExceedProcessCount(0) || _buffer.HasTrayAndExceedProcessCount(1) || _buffer.HasTrayAndExceedProcessCount(2)) { return false; } if (!_tmRobot.IsAvailable) { return false; } if (!_waferRobot.IsAvailable) { return false; } if (!_trayRobot.IsAvailable) { return false; } if (!_unload.IsAvailable) { return false; } if (!_load.IsAvailable) { return false; } return true; } private void MonitorTmRobotTask() { if (!_tmRobot.IsAvailable) return; foreach (var pm in _lstPms) { if (pm.IsWaitTransfer(ModuleName.TMRobot)) pm.StopWaitTransfer(ModuleName.TMRobot); } if (_buffer.IsWaitTransfer(ModuleName.TMRobot)) _buffer.StopWaitTransfer(ModuleName.TMRobot); if (_load.IsWaitTransfer(ModuleName.TMRobot)) _load.StopWaitTransfer(ModuleName.TMRobot); if (_unload.IsWaitTransfer(ModuleName.TMRobot)) _unload.StopWaitTransfer(ModuleName.TMRobot); MonitorTmRobotPMTask(); MonitorTmRobotBufferTask(); MonitorTmRobotLoadTask(); MonitorTmRobotUnLoadTask(); } private void MonitorWaferRobotTask() { foreach (var cass in _lstWaferCassettes) { if (cass.IsWaitTransfer(ModuleName.WaferRobot)) cass.StopWaitTransfer(ModuleName.WaferRobot); } if (_aligner.IsWaitTransfer(ModuleName.WaferRobot)) _aligner.StopWaitTransfer(ModuleName.WaferRobot); if (_load.IsWaitTransfer(ModuleName.WaferRobot)) _load.StopWaitTransfer(ModuleName.WaferRobot); if (_unload.IsWaitTransfer(ModuleName.WaferRobot)) _unload.StopWaitTransfer(ModuleName.WaferRobot); MonitorWaferRobotCassetteTask(); MonitorWaferRobotAlignerTask(); MonitorWaferRobotLoadTask(); MonitorWaferRobotUnLoadTask(); } private void MonitorTrayRobotTask() { if (_cassetteBL.IsWaitTransfer(ModuleName.TrayRobot)) _cassetteBL.StopWaitTransfer(ModuleName.TrayRobot); if (_load.IsWaitTransfer(ModuleName.TrayRobot)) _load.StopWaitTransfer(ModuleName.TrayRobot); MonitorTrayRobotLoadTask(); MonitorTrayRobotCassetteTask(); } private void MonitorTmRobotLoadTask() { if (!_load.IsAvailable || !_tmRobot.IsAvailable) { return; } //place 第二种情况 : Load腔无Tray,TMRobot上有使用次数用完的Tray bool canPlace = _tmRobot.HasTrayAndExceedProcessCount(0) && _tmRobot.NoWafer(0) && _load.NoTray(0); if (canPlace) { if (_load.IsReadyForPlace(ModuleName.TMRobot, 0)) { if(_unload.IsInPumping) { return; } if (_tmRobot.Place(_load.Module, 0, Hand.Blade1)) { _load.WaitTransfer(ModuleName.TMRobot); return; } } } //pick 第一种情况 : Load腔无Wafer有次数未超过的Tray,TMRobot无Tray bool canPick = _tmRobot.NoTray(0) && _tmRobot.NoWafer(0) && _load.HasTrayAndNotExceedProcessCount(0) && _load.NoWafer(0); if (canPick) { if (_load.IsReadyForPick(ModuleName.TMRobot, 0)) { if (_unload.IsInPumping) { return; } if (_tmRobot.Pick(_load.Module, 0, Hand.Blade1)) { _load.WaitTransfer(ModuleName.TMRobot); return; } } } } private void MonitorTmRobotUnLoadTask() { if (!_unload.IsAvailable || !_tmRobot.IsAvailable) { return; } //place Robot有Wafer,UnLoad无Tray无Wafer bool canPlaceUnLoad = _tmRobot.HasWafer(0) && _tmRobot.HasTray(0) && _unload.NoTray(0) && _unload.NoWafer(0); if (canPlaceUnLoad) { if (_unload.IsReadyForPlace(ModuleName.TMRobot, 0)) { if (_tmRobot.Place(_unload.Module, 0, Hand.Blade1)) { _unload.WaitTransfer(ModuleName.TMRobot); return; } } } if (!_unload.IsAvailable || !_tmRobot.IsAvailable) { return; } //pick UnLoad有Tray,TM无Tray,UnLoad分离完成 bool canPickUnLoad = _tmRobot.NoTray(0) && _unload.HasTray(0) && _unload.CheckWaferTraySeparated(); if (canPickUnLoad) { if (_unload.IsReadyForPick(ModuleName.TMRobot, 0)) { if (_tmRobot.Pick(_unload.Module, 0, Hand.Blade1)) { _unload.WaitTransfer(ModuleName.TMRobot); return; } } } } private void MonitorTmRobotBufferTask() { if (!_tmRobot.IsAvailable || !_buffer.IsAvailable) { return; } //place 次数未耗尽的Tray放入Buffer中 bool canPalce = _tmRobot.NoWafer(0) && _tmRobot.HasTrayAndNotExceedProcessCount(0); if (canPalce) { SlotItem bufferEmptySlot = null; if(_tmRobot.GetWaferInfo(0).TrayOriginSlot % 2 == 0) { if(_buffer.NoWafer(0) && _buffer.NoTray(0)) { bufferEmptySlot = new SlotItem(ModuleName.Buffer, 0); } //else if (_buffer.NoWafer(2) && _buffer.NoTray(2)) //{ // bufferEmptySlot = new SlotItem(ModuleName.Buffer, 2); //} } else if (_tmRobot.GetWaferInfo(0).TrayOriginSlot % 2 == 1) { if (_buffer.NoWafer(1) && _buffer.NoTray(1)) { bufferEmptySlot = new SlotItem(ModuleName.Buffer,1); } //else if (_buffer.NoWafer(2) && _buffer.NoTray(2)) //{ // bufferEmptySlot = new SlotItem(ModuleName.Buffer, 2); //} } if (bufferEmptySlot == null) { return; } if (_buffer.IsReadyForPlace(ModuleName.TMRobot, bufferEmptySlot.Slot)) { if (_tmRobot.Place(_buffer.Module, bufferEmptySlot.Slot, Hand.Blade1)) { _buffer.WaitTransfer(ModuleName.TMRobot); return; } } } if (!_tmRobot.IsAvailable || !_buffer.IsAvailable) { return; } //pick 当前步(UnLoad没有Wafer),Buffer有Tray,机械手没有Tray bool canPick = _tmRobot.NoTray(0) && _unload.NoTray(0) && _unload.NoWafer(0); if (canPick) { for (int i = 0; i < 3; i++) { if (_buffer.HasTray(i) && _buffer.HasWafer(i)) { if (_buffer.IsReadyForPick(ModuleName.TMRobot, i)) { if (_tmRobot.Pick(_buffer.Module, i, Hand.Blade1)) { _buffer.WaitTransfer(ModuleName.TMRobot); return; } } } if (_buffer.HasTrayAndExceedProcessCount(i) && _load.NoTray(0)) { if (_buffer.IsReadyForPick(ModuleName.TMRobot, i)) { if (_tmRobot.Pick(_buffer.Module, i, Hand.Blade1)) { _buffer.WaitTransfer(ModuleName.TMRobot); return; } } } } if(_buffer.HasTray(2)) { if (_buffer.IsReadyForPick(ModuleName.TMRobot, 2)) { if (_tmRobot.Pick(_buffer.Module, 2, Hand.Blade1)) { _buffer.WaitTransfer(ModuleName.TMRobot); return; } } } } } private void MonitorTmRobotPMTask() { if (!_tmRobot.IsAvailable) { return; } //pick from pm if (_tmRobot.NoWafer(0) && _tmRobot.NoTray(0) && _unload.NoWafer(0) && _unload.NoTray(0)) { Hand pickBlade = Hand.Blade1; ModuleName pickPm = ModuleName.System; foreach (var schedulerPm in _lstPms) { //增加温度低于900才能Pick的限制 if (!schedulerPm.IsAvailable || GetModule(schedulerPm.Module).NoWafer(0) || !schedulerPm.CheckTempBelow900()) continue; pickPm = schedulerPm.Module; break; } if (pickPm != ModuleName.System) { SchedulerModule pm = GetModule(pickPm.ToString()); if (pm.IsReadyForPick(ModuleName.TMRobot, 0)) { if (_tmRobot.Pick(pm.Module, 0, pickBlade)) { pm.WaitTransfer(ModuleName.TMRobot); return; } } } } //place to pm bool canPlace = _tmRobot.HasTrayAndNotExceedProcessCount(0) && _tmRobot.NoWafer(0); if(canPlace) { if(_tmRobot.GetWaferInfo(0).TrayOriginSlot % 2 == 0 && _pm1.NoWafer(0) && _pm1.NoTray(0) && _pm1.IsAvailable && _pm1.CheckTempBelow900() && _buffer.HasTray(0)) { if (_pm1.IsReadyForPlace(ModuleName.TMRobot, 0)) { if (_tmRobot.Place(_pm1.Module, 0, Hand.Blade1)) { _pm1.WaitTransfer(ModuleName.TMRobot); return; } } } else if (_tmRobot.GetWaferInfo(0).TrayOriginSlot % 2 == 1 && _pm2.NoWafer(0) && _pm2.NoTray(0) && _pm2.IsAvailable && _pm2.CheckTempBelow900() && _buffer.HasTray(1)) { if (_pm2.IsReadyForPlace(ModuleName.TMRobot, 0)) { if (_tmRobot.Place(_pm2.Module, 0, Hand.Blade1)) { _pm2.WaitTransfer(ModuleName.TMRobot); return; } } } } } private void MonitorWaferRobotLoadTask() { if (!_waferRobot.IsAvailable || !_load.IsAvailable) { return; } bool canPick = _waferRobot.NoWafer(0) && _load.HasWafer(0) &&_load.NoTray(0); if (canPick) { if (_load.IsReadyForPick(ModuleName.WaferRobot, 0)) { if (_waferRobot.Pick(_load.Module, 0, Hand.Blade1)) { _load.WaitTransfer(ModuleName.WaferRobot); return; } } } } private void MonitorWaferRobotUnLoadTask() { if (!_waferRobot.IsAvailable || !_unload.IsAvailable) { return; } //WaferRobot没有Wafer,Unload有Wafer并且已分离 bool canPick = _waferRobot.NoWafer(0) && _unload.HasWafer(0) && _unload.NoTray(0); if (canPick) { if (_unload.IsReadyForPick(ModuleName.WaferRobot, 0)) { if (_waferRobot.Pick(_unload.Module, 0, Hand.Blade1)) { _unload.WaitTransfer(ModuleName.WaferRobot); return; } } } } private void MonitorWaferRobotAlignerTask() { if (_load.HasWafer(0) && _load.GetWaferInfo(0).NextStation != (int)ModuleName.Aligner) { _load.GetWaferInfo(0).NextStation = (int)ModuleName.Aligner; } if (_unload.HasWafer(0) && _unload.GetWaferInfo(0).NextStation != (int)ModuleName.Aligner) { _unload.GetWaferInfo(0).NextStation = (int)ModuleName.Aligner; } if (_waferRobot.HasWafer(0) && _waferRobot.GetWaferInfo(0).NextStation != (int)ModuleName.Aligner && _waferRobot.GetWaferInfo(0).NextStation != (int)ModuleName.System) { _waferRobot.GetWaferInfo(0).NextStation = (int)ModuleName.Aligner; } if (!_waferRobot.IsAvailable || !_aligner.IsAvailable) { return; } //place 任务还没完成,下一步是Aligner,Robot有片子,Aligner没片子 bool canPlaceAligner = _aligner.NoWafer(0) && _waferRobot.HasWafer(0) && _waferRobot.GetWaferInfo(0).NextStation == (int)ModuleName.Aligner; if (canPlaceAligner) { if (_aligner.IsReadyForPlace(ModuleName.WaferRobot, 0)) { if (_waferRobot.Place(_aligner.Module, 0, Hand.Blade1)) { _aligner.WaitTransfer(ModuleName.WaferRobot); return; } } } if (!_waferRobot.IsAvailable || !_aligner.IsAvailable) { return; } //pick Robot没片子,Aligner有片子 bool canPickAligner = _aligner.HasWafer(0) && _waferRobot.NoWafer(0); if (canPickAligner) { if (_aligner.IsReadyForPick(ModuleName.WaferRobot, 0)) { if (_waferRobot.Pick(_aligner.Module, 0, Hand.Blade1)) { _aligner.WaitTransfer(ModuleName.WaferRobot); return; } } } } private void MonitorWaferRobotCassetteTask() { if (!_waferRobot.IsAvailable) { return; } //place bool canPlaceCassette = _waferRobot.HasWafer(0)&& _waferRobot.GetWaferInfo(0).NextStation!=(int)ModuleName.Aligner; if (canPlaceCassette) { var wafer = _waferRobot.GetWaferInfo(0); if (wafer.WaferOriginStation == (int)ModuleName.CassAL) { if (_cassetteAL.IsReadyForPlace(ModuleName.WaferRobot, wafer.WaferOriginSlot) && WaferManager.Instance.CheckNoWafer(ModuleName.CassAL, wafer.WaferOriginSlot)) { if (_waferRobot.Place(_cassetteAL.Module, wafer.WaferOriginSlot, Hand.Blade1)) { _cassetteAL.WaitTransfer(ModuleName.WaferRobot); return; } } } else if (wafer.WaferOriginStation == (int)ModuleName.CassAR) { if (_cassetteAR.IsReadyForPlace(ModuleName.WaferRobot, wafer.WaferOriginSlot) && WaferManager.Instance.CheckNoWafer(ModuleName.CassAR, wafer.WaferOriginSlot)) { if (_waferRobot.Place(_cassetteAR.Module, wafer.WaferOriginSlot, Hand.Blade1)) { _cassetteAR.WaitTransfer(ModuleName.WaferRobot); return; } } } } } private void MonitorTrayRobotLoadTask() { if (!_load.IsAvailable) { return; } //先取Wafer再取石墨盘 bool canPick = _load.HasTray(0) && _load.NoWafer(0); if (canPick) { if(_load.HasTrayAndExceedProcessCount(0)) { if(_trayRobot.IsAvailable) { return; } SlotItem emptyTraySlot = GetTrayOrignSlot(ModuleName.LoadLock, 0); if (emptyTraySlot != null) { if (_load.IsReadyForPick(ModuleName.TrayRobot, 0)) { if (_trayRobot.Pick(_load.Module, 0, Hand.Blade1)) { _load.WaitTransfer(ModuleName.TrayRobot); return; } } } } else { if (!_tmRobot.IsAvailable) { return; } if (_load.IsReadyForPick(ModuleName.TMRobot, 0)) { if (_unload.IsInPumping) { return; } if (_tmRobot.Pick(_load.Module, 0, Hand.Blade1)) { _load.WaitTransfer(ModuleName.TMRobot); return; } } } } } private void MonitorTrayRobotCassetteTask() { if (!_trayRobot.IsAvailable || !_cassetteBL.IsAvailable) { return; } bool canPlace = _trayRobot.HasTray(0); if (canPlace) { SlotItem slotItem = GetTrayOrignSlot(ModuleName.TrayRobot, 0); if (slotItem != null) { if (_cassetteBL.IsReadyForPlace(ModuleName.TrayRobot, slotItem.Slot)) { if (_trayRobot.Place(slotItem.Module, slotItem.Slot, Hand.Blade1)) { _cassetteBL.WaitTransfer(ModuleName.TrayRobot); return; } } } } } private void MonitorBufferTask() { if (!_buffer.IsAvailable) { return; } if (!_buffer.IsReadyForPick(ModuleName.TMRobot, 0)) { _buffer.PrepareTransfer(ModuleName.TMRobot, EnumTransferType.Place, 0); } } private void MonitorAlignerTask() { if (!_aligner.IsAvailable) { return; } if (_aligner.HasWafer(0) && _aligner.GetWaferInfo(0).NextStation==(int)ModuleName.Aligner) { _aligner.Aligning(); _aligner.GetWaferInfo(0).NextStation = (int)ModuleName.System; } } private void MonitorPMTask() { foreach (var pm in _lstPms) { if (!pm.IsAvailable) { continue; } if (pm.NoTray(0) && pm.NoWafer(0)) { continue; } int bufferIndex = 0; if(pm ==_pm2) { bufferIndex = 1; } if(pm.NoWafer(0) && pm.HasTray(0) && _buffer.HasTray(bufferIndex)) { continue; } if (!pm.IsReadyForPick(ModuleName.TMRobot, 0)) { pm.PrepareTransfer(ModuleName.TMRobot, EnumTransferType.Pick, 0); } } } private void MonitorLoadTask() { if (_load.FirstDetectWaferArrive(0) || _load.FirstDetectWaferLeave(0)) { _load.ResetPurgedAndSeparatedStatus(); } if (!_load.IsAvailable) { return; } bool canExcute = _load.HasWafer(0) && _load.HasTray(0); if (canExcute) { if (!_load.CheckWaferTraySeparated()) { _load.SeparateWaferTray(); return; } } if (_load.HasWafer(0)) { if (!_load.IsReadyForPick(ModuleName.WaferRobot, 0)) { _load.PrepareTransfer(ModuleName.WaferRobot, EnumTransferType.Pick, 0); return; } } else if (_load.HasTrayAndExceedProcessCount(0)) { if (!_load.IsReadyForPick(ModuleName.TrayRobot, 0)) { _load.PrepareTransfer(ModuleName.TrayRobot, EnumTransferType.Pick, 0); return; } } else if(_load.HasTrayAndNotExceedProcessCount(0)) { if (!_load.IsReadyForPick(ModuleName.TMRobot, 0)) { _load.PrepareTransfer(ModuleName.TMRobot, EnumTransferType.Pick, 0); return; } } else if (_tmRobot.HasTrayAndExceedProcessCount(0) && _tmRobot.NoWafer(0)) { if (!_load.IsReadyForPlace(ModuleName.TMRobot, 0)) { _load.PrepareTransfer(ModuleName.TMRobot, EnumTransferType.Place, 0); return; } } else { if (!_load.IsReadyForPlace(ModuleName.TMRobot, 0)) { _load.PrepareTransfer(ModuleName.TMRobot, EnumTransferType.Place, 0); return; } } } private void MonitorUnLoadTask() { if (!_unload.IsAvailable) { return; } // 重置UnLoad Purge和分离状态 if (_unload.FirstDetectWaferArrive(0) || _unload.FirstDetectWaferLeave(0)) { _unload.ResetPurgedAndSeparatedStatus(); } // TM把Wafer和Tray放如UnLoad后,先冷却,再分离,然后取Tray前Purge if (_unload.HasWafer(0) && _unload.HasTray(0)) { // 取Tray前Purge if (!_unload.CheckPurgedBeforeTrayPicking()) { if (_tmRobot.IsInPumping) return; _unload.PurgeBeforeTrayPicking( _unload.GetWaferPurgeCount(0), _unload.GetWaferPumpDelayTime(0)); return; } // Cooling if (!_unload.CheckCoolingCompleted()) { GetWaferSequenceCoolingTime(_unload.Module, 0, out var coolingTime); _unload.Cooling(true, coolingTime); return; } // 如果没分离,先分离 if (!_unload.CheckWaferTraySeparated()) { _unload.SeparateWaferTray(); return; } } if (_unload.HasTray(0)) // UnLoad有Tray,先让TMRobot取Tray { if (_unload.CheckWaferTraySeparated()) { // 如果Sequence下一步是UnLoad,并且W&T已冷却和分离 if (!_unload.CheckPurgedBeforeTrayPicking()) { if (_tmRobot.IsInPumping) return; _unload.PurgeBeforeTrayPicking( _unload.GetWaferPurgeCount(0), _unload.GetWaferPumpDelayTime(0)); return; } // 如果Tray拿走以前还没Purge,先Purge,在让TMRobot取Tray if (!_unload.CheckPurgedBeforeTrayPicking()) return; if (!_unload.IsReadyForPick(ModuleName.TMRobot, 0)) { if (_tmRobot.IsInPumping) return; // UnLoad中有Tray,则准备好让TMRobot来取 _unload.PrepareTransfer(ModuleName.TMRobot, EnumTransferType.Pick, 0); return; } } } else if (_unload.HasWafer(0)) // 如果没Tray,下一步让WaferRobot取Wafer { //if (_unload.CheckWaferTraySeparated()) { // 如果取Wafer前还未Purge,先Purge if (!_unload.CheckPurgedBeforeWaferPicking()) { if (_tmRobot.IsInPumping) return; var cycle = _unload.GetWaferPurgeCount(0, "PurgeCountBeforeWaferPicking"); var pumpDelay = _unload.GetWaferPumpDelayTime(0, "PumpDelayTimeBeforeWaferPicking"); _unload.PurgeBeforeWaferPicking(cycle, pumpDelay); _unload.GetWaferInfo(0).NextSequenceStep++; return; } if (_unload.CheckPurgedBeforeWaferPicking() && !_unload.IsReadyForPick(ModuleName.WaferRobot, 0)) { if (_tmRobot.IsInPumping) return; // 准备好让WaferRobot来取 _unload.PrepareTransfer(ModuleName.WaferRobot, EnumTransferType.Pick, 0); } } return; } else // 如果UnLoad里啥也没有,则准备好下次TMRobot喂 W&T { // 如果Wafer取完后还没有Purge,先Purge if (!_unload.CheckPurgedAfterWaferPicked()) { if (_tmRobot.IsInPumping) return; var cycle = _unload.GetWaferPurgeCount(0, "PurgeCountAfterWaferPicking"); var pumpDelay = _unload.GetWaferPumpDelayTime(0, "PumpDelayTimeAfterWaferPicking"); _unload.PurgeAfterWaferPicked(cycle, pumpDelay); } // 如果Wafer取完后还没有Purge,则终止后去操作。 if (!_unload.CheckPurgedAfterWaferPicked()) return; if (!_unload.IsReadyForPlace(ModuleName.TMRobot, 0)) { if (_tmRobot.IsInPumping) return; _unload.PrepareTransfer(ModuleName.TMRobot, EnumTransferType.Place, 0); return; } } } private SlotItem GetEmptyTraySlot() { for (int i = 0; i < WaferManager.Instance.GetWafers(ModuleName.CassBL).Length; i++) { if (WaferManager.Instance.CheckNoTray(ModuleName.CassBL, i)) { return new SlotItem(ModuleName.CassBL, i); } } return null; } private SlotItem GetTrayOrignSlot(ModuleName module, int slot) { var wafer = GetModule(module).GetWaferInfo(slot); if (wafer != null && GetModule(module).HasTray(slot) && _cassetteBL.NoTray(wafer.TrayOriginSlot)) { return new SlotItem(ModuleName.CassBL, wafer.TrayOriginSlot); } return null; } private bool CheckWaferCouldBeReturn(ModuleName module, int slot) { var wafer = WaferManager.Instance.GetWafer(module, slot); if (!wafer.IsWaferEmpty) { return true; } if(module== ModuleName.Buffer || module == ModuleName.PM1 || module == ModuleName.PM2) { return false; } else if (wafer.TrayState == TrayStatus.Normal) { return true; } return false; } private bool GetWaferSequenceCoolingTime(ModuleName module, int slot, out int coolingTime) { coolingTime = 0; if (!WaferManager.Instance.CheckHasWafer(module, slot)) return false; var wafer = WaferManager.Instance.GetWafer(module, slot); if (wafer.ProcessJob == null || wafer.ProcessJob.Sequence == null) return false; if (wafer.NextSequenceStep >= wafer.ProcessJob.Sequence.Steps.Count) return false; if (!wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepModules.Contains(module)) return false; if (!int.TryParse(wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepParameter["CoolingTime"].ToString(), out coolingTime)) { coolingTime = 0; //coolingTime = SC.GetValue("Unload.DefaultCoolingTime"); //EV.PostWarningLog("Scheduler", $"Sequence step Unload cooling time is not valid, instead with the SC default value {coolingTime} seconds"); return false; } return true; } } }