| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345 | using System;using System.Collections.Generic;using Aitex.Core.RT.Event;using Aitex.Core.RT.Log;using Aitex.Core.RT.RecipeCenter;using Aitex.Core.RT.Routine;using Aitex.Core.RT.SCCore;using MECF.Framework.Common.DBCore;using MECF.Framework.Common.Equipment;using MECF.Framework.Common.SubstrateTrackings;using VirgoRT.Devices;using VirgoCommon;namespace VirgoRT.Modules.PMs{    class PreProcessRoutine : PMRoutineBase    {        public enum Routine        {            DelayForTest,            CheckDoor,            CheckDryPump,            PrePumpDown,            PostPumpDown,            SetRfMatchMode,            SetElectrodeTemp,            SetHeaterTemp,            SetLiftPin,            PinDownAndPump,            End,        }        //---------------------------------Fields----------------------------------------        //         private readonly PumpDownRoutine           _pumpRoutine;        //private readonly TemperatureControlRoutine _TempRoutine;        private int _checkSubstrateTempTimeout = 60;        private double _tolerance;        private double _OffsetTemp = 0.0f;        private bool _bPinDownExecuted = false;        private readonly int _PumpingAndPinDownTimeout = 60 * 1000;        //---------------------------------Properties------------------------------------        //         public string CurrentRecipeBaseName           { get; private set; }        public string CurrentRecipeRunningName        { get; private set; }        public string CurrentRecipeContent            { get; private set; }        public string CurrentLotName                  { get; set; }        public List<RecipeStep> CurrentRecipeStepList { get; set; }        public RecipeHead CurrentRecipeHead           { get; set; }        public string CurrentRecipeGuid { get; set; }        private bool _withWafer;        private double BasePressure        {            get            {                if (CurrentRecipeHead != null)                {                    if (!string.IsNullOrEmpty(CurrentRecipeHead.BasePressure))                    {                        double setpoint = Convert.ToDouble(CurrentRecipeHead.BasePressure);                        if (setpoint > 0 && setpoint < 750000)                            return setpoint;                    }                }                return SC.GetValue<int>($"{Module}.Pump.PumpBasePressure");            }        }        private double PumpDownLimit        {            get            {                if (CurrentRecipeHead != null)                {                    if (!string.IsNullOrEmpty(CurrentRecipeHead.PumpDownLimit))                    {                        double setpoint = Convert.ToDouble(CurrentRecipeHead.PumpDownLimit);                        if (setpoint > 0 && setpoint < 600)                            return setpoint;                    }                }                return SC.GetValue<double>($"{Module}.Pump.PumpTimeLimit");            }        }        public MovementPosition LiftPinPosition        {            get            {                if (CurrentRecipeHead != null)                {                    if (!string.IsNullOrEmpty(CurrentRecipeHead.PumpingPinState))                    {                        switch (CurrentRecipeHead.PumpingPinState)                        {                            case "Up":                                return MovementPosition.Up;                            case "Middle":                                return MovementPosition.Middle;                            case "Down":                                return MovementPosition.Down;                        }                    }                }                return MovementPosition.Down;            }        }        public double SubstrateTemp        {            get            {                if (CurrentRecipeHead != null)                {                    if (!string.IsNullOrEmpty(CurrentRecipeHead.SubstrateTemp))                    {                        double setpoint = Convert.ToDouble(CurrentRecipeHead.SubstrateTemp);                        if (setpoint > 0 && setpoint < 600)                            return setpoint;                    }                }                return 0;            }        }        private int PinDownPressure        {            get            {                if (CurrentRecipeHead != null)                {                    if (!string.IsNullOrEmpty(CurrentRecipeHead.PinDownPressure))                    {                        int setpoint = Convert.ToInt32(CurrentRecipeHead.PinDownPressure);                        if (setpoint > 0)                            return setpoint;                    }                }                return 1000;            }        }        private string alarmRecipeFileInvalid = "RecipeFileInvalid";        public PreProcessRoutine(JetPM chamber, PumpDownRoutine pdr) : base(chamber)        {            Name = "Pre Process";            _pumpRoutine = pdr;            EV.Subscribe(new EventItem("Event", alarmRecipeFileInvalid, "Recipe File Invalid", EventLevel.Alarm, EventType.HostNotification));        }        public void Terminate()        {        }        public Result LoadRecipe(params object[] param)        {            CurrentRecipeBaseName = (string)param[0];            if (param.Length > 1)                WaferID = (string)param[1];            else                WaferID = null;            if (param.Length > 2)                _withWafer = (bool)param[2];            else                _withWafer = true;            CurrentRecipeContent = RecipeFileManager.Instance.LoadRecipe("", CurrentRecipeBaseName, true);            if (string.IsNullOrEmpty(CurrentRecipeContent))            {                EV.PostInfoLog(ModuleName.System.ToString(), $"error during read recipe file {CurrentRecipeBaseName}");                return Result.FAIL;            }            if (!RecipeFileManager.Instance.CheckRecipe(Module, CurrentRecipeContent, out var reasons))            {                LOG.Write($"recipe file content not valid {CurrentRecipeBaseName}");                EV.Notify(alarmRecipeFileInvalid);                string info = "";                foreach (var item in reasons)                    info += item;                EV.PostPopDialogMessage(EventLevel.Alarm, "recipe file not valid", info);            }            CurrentRecipeRunningName = $"{CurrentRecipeBaseName}";            if (!Recipe.Parse(Module, CurrentRecipeContent, out RecipeHead recipeHead, out var recipeSteps))            {                return Result.FAIL;            }            CurrentRecipeStepList = recipeSteps;            CurrentRecipeHead = recipeHead;            return Result.DONE;        }        public Result Start(params object[] param)        {            if (_withWafer && WaferManager.Instance.CheckNoWafer(Module.ToString(), 0))            {                EV.PostWarningLog(Module.ToString(), $"can not run process, no wafer at {Module}");                return Result.FAIL;            }            if (CheckSlitDoor() != Result.RUN || CheckDryPump() != Result.RUN)            {                return Result.FAIL;            }            _chamber.SetGeneratorCommunicationMode(1);  // RS232 mode            _tolerance = SC.GetValue<double>($"System.MaxTemperatureToleranceToTarget");            _OffsetTemp = SC.GetValue<double>($"{Module}.Chiller.ChillerTemperatureOffset");            try            {                if (BasePressure <= 0 || BasePressure >= 760000)                {                    return Result.FAIL;                }                if (PumpDownLimit <= 0.01 || PumpDownLimit >= 600)                {                    return Result.FAIL;                }                _checkSubstrateTempTimeout = SC.GetValue<int>($"{Module}.CheckSubstrateTempTimeout");                Reset();                //RecipeRunGuid = Guid.NewGuid();                //ProcessDataRecorder.Start(RecipeRunGuid.ToString(), CurrentRecipeRunningName.Split('\\')[1], WaferID, CurrentRecipeRunningName.Split('\\')[0]);                //RecipeFileManager.Instance.SaveRecipeHistory(ModuleName.System.ToString(), CurrentRecipeRunningName, CurrentRecipeContent);            }            catch (Exception ex)            {                LOG.Write(ex, "Preprocess Start has exception");                throw ex;            }            Notify("Start");            _bPinDownExecuted = false;            return Result.RUN;        }        public Result Monitor()        {            try            {                ParallellyPumpAndPinDown((int)Routine.PinDownAndPump);                if (SC.GetValue<bool>($"{Module}.Chiller.EnableChiller"))                {                    CheckCoolantTemp((int)Routine.CheckDoor, SubstrateTemp, _OffsetTemp, _checkSubstrateTempTimeout, _tolerance);                }                else                {                    CheckSubstrateTemp((int)Routine.CheckDoor, SubstrateTemp, _checkSubstrateTempTimeout, _tolerance);                }                //设置RF Match Mode                //SetRfMatchMode((int)Routine.SetRfMatchMode, string.Format(Resources.PreProcess_Monitor_SetRFMatchMode, _rfMatchModeDuringProcess==(int)VirgoRfMatchMode.Manual ? "Manual" : "Auto"), _rfMatchModeDuringProcess);                End((int)Routine.End);            }            catch (RoutineBreakException)            {                return Result.RUN;            }            catch (RoutineFaildException)            {                return Result.FAIL;            }            catch (Exception ex)            {                Stop(ex.Message);                return Result.FAIL;            }            Notify("Finish");            return Result.DONE;        }        public void Exit()        {  }        private void ParallellyPumpAndPinDown(int id)        {            bool Func()            {                _pumpRoutine.Start(BasePressure);                return true;            }            bool? Check1()            {                if (!_bPinDownExecuted)                {                    if ((_chamber.ChamberPressure <= PinDownPressure) || (PinDownPressure <= BasePressure))                    {                        _bPinDownExecuted = true;                        Notify($"Set lift pin {_chamber.Name} {LiftPinPosition}");                        if (!_chamber.SetLiftPin(LiftPinPosition, out string reason))                        {                            Stop(reason);                            return false;                        }                    }                }                bool res1 = _chamber.CheckLiftPinPos(LiftPinPosition);                var result = _pumpRoutine.Monitor();                return res1 && (result == Result.DONE);            }            Tuple<bool, Result> ret = ExecuteAndWait(id, Func, Check1, _PumpingAndPinDownTimeout);            if (ret.Item1)            {                if (ret.Item2 == Result.FAIL)                {                    throw new RoutineFaildException();                }                if (ret.Item2 == Result.TIMEOUT)                {                    Stop(_chamber.CheckLiftPinPos(LiftPinPosition) ? $"Set Pin Position timeout in {_PumpingAndPinDownTimeout / 1000} seconds" : $"Pumping timeout  in {_PumpingAndPinDownTimeout / 1000} seconds");                    throw new RoutineFaildException();                }                throw new RoutineBreakException();            }        }    }}
 |