using System; using Aitex.Core.Util; using Aitex.Core.RT.Fsm; using Aitex.Core.RT.Log; using MECF.Framework.Common.Equipment; using MECF.Framework.Common.SubstrateTrackings; using Venus_RT.Modules.TM; using Venus_RT.Devices; using Venus_Core; using Aitex.Core.RT.DataCenter; using Aitex.Core.RT.OperationCenter; using Aitex.Core.RT.Device; using Aitex.Core.RT.SCCore; namespace Venus_RT.Modules { class LLEntity : Entity, IEntity, IModuleEntity { public enum LLStatus { Not_Ready, Ready_For_TM, Ready_For_EFEM, } public enum STATE { Unknown, Init, Initializing, Idle, Error, Pumping, Venting, Purging, LeakCheck, Prepare_For_TM, Prepare_For_EFEM, Ready_For_TM, Ready_For_EFEM, } public enum MSG { Home, Online, Offline, Pump, Vent, Purge, CyclePurge, LeakCheck, Prepare_TM, Prepare_EFEM, TM_Exchange_Ready, EFEM_Exchange_Ready, Error, Abort, } public ModuleName Module { get; private set; } public LLStatus Status { get; private set; } public bool Check(int msg, out string reason, params object[] args) { throw new NotImplementedException(); } public bool IsIdle { get { return fsm.State == (int)STATE.Idle; } } public bool IsError { get { return fsm.State == (int)STATE.Error; } } public bool IsInit { get { return fsm.State == (int)STATE.Unknown || fsm.State == (int)STATE.Init; } } public bool IsBusy { get { return !IsInit && !IsError && !IsIdle; } } public bool IsOnline { get; internal set; } private readonly JetTM _JetTM; private readonly MFPumpRoutine _pumpingRoutine; private readonly MFVentRoutine _ventingRoutine; private readonly MFLeakCheckRoutine _leakCheckRoutine; private readonly MFPurgeRoutine _purgeRoutine; public LLEntity(ModuleName module) { Module = module; //_JetTM = Singleton.Instance; _JetTM= DEVICE.GetDevice("TM"); _pumpingRoutine = new MFPumpRoutine(_JetTM, Module); _ventingRoutine = new MFVentRoutine(_JetTM, Module); _leakCheckRoutine = new MFLeakCheckRoutine(_JetTM, Module); _purgeRoutine = new MFPurgeRoutine(_JetTM, Module); var soltCount= SC.GetValue($"{module.ToString()}.SlotNumber"); WaferManager.Instance.SubscribeLocation(Module, soltCount); InitFsmMap(); } protected override bool Init() { OP.Subscribe($"{Module}.Home", (cmd, args) => CheckToPostMessage((int)MSG.Home)); OP.Subscribe($"{Module}.{RtOperation.Pump}", (cmd, args) => CheckToPostMessage((int)MSG.Pump)); OP.Subscribe($"{Module}.{RtOperation.Vent}", (cmd, args) => CheckToPostMessage((int)MSG.Vent)); OP.Subscribe($"{Module}.{RtOperation.Purge}", (cmd, args) => CheckToPostMessage((int)MSG.Purge)); OP.Subscribe($"{Module}.{RtOperation.Abort}", (cmd, args) => CheckToPostMessage((int)MSG.Abort)); OP.Subscribe($"{Module}.{RtOperation.LeakCheck}", (cmd, args) => CheckToPostMessage((int)MSG.LeakCheck)); OP.Subscribe($"{Module}.{RtOperation.Online}", (cmd, args) => CheckToPostMessage((int)MSG.Online)); OP.Subscribe($"{Module}.{RtOperation.Offline}", (cmd, args) => CheckToPostMessage((int)MSG.Offline)); DATA.Subscribe($"{Module}.FsmState", () => (((STATE)fsm.State).ToString()), SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.FsmPrevState", () => (((PMState)fsm.PrevState).ToString()),SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.FsmLastMessage", () => (((MSG)fsm.LastMsg).ToString()), SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.IsOnline", () => IsOnline,SubscriptionAttribute.FLAG.IgnoreSaveDB); return true; } private void InitFsmMap() { fsm = new StateMachine(Module.ToString(), (int)STATE.Init, 50); fsm.EnableRepeatedMsg(true); EnterExitTransition(STATE.Ready_For_TM, fnEnterTMReady, FSM_MSG.NONE, fnExitTMReady); EnterExitTransition(STATE.Ready_For_EFEM, fnEnterEFEMReady, FSM_MSG.NONE, fnExitEFEMReady); //AnyStateTransition(FSM_MSG.TIMER, fnMonitor, FSM_STATE.SAME); AnyStateTransition(MSG.Error, fnError, STATE.Error); AnyStateTransition(MSG.Online, fnOnline, FSM_STATE.SAME); AnyStateTransition(MSG.Offline, fnOffline, FSM_STATE.SAME); AnyStateTransition(MSG.Home, fnHome, STATE.Initializing); // Home Transition(STATE.Initializing, FSM_MSG.TIMER, fnHoming, STATE.Idle); Transition(STATE.Idle, FSM_MSG.TIMER, fnMonitor, STATE.Idle); Transition(STATE.Init, FSM_MSG.TIMER, fnMonitor, STATE.Init); //vent sequence Transition(STATE.Idle, MSG.Vent, FnStartVent, STATE.Venting); Transition(STATE.Venting, FSM_MSG.TIMER, FnVentTimeout, STATE.Idle); Transition(STATE.Venting, MSG.Abort, FnAbortVent, STATE.Idle); //Pump sequence Transition(STATE.Idle, MSG.Pump, FnStartPump, STATE.Pumping); Transition(STATE.Pumping, FSM_MSG.TIMER, FnPumpTimeout, STATE.Idle); Transition(STATE.Pumping, MSG.Abort, FnAbortPump, STATE.Idle); // Purge sequence Transition(STATE.Idle, MSG.Purge, FnStartPurge, STATE.Purging); Transition(STATE.Purging, FSM_MSG.TIMER, FnPurgeTimeout, STATE.Idle); Transition(STATE.Purging, MSG.Abort, FnAbortPurge, STATE.Idle); // Leak check sequence Transition(STATE.Idle, MSG.LeakCheck, FnStartLeakCheck, STATE.LeakCheck); Transition(STATE.LeakCheck, FSM_MSG.TIMER, FnLeakCheckTimeout, STATE.Idle); Transition(STATE.LeakCheck, MSG.Abort, FnAbortLeakCheck, STATE.Idle); // Prepare TM Transfer Transition(STATE.Idle, MSG.Prepare_TM, FnStartPrepareTM, STATE.Prepare_For_TM); Transition(STATE.Prepare_For_TM, FSM_MSG.TIMER, FnPreparaTMTimeout, STATE.Ready_For_TM); Transition(STATE.Prepare_For_TM, MSG.Abort, FnAbortPreparaTM, STATE.Idle); Transition(STATE.Ready_For_TM, MSG.TM_Exchange_Ready, null, STATE.Idle); Transition(STATE.Ready_For_TM, MSG.Abort, null, STATE.Idle); // Prepare EFEM Transfer Transition(STATE.Idle, MSG.Prepare_EFEM, FnStartPrepareEFEM, STATE.Prepare_For_EFEM); Transition(STATE.Prepare_For_EFEM, FSM_MSG.TIMER, FnPrepareEFEMTimeout, STATE.Ready_For_EFEM); Transition(STATE.Prepare_For_EFEM, MSG.Abort, FnAbortPrepareEFEM, STATE.Idle); Transition(STATE.Ready_For_EFEM, MSG.EFEM_Exchange_Ready, null, STATE.Idle); Transition(STATE.Ready_For_EFEM, MSG.Abort, null, STATE.Idle); Running = true; } public int Invoke(string function, params object[] args) { switch (function) { case "Home": CheckToPostMessage((int)MSG.Home); return (int)MSG.Home; } return (int)FSM_MSG.NONE; } public bool CheckAcked(int msg) { return fsm.CheckExecuted(msg); } public bool CheckToPostMessage(int msg, params object[] args) { if (!fsm.FindTransition(fsm.State, msg)) { LOG.Write(eEvent.WARN_FSM_WARN, Module, $"{Module} is in {(STATE)fsm.State} state,can not do {(MSG)msg}"); return false; } Running = true; fsm.PostMsg(msg, args); return true; } private bool fnEnterTMReady(object[] param) { Status = LLStatus.Ready_For_TM; return true; } private bool fnExitTMReady(object[] param) { Status = LLStatus.Not_Ready; return true; } private bool fnEnterEFEMReady(object[] param) { Status = LLStatus.Ready_For_EFEM; return true; } private bool fnExitEFEMReady(object[] param) { Status = LLStatus.Not_Ready; return true; } private bool fnMonitor(object[] param) { _debugRoutine(); return true; } private bool fnError(object[] param) { IsOnline = false; return true; } private bool fnOnline(object[] param) { IsOnline = true; return true; } private bool fnOffline(object[] param) { IsOnline = false; return true; } private bool fnAbort(object[] param) { return true; } private bool fnHome(object[] param) { IsOnline = true; return true; } private bool fnHoming(object[] param) { return true; } private bool FnStartVent(object[] param) { return _ventingRoutine.Start() == RState.Running; } private bool FnVentTimeout(object[] param) { RState ret = _ventingRoutine.Monitor(); if (ret == RState.Failed || ret == RState.Timeout) { PostMsg(MSG.Error); return false; } return ret == RState.End; } private bool FnAbortVent(object[] param) { _ventingRoutine.Abort(); return true; } private bool FnStartPump(object[] param) { return _pumpingRoutine.Start() == RState.Running; } private bool FnPumpTimeout(object[] param) { RState ret = _pumpingRoutine.Monitor(); if (ret == RState.Failed || ret == RState.Timeout) { PostMsg(MSG.Error); return false; } return ret == RState.End; } private bool FnAbortPump(object[] param) { _pumpingRoutine.Abort(); return true; } private bool FnStartPurge(object[] param) { return _purgeRoutine.Start() == RState.Running; } private bool FnPurgeTimeout(object[] param) { RState ret = _purgeRoutine.Monitor(); if (ret == RState.Failed || ret == RState.Timeout) { PostMsg(MSG.Error); return false; } return ret == RState.End; } private bool FnAbortPurge(object[] param) { _purgeRoutine.Abort(); return true; } private bool FnStartLeakCheck(object[] param) { return _leakCheckRoutine.Start() == RState.Running; } private bool FnLeakCheckTimeout(object[] param) { RState ret = _leakCheckRoutine.Monitor(); if (ret == RState.Failed || ret == RState.Timeout) { PostMsg(MSG.Error); return false; } return ret == RState.End; } private bool FnAbortLeakCheck(object[] param) { _leakCheckRoutine.Abort(); return true; } private bool FnStartPrepareTM(object[] param) { if (RouteManager.IsATMMode) return true; return _pumpingRoutine.Start() == RState.Running; } private bool FnPreparaTMTimeout(object[] param) { if (RouteManager.IsATMMode) { if (fsm.ElapsedTime > 10000) { LOG.Write(eEvent.ERR_TM, Module, $"Cannot transfer wafer as {Module} is not ATM."); PostMsg(MSG.Error); return true; } return _JetTM.IsModuleATM(Module); } RState ret = _pumpingRoutine.Monitor(); if (ret == RState.Failed || ret == RState.Timeout) { PostMsg(MSG.Error); return false; } return ret == RState.End; } private bool FnAbortPreparaTM(object[] param) { _pumpingRoutine.Abort(); return true; } private bool FnStartPrepareEFEM(object[] param) { if (RouteManager.IsATMMode) return true; return _ventingRoutine.Start() == RState.Running; } private bool FnPrepareEFEMTimeout(object[] param) { if (RouteManager.IsATMMode) { if (fsm.ElapsedTime > 10000) { LOG.Write(eEvent.ERR_TM, Module, $"Cannot transfer wafer as {Module} is not ATM."); PostMsg(MSG.Error); return true; } return _JetTM.IsModuleATM(Module); } RState ret = _ventingRoutine.Monitor(); if (ret == RState.Failed || ret == RState.Timeout) { PostMsg(MSG.Error); return false; } return ret == RState.End; } private bool FnAbortPrepareEFEM(object[] param) { _ventingRoutine.Abort(); return true; } private void _debugRoutine() { int flag = 0; // Test Home routine if (flag == 1) { PostMsg(MSG.Home); } else if (flag == 2) { PostMsg(MSG.Vent); } else if (flag == 3) { PostMsg(MSG.Pump); } //else if (flag == 4) //{ // PostMsg(MSG.PumpLoadLock); //} //else if (flag == 5) //{ // PostMsg(MSG.VentLoadLock); //} //else if (flag == 6) //{ // PostMsg(MSG.PurgeLoadLock); //} //else if (flag == 7) //{ // PostMsg(MSG.LaunchPump); //} //else if (flag == 8) //{ // PostMsg(MSG.LaunchTurboPump); //} //else if (flag == 9) //{ // PostMsg(MSG.LoadLockLeakCheck); //} else if (flag == 10) { PostMsg(MSG.CyclePurge); } //else if (flag == 11) //{ // PostMsg(MSG.GasLinePurge); //} //else if (flag == 12) //{ // PostMsg(MSG.LeakCheck); //} //else if (flag == 13) //{ // PostMsg(MSG.GasLeakCheck); //} //else if (flag == 14) //{ // PostMsg(MSG.LLPlace); //} //else if (flag == 15) //{ // PostMsg(MSG.LLPick); //} //else if (flag == 16) //{ // PostMsg(MSG.RunRecipe, "7777"); //} //else if (flag == 17) //{ // PostMsg(MSG.MFCVerification, "MFC2", (double)50, 10); //} } } }