Sic04/SicRT/Equipments/Schedulers/SchedulerLoadLock.cs

450 lines
14 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Linq;
using Aitex.Core.Common;
using Aitex.Core.RT.Device;
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;
namespace SicRT.Scheduler
{
public class SchedulerLoadLock : SchedulerModule
{
#region Variables
private LoadLockModuleBase _ll = null;
private ModuleName _taskRobot;
private int _taskSlot;
private int _entityTaskToken = (int)FSM_MSG.NONE;
#endregion
#region Constructors
public SchedulerLoadLock(ModuleName module) : base(module.ToString())
{
_module = module.ToString();
_ll = Singleton<EquipmentManager>.Instance.Modules[module] as LoadLockModuleBase;
}
#endregion
#region Properties
public override bool IsAvailable
{
get { return _ll.IsIdle && _ll.IsOnline && CheckTaskDone() && _ll.CheckSlitValveClosed(); }
}
public override bool IsOnline
{
get { return _ll.IsOnline; }
}
public override bool IsError
{
get { return _ll.IsError; }
}
public bool IsInPumping =>
_task == TaskType.Pump || _task == TaskType.Purge || _task == TaskType.PrepareTransfer;
/// <summary>
/// 是否执行放Wafer后TM放Tray前的Purge。
/// <para>如果Tray来自TMRobot放完Wafer马上Purge。</para>
/// <para>如果Tray来自TrayCassette放完Tray以后统一Purge。</para>
/// </summary>
public bool HasPurgedAfterWaferPlaced { get; private set; }
/// <summary>
/// 是否已执行组合后、TM取盘前的Purge.
/// <para>无论Tray来自TMRobot还是TrayRobotGroup以后一定要Purge。</para>
/// <para>Purge次数使用Sequence中的配置。</para>
public bool HasPurgedAfterGrouped { get; private set; }
#endregion
public override bool PrepareTransfer(ModuleName robot, EnumTransferType type, int slot)
{
lock (SyncRoot)
{
_task = TaskType.PrepareTransfer;
_taskRobot = robot;
_taskSlot = slot;
LogTaskStart(_task, $"{robot} {type} slot {slot + 1}");
return _ll.PrepareTransfer(robot, Hand.Blade1, slot, type, out _);
}
}
internal bool CheckAtAtm()
{
lock (SyncRoot)
{
SicLoadLock deviceLL = DEVICE.GetDevice<SicLoadLock>($"{_module}.{_module}");
return deviceLL.CheckAtm();
}
}
internal bool CheckAtVacuum()
{
lock (SyncRoot)
{
SicLoadLock deviceLL = DEVICE.GetDevice<SicLoadLock>($"{_module}.{_module}");
return deviceLL.CheckVacuum();
}
}
internal void SetJobStatue()
{
lock (SyncRoot)
{
SicLoadLock deviceLL = DEVICE.GetDevice<SicLoadLock>($"{_module}.{_module}");
//deviceLL.SetJobDoneStatus();
}
}
public override bool IsReadyForPick(ModuleName robot, int slot)
{
lock (SyncRoot)
{
if (robot == ModuleName.WaferRobot)
{
return _ll.CheckReadyForTransfer(robot, Hand.Blade1, slot, EnumTransferType.Pick, out _)
&& WaferManager.Instance.CheckHasWafer(ModuleHelper.Converter(_module), slot);
}
else if (robot == ModuleName.TMRobot || robot == ModuleName.TrayRobot)
{
return _ll.CheckReadyForTransfer(robot, Hand.Blade1, slot, EnumTransferType.Pick, out _)
&& WaferManager.Instance.CheckHasTray(ModuleHelper.Converter(_module), slot);
}
return false;
}
}
public override bool IsReadyForPlace(ModuleName robot, int slot)
{
lock (SyncRoot)
{
if (robot == ModuleName.WaferRobot)
{
return _ll.CheckReadyForTransfer(robot, Hand.Blade1, slot, EnumTransferType.Place, out _);
}
else if (robot == ModuleName.TMRobot || robot == ModuleName.TrayRobot)
{
return _ll.CheckReadyForTransfer(robot, Hand.Blade1, slot, EnumTransferType.Place, out _)
&& WaferManager.Instance.CheckNoTray(ModuleHelper.Converter(_module), slot);
}
return false;
}
}
/// <summary>
/// 重置HasPurged和HasGrouped标记。
/// </summary>
public void ResetPurgedAndGroupedStatus()
{
lock (SyncRoot)
{
HasPurgedAfterWaferPlaced = false;
HasPurgedAfterGrouped = false;
}
}
public bool Vent()
{
lock (SyncRoot)
{
_task = TaskType.Vent;
_entityTaskToken = _ll.InvokeVent();
LogTaskStart(_task, $"{Module} vent to ATM");
return _entityTaskToken != (int)FSM_MSG.NONE;
}
}
public bool Pump()
{
lock (SyncRoot)
{
_entityTaskToken = _ll.InvokePump();
if (_entityTaskToken != (int)FSM_MSG.NONE)
{
_task = TaskType.Pump;
LogTaskStart(_task, $"{Module} pump to Vaccum");
return true;
}
return false;
}
}
/// <summary>
/// Wafer放好后如果Tray将从TMRobot喂进来执行此Purge。
/// <para>Purge次数有Configuration\LoadLock\Purge中的相关次数决定。</para>
/// </summary>
/// <param name="args"></param>
/// <returns></returns>
public bool PurgeAfterWaferPlaced(params object[] args)
{
lock (SyncRoot)
{
// 如果循环次数为0则跳过此步骤。
if (args is null || (args[0] is int cycle && cycle <= 0))
{
LogTaskStart(_task, " Purge after wafer placed was ignored since the cycle is zero");
HasPurgedAfterGrouped = true;
return true;
}
_entityTaskToken = _ll.InvokePurge(args);
if (_entityTaskToken != (int)FSM_MSG.NONE)
{
_task = TaskType.Purge;
LogTaskStart(_task, $" Purge after wafer placed");
HasPurgedAfterWaferPlaced = true;
return true;
}
return false;
}
}
/// <summary>
/// 当Wafer和Tray组合完毕后执行此Purge。
/// <para>组合完毕后无条件支持此PurgePurge次数有Sequence设定。</para>
/// </summary>
/// <param name="args"></param>
/// <returns></returns>
public bool PurgeAfterGrouped(params object[] args)
{
lock (SyncRoot)
{
// 如果循环次数为0则跳过此步骤。
if (args is null || (args[0] is int cycle && cycle <= 0))
{
LogTaskStart(_task, " Purge after Grouping was ignored since the cycle is zero");
HasPurgedAfterGrouped = true;
return true;
}
_entityTaskToken = _ll.InvokePurge(args);
if (_entityTaskToken != (int)FSM_MSG.NONE)
{
_task = TaskType.Purge;
LogTaskStart(_task, $"Purge after grouping");
HasPurgedAfterGrouped = true;
return true;
}
return false;
}
}
public bool GroupWaferTray()
{
lock (SyncRoot)
{
_entityTaskToken = _ll.InvokeGroupWaferTray();
if (_entityTaskToken != (int)FSM_MSG.NONE)
{
_task = TaskType.Group;
LogTaskStart(_task, $"{Module} start group wafer and tray");
return true;
}
return false;
}
}
public bool SeparateWaferTray()
{
throw new NotSupportedException();
}
public int? GetWaferPurgeCount(int slot)
{
lock (SyncRoot)
{
if (!WaferManager.Instance.CheckHasWafer(Module, slot))
return null;
WaferInfo wafer = WaferManager.Instance.GetWafer(Module, slot);
if (wafer.ProcessJob == null || wafer.ProcessJob.Sequence == null)
return null;
if (wafer.NextSequenceStep >= wafer.ProcessJob.Sequence.Steps.Count)
return null;
if (!wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepModules
.Any(m => m == ModuleName.LoadLock || m == ModuleName.Load))
return null;
if (!wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepParameter.ContainsKey("PurgeCount"))
return null;
if (int.TryParse(
wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepParameter["PurgeCount"].ToString(),
out int purgeCount))
{
return purgeCount;
}
return null;
}
}
public int? GetWaferPumpDelayTime(int slot)
{
lock (SyncRoot)
{
if (!WaferManager.Instance.CheckHasWafer(Module, slot))
return null;
WaferInfo wafer = WaferManager.Instance.GetWafer(Module, slot);
if (wafer.ProcessJob == null || wafer.ProcessJob.Sequence == null)
return null;
if (wafer.NextSequenceStep >= wafer.ProcessJob.Sequence.Steps.Count)
return null;
if (!wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepModules
.Any(m => m == ModuleName.LoadLock || m == ModuleName.Load))
return null;
if (!wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepParameter.ContainsKey("PumpDelayTime"))
return null;
if (int.TryParse(
wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepParameter["PumpDelayTime"]
.ToString(), out int pumpDelayTime))
{
return pumpDelayTime;
}
return null;
}
}
public override bool CheckWaferNextStepIsThis(ModuleName module, int slot)
{
lock (SyncRoot)
{
if (!WaferManager.Instance.CheckHasWafer(module, slot))
return false;
WaferInfo 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
.Any(m => m == ModuleName.LoadLock || m == ModuleName.Load))
return false;
return true;
}
}
public override bool CheckWaferTrayGrouped()
{
lock (SyncRoot)
{
return !_ll.CheckWaferClamped() && WaferManager.Instance.CheckHasWafer(Module, 0);
}
}
public override bool CheckWaferTraySeparated()
{
throw new NotSupportedException();
}
public override bool CheckSlitValveClosed()
{
lock (SyncRoot)
{
return _ll.CheckSlitValveClosed();
}
}
public bool Monitor()
{
lock (SyncRoot)
{
return true;
}
}
public string GetTaskRunning()
{
return $"{_task.ToString()}/{_taskRobot}";
}
public bool CheckTaskDone()
{
lock (SyncRoot)
{
bool ret = false;
switch (_task)
{
case TaskType.None:
ret = true;
break;
case TaskType.PrepareTransfer:
ret = _ll.CheckAcked(
_entityTaskToken); //&& _ll.CheckReadyForTransfer(_taskRobot, Hand.Blade1, _taskSlot, EnumTransferType.Place, out _);
break;
case TaskType.Cooling:
ret = _ll.CheckAcked(_entityTaskToken);
break;
case TaskType.Vent:
ret = _ll.CheckAcked(_entityTaskToken);
break;
case TaskType.Pump:
ret = _ll.CheckAcked(_entityTaskToken);
break;
case TaskType.Purge:
ret = _ll.CheckAcked(_entityTaskToken);
break;
case TaskType.Group:
ret = _ll.CheckAcked(_entityTaskToken);
break;
case TaskType.Separate:
ret = _ll.CheckAcked(_entityTaskToken);
break;
}
if (ret && _task != TaskType.None)
{
LogTaskDone(_task, "");
_task = TaskType.None;
}
return ret;
}
}
}
}