2023-03-03 15:42:13 +08:00
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using Aitex.Core.Common;
|
|
|
|
|
using Aitex.Core.RT.Event;
|
|
|
|
|
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.Equipment;
|
|
|
|
|
using MECF.Framework.Common.Schedulers;
|
|
|
|
|
using MECF.Framework.Common.SubstrateTrackings;
|
|
|
|
|
using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Buffers;
|
|
|
|
|
|
|
|
|
|
namespace SicRT.Modules
|
|
|
|
|
{
|
|
|
|
|
public class ReturnAllWafer : SchedulerModuleFactory
|
|
|
|
|
{
|
|
|
|
|
//private bool needAligner = false;
|
|
|
|
|
Dictionary<ModuleName, int> _checkPosition = new Dictionary<ModuleName, int>()
|
|
|
|
|
{
|
|
|
|
|
{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)
|
|
|
|
|
{
|
2023-03-13 17:37:55 +08:00
|
|
|
|
var wafer = _waferRobot.GetWaferInfo(0);
|
2023-03-03 15:42:13 +08:00
|
|
|
|
if (wafer.OriginStation == (int)ModuleName.CassAL)
|
|
|
|
|
{
|
|
|
|
|
if (_cassetteAL.IsReadyForPlace(ModuleName.WaferRobot, wafer.OriginSlot) && WaferManager.Instance.CheckNoWafer(ModuleName.CassAL, wafer.OriginSlot))
|
|
|
|
|
{
|
|
|
|
|
if (_waferRobot.Place(_cassetteAL.Module, wafer.OriginSlot, Hand.Blade1))
|
|
|
|
|
{
|
|
|
|
|
_cassetteAL.WaitTransfer(ModuleName.WaferRobot);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (wafer.OriginStation == (int)ModuleName.CassAR)
|
|
|
|
|
{
|
|
|
|
|
if (_cassetteAR.IsReadyForPlace(ModuleName.WaferRobot, wafer.OriginSlot) && WaferManager.Instance.CheckNoWafer(ModuleName.CassAR, wafer.OriginSlot))
|
|
|
|
|
{
|
|
|
|
|
if (_waferRobot.Place(_cassetteAR.Module, wafer.OriginSlot, 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)
|
|
|
|
|
{
|
2023-03-13 17:37:55 +08:00
|
|
|
|
var wafer = GetModule(module).GetWaferInfo(slot);
|
2023-03-03 15:42:13 +08:00
|
|
|
|
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)
|
|
|
|
|
{
|
2023-03-13 17:37:55 +08:00
|
|
|
|
var wafer = WaferManager.Instance.GetWafer(module, slot);
|
2023-03-03 15:42:13 +08:00
|
|
|
|
if (!wafer.IsEmpty)
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(module== ModuleName.Buffer || module == ModuleName.PM1 || module == ModuleName.PM2)
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
else if (wafer.TrayState == WaferTrayStatus.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;
|
|
|
|
|
|
2023-03-13 17:37:55 +08:00
|
|
|
|
var wafer = WaferManager.Instance.GetWafer(module, slot);
|
2023-03-03 15:42:13 +08:00
|
|
|
|
|
|
|
|
|
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<int>("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;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|