using System; using System.Collections.Generic; using Aitex.Core.Equipment.SusceptorDefine; using Aitex.Core.RT.Event; using Aitex.Core.RT.Log; using Aitex.Core.RT.Routine; using Aitex.Core.RT.SCCore; using MECF.Framework.Common.DBCore; using VirgoRT.Devices; using VirgoCommon; namespace VirgoRT.Modules.PMs { class PostProcessRoutine : PMRoutineBase { private enum PostProcessSequence { DelayForTest, RFPowerOff, StopGasFlow, CloseAllValves, ClosePumpValve, DelayWaitValve, Loop, SetLiftPin, Pump, PumpDelay, Vent, VentDelay, EndLoop, ClosePurgeValve, VentEndToPrecision, VentEndDelay, VentEndCloseVentValve, 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; //---------------------------------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(JetPM chamber, VentRoutine _vRoutine) : base(chamber) { Name = "PostProcess"; _rfPowerRoutine = new RfPowerRoutine(_chamber, false); _ventRoutine = _vRoutine; } public void Terminate() { } public Result 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 Result.FAIL; } _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"); _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 Result.FAIL; } Notify("开始"); return Result.RUN; } public Result Monitor() { try { if (SC.GetValue("System.IsSimulatorMode")) { TimeDelay((int)PostProcessSequence.DelayForTest, 10); } ExecuteRoutine((int)PostProcessSequence.RFPowerOff, _rfPowerRoutine); CloseAllValve((int)PostProcessSequence.CloseAllValves, 1); if (!NotToPurgeOrVent) //For keep vacuum after idle clean { if (PurgeActive) { StartLoop((int)PostProcessSequence.Loop, "", _purgeCycleCount, Notify, Stop); CyclePump((int)PostProcessSequence.Pump, _purgePumpPressure, _purgePumpTimeLimit, true); TimeDelay((int)PostProcessSequence.PumpDelay, _purgePumpStableTime); CycleVent((int)PostProcessSequence.Vent, _purgeVentPressure, _purgeVentTimeLimit, true); TimeDelay((int)PostProcessSequence.VentDelay, _purgeVentStableTime); EndLoop((int)PostProcessSequence.EndLoop, Notify, Stop); } if(LiftPinWhileVenting) { ParallellyVentAndLiftPin((int)PostProcessSequence.VentAndPinDown); } else { SetLiftPinUpDown((int)PostProcessSequence.SetLiftPin, false, 5000); ExecuteRoutine((int)PostProcessSequence.VentEndToPrecision, _ventRoutine); } CloseValve((int)PostProcessSequence.VentEndCloseVentValve, valveOpenCloseTimeout); } End((int)PostProcessSequence.End); } catch (RoutineBreakException) { return Result.RUN; } catch (RoutineFaildException) { Notify("出错"); return Result.FAIL; } catch (Exception ex) { Stop(ex.Message); return Result.FAIL; } Notify("结束"); return Result.DONE; } 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 void ParallellyVentAndLiftPin(int id) { bool Func() { Notify($"设置 lift pin {_chamber.Name} " + "升"); if (!_chamber.SetLiftPin(MovementPosition.Up, out string reason)) { Stop(reason); return false; } _ventRoutine.Start(); return true; } bool? Check1() { bool res1 = _chamber.CheckLiftUp(); var result = _ventRoutine.Monitor(); return res1 && result == Result.DONE; } Tuple ret = ExecuteAndWait(id, Func, Check1, _VentingAndPinUpTimeout); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { throw new RoutineFaildException(); } if (ret.Item2 == Result.TIMEOUT) { Stop(_chamber.CheckLiftUp() ? $"Set Pin Up timeout in {_VentingAndPinUpTimeout / 1000} seconds" : $"Venting timeout in {_VentingAndPinUpTimeout / 1000} seconds"); throw new RoutineFaildException(); } throw new RoutineBreakException(); } } } }