using System; using System.Collections.Generic; //using System. using Venus_RT.Devices; using Venus_RT.Modules; using Aitex.Core.RT.Log; using Venus_Core; using Aitex.Core.RT.SCCore; using System.Reflection; using System.Diagnostics; using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Robot; using Aitex.Core.Common.DeviceData; //#pragma warning disable 0436 namespace Venus_RT.Modules.PMs { class ProcessHelper { protected JetPMBase Chamber; private string Module; public RecipeHead m_RecipeHead; private static Dictionary<string, Func<ProcessUnitBase, RecipeStep, RState>> startHelper = new Dictionary<string, Func<ProcessUnitBase, RecipeStep, RState>>(); private static Dictionary<string, Func<ProcessUnitBase, RecipeStep, RState>> checkerHelper = new Dictionary<string, Func<ProcessUnitBase, RecipeStep, RState>>(); private static Dictionary<string, Action<ProcessUnitBase, RecipeStep>> endHelper = new Dictionary<string, Action<ProcessUnitBase, RecipeStep>>(); private List<float> rfMatchC1 = new List<float>(); private List<float> rfMatchC2 = new List<float>(); private int rfMatchC1C2Index = 0; private List<float> biasRfMatchC1 = new List<float>(); private List<float> biasRfMatchC2 = new List<float>(); private int biasRfMatchC1C2Index = 0; public bool isLoop = false; public int loopsteps = 0; public int currentStepIndex = 0; //private int cycleIndex = 0; private bool biasRFSetPointFlag = true; public ProcessHelper(JetPMBase pm) { Chamber = pm; Module = pm.Module.ToString(); Init(); } private void Init() { startHelper[$"{Module}.PressureByPressureModeUnit"] = (ProcessUnitBase unit, RecipeStep step) => PressureByPressureModeUnit_Start(unit, step); checkerHelper[$"{Module}.PressureByPressureModeUnit"] = (ProcessUnitBase unit, RecipeStep step) => PressureByPressureModeUnit_Check(unit, step); endHelper[$"{Module}.PressureByPressureModeUnit"] = (ProcessUnitBase unit, RecipeStep step) => PressureByPressureModeUnit_End(unit, step); //startHelper [$"{Module}.PressureByValveModeUnit"] = (ProcessUnitBase unit, RecipeStep step) => PressureByValveModeUnit_Start(unit, step); //checkerHelper [$"{Module}.PressureByValveModeUnit"] = (ProcessUnitBase unit, RecipeStep step) => PressureByValveModeUnit_Check(unit, step); //endHelper [$"{Module}.PressureByValveModeUnit"] = (ProcessUnitBase unit, RecipeStep step) => PressureByValveModeUnit_End(unit, step); startHelper[$"{Module}.TCPUnit"] = (ProcessUnitBase unit, RecipeStep step) => TCPUnit_Start(unit, step); checkerHelper[$"{Module}.TCPUnit"] = (ProcessUnitBase unit, RecipeStep step) => TCPUnit_Check(unit, step); endHelper[$"{Module}.TCPUnit"] = (ProcessUnitBase unit, RecipeStep step) => TCPUnit_End(unit, step); startHelper[$"{Module}.BiasUnit"] = (ProcessUnitBase unit, RecipeStep step) => BiasUnit_Start(unit, step); checkerHelper[$"{Module}.BiasUnit"] = (ProcessUnitBase unit, RecipeStep step) => BiasUnit_Check(unit, step); endHelper[$"{Module}.BiasUnit"] = (ProcessUnitBase unit, RecipeStep step) => BiasUnit_End(unit, step); startHelper[$"{Module}.GasControlUnit"] = (ProcessUnitBase unit, RecipeStep step) => GasControlUnit_Start(unit, step); checkerHelper[$"{Module}.GasControlUnit"] = (ProcessUnitBase unit, RecipeStep step) => GasControlUnit_Check(unit, step); endHelper[$"{Module}.GasControlUnit"] = (ProcessUnitBase unit, RecipeStep step) => GasControlUnit_End(unit, step); startHelper[$"{Module}.ESCHVUnit"] = (ProcessUnitBase unit, RecipeStep step) => ESCHVUnit_Start(unit, step); checkerHelper[$"{Module}.ESCHVUnit"] = (ProcessUnitBase unit, RecipeStep step) => ESCHVUnit_Check(unit, step); endHelper[$"{Module}.ESCHVUnit"] = (ProcessUnitBase unit, RecipeStep step) => ESCHVUnit_End(unit, step); startHelper[$"{Module}.ProcessKitUnit"] = (ProcessUnitBase unit, RecipeStep step) => ProcessKitUnit_Start(unit, step); checkerHelper[$"{Module}.ProcessKitUnit"] = (ProcessUnitBase unit, RecipeStep step) => ProcessKitUnit_Check(unit, step); endHelper[$"{Module}.ProcessKitUnit"] = (ProcessUnitBase unit, RecipeStep step) => ProcessKitUnit_End(unit, step); startHelper[$"{Module}.Kepler2200GasControlUnit"] = (ProcessUnitBase unit, RecipeStep step) => Kepler2200GasControlUnit_Start(unit, step); checkerHelper[$"{Module}.Kepler2200GasControlUnit"] = (ProcessUnitBase unit, RecipeStep step) => Kepler2200GasControlUnit_Check(unit, step); endHelper[$"{Module}.Kepler2200GasControlUnit"] = (ProcessUnitBase unit, RecipeStep step) => Kepler2200GasControlUnit_End(unit, step); startHelper[$"{Module}.HeaterUnit"] = (ProcessUnitBase unit, RecipeStep step) => HeaterUnit_Start(unit, step); checkerHelper[$"{Module}.HeaterUnit"] = (ProcessUnitBase unit, RecipeStep step) => HeaterUnit_Check(unit, step); endHelper[$"{Module}.HeaterUnit"] = (ProcessUnitBase unit, RecipeStep step) => HeaterUnit_End(unit, step); } private RState PressureByPressureModeUnit_Start(ProcessUnitBase unit, RecipeStep step) { var ProcessUnit = unit as PressureByPressureModeUnit; if (ProcessUnit.PressureUnitMode == PressureUnitMode.Pressure) { if (Chamber.SetPVPressure(ProcessUnit.StartValue)) { return RState.Running; } } else if (ProcessUnit.PressureUnitMode == PressureUnitMode.Valve) { if (Chamber.SetPVPostion(ProcessUnit.StartValue)) { return RState.Running; } } return RState.Failed; } private RState PressureByPressureModeUnit_Check(ProcessUnitBase unit, RecipeStep step) { var ProcessUnit = unit as PressureByPressureModeUnit; if (ProcessUnit.EnableRamp) { if (ProcessUnit.PressureUnitMode == PressureUnitMode.Pressure) { if (Chamber.SetPVPressure(ProcessUnit.StartValue + (int)((ProcessUnit.TargetValue - ProcessUnit.StartValue) * step.RampFactor()))) return RState.Running; else return RState.Failed; } else if (ProcessUnit.PressureUnitMode == PressureUnitMode.Valve) { if (Chamber.SetPVPressure(ProcessUnit.StartValue + (int)((ProcessUnit.TargetValue - ProcessUnit.StartValue) * step.RampFactor()))) return RState.Running; else return RState.Failed; } } if (ProcessUnit.PressureUnitMode == PressureUnitMode.Pressure) { if (step.Type == StepType.Stable && Chamber.ChamberPressure == ProcessUnit.StartValue) { return RState.End; } } else if (ProcessUnit.PressureUnitMode == PressureUnitMode.Valve) { if (step.Type == StepType.Stable && Chamber.GetPVPosition() == ProcessUnit.StartValue) { return RState.End; } } return RState.Running; } private void PressureByPressureModeUnit_End(ProcessUnitBase unit, RecipeStep step) { } #region Valve Mode已取消,合并到压力模式 //private RState PressureByValveModeUnit_Start(ProcessUnitBase unit, RecipeStep step) //{ // var ProcessUnit = unit as PressureByValveModeUnit; // if (Chamber.SetPVPostion(ProcessUnit.StartPosition)) // { // return RState.Running; // } // return RState.Failed; //} //private RState PressureByValveModeUnit_Check(ProcessUnitBase unit, RecipeStep step) //{ // var ProcessUnit = unit as PressureByValveModeUnit; // if (ProcessUnit.EnableRamp) // { // if (Chamber.SetPVPostion(ProcessUnit.StartPosition + (int)((ProcessUnit.TargetPosition - ProcessUnit.StartPosition) * step.RampFactor()))) // return RState.Running; // else // return RState.Failed; // } // return RState.Running; //} //private void PressureByValveModeUnit_End(ProcessUnitBase unit, RecipeStep step) //{ //} #endregion private RState TCPUnit_Start(ProcessUnitBase unit, RecipeStep step) { var ProcessUnit = unit as TCPUnit; if (ProcessUnit.RFPower > 5) { Chamber.GeneratorSetpower(ProcessUnit.RFPower); Chamber.GeneratorPowerOn(true); } else { Chamber.GeneratorSetpower(0); Chamber.GeneratorPowerOn(false); } int p1; int p2; if (ProcessUnit.TuneCapPreset > 0) { p1 = ProcessUnit.TuneCapPreset; } else { p1 = ProcessUnit.AutoTuneCapPreset; } if (ProcessUnit.LoadCapPreset > 0) { p2 = ProcessUnit.LoadCapPreset; } else { p2 = ProcessUnit.AutoLoadCapPreset; } Chamber.SetMatchPosition(p1, p2); rfMatchC1.Clear(); rfMatchC1.Clear(); rfMatchC1C2Index = 0; return RState.Running; } private RState TCPUnit_Check(ProcessUnitBase unit, RecipeStep step) { var _scPowerAlarmTime = SC.GetValue<double>($"{Chamber.Name}.Rf.PowerAlarmTime"); var ProcessUnit = unit as TCPUnit; if (ProcessUnit.MaxReflectedPower > 0 && Chamber.ReflectPower > ProcessUnit.MaxReflectedPower && step.ElapsedTime() > _scPowerAlarmTime * 1000) { LOG.Write(eEvent.ERR_PROCESS, Chamber.Module, $"Step:{step.StepNo} failed, RF Reflect Power:{Chamber.ReflectPower} exceeds the Max Limit:{ProcessUnit.MaxReflectedPower}"); return RState.Failed; } if (step.ElapsedTime() > m_RecipeHead.RFHoldTime * 1000) { Chamber.GeneratorSetpower(0); Chamber.GeneratorPowerOn(false); } if (step.ElapsedTime() > rfMatchC1C2Index * 1000) { rfMatchC1.Add(Chamber.RFMatchC1); rfMatchC2.Add(Chamber.RFMatchC2); rfMatchC1C2Index += 1; } return RState.Running; } private void TCPUnit_End(ProcessUnitBase unit, RecipeStep step) { var ProcessUnit = unit as TCPUnit; if (rfMatchC1.Count >= 6) { float allValue = 0; for (int i = 4; i < rfMatchC1.Count; i++) { allValue += rfMatchC1[i]; } var average = allValue / (rfMatchC1.Count - 4); ProcessUnit.AutoTuneCapPreset = (int)average; } if (rfMatchC2.Count >= 6) { float allValue = 0; for (int i = 4; i < rfMatchC2.Count; i++) { allValue += rfMatchC2[i]; } var average = allValue / (rfMatchC2.Count - 4); ProcessUnit.AutoLoadCapPreset = (int)average; } rfMatchC1.Clear(); rfMatchC2.Clear(); rfMatchC1C2Index = 0; } private RState BiasUnit_Start(ProcessUnitBase unit, RecipeStep step) { var ProcessUnit = unit as BiasUnit; if (ProcessUnit.BiasRFPower > 5) { Chamber.GeneratorBiasPowerOn(true); if ((ProcessUnit.EnableRamp == false)) { Chamber.GeneratorBiasSetpower(ProcessUnit.BiasRFPower); } } int p1; int p2; if (ProcessUnit.BiasTuneCapPreset > 0) { p1 = ProcessUnit.BiasTuneCapPreset; } else { p1 = ProcessUnit.AutoBiasTuneCapPreset; } if (ProcessUnit.BiasLoadCapPreset > 0) { p2 = ProcessUnit.BiasLoadCapPreset; } else { p2 = ProcessUnit.AutoBiasLoadCapPreset; } Chamber.SetBiasMatchPosition(p1, p2); if (ProcessUnit.BiasGeneratorMode == GeneratorMode.Pulsing) { Chamber.SetBiasPulseMode(true); Chamber.SetBiasPulseRateFreq(ProcessUnit.PulseRateFreq); Chamber.SetDiasPulseDutyCycle(ProcessUnit.PulseDutyCycle); } biasRfMatchC1.Clear(); biasRfMatchC1.Clear(); biasRfMatchC1C2Index = 0; biasRFSetPointFlag = true; return RState.Running; } private RState BiasUnit_Check(ProcessUnitBase unit, RecipeStep step) { var _scPowerAlarmTime = SC.GetValue<double>($"{Chamber.Name}.BiasRf.PowerAlarmTime"); var ProcessUnit = unit as BiasUnit; if (ProcessUnit.BiasMaxReflectedPower > 0 && Chamber.BiasReflectPower > ProcessUnit.BiasMaxReflectedPower && step.ElapsedTime() > _scPowerAlarmTime * 1000) { LOG.Write(eEvent.ERR_PROCESS, Chamber.Module, $"Step:{step.StepNo} failed, Bias Reflect Power:{Chamber.BiasReflectPower} exceeds the Max Limit:{ProcessUnit.BiasMaxReflectedPower}"); return RState.Failed; } if (step.ElapsedTime() > m_RecipeHead.BiasRFHoldTime * 1000) { Chamber.GeneratorBiasSetpower(0); Chamber.GeneratorBiasPowerOn(false); } if (step.ElapsedTime() > biasRfMatchC1C2Index * 1000) { biasRfMatchC1.Add(Chamber.BiasRFMatchC1); biasRfMatchC2.Add(Chamber.BiasRFMatchC2); biasRfMatchC1C2Index += 1; } if (ProcessUnit.EnableRamp) { //if (step.ElapsedTime() <= 500*cycleIndex) //{ // return RState.Running; //} //cycleIndex += 1; if (ProcessUnit.TargetMode == TargetMode.Cycle) { if ( biasRFSetPointFlag==true) { biasRFSetPointFlag = false; Chamber.GeneratorBiasSetpower((float)((ProcessUnit.BiasRFPower + (float)((float)(ProcessUnit.TargetBiasRFPower - ProcessUnit.BiasRFPower) / ((float)(loopsteps-1) / (float)(currentStepIndex)))))); } //float rampFactor = (float)currentStepIndex / (float)(loopsteps-1); //double rampFactor = step.RampFactor(); //Chamber.GeneratorBiasSetpower((float)((ProcessUnit.BiasRFPower+ (ProcessUnit.TargetBiasRFPower - ProcessUnit.BiasRFPower)/(loopsteps)*currentStepIndex) + ((double)(ProcessUnit.TargetBiasRFPower - ProcessUnit.BiasRFPower) / ((double)loopsteps)) * rampFactor)); } else { //double rampFactor = step.RampFactor(); //Chamber.GeneratorBiasSetpower((float)(ProcessUnit.BiasRFPower + (ProcessUnit.TargetBiasRFPower - ProcessUnit.BiasRFPower) * rampFactor)); } } return RState.Running; } private void BiasUnit_End(ProcessUnitBase unit, RecipeStep step) { var ProcessUnit = unit as BiasUnit; Chamber.GeneratorBiasSetpower(0); Chamber.GeneratorBiasPowerOn(false); if (biasRfMatchC1.Count >= 6) { float allValue = 0; for (int i = 4; i < biasRfMatchC1.Count; i++) { allValue += biasRfMatchC1[i]; } var average = allValue / (biasRfMatchC1.Count - 4); ProcessUnit.AutoBiasTuneCapPreset = (int)average; } if (biasRfMatchC2.Count >= 6) { float allValue = 0; for (int i = 4; i < biasRfMatchC2.Count; i++) { allValue += biasRfMatchC2[i]; } var average = allValue / (biasRfMatchC2.Count - 4); ProcessUnit.AutoBiasLoadCapPreset = (int)average; } biasRfMatchC1.Clear(); biasRfMatchC1.Clear(); biasRfMatchC1C2Index = 0; //cycleIndex = 0; biasRFSetPointFlag = true; } private RState GasControlUnit_Start(ProcessUnitBase unit, RecipeStep step) { Chamber.OpenValve(ValveType.GasFinal, true); var ProcessUnit = unit as GasControlUnit; Chamber.FlowGas(0, ProcessUnit.Gas1); if (ProcessUnit.Gas1 >= 1) { Chamber.OpenValve(ValveType.PV11, true); } Chamber.FlowGas(1, ProcessUnit.Gas2); if (ProcessUnit.Gas2 >= 1) { Chamber.OpenValve(ValveType.PV21, true); } Chamber.FlowGas(2, ProcessUnit.Gas3); if (ProcessUnit.Gas3 >= 1) { Chamber.OpenValve(ValveType.PV31, true); } Chamber.FlowGas(3, ProcessUnit.Gas4); if (ProcessUnit.Gas4 >= 1) { Chamber.OpenValve(ValveType.PV41, true); } Chamber.FlowGas(4, ProcessUnit.Gas5); Chamber.FlowGas(5, ProcessUnit.Gas6); Chamber.FlowGas(6, ProcessUnit.Gas7); Chamber.FlowGas(7, ProcessUnit.Gas8); return RState.Running; } private RState GasControlUnit_Check(ProcessUnitBase unit, RecipeStep step) { var ProcessUnit = unit as GasControlUnit; if (ProcessUnit.EnableRamp) { double rampFactor = step.RampFactor(); Chamber.FlowGas(0, ProcessUnit.Gas1 + (ProcessUnit.Gas1Target - ProcessUnit.Gas1) * rampFactor); Chamber.FlowGas(1, ProcessUnit.Gas2 + (ProcessUnit.Gas2Target - ProcessUnit.Gas2) * rampFactor); Chamber.FlowGas(2, ProcessUnit.Gas3 + (ProcessUnit.Gas3Target - ProcessUnit.Gas3) * rampFactor); Chamber.FlowGas(3, ProcessUnit.Gas4 + (ProcessUnit.Gas4Target - ProcessUnit.Gas4) * rampFactor); Chamber.FlowGas(4, ProcessUnit.Gas5 + (ProcessUnit.Gas5Target - ProcessUnit.Gas5) * rampFactor); Chamber.FlowGas(5, ProcessUnit.Gas6 + (ProcessUnit.Gas6Target - ProcessUnit.Gas6) * rampFactor); Chamber.FlowGas(6, ProcessUnit.Gas7 + (ProcessUnit.Gas7Target - ProcessUnit.Gas7) * rampFactor); Chamber.FlowGas(7, ProcessUnit.Gas8 + (ProcessUnit.Gas8Target - ProcessUnit.Gas8) * rampFactor); } return RState.Running; } private void GasControlUnit_End(ProcessUnitBase unit, RecipeStep step) { Chamber.FlowGas(0, 0); Chamber.FlowGas(1, 0); Chamber.FlowGas(2, 0); Chamber.FlowGas(3, 0); Chamber.FlowGas(4, 0); Chamber.FlowGas(5, 0); Chamber.FlowGas(6, 0); Chamber.FlowGas(7, 0); } private RState ESCHVUnit_Start(ProcessUnitBase unit, RecipeStep step) { var ProcessUnit = unit as ESCHVUnit; Chamber.SetESCClampVoltage(ProcessUnit.ESCClampValtage); Chamber.SetBacksideHePressure(ProcessUnit.BacksideHelum); Chamber.SetBacksideHeThreshold(ProcessUnit.MinHeFlow, ProcessUnit.MaxHeFlow); return RState.Running; } private RState ESCHVUnit_Check(ProcessUnitBase unit, RecipeStep step) { if (Chamber.BackSideHeOutOfRange) { LOG.Write(eEvent.ERR_PROCESS, Chamber.Module, $"Step:{step.StepNo} failed, Backside Helium out of range."); return RState.Failed; } return RState.Running; } private void ESCHVUnit_End(ProcessUnitBase unit, RecipeStep step) { Chamber.SetESCClampVoltage(0); //Chamber.SetBacksideHePressure(0); Chamber.SetBacksideHeThreshold(0, 0); //Chamber.OnOffSetESCHV(false); } private RState ProcessKitUnit_Start(ProcessUnitBase unit, RecipeStep step) { var ProcessUnit = unit as ProcessKitUnit; return RState.Running; } private RState ProcessKitUnit_Check(ProcessUnitBase unit, RecipeStep step) { var ProcessUnit = unit as ProcessKitUnit; return RState.Running; } private void ProcessKitUnit_End(ProcessUnitBase unit, RecipeStep step) { } private RState Kepler2200GasControlUnit_Start(ProcessUnitBase unit, RecipeStep step) { Chamber.OpenValve(ValveType.GasFinal, true); var ProcessUnit = unit as Kepler2200GasControlUnit; Chamber.FlowGas(0, ProcessUnit.Gas1); if (ProcessUnit.Gas1 >= 1) { Chamber.OpenValve(ValveType.PV11, true); } Chamber.FlowGas(1, ProcessUnit.Gas2); if (ProcessUnit.Gas2 >= 1) { Chamber.OpenValve(ValveType.PV21, true); } Chamber.FlowGas(2, ProcessUnit.Gas3); if (ProcessUnit.Gas3 >= 1) { Chamber.OpenValve(ValveType.PV31, true); } Chamber.FlowGas(3, ProcessUnit.Gas4); if (ProcessUnit.Gas4 >= 1) { Chamber.OpenValve(ValveType.PV41, true); } Chamber.FlowGas(4, ProcessUnit.Gas5); Chamber.FlowGas(5, ProcessUnit.Gas6); return RState.Running; } private RState Kepler2200GasControlUnit_Check(ProcessUnitBase unit, RecipeStep step) { return RState.Running; } private void Kepler2200GasControlUnit_End(ProcessUnitBase unit, RecipeStep step) { Chamber.FlowGas(0, 0); Chamber.FlowGas(1, 0); Chamber.FlowGas(2, 0); Chamber.FlowGas(3, 0); Chamber.FlowGas(4, 0); Chamber.FlowGas(5, 0); } private RState HeaterUnit_Start(ProcessUnitBase unit, RecipeStep step) { return RState.Running; } private RState HeaterUnit_Check(ProcessUnitBase unit, RecipeStep step) { return RState.Running; } private void HeaterUnit_End(ProcessUnitBase unit, RecipeStep step) { } public bool LoadMethods(ProcessUnitBase unit) { var className = $"{Module}.{unit.GetType().Name}"; if (startHelper.ContainsKey(className) && checkerHelper.ContainsKey(className) && endHelper.ContainsKey(className)) { unit.starter = startHelper[className]; unit.checker = checkerHelper[className]; unit.end = endHelper[className]; return true; } return false; } //public void loopStep(bool isloop,int loopCount,int loopIndex) //{ // isLoop = isloop; // loopsteps=loopCount; // currentStepIndex = loopIndex; //} private RState stepStarter(RecipeStep step) { step.StartStepTimer(); switch (step.Type) { case StepType.EndPoint: Chamber.EPDStepStart(step.EPDConfig, step.StepNo); break; } return RState.Running; } private RState stepChecker(RecipeStep step) { switch (step.Type) { case StepType.Time: return step.ElapsedTime() >= step.Time * 1000 ? RState.End : RState.Running; case StepType.OverEtch: return step.ElapsedTime() >= (step.GetLastEPDStepTime() * step.OverEtchPercent / 100) ? RState.End : RState.Running; case StepType.EndPoint: if (step.ElapsedTime() > step.MaxEndPointTime * 1000) { LOG.Write(eEvent.INFO_PROCESS, Chamber.Module, $"Step:{step.StepNo} timeout, did not capture endpoint signal in {step.MaxEndPointTime} seconds"); return RState.End; } else { return Chamber.EPDCaptured ? RState.End : RState.Running; } } return RState.Running; } private RState stepEnder(RecipeStep step) { if (step.Type == StepType.EndPoint) { Chamber.EPDStepStop(); } return RState.End; } public bool LoadStepFuns(RecipeStep step) { step.starter = stepStarter; step.checker = stepChecker; step.ender = stepEnder; return true; } } }