Sic04/SicRT/Equipments/Schedulers/SchedulerUnLoad.cs

514 lines
16 KiB
C#
Raw Normal View History

using System.Diagnostics;
using System.Linq;
2022-09-19 09:16:33 +08:00
using Aitex.Core.Common;
using Aitex.Core.RT.Device;
using Aitex.Core.RT.Event;
2022-09-19 09:16:33 +08:00
using Aitex.Core.RT.Fsm;
using Aitex.Core.Util;
using Aitex.Sorter.Common;
using MECF.Framework.Common.Equipment;
using MECF.Framework.Common.Schedulers;
using MECF.Framework.Common.SubstrateTrackings;
using Mainframe.LLs;
using SicRT.Equipments.Systems;
using SicRT.Modules.Schedulers;
using Mainframe.UnLoads;
namespace SicRT.Scheduler
{
public class SchedulerUnLoad : SchedulerModule
{
public override bool IsAvailable
{
get
{
lock (SyncRoot)
{
return _unL.IsIdle && _unL.IsOnline && CheckTaskDone() && _unL.CheckSlitValveClosed();
}
2022-09-19 09:16:33 +08:00
}
}
public override bool IsOnline
{
get
{
lock (SyncRoot)
{
lock (SyncRoot)
{
return _unL.IsOnline;
}
}
2022-09-19 09:16:33 +08:00
}
}
public override bool IsError
{
get
{
lock (SyncRoot)
{
return _unL.IsError;
}
2022-09-19 09:16:33 +08:00
}
}
private UnLoadModuleBase _unL = null;
private ModuleName _taskRobot;
private int _taskSlot;
private int _entityTaskToken = (int)FSM_MSG.NONE;
private bool _separated = false;
private bool _purgedBefTrayPicking = false;
private bool _purgedBefWaferPicking = false;
private bool _purgedAfWaferPicked;
2022-09-19 09:16:33 +08:00
private bool _coolingCompleted = false;
private readonly Stopwatch _swStayInUnLoadBeforeCooling = new Stopwatch();
2022-09-19 09:16:33 +08:00
public bool IsInPumping
{
get
{
lock (SyncRoot)
{
return _task == TaskType.Pump || _task == TaskType.Purge || _task == TaskType.PrepareTransfer;
}
}
}
2022-09-19 09:16:33 +08:00
public int LastAfAtmPurgeCount { get; set; }
public int LastAfAtmPurgeDelay { get; set; }
public bool HasWaferPickedByWaferRobot { get; set; }
public SchedulerUnLoad() : base(ModuleName.UnLoad.ToString())
2022-09-19 09:16:33 +08:00
{
lock (SyncRoot)
{
_unL = Singleton<EquipmentManager>.Instance.Modules[ModuleName.UnLoad] as UnLoadModuleBase;
}
2022-09-19 09:16:33 +08:00
}
public override bool PrepareTransfer(ModuleName robot, EnumTransferType type, int slot)
{
lock (SyncRoot)
{
_task = TaskType.PrepareTransfer;
_taskRobot = robot;
_taskSlot = slot;
2022-09-19 09:16:33 +08:00
LogTaskStart(_task, $"{robot} {type} slot {slot + 1}");
2022-09-19 09:16:33 +08:00
return _unL.PrepareTransfer(robot, Hand.Blade1, slot, type, out _);
}
2022-09-19 09:16:33 +08:00
}
internal bool CheckAtAtm()
{
lock (SyncRoot)
{
SicLoadLock deviceLL = DEVICE.GetDevice<SicLoadLock>($"{_module}.{_module}");
2022-09-19 09:16:33 +08:00
return deviceLL.CheckAtm();
}
2022-09-19 09:16:33 +08:00
}
internal bool CheckAtVacuum()
{
lock (SyncRoot)
{
SicLoadLock deviceLL = DEVICE.GetDevice<SicLoadLock>($"{_module}.{_module}");
2022-09-19 09:16:33 +08:00
return deviceLL.CheckVacuum();
}
2022-09-19 09:16:33 +08:00
}
internal void SetJobStatue()
{
lock (SyncRoot)
{
SicLoadLock deviceLL = DEVICE.GetDevice<SicLoadLock>($"{_module}.{_module}");
//deviceLL.SetJobDoneStatus();
}
2022-09-19 09:16:33 +08:00
}
public override bool IsReadyForPick(ModuleName robot, int slot)
{
lock (SyncRoot)
2022-09-19 09:16:33 +08:00
{
if (robot == ModuleName.WaferRobot)
{
return _unL.CheckReadyForTransfer(robot, Hand.Blade1, slot, EnumTransferType.Pick, out _)
&& WaferManager.Instance.CheckHasWafer(ModuleHelper.Converter(_module), slot);
}
else if (robot == ModuleName.TMRobot)
{
return _unL.CheckReadyForTransfer(robot, Hand.Blade1, slot, EnumTransferType.Pick, out _)
&& WaferManager.Instance.CheckHasTray(ModuleHelper.Converter(_module), slot);
}
return false;
2022-09-19 09:16:33 +08:00
}
}
public override bool IsReadyForPlace(ModuleName robot, int slot)
{
lock (SyncRoot)
{
return _unL.CheckReadyForTransfer(robot, Hand.Blade1, slot, EnumTransferType.Place, out _)
&& WaferManager.Instance.CheckNoWafer(ModuleHelper.Converter(_module), slot)
&& WaferManager.Instance.CheckNoTray(ModuleHelper.Converter(_module), slot);
}
2022-09-19 09:16:33 +08:00
}
public bool Vent()
{
lock (SyncRoot)
{
_task = TaskType.Vent;
2022-09-19 09:16:33 +08:00
_entityTaskToken = _unL.InvokeVent();
2022-09-19 09:16:33 +08:00
LogTaskStart(_task, $"{Module} vent to ATM");
2022-09-19 09:16:33 +08:00
return _entityTaskToken != (int)FSM_MSG.NONE;
}
2022-09-19 09:16:33 +08:00
}
public bool Pump()
{
lock (SyncRoot)
2022-09-19 09:16:33 +08:00
{
_entityTaskToken = _unL.InvokePump();
if (_entityTaskToken != (int)FSM_MSG.NONE)
{
_task = TaskType.Pump;
LogTaskStart(_task, $"{Module} pump to Vaccum");
return true;
}
2022-09-19 09:16:33 +08:00
return false;
}
2022-09-19 09:16:33 +08:00
}
public override bool Cooling(bool coolingType, int coolingTime)
{
lock (SyncRoot)
2022-09-19 09:16:33 +08:00
{
// Wafer进入UnLoad不会立即执行Cooling因此需要记录Cooling前Wafer在UnLoad中的停留时间这部分时间包括UnLoad等待时长和Purge时长。
// 当开始Cooling时已等待的时间从Cooling时间里减去已节省时间。
_swStayInUnLoadBeforeCooling.Stop();
var newCoolingTime = coolingTime - _swStayInUnLoadBeforeCooling.Elapsed.TotalSeconds;
EV.PostInfoLog(Module.ToString(), $"Wafer stays in UnLoad for {_swStayInUnLoadBeforeCooling.Elapsed.TotalSeconds:F1}s");
_entityTaskToken = _unL.InvokeCooling((int)newCoolingTime);
if (_entityTaskToken != (int)FSM_MSG.NONE)
{
_task = TaskType.Cooling;
LogTaskStart(_task, $"{Module} cooling {coolingTime} seconds");
}
_coolingCompleted = _entityTaskToken != (int)FSM_MSG.NONE;
return _coolingCompleted;
2022-09-19 09:16:33 +08:00
}
}
public bool PurgeBeforeTrayPicking(params object[] args)
2022-09-19 09:16:33 +08:00
{
lock (SyncRoot)
{
// 如果循环次数为0则跳过此步骤。
if (args is null || (args[0] is int cycle && cycle <= 0))
{
LogTaskStart(_task,
$" Purge before tray picking was ignored since the cycle is zero");
_purgedBefTrayPicking = true;
return true;
}
_entityTaskToken = _unL.InvokePurge(args);
if (_entityTaskToken != (int)FSM_MSG.NONE)
{
_task = TaskType.Purge;
LogTaskStart(_task, $" Purge before tray picking");
_purgedBefTrayPicking = true;
return true;
}
return false;
}
}
public bool PurgeBeforeWaferPicking(params object[] args)
{
lock (SyncRoot)
{
// 如果循环次数为0则跳过此步骤。
if (args is null || (args[0] is int cycle && cycle <= 0))
{
LogTaskStart(_task,
$"[{Module}] Purge before wafer picking was ignored since the cycle is zero");
_purgedBefWaferPicking = true;
return true;
}
_entityTaskToken = _unL.InvokePurge(args);
if (_entityTaskToken != (int)FSM_MSG.NONE)
{
_task = TaskType.Purge;
LogTaskStart(_task, $" Purge before wafer picking");
_purgedBefWaferPicking = true;
return true;
}
return false;
2022-09-19 09:16:33 +08:00
}
}
public bool PurgeAfterWaferPicked(params object[] args)
{
lock (SyncRoot)
{
// 如果循环次数为0则跳过此步骤。
if (args is null || (args[0] is int cycle && cycle <= 0))
{
LogTaskStart(_task,
$" Purge after wafer picked was ignored since the cycle is zero");
_purgedAfWaferPicked = true;
HasWaferPickedByWaferRobot = false;
return true;
}
_entityTaskToken = _unL.InvokePurge(args);
if (_entityTaskToken != (int)FSM_MSG.NONE)
{
_task = TaskType.Purge;
LogTaskStart(_task, $" Purge after wafer picked");
_purgedAfWaferPicked = true;
HasWaferPickedByWaferRobot = false;
LastAfAtmPurgeCount = 0;
LastAfAtmPurgeDelay = 0;
return true;
}
return false;
}
}
2022-09-19 09:16:33 +08:00
public bool Monitor()
{
lock (SyncRoot)
{
return true;
}
2022-09-19 09:16:33 +08:00
}
public bool GroupWaferTray()
{
lock (SyncRoot)
2022-09-19 09:16:33 +08:00
{
_entityTaskToken = _unL.InvokeGroupWaferTray();
if (_entityTaskToken != (int)FSM_MSG.NONE)
{
_task = TaskType.Group;
LogTaskStart(_task, $"{Module} start group wafer and tray");
}
2022-09-19 09:16:33 +08:00
return _entityTaskToken != (int)FSM_MSG.NONE;
2022-09-19 09:16:33 +08:00
}
}
public bool SeparateWaferTray()
{
lock (SyncRoot)
2022-09-19 09:16:33 +08:00
{
_entityTaskToken = _unL.InvokeSeparateWaferTray();
if (_entityTaskToken != (int)FSM_MSG.NONE)
{
_task = TaskType.Separate;
LogTaskStart(_task, $"{Module} start separate wafer and tray");
}
_separated = _entityTaskToken != (int)FSM_MSG.NONE;
return _entityTaskToken != (int)FSM_MSG.NONE;
2022-09-19 09:16:33 +08:00
}
}
public void ResetPurgedAndSeparatedStatus()
{
lock (SyncRoot)
{
_coolingCompleted = false;
_separated = false;
_purgedBefTrayPicking = false;
_purgedBefWaferPicking = false;
_purgedAfWaferPicked = false;
// 开始记录Wafer进入UnLoad后停留的时长
_swStayInUnLoadBeforeCooling.Restart();
EV.PostInfoLog(Module.ToString(), "Start to record cooling time");
}
2022-09-19 09:16:33 +08:00
}
public bool CheckCoolingCompleted()
{
lock (SyncRoot)
{
return _coolingCompleted;
}
2022-09-19 09:16:33 +08:00
}
public override bool CheckWaferTraySeparated()
{
lock (SyncRoot)
{
return _separated;
}
2022-09-19 09:16:33 +08:00
}
public bool CheckPurgedBeforeTrayPicking()
{
lock (SyncRoot)
{
return _purgedBefTrayPicking;
}
}
public bool CheckPurgedBeforeWaferPicking()
2022-09-19 09:16:33 +08:00
{
lock (SyncRoot)
{
return _purgedBefWaferPicking;
}
2022-09-19 09:16:33 +08:00
}
public bool CheckPurgedAfterWaferPicked()
{
lock (SyncRoot)
{
return _purgedAfWaferPicked;
}
}
2022-09-19 09:16:33 +08:00
public override bool CheckSlitValveClosed()
{
lock (SyncRoot)
{
return _unL.CheckSlitValveClosed();
}
2022-09-19 09:16:33 +08:00
}
public int GetWaferPurgeCount(int slot, string whichPurge = "PurgeCount")
2022-09-19 09:16:33 +08:00
{
lock (SyncRoot)
{
if (!WaferManager.Instance.CheckHasWafer(Module, slot))
return 0;
2022-09-19 09:16:33 +08:00
WaferInfo wafer = WaferManager.Instance.GetWafer(Module, slot);
2022-09-19 09:16:33 +08:00
if (wafer.ProcessJob == null || wafer.ProcessJob.Sequence == null)
return 0;
2022-09-19 09:16:33 +08:00
if (wafer.NextSequenceStep >= wafer.ProcessJob.Sequence.Steps.Count)
return 0;
2022-09-19 09:16:33 +08:00
if (!wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepModules.Contains(Module))
return 0;
2022-09-19 09:16:33 +08:00
if (!wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepParameter.ContainsKey(whichPurge))
return 0;
2022-09-19 09:16:33 +08:00
if (int.TryParse(
wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepParameter[whichPurge].ToString(),
out int purgeCount))
{
return purgeCount;
}
2022-09-19 09:16:33 +08:00
return 0;
}
2022-09-19 09:16:33 +08:00
}
public int GetWaferPumpDelayTime(int slot, string whichPumpDelay = "PumpDelayTime")
2022-09-19 09:16:33 +08:00
{
lock (SyncRoot)
{
if (!WaferManager.Instance.CheckHasWafer(Module, slot))
return 0;
2022-09-19 09:16:33 +08:00
WaferInfo wafer = WaferManager.Instance.GetWafer(Module, slot);
2022-09-19 09:16:33 +08:00
if (wafer.ProcessJob == null || wafer.ProcessJob.Sequence == null)
return 0;
2022-09-19 09:16:33 +08:00
if (wafer.NextSequenceStep >= wafer.ProcessJob.Sequence.Steps.Count)
return 0;
2022-09-19 09:16:33 +08:00
if (!wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepModules.Contains(Module))
return 0;
2022-09-19 09:16:33 +08:00
if (!wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepParameter.ContainsKey(whichPumpDelay))
return 0;
2022-09-19 09:16:33 +08:00
if (int.TryParse(
wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepParameter[whichPumpDelay]
.ToString(), out int pumpDelayTime))
{
return pumpDelayTime;
}
return 0;
2022-09-19 09:16:33 +08:00
}
}
2022-09-19 09:16:33 +08:00
public string GetTaskRunning()
{
return _task.ToString();
2022-09-19 09:16:33 +08:00
}
public bool CheckTaskDone()
{
lock (SyncRoot)
2022-09-19 09:16:33 +08:00
{
var taskSucceed = false;
switch (_task)
{
case TaskType.None:
taskSucceed = true;
break;
case TaskType.PrepareTransfer:
taskSucceed = _unL.CheckAcked(_entityTaskToken);
break;
case TaskType.Cooling:
taskSucceed = _unL.CheckAcked(_entityTaskToken);
break;
case TaskType.Vent:
taskSucceed = _unL.CheckAcked(_entityTaskToken);
break;
case TaskType.Pump:
taskSucceed = _unL.CheckAcked(_entityTaskToken);
break;
case TaskType.Group:
taskSucceed = _unL.CheckAcked(_entityTaskToken);
break;
case TaskType.Purge:
taskSucceed = _unL.CheckAcked(_entityTaskToken);
break;
case TaskType.Separate:
taskSucceed = _unL.CheckAcked(_entityTaskToken);
break;
}
2022-09-19 09:16:33 +08:00
return SuperCheckTaskDone(taskSucceed, _unL.IsIdle | _unL.IsError);
}
}
2022-09-19 09:16:33 +08:00
}
}