Sic08/SicRT/Equipments/Systems/EquipmentManager.cs

1442 lines
48 KiB
C#
Raw Normal View History

2023-03-03 15:42:13 +08:00
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;
2023-04-13 15:35:13 +08:00
using SicModules.Aligners;
using SicModules.Buffers;
using SicModules.Cassettes;
using SicModules.EFEMs;
using SicModules.LLs;
using SicModules.PMs;
using SicModules.TMs;
using SicModules.UnLoads;
2023-04-23 14:18:42 +08:00
using Aitex.Core.RT.DBCore;
using System.Diagnostics;
2023-04-26 11:27:40 +08:00
using Aitex.Core.RT.Log;
2023-03-03 15:42:13 +08:00
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
2023-03-03 15:42:13 +08:00
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;
2023-04-13 15:35:13 +08:00
private SicModules.Devices.IoInterLock _tmInterLock = null;
2023-03-03 15:42:13 +08:00
private IoSlitValve _pm1SlitValve = null;
private IoSlitValve _pm2SlitValve = null;
private PeriodicJob _thread;
2023-03-28 13:24:11 +08:00
private IoTC _tc = null;
2023-03-03 15:42:13 +08:00
2023-03-03 15:42:13 +08:00
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();
2023-03-03 15:42:13 +08:00
Singleton<EventManager>.Instance.OnAlarmEvent += Instance_OnAlarmEvent;
_manualTransfer = new ManualTransfer();
_homeAll = new HomeAll();
_auto = new AutoTransfer();
_returnAll = new ReturnAllWafer();
2023-04-26 11:27:40 +08:00
SC.RegisterValueChangedCallback("TM.ProcessPressure", SetTansferPressure);
2023-03-03 15:42:13 +08:00
return true;
}
2023-04-26 11:27:40 +08:00
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
2023-03-03 15:42:13 +08:00
{
ModuleFsmDevice module;
2023-03-03 15:42:13 +08:00
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}");
2023-03-28 13:24:11 +08:00
// 创建Module实例失败
if (module == null)
{
LOG.Error($"Failed to create instance of module {name}");
return;
}
2023-03-03 15:42:13 +08:00
// 如果Module在系统配置中配置为“未安装”则不要注册Alarm事件
/*if (!module.IsInstalled)
{
LOG.Warning($"{name} is configured as NotInstalled");
return;
}*/
2023-03-03 15:42:13 +08:00
module.OnEnterError += OnModuleError;
Modules[name] = module;
}
2023-03-03 15:42:13 +08:00
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);
2023-03-03 15:42:13 +08:00
_modules = new List<string>() { "System" };
foreach (var modulesKey in Modules.Keys)
_modules.Add(modulesKey.ToString());
foreach (var module in Modules.Values)
2023-03-03 15:42:13 +08:00
{
if(module.IsInstalled)
module.Initialize();
else
{
// 如果Module设置为NotInstalled则禁用其下的所有Device。
DEVICE.GetAllDevice().ForEach(x =>
{
if (x.Module == module.Module)
x.IsEnabled = false;
});
}
2023-03-03 15:42:13 +08:00
}
_pm1SlitValve = DEVICE.GetDevice<IoSlitValve>("TM.PM1Door");
_pm2SlitValve = DEVICE.GetDevice<IoSlitValve>("TM.PM2Door");
_pm1InterLock = DEVICE.GetDevice<IoInterLock>("PM1.PMInterLock");
_pm2InterLock = DEVICE.GetDevice<IoInterLock>("PM2.PMInterLock");
2023-04-13 15:35:13 +08:00
_tmInterLock = DEVICE.GetDevice<SicModules.Devices.IoInterLock>("TM.IoInterLock");
2023-03-03 15:42:13 +08:00
_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)));
}
2023-03-03 15:42:13 +08:00
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());
2023-03-03 16:45:39 +08:00
DATA.Subscribe("System.IsEngMode", () => _isEngMode);
2023-03-03 15:42:13 +08:00
}
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
2023-03-03 15:42:13 +08:00
}
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;
}
2023-03-28 13:24:11 +08:00
if (Modules.ContainsKey(ModuleHelper.Converter(obj.Source)))
2023-03-03 15:42:13 +08:00
{
2023-03-28 13:24:11 +08:00
Modules[ModuleHelper.Converter(obj.Source)]?.PostMsg(msg, obj.Id, obj.Description);
2023-03-03 15:42:13 +08:00
}
}
}
#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();
2023-03-28 13:24:11 +08:00
var pm1 = Modules[ModuleName.PM1] as PMModule;
2023-03-03 15:42:13 +08:00
pm1.InvokeOffline();
2023-03-28 13:24:11 +08:00
var pm2 = Modules[ModuleName.PM2] as PMModule;
2023-03-03 15:42:13 +08:00
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();
2023-03-28 13:24:11 +08:00
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();
}
2023-03-03 15:42:13 +08:00
2023-03-28 13:24:11 +08:00
2023-03-03 15:42:13 +08:00
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;
}
2023-03-13 17:37:55 +08:00
var wafer = WaferManager.Instance.GetWafer(target, slot);
2023-03-03 15:42:13 +08:00
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];
2023-04-23 14:18:42 +08:00
//获取TrayID
var wi = WaferManager.Instance.GetWafer(ModuleHelper.Converter(chamber.ToString()), Convert.ToInt16(args[1]));
int _trayOriginSlot = wi.TrayOriginSlot;
2023-03-03 15:42:13 +08:00
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);
}
}
2023-04-23 14:18:42 +08:00
//从数据库中删除Tray更新界面
string cmd_DeleteWafer = $"delete from tray_thickness_data where wafer_guid = '{_trayOriginSlot + 1}'";
2023-05-06 08:42:43 +08:00
DB.ExcuteTransAction(new List<string> { cmd_DeleteWafer });
2023-04-23 14:18:42 +08:00
EV.PostInfoLog(chamber.ToString(), cmd_DeleteWafer);
OP.DoOperation("CoatingManager.QueryUpdate");
2023-03-03 15:42:13 +08:00
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];
2023-03-13 17:37:55 +08:00
var wafer = WaferManager.Instance.GetWafer(chamber, slot);
2023-03-03 15:42:13 +08:00
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)
2023-03-03 15:42:13 +08:00
{
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();
2023-03-03 16:45:39 +08:00
MonitorEngMode();
2023-03-03 15:42:13 +08:00
return true;
}
2023-03-03 16:45:39 +08:00
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");
}
}
2023-03-03 15:42:13 +08:00
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
}
}