using System; using System.Collections.Generic; using Aitex.Core.RT.Log; using Aitex.Core.RT.Routine; using Aitex.Core.RT.SCCore; using JetVirgoPM.Devices; using JetVirgoPM.PMs.Routines; using MECF.Framework.Common.Equipment; using MECF.Framework.Common.Routine; using MECF.Framework.Common.SubstrateTrackings; using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.PMs; using MECF.Framework.RT.ModuleLibrary.PMModules; namespace JetVirgoPM.PMs.RecipeExecutors { class PostProcessRoutine : PMRoutineBase { private enum PostProcessSequence { DelayForTest, RFPowerOff, StopGasFlow, CloseAllValves, ClosePumpValve, DelayWaitValve, Loop, SetLiftPin1, SetLiftPin2, Pump, PumpDelay, Vent, VentDelay, EndLoop, ClosePurgeValve, VentEndToPrecision, VentEndDelay, VentEndCloseVentValve, SetSlitDoor, VentAndPinDown, End, }; private RecipeHead head; private int _purgeCycleCount; private int _purgeVentPressure; private int _purgePumpPressure; private int _purgeVentTimeLimit; private int _purgePumpTimeLimit; private int _purgeVentStableTime; private int _purgePumpStableTime; private int _ventTime; //private int _ventTimeLimit; private readonly RfPowerRoutine _rfPowerRoutine; private readonly VentRoutine _ventRoutine; private readonly int _VentingAndPinUpTimeout = 60 * 1000; private bool _isSimulatorMode; private bool _isVented = false; //---------------------------------Properties------------------------------------ // public string RecipeName { get; private set; } public string RecipeContext { get; private set; } private bool PurgeActive { get { if (head != null) { if (!string.IsNullOrEmpty(head.PurgeActive)) { return Convert.ToBoolean(head.PurgeActive); } } return true; } } //For keep vacuum after idle clean private bool NotToPurgeOrVent { get { if (head != null) { if (!string.IsNullOrEmpty(head.NotToPurgeOrVent)) { return Convert.ToBoolean(head.NotToPurgeOrVent); } } return false; } } private bool LiftPinWhileVenting { get { if (head != null) { if (!string.IsNullOrEmpty(head.VentingPinState)) { return head.VentingPinState == "Up" ? true : false; } } return false; } } //--------------------------------Constructor------------------------------------ // public PostProcessRoutine(JetDualPM chamber, VentRoutine _vRoutine) : base(chamber) { Name = "PostProcess"; _rfPowerRoutine = new RfPowerRoutine(_chamber, false); _ventRoutine = _vRoutine; } public void Terminate() { } public RState Start(params object[] objs) { try { Reset(); //this.UpdateSCValue(); RecipeName = (string)objs[0]; RecipeContext = (string)objs[1]; List recipeSteps; if (!Recipe.Parse(Module, RecipeContext, out head, out recipeSteps)) { return RState.Failed; } _purgeCycleCount = (int)SC.GetValue($"{_chamber.Module}.Purge.PurgeCycleCount"); _purgeVentPressure = (int)SC.GetValue($"{_chamber.Module}.Purge.PurgeVentPressure"); _purgePumpPressure = (int)SC.GetValue($"{_chamber.Module}.Purge.PurgePumpPressure"); _purgeVentTimeLimit = (int)SC.GetValue($"{_chamber.Module}.Purge.PurgeVentTimeLimit"); _purgePumpTimeLimit = (int)SC.GetValue($"{_chamber.Module}.Purge.PurgePumpTimeLimit"); _purgeVentStableTime = (int)SC.GetValue($"{_chamber.Module}.Purge.PurgeVentStableTime"); _purgePumpStableTime = (int)SC.GetValue($"{_chamber.Module}.Purge.PurgePumpStableTime"); _isSimulatorMode = SC.GetValue("System.IsSimulatorMode"); _ventTime = (int)SC.GetValue($"{_chamber.Module}.VentTime"); //_ventTimeLimit = (int)SC.GetSC(SCName.System_VentTimeLimit).Value; } catch (Exception ex) { LOG.Write(ex, "Post process Start has exception"); return RState.Failed; } return Runner.Start(_chamber.Module.ToString(), Name); } public RState Monitor() { var hasWafer0 = WaferManager.Instance.CheckHasWafer(Module, 0); var hasWafer1 = WaferManager.Instance.CheckHasWafer(Module, 1); var pos = (hasWafer0 && hasWafer1) ? EnumDualPM.Both : hasWafer0 ? EnumDualPM.Left : hasWafer1 ? EnumDualPM.Right : EnumDualPM.None; var pos2 = LiftPinWhileVenting ? EnumDualPM.None : EnumDualPM.Both; if (!NotToPurgeOrVent && PurgeActive) //For keep vacuum after idle clean { Runner.Run(PostProcessSequence.DelayForTest, HOFs.Apply(DelayTime, _isSimulatorMode ? _delay_1s : 0), _isSimulatorMode ? _delay_1s : 0) .Run(PostProcessSequence.RFPowerOff, RFPowerOff, CheckRFPowerOff) .Wait(PostProcessSequence.CloseAllValves, CloseAllValve, _delay_1s) .LoopStart(PostProcessSequence.Loop, "", _purgeCycleCount, HOFs.Apply(Pump, _purgePumpPressure), HOFs.Apply(CheckPump, _purgePumpPressure, true), _purgePumpTimeLimit * 1000) .LoopDelay(PostProcessSequence.PumpDelay, _purgePumpStableTime * 1000) .LoopRun(PostProcessSequence.Vent, HOFs.Apply(Vent, _purgeVentPressure), HOFs.Apply(CheckVent, _purgeVentPressure, true), _purgeVentTimeLimit * 1000) .LoopDelay(PostProcessSequence.VentDelay, _purgeVentStableTime * 1000) .LoopEnd(PostProcessSequence.EndLoop, NullFun, _delay_1s) .Run(PostProcessSequence.VentAndPinDown, ParallellyVentAndLiftPin, CheckParallellyVentAndLiftPin, _VentingAndPinUpTimeout * 1000) .Run(PostProcessSequence.SetLiftPin1, HOFs.Apply(SetLiftPinUpDown, pos2, false), HOFs.Apply(ChecktLiftPinUpDown, pos2, false), _delay_5s) .Run(PostProcessSequence.VentEndToPrecision, Vent, CheckVent) .Wait(PostProcessSequence.VentEndCloseVentValve, CloseValve, valveOpenCloseTimeout*1000) .Run(PostProcessSequence.SetLiftPin2, HOFs.Apply(SetLiftPinUpDown, pos, true), HOFs.Apply(ChecktLiftPinUpDown, pos, true), _delay_5s) .Run(PostProcessSequence.SetSlitDoor, HOFs.Apply(SetSlitDoor, pos, true), HOFs.Apply(CheckSlitDoor, pos, true), _delay_5s) .End(PostProcessSequence.End, EndFunc, _delay_1s); } else if(!NotToPurgeOrVent) { Runner.Run(PostProcessSequence.DelayForTest, HOFs.Apply(DelayTime, _isSimulatorMode ? _delay_1s : 0), _isSimulatorMode ? _delay_1s : 0) .Run(PostProcessSequence.RFPowerOff, RFPowerOff, CheckRFPowerOff) .Wait(PostProcessSequence.CloseAllValves, CloseAllValve, _delay_1s) .Run(PostProcessSequence.VentAndPinDown, ParallellyVentAndLiftPin, CheckParallellyVentAndLiftPin, _VentingAndPinUpTimeout * 1000) .Run(PostProcessSequence.SetLiftPin1, HOFs.Apply(SetLiftPinUpDown, pos2, false), HOFs.Apply(ChecktLiftPinUpDown, pos2, false), _delay_5s) .Run(PostProcessSequence.VentEndToPrecision, Vent, CheckVent) .Wait(PostProcessSequence.VentEndCloseVentValve, CloseValve, valveOpenCloseTimeout * 1000) .Run(PostProcessSequence.SetLiftPin2, HOFs.Apply(SetLiftPinUpDown, pos, true), HOFs.Apply(ChecktLiftPinUpDown, pos, true), _delay_5s) .Run(PostProcessSequence.SetSlitDoor, HOFs.Apply(SetSlitDoor, pos, true), HOFs.Apply(CheckSlitDoor, pos, true), _delay_5s) .End(PostProcessSequence.End, EndFunc, _delay_1s); } else { Runner.Run(PostProcessSequence.DelayForTest, HOFs.Apply(DelayTime, _isSimulatorMode ? _delay_1s : 0), _isSimulatorMode ? _delay_1s : 0) .Run(PostProcessSequence.RFPowerOff, RFPowerOff, CheckRFPowerOff) .Wait(PostProcessSequence.CloseAllValves, CloseAllValve, _delay_1s) .End(PostProcessSequence.End, EndFunc, _delay_1s); } return Runner.Status; } bool RFPowerOff() { return _rfPowerRoutine.Start() == RState.Running; } bool CheckRFPowerOff() { var status = _rfPowerRoutine.Monitor(); if (status == RState.End) { return true; } else if (status == RState.Failed || status == RState.Timeout) { Runner.Stop($"RF power off failed."); return true; } return false; } bool Vent() { if (LiftPinWhileVenting) return true; _isVented = _ventRoutine.Start() == RState.End; return _ventRoutine.Start() == RState.Running || _isVented; } bool CheckVent() { if (LiftPinWhileVenting || _isVented) return true; var status = _ventRoutine.Monitor(); if (status == RState.End) { return true; } else if (status == RState.Failed || status == RState.Timeout) { Runner.Stop($"Vent failed."); return true; } return false; } public void Exit() { //ProcessDataRecorder.End(RecipeRunGuid.ToString(), SusceptorStatus.Processed.ToString(), Module); //if (DeviceModel.SignalTower != null) //{ // DeviceModel.SignalTower.BuzzerBlinking(SC.GetValue(SCName.System_BuzzerBlinkingTime)); //} //update processing end time //Singleton.Instance.EndRecipeProcess(Singleton.Instance.CurrentRunningJob.RecipeRunId, SusceptorStatus.Processed); } private bool ParallellyVentAndLiftPin() { if(LiftPinWhileVenting) { Notify($"设置 lift pin {_chamber.Name} " + "升"); if (!_chamber.Chamber1Disable) { if (!_chamber.SetLiftPin1(MovementPosition.Up, out string reasonPin1)) { Stop(reasonPin1); return false; } } if (!_chamber.Chamber2Disable) { if (!_chamber.SetLiftPin2(MovementPosition.Up, out string reasonPin2)) { Stop(reasonPin2); return false; } } _ventRoutine.Start(); return true; } else return true; } bool CheckParallellyVentAndLiftPin() { if (LiftPinWhileVenting) { bool res1 = _chamber.CheckLift1Up(); bool res2 = _chamber.CheckLift2Up(); if (_chamber.Chamber1Disable) { res1 = true; } if (_chamber.Chamber2Disable) { res2 = true; } var result = _ventRoutine.Monitor(); if (result == RState.Failed || result == RState.Timeout) { Runner.Stop($"Vent failed."); if (result == RState.Timeout) { Stop(_chamber.CheckLift1Up() ? $"Set Lift1 Pin Up timeout in {_VentingAndPinUpTimeout / 1000} seconds" : $"Venting timeout in {_VentingAndPinUpTimeout / 1000} seconds"); Stop(_chamber.CheckLift2Up() ? $"Set Lift2 Pin Up timeout in {_VentingAndPinUpTimeout / 1000} seconds" : $"Venting timeout in {_VentingAndPinUpTimeout / 1000} seconds"); } return true; } return res1 && res2 && result == RState.End; } else return true; } } }