using System; using System.Collections.Generic; using Aitex.Core.Common; using Aitex.Core.RT.Device; using Aitex.Core.RT.Fsm; using Aitex.Core.RT.Routine; using Aitex.Core.Utilities; using MECF.Framework.Common.Fsm; 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 System.Diagnostics; using MECF.Framework.RT.EquipmentLibrary.Devices; 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 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 IsAutoIdle { get => FsmState == (int)RtState.AutoIdle; } 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 _modules = new List(); //readonly IEnumerable 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; 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; /// /// 主三色灯对象。 /// 主三色灯判断方式参考方法。 /// private IoSignalTower _mainSignalTower; public EquipmentManager() { Module = "System"; Name = "System"; Modules = new Dictionary(); } public override bool Initialize() { InitModules(); GetMainSignalTower(); EnumLoop.ForEach((item) => { MapState((int)item, item.ToString()); }); EnumLoop.ForEach((item) => { MapMessage((int)item, item.ToString()); }); EnableFsm(100, RtState.Init); BuildTransitionTable(); SubscribeDataVariable(); SubscribeOperation(); //InitSetPSUY(); Singleton.Instance.OnAlarmEvent += Instance_OnAlarmEvent; _manualTransfer = new ManualTransfer(); _homeAll = new HomeAll(); _auto = new AutoTransfer(); _returnAll = new ReturnAllWafer(); SC.RegisterValueChangedCallback("TM.ProcessPressure", SetTansferPressure1); SC.RegisterValueChangedCallback("TM.VacuumPressureBaseOffset", SetTansferPressure2); return true; } private void SetTansferPressure1(object value) { try { double.TryParse(value.ToString(), out double dbValue); double offset = SC.GetValue("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", dbValue); SC.SetItemValue("PM.PM1.PreProcess.ChamberPressure", dbValue); SC.SetItemValue("PM.PM2.ProcessIdle.FinalPressure", dbValue); SC.SetItemValue("PM.PM2.PreProcess.ChamberPressure", dbValue); SC.SetItemValue("LoadLock.VacuumPressureBase", basePressure); SC.SetItemValue("LoadLock.Purge.VentBasePressure", dbValue); SC.SetItemValue("UnLoad.VacuumPressureBase", basePressure); SC.SetItemValue("UnLoad.Purge.VentBasePressure", dbValue); } catch (Exception ex) { EV.PostWarningLog("System", ex.Message); } } private void SetTansferPressure2(object value) { try { double dbValue = SC.GetValue("TM.ProcessPressure"); double.TryParse(value.ToString(), out double offset); 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", dbValue); SC.SetItemValue("PM.PM1.PreProcess.ChamberPressure", dbValue); SC.SetItemValue("PM.PM2.ProcessIdle.FinalPressure", dbValue); SC.SetItemValue("PM.PM2.PreProcess.ChamberPressure", dbValue); SC.SetItemValue("LoadLock.VacuumPressureBase", basePressure); SC.SetItemValue("LoadLock.Purge.VentBasePressure", dbValue); SC.SetItemValue("UnLoad.VacuumPressureBase", basePressure); SC.SetItemValue("UnLoad.Purge.VentBasePressure", dbValue); } catch (Exception ex) { EV.PostWarningLog("System", ex.Message); } } /// /// 创建指定的Module的实例。 /// /// Module类型。 /// Module名称。 /// Module包含的Wafer槽位总数。 private void GenModule(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(ModuleName.TM); GenModule(ModuleName.LoadLock); GenModule(ModuleName.UnLoad); GenModule(ModuleName.Buffer); GenModule(ModuleName.Aligner); GenModule(ModuleName.WaferRobot); GenModule(ModuleName.TrayRobot); GenModule(ModuleName.EFEM); GenModule(ModuleName.CassAL, 25); GenModule(ModuleName.CassAR, 25); GenModule(ModuleName.CassBL, 8); GenModule(ModuleName.PM1); GenModule(ModuleName.PM2); _modules = new List() { "System" }; foreach (var modulesKey in Modules.Keys) _modules.Add(modulesKey.ToString()); foreach (var module in Modules.Values) { module.Initialize(); if (!module.IsInstalled) { // 如果Module设置为NotInstalled,则禁用其下的所有Device。 DEVICE.GetAllDevice().ForEach(x => { if (x.Module == module.Module) x.IsEnabled = false; }); } } _pm1SlitValve = DEVICE.GetDevice("TM.PM1Door"); _pm2SlitValve = DEVICE.GetDevice("TM.PM2Door"); _pm1InterLock = DEVICE.GetDevice("PM1.PMInterLock"); _pm2InterLock = DEVICE.GetDevice("PM2.PMInterLock"); _tmInterLock = DEVICE.GetDevice("TM.IoInterLock"); _upsPM1A = DEVICE.GetDevice("PM1.ITAUPSA"); _upsPM1B = DEVICE.GetDevice("PM1.ITAUPSB"); _pm1UPS = DEVICE.GetDevice("PM1.UPS"); _upsPM2A = DEVICE.GetDevice("PM2.ITAUPSA"); _upsPM2B = DEVICE.GetDevice("PM2.ITAUPSB"); _pm2UPS = DEVICE.GetDevice("PM2.UPS"); _tc = DEVICE.GetDevice("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.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.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.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.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);//System.IsBusy=>IsRunning,绑定相同的值,不同的地方用 DATA.Subscribe("System.IsAutoIdle", () => IsAutoIdle); DATA.Subscribe("System.IsAutoRunning", () => IsRunning);//System.IsAutoRunning=>IsRunning,绑定相同的值,不同的地方用 DATA.Subscribe("System.Modules", () => _modules); DATA.Subscribe("System.SignalTowerData", () => _mainSignalTower?.DeviceData); } void SubscribeOperation() { OP.Subscribe("CreateWafer", InvokeCreateWafer); OP.Subscribe("DeleteWafer", InvokeDeleteWafer); OP.Subscribe("ReturnWafer", InvokeReturnWafer); OP.Subscribe("DeleteTray", InvokeDeleteTray); OP.Subscribe("AlterWaferInfo", InvokeAlterWaferInfo); OP.Subscribe("UpdatTrayBelongTo", (string cmd, object[] args) => { return true; });//注册空的方法,否则调用时日志有错误输出 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 } private void InitSetPSUY() { Task.Delay(2000).ContinueWith(x=> _tc.SetPCPSUY()); } private void Instance_OnAlarmEvent(EventItem obj) { FSM_MSG msg; if (obj.Level == EventLevel.Warning) msg = FSM_MSG.WARNING; else if (obj.Level == EventLevel.Alarm) { msg = FSM_MSG.ALARM; if(obj.Source == null) { return; } // 如果设备产生报警,则向设备所在的Module发送状态机信号,切换到Error状态。 if (Modules.ContainsKey(ModuleHelper.Converter(obj.Source))) { Modules[ModuleHelper.Converter(obj.Source)]?.PostMsg(msg, obj.Id, obj.Description); } // 产生新的报警时,重新启用Buzzer _mainSignalTower?.SwitchOffBuzzer(false); } } /// /// 获取主三色灯对象。 /// /// /// 系统设备配置中配置多个三色灯对象,但软件仅控制唯一个三色灯。 ///
/// 该三色灯定义为主三色灯,其余三色灯对象将被禁用,其工作状态自动跟随主三色灯。 ///
/// 通常情况下,使用PM1的三色灯作为主三色灯。 ///
/// 如果PM1被卸载,则系统自动使用PM2控制的三色灯,依此类推。 ///
/// private void GetMainSignalTower() { // 系统配置,是否PM控制三色灯 var isPmHostSt = SC.GetValue("System.IsPMHostSignalTower", true); // 获取三色灯列表,并按名称排序 var sts = DEVICE.GetAllDevice() .Where(x => x is IoSignalTower) .OrderBy(x => x.Module) .Cast() .ToList(); // 禁用所有三色灯,待确定完主灯后再使能主灯。 foreach (var st in sts) { st.IsEnabled = false; } // 判断三色灯主灯 if (isPmHostSt) { var pmAttachedSts = sts.Where(x => x.Module.StartsWith("PM")) .OrderBy(x => x.Module) .ToList(); if (pmAttachedSts.Any()) { foreach (var st in pmAttachedSts) { if (st != null && Modules.TryGetValue(ModuleHelper.Converter(st.Module), out var module)) { if (module.IsInstalled) { // 找到第一个有效的PM,获取其三色灯对象。 _mainSignalTower = st; break; } } } } } // 如果没找到PM三色灯,或系统配置指定使用TM三色灯 // 获取隶属于TM的三色灯对象 _mainSignalTower ??= sts.FirstOrDefault(x => x.Module.StartsWith("TM")); // 使能三色灯 if (_mainSignalTower != null) { LOG.Write($"SignalTower attaches to {_mainSignalTower.Module}"); _mainSignalTower.IsEnabled = true; } else { LOG.Error("SignalTower object not found"); } } #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.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)param[3], (bool)param[4]); break; case "CreateControlJob": //_auto.CreateControlJob((string)param[1], (string)param[2], (List)param[3], (bool)param[4]); CheckToPostMessage((int)MSG.StartJob, (string)param[1]); break; } return true; } private bool FsmCreateJob(object[] param) { _auto.CreateJob((Dictionary)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(); if (SC.GetValue($"System.SetUp.IsPM1Installed")) { var pm1 = Modules[ModuleName.PM1] as PMModule; pm1.InvokeOffline(); } if (SC.GetValue($"System.SetUp.IsPM2Installed")) { 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($"System.SetUp.IsPM1Installed")) { var pm1 = Modules[ModuleName.PM1] as PMModule; pm1.InvokeOnline(); } if (SC.GetValue($"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.IsWaferEmpty) { 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.WaferOriginStation, wafer.WaferOriginSlot, 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]; 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 = TrayStatus.Empty; } } else { WaferManager.Instance.DeleteWafer(chamber, slot); } } 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 == WaferProcessStatus.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(); return true; } 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); } } } #endregion } }