Sic08/SicRT/Equipments/Systems/EquipmentManager.cs

1442 lines
48 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.Collections.Generic;
using Aitex.Core.Common;
using Aitex.Core.RT.DataCenter;
using Aitex.Core.RT.Device;
using Aitex.Core.RT.Event;
using Aitex.Core.RT.Fsm;
using Aitex.Core.RT.OperationCenter;
using Aitex.Core.RT.Routine;
using Aitex.Core.Util;
using Aitex.Core.Utilities;
using MECF.Framework.Common.Equipment;
using MECF.Framework.Common.Fsm;
using MECF.Framework.Common.SubstrateTrackings;
using MECF.Framework.RT.Core.IoProviders;
using SicRT.Instances;
using SicRT.Modules;
using System.Linq;
using System.Threading.Tasks;
using Aitex.Core.RT.Device.Unit;
using Aitex.Core.RT.SCCore;
using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.UPS;
using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Temps.AE;
using Aitex.Core.RT.Device.Devices;
using SicModules.Aligners;
using SicModules.Buffers;
using SicModules.Cassettes;
using SicModules.EFEMs;
using SicModules.LLs;
using SicModules.PMs;
using SicModules.TMs;
using SicModules.UnLoads;
using Aitex.Core.RT.DBCore;
using System.Diagnostics;
using Aitex.Core.RT.Log;
namespace SicRT.Equipments.Systems
{
public enum RtState
{
Init,
Initializing,
Idle,
Transfer,
AutoRunning,
AutoIdle,
Cycle,
PlatformCycle,
ReturnAllWafer,
Error,
ShutDown = 999
}
public class EquipmentManager : FsmDevice
{
public enum MSG
{
HOME,
RESET,
ABORT,
ERROR,
MoveWafer,
ReturnAllWafer,
PlatformCycle,
HomeUnit,
PauseAuto,
ResumeAuto,
Stop,
StopPlatformCycle,
StartCycle,
SetAutoMode,
SetManualMode,
CreateJob,
PauseJob,
ResumeJob,
StartJob,
StopJob,
AbortJob,
JobDone,
FAJobCommand,
SetOnline,
SetOffline,
ModuleError,
ShutDown = 999,
}
public Dictionary<ModuleName, ModuleFsmDevice> Modules { get; set; }
public bool IsAutoMode
{
get
{
return FsmState == (int)RtState.AutoRunning;
}
}
public bool IsInit
{
get { return FsmState == (int)RtState.Init; }
}
public bool IsOnline
{
get;
set;
}
public bool IsIdle
{
get { return FsmState == (int)RtState.Idle; }
}
public bool IsAlarm
{
get { return FsmState == (int)RtState.Error; }
}
public bool IsRunning
{
get
{
return FsmState == (int)RtState.Initializing
|| FsmState == (int)RtState.Transfer
|| FsmState == (int)RtState.Cycle
|| FsmState == (int)RtState.AutoRunning;
}
}
private ManualTransfer _manualTransfer;
private AutoTransfer _auto = null;
private HomeAll _homeAll;
private ReturnAllWafer _returnAll;
//TODO 更名为_lstModuleNames
private List<string> _modules = new List<string>();
//readonly IEnumerable<PropertyInfo> IEntityModules;
private ITAUPS _upsPM1A = null;
private ITAUPS _upsPM1B = null;
private ITAUPS _upsPM2A = null;
private ITAUPS _upsPM2B = null;
private IoUPS _pm1UPS = null;
private IoUPS _pm2UPS = null;
//AETEmp
private AETemp _aeTemp = null;
private SicAETemp _pmAETemp1 = null;
private SicAETemp _pmAETemp2 = null;
//
private IoInterLock _pm1InterLock = null;
private IoInterLock _pm2InterLock = null;
private SicModules.Devices.IoInterLock _tmInterLock = null;
private IoSlitValve _pm1SlitValve = null;
private IoSlitValve _pm2SlitValve = null;
private PeriodicJob _thread;
private IoTC _tc = null;
public EquipmentManager()
{
Module = "System";
Name = "System";
Modules = new Dictionary<ModuleName, ModuleFsmDevice>();
}
public override bool Initialize()
{
InitModules();
EnumLoop<RtState>.ForEach((item) =>
{
MapState((int)item, item.ToString());
});
EnumLoop<MSG>.ForEach((item) =>
{
MapMessage((int)item, item.ToString());
});
EnableFsm(100, RtState.Init);
BuildTransitionTable();
SubscribeDataVariable();
SubscribeOperation();
//InitSetPSUY();
Singleton<EventManager>.Instance.OnAlarmEvent += Instance_OnAlarmEvent;
_manualTransfer = new ManualTransfer();
_homeAll = new HomeAll();
_auto = new AutoTransfer();
_returnAll = new ReturnAllWafer();
SC.RegisterValueChangedCallback("TM.ProcessPressure", SetTansferPressure);
return true;
}
private void SetTansferPressure(object value)
{
try
{
double.TryParse(value.ToString(), out double dbValue);
double offset = SC.GetValue<double>("TM.VacuumPressureBaseOffset");
double basePressure = offset + dbValue;
SC.SetItemValue("TM.PressureBalance.BalancePressure", dbValue);
SC.SetItemValue("TM.VacuumPressureBase", basePressure);
SC.SetItemValue("TM.Purge.VentBasePressure", dbValue);
SC.SetItemValue("PM.VacuumPressureBase", basePressure);
SC.SetItemValue("PM.PM1.ProcessIdle.FinalPressure", value);
SC.SetItemValue("PM.PM1.PreProcess.ChamberPressure", value);
SC.SetItemValue("PM.PM2.ProcessIdle.FinalPressure", value);
SC.SetItemValue("PM.PM2.PreProcess.ChamberPressure", value);
SC.SetItemValue("LoadLock.VacuumPressureBase", basePressure);
SC.SetItemValue("LoadLock.Purge.VentBasePressure", value);
SC.SetItemValue("UnLoad.VacuumPressureBase", basePressure);
SC.SetItemValue("UnLoad.Purge.VentBasePressure", value);
}
catch (Exception ex)
{
EV.PostWarningLog("System", ex.Message);
}
}
/// <summary>
/// 创建指定的Module的实例。
/// </summary>
/// <typeparam name="T">Module类型。</typeparam>
/// <param name="name">Module名称。</param>
/// <param name="totalSlots">Module包含的Wafer槽位总数。</param>
private void GenModule<T>(ModuleName name, int totalSlots = 1)
where T : ModuleFsmDevice
{
ModuleFsmDevice module;
if (totalSlots > 1)
module = (ModuleFsmDevice)Activator.CreateInstance(typeof(T), name, totalSlots);
else
module = (ModuleFsmDevice)Activator.CreateInstance(typeof(T), name);
Debug.Assert(module != null, $"Failed to create instance of module {name}");
// 创建Module实例失败
if (module == null)
{
LOG.Error($"Failed to create instance of module {name}");
return;
}
// 如果Module在系统配置中配置为“未安装”则不要注册Alarm事件
/*if (!module.IsInstalled)
{
LOG.Warning($"{name} is configured as NotInstalled");
return;
}*/
module.OnEnterError += OnModuleError;
Modules[name] = module;
}
private void InitModules()
{
GenModule<TMModule>(ModuleName.TM);
GenModule<LoadLockModule>(ModuleName.LoadLock);
GenModule<UnLoadModule>(ModuleName.UnLoad);
GenModule<BufferModule>(ModuleName.Buffer);
GenModule<AlignerModule>(ModuleName.Aligner);
GenModule<WaferRobotModule>(ModuleName.WaferRobot);
GenModule<TrayRobotModule>(ModuleName.TrayRobot);
GenModule<EFEMModule>(ModuleName.EFEM);
GenModule<CassetteModule>(ModuleName.CassAL, 25);
GenModule<CassetteModule>(ModuleName.CassAR, 25);
GenModule<CassetteModule>(ModuleName.CassBL, 8);
GenModule<PMModule>(ModuleName.PM1);
GenModule<PMModule>(ModuleName.PM2);
_modules = new List<string>() { "System" };
foreach (var modulesKey in Modules.Keys)
_modules.Add(modulesKey.ToString());
foreach (var module in Modules.Values)
{
if(module.IsInstalled)
module.Initialize();
else
{
// 如果Module设置为NotInstalled则禁用其下的所有Device。
DEVICE.GetAllDevice().ForEach(x =>
{
if (x.Module == module.Module)
x.IsEnabled = false;
});
}
}
_pm1SlitValve = DEVICE.GetDevice<IoSlitValve>("TM.PM1Door");
_pm2SlitValve = DEVICE.GetDevice<IoSlitValve>("TM.PM2Door");
_pm1InterLock = DEVICE.GetDevice<IoInterLock>("PM1.PMInterLock");
_pm2InterLock = DEVICE.GetDevice<IoInterLock>("PM2.PMInterLock");
_tmInterLock = DEVICE.GetDevice<SicModules.Devices.IoInterLock>("TM.IoInterLock");
_upsPM1A = DEVICE.GetDevice<ITAUPS>("PM1.ITAUPSA");
_upsPM1B = DEVICE.GetDevice<ITAUPS>("PM1.ITAUPSB");
_pm1UPS = DEVICE.GetDevice<IoUPS>("PM1.UPS");
_upsPM2A = DEVICE.GetDevice<ITAUPS>("PM2.ITAUPSA");
_upsPM2B = DEVICE.GetDevice<ITAUPS>("PM2.ITAUPSB");
_pm2UPS = DEVICE.GetDevice<IoUPS>("PM2.UPS");
//AETemp
_aeTemp = DEVICE.GetDevice<AETemp>("PM.AETemp");
_pmAETemp1 = DEVICE.GetDevice<SicAETemp>("PM1.PMAETemp");
_pmAETemp2 = DEVICE.GetDevice<SicAETemp>("PM2.PMAETemp");
_tc = DEVICE.GetDevice<IoTC>("PM1.TC1");
_thread = new PeriodicJob(200, OnTimer, "PmSlitDoor", false, true);
Task.Delay(15000).ContinueWith((a) => _thread.Start());
//IEntityModules = this.GetType().GetProperties(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public)
// .Where(t => t.PropertyType.GetInterfaces().Contains(typeof(IEntity)) && t.PropertyType.GetInterfaces().Contains(typeof(IModuleEntity)));
}
private void BuildTransitionTable()
{
//ShutDown
Transition(RtState.Init, MSG.ShutDown, FsmStartShutDown, RtState.ShutDown);
Transition(RtState.Idle, MSG.ShutDown, FsmStartShutDown, RtState.ShutDown);
Transition(RtState.AutoIdle, MSG.ShutDown, FsmStartShutDown, RtState.ShutDown);
EnterExitTransition<RtState, FSM_MSG>(RtState.ShutDown, FsmShutDown, null, null);
//Init sequence
Transition(RtState.Init, MSG.HOME, FsmStartHome, RtState.Initializing);
Transition(RtState.Idle, MSG.HOME, FsmStartHome, RtState.Initializing);
Transition(RtState.Error, MSG.HOME, FsmStartHome, RtState.Initializing);
// EnterExitTransition<RtState, FSM_MSG>(RtState.Initializing, fStartInit, FSM_MSG.NONE, null);
Transition(RtState.Initializing, FSM_MSG.TIMER, FsmMonitorHome, RtState.Idle);
Transition(RtState.Initializing, MSG.ERROR, fError, RtState.Error);
Transition(RtState.Initializing, MSG.ABORT, FsmAbort, RtState.Init);
//Online
Transition(RtState.Idle, MSG.SetOnline, FsmStartSetOnline, RtState.Idle);
Transition(RtState.Idle, MSG.SetOffline, FsmStartSetOffline, RtState.Idle);
//Reset
AnyStateTransition(MSG.RESET, fStartReset, RtState.Idle);
AnyStateTransition(MSG.ERROR, fError, RtState.Error);
AnyStateTransition((int)FSM_MSG.ALARM, fError, (int)RtState.Error);
//Auto/manual sequence
Transition(RtState.Idle, MSG.SetAutoMode, fStartAutoTransfer, RtState.AutoIdle);
Transition(RtState.AutoRunning, FSM_MSG.TIMER, fAutoTransfer, RtState.AutoRunning);
Transition(RtState.AutoRunning, MSG.ABORT, fAbortAutoTransfer, RtState.AutoIdle);
Transition(RtState.AutoRunning, MSG.JobDone, null, RtState.AutoIdle);
Transition(RtState.AutoRunning, MSG.FAJobCommand, FsmFAJobCommand, RtState.AutoRunning);
Transition(RtState.AutoRunning, MSG.CreateJob, FsmCreateJob, RtState.AutoRunning);
Transition(RtState.AutoRunning, MSG.StartJob, FsmStartJob, RtState.AutoRunning);
Transition(RtState.AutoRunning, MSG.PauseJob, FsmPauseJob, RtState.AutoRunning);
Transition(RtState.AutoRunning, MSG.ResumeJob, FsmResumeJob, RtState.AutoRunning);
Transition(RtState.AutoRunning, MSG.StopJob, FsmStopJob, RtState.AutoRunning);
Transition(RtState.AutoRunning, MSG.AbortJob, FsmAbortJob, RtState.AutoRunning);
Transition(RtState.AutoIdle, FSM_MSG.TIMER, FsmMonitorAutoIdle, RtState.AutoIdle);
Transition(RtState.AutoIdle, MSG.SetManualMode, FsmStartSetManualMode, RtState.Idle);
Transition(RtState.AutoIdle, MSG.FAJobCommand, FsmFAJobCommand, RtState.AutoIdle);
Transition(RtState.AutoIdle, MSG.CreateJob, FsmCreateJob, RtState.AutoIdle);
Transition(RtState.AutoIdle, MSG.StartJob, FsmStartJob, RtState.AutoRunning);
Transition(RtState.AutoIdle, MSG.ABORT, FsmAbort, RtState.AutoIdle);
Transition(RtState.AutoIdle, MSG.AbortJob, FsmAbortJob, RtState.AutoIdle);
EnterExitTransition<RtState, FSM_MSG>(RtState.AutoRunning, null, FSM_MSG.NONE, fExitAutoTransfer);
//return all wafer
Transition(RtState.Idle, MSG.ReturnAllWafer, FsmStartReturnAllWafer, RtState.ReturnAllWafer);
Transition(RtState.ReturnAllWafer, FSM_MSG.TIMER, FsmMonitorReturnAllWafer, RtState.Idle);
Transition(RtState.ReturnAllWafer, MSG.ABORT, FsmAbortReturnAllWafer, RtState.Idle);
//Transfer sequence
Transition(RtState.Idle, MSG.MoveWafer, fStartTransfer, RtState.Transfer);
Transition(RtState.Transfer, FSM_MSG.TIMER, fTransfer, RtState.Idle);
EnterExitTransition<RtState, FSM_MSG>(RtState.Transfer, null, FSM_MSG.NONE, fExitTransfer);
Transition(RtState.Transfer, MSG.ABORT, FsmAbort, RtState.Idle);
}
void SubscribeDataVariable()
{
DATA.Subscribe("Rt.Status", () => StringFsmStatus);
DATA.Subscribe("System.IsOnline", () => IsOnline);
DATA.Subscribe("System.IsIdle", () => IsIdle || IsInit);
DATA.Subscribe("System.IsAlarm", () => IsAlarm);
DATA.Subscribe("System.IsBusy", () => IsRunning);
DATA.Subscribe("System.IsAutoRunning", () => IsRunning);
DATA.Subscribe("System.Modules", () => _modules);
DATA.Subscribe("System.LiveAlarmEvent", () => EV.GetAlarmEvent());
DATA.Subscribe("System.IsEngMode", () => _isEngMode);
}
void SubscribeOperation()
{
OP.Subscribe("CreateWafer", InvokeCreateWafer);
OP.Subscribe("DeleteWafer", InvokeDeleteWafer);
OP.Subscribe("ReturnWafer", InvokeReturnWafer);
OP.Subscribe("DeleteTray", InvokeDeleteTray);
OP.Subscribe("AlterWaferInfo", InvokeAlterWaferInfo);
OP.Subscribe("System.ReturnAllWafer", (string cmd, object[] args) =>
{
return CheckToPostMessage((int)MSG.ReturnAllWafer);
});
OP.Subscribe("System.MoveWafer", (string cmd, object[] args) =>
{
if (!Enum.TryParse((string)args[0], out ModuleName source))
{
EV.PostWarningLog(Name, $"Parameter source {(string)args[0]} not valid");
return false;
}
if (!Enum.TryParse((string)args[2], out ModuleName destination))
{
EV.PostWarningLog(Name, $"Parameter destination {(string)args[1]} not valid");
return false;
}
if (args.Length > 9 )
{
if ((bool)args[9])
{
WaferManager.Instance.WaferMoved(source, (int)args[1], destination, (int)args[3]);
return true;
}
if ((bool)args[10])
{
WaferManager.Instance.TrayMoved(source, (int)args[1], destination, (int)args[3]);
return true;
}
}
if (args.Length >= 8)
{
return CheckToPostMessage((int)MSG.MoveWafer, source, (int)args[1], destination, (int)args[3],
(bool)args[4], (int)args[5], (bool)args[6], (int)args[7]);
}
if (args.Length == 5)
{
return CheckToPostMessage((int)MSG.MoveWafer, source, (int)args[1], destination, (int)args[3], (bool)args[4]);
}
return CheckToPostMessage((int)MSG.MoveWafer, source, (int)args[1], destination, (int)args[3]);
});
OP.Subscribe("System.HomeAll", (string cmd, object[] args) =>
{
return CheckToPostMessage((int)MSG.HOME);
});
OP.Subscribe("System.Abort", (string cmd, object[] args) =>
{
return CheckToPostMessage((int)MSG.ABORT);
});
OP.Subscribe("System.Reset", (string cmd, object[] args) =>
{
return CheckToPostMessage((int)MSG.RESET);
});
OP.Subscribe("System.SetAutoMode", (string cmd, object[] args) =>
{
return CheckToPostMessage((int)MSG.SetAutoMode);
});
OP.Subscribe("System.SetManualMode", (string cmd, object[] args) =>
{
return CheckToPostMessage((int)MSG.SetManualMode);
});
OP.Subscribe("System.CreateJob", (string cmd, object[] args) =>
{
return CheckToPostMessage((int)MSG.CreateJob, args[0]);
});
OP.Subscribe("System.StartJob", (string cmd, object[] args) =>
{
return CheckToPostMessage((int)MSG.StartJob, args[0]);
});
OP.Subscribe("System.PauseJob", (string cmd, object[] args) =>
{
return CheckToPostMessage((int)MSG.PauseJob, args[0]);
});
OP.Subscribe("System.ResumeJob", (string cmd, object[] args) =>
{
return CheckToPostMessage((int)MSG.ResumeJob, args[0]);
});
OP.Subscribe("System.StopJob", (string cmd, object[] args) =>
{
return CheckToPostMessage((int)MSG.StopJob, args[0]);
});
OP.Subscribe("System.AbortJob", (string cmd, object[] args) =>
{
return CheckToPostMessage((int)MSG.AbortJob, args[0]);
});
OP.Subscribe("System.SetOnline", (string cmd, object[] args) =>
{
return CheckToPostMessage((int)MSG.SetOnline);
});
OP.Subscribe("System.SetOffline", (string cmd, object[] args) =>
{
return CheckToPostMessage((int)MSG.SetOffline);
});
OP.Subscribe("System.ShutDown", (string cmd, object[] args) =>
{
return CheckToPostMessage((int)MSG.ShutDown, null);
});
//OP.Subscribe("System.StartAutoRun", (string cmd, object[] args) =>
//{
// return CheckToPostMessage((int)MSG.StartJob, args[0]);
//});
#region Recipe Editor Lock Password Management
const string SC_PATH_REQ_RESET_PASS = "System.Recipe.ResetEditorPassword";
const string SC_PATH_PASSWORD = "System.Recipe.EditorPassword";
OP.Subscribe("System.SetNewRecipeEditorPassword", (string cmd, object[] args) =>
{
if (args.Length == 2 && args[0] is string oldPass
&& args[1] is string newPass)
{
var oldPassInSc = SC.GetStringValue(SC_PATH_PASSWORD);
if (oldPass != oldPassInSc)
{
EV.PostWarningLog(Module, "Incorrect old password");
return false;
}
SC.SetItemValue(SC_PATH_REQ_RESET_PASS, false);
SC.SetItemValue(SC_PATH_PASSWORD, newPass);
EV.PostInfoLog(Module, "Recipe Editor Password has been changed");
return true;
}
else
{
EV.PostWarningLog(Module, "Incorrect args of setting new Recipe Editor password");
return false;
}
});
// 程序启动时禁用复位密码选项,写在这里方便移植
SC.SetItemValue(SC_PATH_REQ_RESET_PASS, false);
#endregion
}
void InitSetPSUY()
{
Task.Delay(2000).ContinueWith(x=> _tc.SetPCPSUY());
}
private void Instance_OnAlarmEvent(EventItem obj)
{
FSM_MSG msg = FSM_MSG.NONE;
if (obj.Level == EventLevel.Warning)
msg = FSM_MSG.WARNING;
else if (obj.Level == EventLevel.Alarm)
{
msg = FSM_MSG.ALARM;
if(obj.Source == null)
{
return;
}
if (Modules.ContainsKey(ModuleHelper.Converter(obj.Source)))
{
Modules[ModuleHelper.Converter(obj.Source)]?.PostMsg(msg, obj.Id, obj.Description);
}
}
}
#region Init
private bool FsmStartHome(object[] objs)
{
return _homeAll.Start() == Result.RUN;
}
private bool FsmMonitorHome(object[] objs)
{
Result ret = _homeAll.Monitor();
if (ret == Result.DONE)
{
_homeAll.Clear();
return true;
}
if (ret == Result.FAIL)
{
_homeAll.Clear();
PostMsg(MSG.ERROR);
}
return false;
}
private bool fError(object[] objs)
{
IsOnline = false;
if (FsmState == (int)RtState.Transfer)
{
_manualTransfer.Clear();
}
return true;
}
#endregion
#region AutoTransfer
private bool FsmMonitorAutoIdle(object[] param)
{
//fMonitorFAJob(param);
Result ret = _auto.Monitor();
//if (!_auto.CheckAllJobDone())
//{
// return false;
//}
return ret == Result.DONE;
}
private bool FsmStartSetManualMode(object[] objs)
{
if (_auto.HasJobRunning)
{
EV.PostWarningLog("System", "Can not change to manual mode, abort running job first");
return false;
}
return true;
}
private bool fStartAutoTransfer(object[] objs)
{
Result ret = _auto.Start(objs);
return ret == Result.RUN;
}
private bool fAutoTransfer(object[] objs)
{
Result ret = _auto.Monitor();
if (_auto.CheckAllJobDone())
{
if (!CheckToPostMessage((int)MSG.JobDone))
return false;
}
return ret == Result.DONE;
}
private bool fExitAutoTransfer(object[] objs)
{
_auto.Clear();
return true;
}
private bool fAbortAutoTransfer(object[] objs)
{
if (FsmState == (int)RtState.Transfer)
{
_manualTransfer.Clear();
}
if (FsmState == (int)RtState.AutoRunning)
{
_auto.Clear();
}
foreach (var modulesValue in Modules.Values)
{
if (!modulesValue.Module.Contains("PM"))
{
modulesValue.PostMsg(MSG.ABORT);
}
}
return true;
}
#endregion
#region cycle
private bool FsmAbortCycle(object[] param)
{
return true;
}
private bool FsmMonitorCycle(object[] param)
{
return _auto.Monitor() == Result.DONE;
}
private bool FsmStartCycle(object[] param)
{
return _auto.Start() == Result.RUN;
}
#endregion
#region return all wafer
private bool FsmAbortReturnAllWafer(object[] param)
{
//_returnAll.Clear();
return true;
}
private bool FsmMonitorReturnAllWafer(object[] param)
{
return _returnAll.Monitor() == Result.DONE;
}
private bool FsmStartReturnAllWafer(object[] param)
{
return _returnAll.Start() == Result.RUN;
}
#endregion
#region Transfer
private bool fStartTransfer(object[] objs)
{
Result ret = _manualTransfer.Start(objs);
if (ret == Result.FAIL || ret == Result.DONE)
return false;
return ret == Result.RUN;
}
private bool fTransfer(object[] objs)
{
Result ret = _manualTransfer.Monitor(objs);
if (ret == Result.FAIL)
{
PostMsg(MSG.ERROR);
return false;
}
return ret == Result.DONE;
}
private bool fExitTransfer(object[] objs)
{
_manualTransfer.Clear();
return true;
}
private bool fAbortTransfer(object[] objs)
{
return true;
}
#endregion
#region reset
private bool fStartReset(object[] objs)
{
EV.ClearAlarmEvent();
if (FsmState == (int)RtState.AutoRunning)
{
_auto.ResetTask();
}
Singleton<DeviceEntity>.Instance.PostMsg(DeviceEntity.MSG.RESET);
foreach (var modulesValue in Modules.Values)
{
modulesValue.PostMsg(MSG.RESET);
}
IoProviderManager.Instance.Reset();
if (FsmState == (int)RtState.Error)
return true;
return false;
}
#endregion
private bool FsmFAJobCommand(object[] param)
{
switch ((string)param[0])
{
case "CreateProcessJob":
//_auto.CreateProcessJob((string)param[1], (string)param[2], (List<int>)param[3], (bool)param[4]);
break;
case "CreateControlJob":
//_auto.CreateControlJob((string)param[1], (string)param[2], (List<string>)param[3], (bool)param[4]);
CheckToPostMessage((int)MSG.StartJob, (string)param[1]);
break;
}
return true;
}
private bool FsmCreateJob(object[] param)
{
_auto.CreateJob((Dictionary<string, object>)param[0]);
return true;
}
private bool FsmAbortJob(object[] param)
{
_auto.AbortJob((string)param[0]);
return true;
}
private bool FsmStopJob(object[] param)
{
_auto.StopJob((string)param[0]);
return true;
}
private bool FsmResumeJob(object[] param)
{
_auto.ResumeJob((string)param[0]);
return true;
}
private bool FsmPauseJob(object[] param)
{
_auto.PauseJob((string)param[0]);
return true;
}
private bool FsmStartJob(object[] param)
{
_auto.StartJob((string)param[0]);
return true;
}
private bool FsmAbort(object[] param)
{
if (FsmState == (int)RtState.Transfer)
{
_manualTransfer.Clear();
}
if (FsmState == (int)RtState.AutoRunning)
{
_auto.Clear();
}
foreach (var modulesValue in Modules.Values)
{
if (!modulesValue.Module.Contains("PM"))
{
modulesValue.PostMsg(MSG.ABORT);
}
}
return true;
}
private bool FsmStartSetOffline(object[] param)
{
IsOnline = false;
var tm = Modules[ModuleName.TM] as TMModule;
tm.InvokeOffline();
var ll = Modules[ModuleName.LoadLock] as LoadLockModule;
ll.InvokeOffline();
var buffer = Modules[ModuleName.Buffer] as BufferModule;
buffer.InvokeOffline();
var unLoad = Modules[ModuleName.UnLoad] as UnLoadModule;
unLoad.InvokeOffline();
var efem = Modules[ModuleName.EFEM] as EFEMModule;
efem.InvokeOffline();
var aligner = Modules[ModuleName.Aligner] as AlignerModule;
aligner.InvokeOffline();
var pm1 = Modules[ModuleName.PM1] as PMModule;
pm1.InvokeOffline();
var pm2 = Modules[ModuleName.PM2] as PMModule;
pm2.InvokeOffline();
var cassAL = Modules[ModuleName.CassAL] as CassetteModule;
cassAL.InvokeOffline();
var cassAR = Modules[ModuleName.CassAR] as CassetteModule;
cassAR.InvokeOffline();
var cassBL = Modules[ModuleName.CassBL] as CassetteModule;
cassBL.InvokeOffline();
var waferRobot = Modules[ModuleName.WaferRobot] as WaferRobotModule;
waferRobot.InvokeOffline();
var trayRobot = Modules[ModuleName.TrayRobot] as TrayRobotModule;
trayRobot.InvokeOffline();
return true;
}
private bool FsmStartSetOnline(object[] param)
{
IsOnline = true;
var tm = Modules[ModuleName.TM] as TMModule;
tm.InvokeOnline();
var ll = Modules[ModuleName.LoadLock] as LoadLockModule;
ll.InvokeOnline();
var buffer = Modules[ModuleName.Buffer] as BufferModule;
buffer.InvokeOnline();
var unLoad = Modules[ModuleName.UnLoad] as UnLoadModule;
unLoad.InvokeOnline();
var efem = Modules[ModuleName.EFEM] as EFEMModule;
efem.InvokeOnline();
var aligner = Modules[ModuleName.Aligner] as AlignerModule;
aligner.InvokeOnline();
if (SC.GetValue<bool>($"System.SetUp.IsPM1Installed"))
{
var pm1 = Modules[ModuleName.PM1] as PMModule;
pm1.InvokeOnline();
}
if (SC.GetValue<bool>($"System.SetUp.IsPM2Installed"))
{
var pm2 = Modules[ModuleName.PM2] as PMModule;
pm2.InvokeOnline();
}
var cassAL = Modules[ModuleName.CassAL] as CassetteModule;
cassAL.InvokeOnline();
var cassAR = Modules[ModuleName.CassAR] as CassetteModule;
cassAR.InvokeOnline();
var cassBL = Modules[ModuleName.CassBL] as CassetteModule;
cassBL.InvokeOnline();
var waferRobot = Modules[ModuleName.WaferRobot] as WaferRobotModule;
waferRobot.InvokeOnline();
var trayRobot = Modules[ModuleName.TrayRobot] as TrayRobotModule;
trayRobot.InvokeOnline();
return true;
}
#region cassette popup menu
private bool InvokeReturnWafer(string arg1, object[] args)
{
ModuleName target = ModuleHelper.Converter(args[0].ToString());
int slot = (int)args[1];
if (ModuleHelper.IsLoadPort(target))
{
EV.PostInfoLog("System", string.Format("Wafer already at LoadPort {0} {1}, return operation is not valid", target.ToString(), slot + 1));
return false;
}
if (!WaferManager.Instance.IsWaferSlotLocationValid(target, slot))
{
EV.PostWarningLog("System", string.Format("Invalid position{0}{1}", target.ToString(), slot.ToString()));
return false;
}
var wafer = WaferManager.Instance.GetWafer(target, slot);
if (wafer.IsEmpty)
{
EV.PostInfoLog("System", string.Format("No wafer at {0} {1}, return operation is not valid", target.ToString(), slot + 1));
return false;
}
return CheckToPostMessage((int)MSG.MoveWafer,
target, slot,
(ModuleName)wafer.OriginStation, wafer.OriginSlot,
false, 0, false, 0);
}
private bool InvokeDeleteWafer(string arg1, object[] args)
{
ModuleName chamber = ModuleHelper.Converter(args[0].ToString());
int slot = (int)args[1];
if (chamber == ModuleName.TrayRobot || chamber == ModuleName.CassBL)
{
if (WaferManager.Instance.CheckHasTray(chamber, slot))
{
WaferManager.Instance.DeleteWafer(chamber, slot);
EV.PostMessage(ModuleName.System.ToString(), EventEnum.WaferDelete, chamber.ToString(), slot + 1);
}
else
{
EV.PostInfoLog("System", string.Format("No wafer at {0} {1}, delete not valid", chamber.ToString(), slot + 1));
}
}
else if (WaferManager.Instance.CheckHasWafer(chamber, slot))
{
if (chamber == ModuleName.TMRobot || chamber == ModuleName.LoadLock || chamber == ModuleName.UnLoad
|| chamber == ModuleName.Buffer || chamber == ModuleName.PM1 || chamber == ModuleName.PM2)
{
if (WaferManager.Instance.CheckHasTray(chamber, slot))
{
WaferManager.Instance.DeleteWaferOnly(chamber, slot);
}
else
{
WaferManager.Instance.DeleteWafer(chamber, slot);
}
}
else
{
WaferManager.Instance.DeleteWafer(chamber, slot);
}
}
else
{
EV.PostWarningLog("System", string.Format("Invalid position{0}{1}", chamber.ToString(), slot.ToString()));
return false;
}
return true;
}
private bool InvokeCreateWafer(string arg1, object[] args)
{
ModuleName chamber = ModuleHelper.Converter(args[0].ToString());
int slot = (int)args[1];
WaferStatus state = WaferStatus.Normal;
if (chamber == ModuleName.TrayRobot || chamber == ModuleName.CassBL)
{
if (WaferManager.Instance.IsWaferSlotLocationValid(chamber, slot))
{
if (WaferManager.Instance.CheckHasTray(chamber, slot))
{
EV.PostInfoLog("System", string.Format("{0} slot {1} already has tray.create wafer is not valid", chamber, slot));
}
else if (WaferManager.Instance.CreateWafer(chamber, slot, state) != null)
{
EV.PostMessage(ModuleName.System.ToString(), EventEnum.WaferCreate, chamber.ToString(), slot + 1, state.ToString());
}
}
else
{
EV.PostWarningLog("System", string.Format("Invalid position{0}{1}", chamber.ToString(), slot.ToString()));
return false;
}
}
else
{
if (WaferManager.Instance.IsWaferSlotLocationValid(chamber, slot))
{
if (WaferManager.Instance.CheckHasWafer(chamber, slot))
{
EV.PostInfoLog("System", string.Format("{0} slot {1} already has wafer.create wafer is not valid", chamber, slot));
}
else if (WaferManager.Instance.CreateWafer(chamber, slot, state) != null)
{
EV.PostMessage(ModuleName.System.ToString(), EventEnum.WaferCreate, chamber.ToString(), slot + 1, state.ToString());
}
}
else
{
EV.PostWarningLog("System", string.Format("Invalid position{0}{1}", chamber.ToString(), slot.ToString()));
return false;
}
}
return true;
}
private bool InvokeDeleteTray(string arg1, object[] args)
{
ModuleName chamber = ModuleHelper.Converter(args[0].ToString());
int slot = (int)args[1];
//获取TrayID
var wi = WaferManager.Instance.GetWafer(ModuleHelper.Converter(chamber.ToString()), Convert.ToInt16(args[1]));
int _trayOriginSlot = wi.TrayOriginSlot;
if (WaferManager.Instance.CheckHasTray(chamber, slot))
{
if (chamber == ModuleName.Buffer)
{
WaferManager.Instance.DeleteWafer(chamber, slot);
}
else if (WaferManager.Instance.CheckHasWafer(chamber, slot))
{
if(chamber == ModuleName.PM1 || chamber == ModuleName.PM2)
{
WaferManager.Instance.DeleteWafer(chamber, slot);
}
else
{
WaferManager.Instance.GetWafer(chamber, slot).TrayState = WaferTrayStatus.Empty;
}
}
else
{
WaferManager.Instance.DeleteWafer(chamber, slot);
}
}
//从数据库中删除Tray更新界面
string cmd_DeleteWafer = $"delete from tray_thickness_data where wafer_guid = '{_trayOriginSlot + 1}'";
DB.ExcuteTransAction(new List<string> { cmd_DeleteWafer });
EV.PostInfoLog(chamber.ToString(), cmd_DeleteWafer);
OP.DoOperation("CoatingManager.QueryUpdate");
return true;
}
private bool InvokeAlterWaferInfo(string arg1, object[] args)
{
ModuleName chamber = ModuleHelper.Converter(args[0].ToString());
int slot = (int)args[1];
string recipeName = args[2].ToString();
int trayProcessCount = (int)args[3];
var wafer = WaferManager.Instance.GetWafer(chamber, slot);
if (WaferManager.Instance.CheckHasWafer(chamber, slot))
{
if(!String.IsNullOrEmpty(recipeName) && wafer != null && wafer.ProcessJob != null && wafer.ProcessJob.Sequence != null && wafer.ProcessState == EnumWaferProcessStatus.Idle)
{
for (int i = 0; i < wafer.ProcessJob.Sequence.Steps.Count; i++)
{
if (!String.IsNullOrEmpty(wafer.ProcessJob.Sequence.Steps[i].RecipeName))
{
wafer.ProcessJob.Sequence.Steps[i].RecipeName = recipeName;
}
}
}
}
if (WaferManager.Instance.CheckHasTray(chamber, slot))
{
if (wafer != null)
{
wafer.TrayProcessCount = trayProcessCount;
}
}
return true;
}
#endregion
private void OnModuleError(object sender, string module)
{
if (FsmState == (int)RtState.AutoRunning)
{
ModuleName mod = ModuleHelper.Converter(module);
PostMsg(MSG.ModuleError, module);
}
}
#region ShutDown
private bool FsmStartShutDown(object[] objs)
{
var InBusyModuleNames = this.GetType().GetProperties(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public)
.Where(t => t.PropertyType.GetInterfaces().Contains(typeof(IModuleEntity)) && ((IModuleEntity)t.GetValue(this, null)).IsBusy)
.Select(n => n.Name).ToArray();
if (InBusyModuleNames.Length > 0)
{
EV.PostWarningLog("System", $"Shut down fail , {string.Join(" , ", InBusyModuleNames)} is in busy");
return false;
}
Term();
EV.PostKickoutMessage("ShutDown");
return true;
}
private bool FsmShutDown(object[] objs)
{
Task.Delay(3000).ContinueWith(a =>
{
Environment.Exit(0);
});
return true;
}
protected void Term()
{
foreach (var modulesValue in Modules.Values)
{
modulesValue.Terminate();
}
}
public bool OnTimer()
{
//MonitorModuleAlarm();
MonitorPmTmInfo();
MonitorUPSAlarm();
//MonitorAETemp();
MonitorEngMode();
return true;
}
private bool _isEngMode;
private readonly DeviceTimer _timEngModeTimeout = new DeviceTimer();
private readonly R_TRIG _trigEngModeEntered = new R_TRIG();
private readonly R_TRIG _trigEngModeLeft = new R_TRIG();
private void MonitorEngMode()
{
var isBypassInterlock = SC.GetValue<bool>("System.BypassInterlock");
_trigEngModeEntered.CLK = isBypassInterlock;
_trigEngModeLeft.CLK = isBypassInterlock == false;
// InterlockBypass 变为 true
if (_trigEngModeEntered.Q)
{
// 获取互锁旁路超时最小值限定5s
var timeout = SC.GetValue<int>("System.BypassInterlockTimeout");
if (timeout <= 5)
timeout = 5;
_isEngMode = true;
_timEngModeTimeout.Restart(timeout * 1000);
EV.PostInfoLog(Name, "Interlock is bypassed");
}
// InterlockBypass 变为 false
if (_trigEngModeLeft.Q)
{
_isEngMode = false;
EV.PostInfoLog(Name, "Interlock is resumed");
}
// Eng Mode 超时
if (_timEngModeTimeout.IsTimeout())
{
_timEngModeTimeout.Stop();
SC.SetItemValue("System.BypassInterlock", false);
EV.PostInfoLog(Name, "Interlock bypass timeout");
}
}
private void MonitorPmTmInfo()
{
if (_pm1SlitValve != null)
{
if (_pm1InterLock != null && _pm1InterLock.DoPMASlitDoorClosed != _pm1SlitValve.IsClose)
{
_pm1InterLock.DoPMASlitDoorClosed = _pm1SlitValve.IsClose;
}
if (_tmInterLock != null && _pm1InterLock != null)
{
if (_tmInterLock.DoPm1LidClosed != _pm1InterLock.DiChamLidClosed)
{
_tmInterLock.DoPm1LidClosed = _pm1InterLock.DiChamLidClosed;
}
if (_tmInterLock.DoRectorAATMTransferReady != _pm1InterLock.DoReactorATMTransferReady)
{
_tmInterLock.DoRectorAATMTransferReady = _pm1InterLock.DoReactorATMTransferReady;
}
if (_tmInterLock.DoRectorAProcessTransferReady != _pm1InterLock.DoReactorVACTransferReady)
{
_tmInterLock.DoRectorAProcessTransferReady = _pm1InterLock.DoReactorVACTransferReady;
}
}
}
if (_pm2SlitValve != null)
{
if (_pm2InterLock != null && _pm2InterLock.DoPMASlitDoorClosed != _pm2SlitValve.IsClose)
{
_pm2InterLock.DoPMASlitDoorClosed = _pm2SlitValve.IsClose;
}
if (_tmInterLock != null && _pm2InterLock != null)
{
if (_tmInterLock.DoPm2LidClosed != _pm2InterLock.DiChamLidClosed)
{
_tmInterLock.DoPm2LidClosed = _pm2InterLock.DiChamLidClosed;
}
if (_tmInterLock.DoRectorBATMTransferReady != _pm2InterLock.DoReactorATMTransferReady)
{
_tmInterLock.DoRectorBATMTransferReady = _pm2InterLock.DoReactorATMTransferReady;
}
if (_tmInterLock.DoRectorBProcessTransferReady != _pm2InterLock.DoReactorVACTransferReady)
{
_tmInterLock.DoRectorBProcessTransferReady = _pm2InterLock.DoReactorVACTransferReady;
}
}
}
}
private void MonitorUPSAlarm()
{
string sReason;
if (_upsPM1A != null && _upsPM1B != null && _pm1UPS != null)
{
bool _power1 = !(_upsPM1A.UPSPowerAlarm || _upsPM1B.UPSPowerAlarm);
bool _lowerBattery1 = !(_upsPM1A.UPSLowerBatteryAlarm || _upsPM1B.UPSLowerBatteryAlarm);
if (_pm1UPS.UPSEnable == _power1)
{
_pm1UPS.SetUPSEnable(_power1, out sReason);
}
if (_pm1UPS.UPSLowBattery == _lowerBattery1)
{
_pm1UPS.SetUPSLowBattery(_lowerBattery1, out sReason);
}
}
if (_upsPM2A != null && _upsPM2B != null && _pm2UPS != null)
{
bool _power2 = !(_upsPM2A.UPSPowerAlarm || _upsPM2B.UPSPowerAlarm);
bool _lowerBattery2 = !(_upsPM2A.UPSLowerBatteryAlarm || _upsPM2B.UPSLowerBatteryAlarm);
if (_pm2UPS.UPSEnable == _power2)
{
_pm2UPS.SetUPSEnable(_power2, out sReason);
}
if (_pm2UPS.UPSLowBattery == _lowerBattery2)
{
_pm2UPS.SetUPSLowBattery(_lowerBattery2, out sReason);
}
}
}
private void MonitorAETemp()
{
if (_aeTemp != null && _pmAETemp1 != null)
{
string sReason;
if (!_aeTemp.IsConnected)
{
_pmAETemp1.SetPyroCommunicationError(true, out sReason);
}
else
{
_pmAETemp1.SetPyroCommunicationError(false, out sReason);
}
}
if (_aeTemp != null && _pmAETemp2 != null)
{
string sReason;
if (!_aeTemp.IsConnected)
{
_pmAETemp2.SetPyroCommunicationError(true, out sReason);
}
else
{
_pmAETemp2.SetPyroCommunicationError(false, out sReason);
}
}
}
#endregion
}
}