| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405 | 
							- using System;
 
- using System.Collections.Generic;
 
- using System.Xml;
 
- using Aitex.Common.Util;
 
- using Aitex.Core.RT.Event;
 
- using Aitex.Core.RT.Log;
 
- using Aitex.Core.RT.SCCore;
 
- using EPInterface.Datas;
 
- namespace VirgoRT.Modules
 
- {
 
-     /// <summary>
 
-     /// Recipe head
 
-     /// </summary>
 
-     public class RecipeHead
 
-     {
 
-         public string RecipeVariation  { get; set; }
 
-         public string CreationTime     { get; set; }
 
-         public string LastRevisionTime { get; set; }
 
-         public string CreatedBy        { get; set; }
 
-         public string LastModifiedBy   { get; set; }
 
-         public string PressureMode     { get; set; }
 
-         public string Description      { get; set; }
 
-         public string Barcode          { get; set; }
 
-         public string BasePressure     { get; set; }
 
-         public string PumpDownLimit    { get; set; }
 
-         //public string ElectrodeTemp    { get; set; }
 
-         //public string HeaterTemp       { get; set; }
 
-         public string PurgeActive      { get; set; }
 
-         public string MatchPositionC1  { get; set; }
 
-         public string MatchPositionC2  { get; set; }
 
-         public string SubstrateTemp    { get; set; }
 
-         public string PumpingPinState  { get; set; }
 
-         public string NotToPurgeOrVent { get; set; }    //For keep vacuum after idle clean
 
-         public string VentingPinState  { get; set; }
 
-         public string PinDownPressure { get; set; }
 
-     }
 
-     public class RecipeStep
 
-     {
 
-         public string StepName;
 
-         public double StepTime;
 
-         public bool IsJumpStep;
 
-         public bool IsLoopStartStep;
 
-         public bool IsLoopEndStep;
 
-         public int LoopCount;
 
-         public string EndBy;
 
-         public string EndPointConfig;
 
-         public bool FaultIfNoEPDTrigger;
 
-         //public double EndByValue;
 
-         public Dictionary<string, string> RecipeCommands = new Dictionary<string, string>();
 
-     }
 
-     public class Recipe
 
-     {
 
-         /// <summary>
 
-         /// 当前Recipe Run 记录对应的Guid
 
-         /// 每个Recipe Run 都对应有一个唯一的Guid
 
-         /// </summary>
 
-         public static Guid CurrentRecipeRunGuid;
 
-         /// <summary>
 
-         /// 解析工艺程序文件
 
-         /// </summary>
 
-         /// <param name="recipeName">工艺程序名</param>
 
-         /// <param name="xmlRecipeData">xml格式的工艺数据内容</param>
 
-         /// <param name="recipeData">返回解析的工艺数据变量</param>
 
-         /// <returns>True:解析成功 | False:解析失败</returns>
 
-         public static bool Parse(string chamberId, string recipe, out RecipeHead recipeHead, out List<RecipeStep> recipeData)
 
-         {
 
-             recipeHead = new RecipeHead();
 
-             recipeData = new List<RecipeStep>();
 
-             try
 
-             {
 
-                 //获取工艺程序文件中允许的命令字符串列表
 
-                 //目的:如果工艺程序文件中含有规定之外的命令,则被禁止执行
 
-                 HashSet<string> recipeAllowedCommands = new HashSet<string>();
 
-                 XmlDocument rcpFormatDoc = new XmlDocument();
 
-                 string recipeSchema = PathManager.GetCfgDir() + "RecipeFormat.xml";
 
-                 rcpFormatDoc.Load(recipeSchema);
 
-                 XmlNodeList rcpItemNodeList = rcpFormatDoc.SelectNodes("/Aitex/TableRecipeFormat/Catalog/Group/Step");
 
-                 foreach (XmlElement item in rcpItemNodeList)
 
-                     recipeAllowedCommands.Add(item.Attributes["ControlName"].Value);
 
-                 //获取工艺程序文件中所有步的内容
 
-                 XmlDocument rcpDataDoc = new XmlDocument();
 
-                 rcpDataDoc.LoadXml(recipe);
 
-                 recipeHead.PressureMode = rcpDataDoc.DocumentElement.HasAttribute("PressureMode") ? rcpDataDoc.DocumentElement.Attributes["PressureMode"].Value : "";
 
-                 recipeHead.BasePressure = rcpDataDoc.DocumentElement.HasAttribute("BasePressure") ? rcpDataDoc.DocumentElement.Attributes["BasePressure"].Value : "";
 
-                 recipeHead.PumpDownLimit = rcpDataDoc.DocumentElement.HasAttribute("PumpDownLimit") ? rcpDataDoc.DocumentElement.Attributes["PumpDownLimit"].Value : "";
 
-                 recipeHead.PurgeActive = rcpDataDoc.DocumentElement.HasAttribute("PurgeActive") ? rcpDataDoc.DocumentElement.Attributes["PurgeActive"].Value : "";
 
-                 recipeHead.MatchPositionC1 = rcpDataDoc.DocumentElement.HasAttribute("MatchPositionC1") ? rcpDataDoc.DocumentElement.Attributes["MatchPositionC1"].Value : "";
 
-                 recipeHead.MatchPositionC2 = rcpDataDoc.DocumentElement.HasAttribute("MatchPositionC2") ? rcpDataDoc.DocumentElement.Attributes["MatchPositionC2"].Value : "";
 
-                 recipeHead.Barcode = rcpDataDoc.DocumentElement.HasAttribute("Barcode") ? rcpDataDoc.DocumentElement.Attributes["Barcode"].Value : "";
 
-                 recipeHead.SubstrateTemp = rcpDataDoc.DocumentElement.HasAttribute("SubstrateTemp") ? rcpDataDoc.DocumentElement.Attributes["SubstrateTemp"].Value : "";
 
-                 recipeHead.PumpingPinState = rcpDataDoc.DocumentElement.HasAttribute("PumpingPinState") ? rcpDataDoc.DocumentElement.Attributes["PumpingPinState"].Value : "Down";
 
-                 
 
-                 //For keep vacuum after idle clean
 
-                 recipeHead.NotToPurgeOrVent = rcpDataDoc.DocumentElement.HasAttribute("NotToPurgeOrVent") ? rcpDataDoc.DocumentElement.Attributes["NotToPurgeOrVent"].Value : "";
 
-                 recipeHead.VentingPinState = rcpDataDoc.DocumentElement.HasAttribute("VentingPinState") ? rcpDataDoc.DocumentElement.Attributes["VentingPinState"].Value : "Down";
 
-                 recipeHead.PinDownPressure = rcpDataDoc.DocumentElement.HasAttribute("PinDownPressure") ? rcpDataDoc.DocumentElement.Attributes["PinDownPressure"].Value : "1000";
 
-                 XmlNodeList stepNodeList = rcpDataDoc.SelectNodes("/TableRecipeData/Step");
 
-                 for (int i = 0; i < stepNodeList.Count; i++)
 
-                 {
 
-                     var recipeStep = new RecipeStep();
 
-                     recipeData.Add(recipeStep);
 
-                     XmlElement stepNode = stepNodeList[i] as XmlElement;
 
-                     Dictionary<string, string> dic = new Dictionary<string, string>();
 
-                     //遍历Step节点
 
-                     foreach (XmlAttribute att in stepNode.Attributes)
 
-                     {
 
-                         if (recipeAllowedCommands.Contains(att.Name))
 
-                         {
 
-                             dic.Add(att.Name, att.Value);
 
-                         }
 
-                     }
 
-                     //遍历Step子节点中所有的attribute属性节点
 
-                     foreach (XmlElement subStepNode in stepNode.ChildNodes)
 
-                     {
 
-                         foreach (XmlAttribute att in subStepNode.Attributes)
 
-                         {
 
-                             if (recipeAllowedCommands.Contains(att.Name))
 
-                             {
 
-                                 dic.Add(att.Name, att.Value);
 
-                             }
 
-                         }
 
-                         //遍历Step子节点的子节点中所有的attribute属性节点
 
-                         foreach (XmlElement subsubStepNode in subStepNode.ChildNodes)
 
-                         {
 
-                             foreach (XmlAttribute att in subsubStepNode.Attributes)
 
-                             {
 
-                                 if (recipeAllowedCommands.Contains(att.Name))
 
-                                 {
 
-                                     dic.Add(att.Name, att.Value);
 
-                                 }
 
-                             }
 
-                         }
 
-                     }
 
-                     recipeStep.IsJumpStep = true;//!Convert.ToBoolean(dic["Ramp"]);
 
-                     recipeStep.StepName = dic["Name"];
 
-                     recipeStep.StepTime = double.Parse(dic["Time"]);
 
-                     string loopStr = dic["Loop"];
 
-                     recipeStep.IsLoopStartStep = System.Text.RegularExpressions.Regex.Match(loopStr, @"Loop\x20\d+\s*$").Success;
 
-                     recipeStep.IsLoopEndStep = System.Text.RegularExpressions.Regex.Match(loopStr, @"Loop End$").Success;
 
-                     if (recipeStep.IsLoopStartStep)
 
-                         recipeStep.LoopCount = Convert.ToInt32(loopStr.Replace("Loop", string.Empty));
 
-                     else
 
-                         recipeStep.LoopCount = 0;
 
-                     //recipeStep.EndByValue = Convert.ToDouble(dic["EndValue"]);
 
-                     recipeStep.EndBy = dic["EndBy"];
 
-                     if (recipeStep.EndBy == "EndByRfTime")
 
-                     {
 
-                         recipeStep.StepTime = double.Parse(dic["Rf.SetPowerOnTime"]);
 
-                         if (recipeStep.StepTime <= 0)
 
-                         {
 
-                             LOG.Error("The recipe does not define the time for RF Power on");
 
-                             return false;
 
-                         }
 
-                     }
 
-                     int rfPower = (int)Convert.ToDouble(dic["Rf.SetPower"]);
 
-                     dic.Add("Rf.SetPowerOnOff", rfPower > 0 ? "true" : "false");
 
-                     if (SC.GetValue<bool>($"{chamberId}.BiasRf.EnableBiasRF"))
 
-                     {
 
-                         int rfPowerBias = (int)Convert.ToDouble(dic["BiasRf.SetPower"]);
 
-                         dic.Add("BiasRf.SetPowerOnOff", rfPowerBias > 0 ? "true" : "false");
 
-                     }
 
-                     else
 
-                     {
 
-                         dic.Remove("BiasRf.SetPower");
 
-                         dic.Remove("BiasRf.SetMatchProcessMode");
 
-                         dic.Remove("BiasRf.SetMatchPositionC1");
 
-                         dic.Remove("BiasRf.SetMatchPositionC2");
 
-                     }
 
-                     bool epdInstalled = SC.ContainsItem("System.SetUp.EPDInstalled") && SC.GetValue<bool>($"System.SetUp.EPDInstalled");
 
-                     if (!epdInstalled)
 
-                     {
 
-                         if (dic.ContainsKey("EPD.SetConfig"))
 
-                             dic.Remove("EPD.SetConfig");
 
-                     }
 
-                     else
 
-                     {
 
-                         recipeStep.EndPointConfig = dic.ContainsKey("EPD.SetConfig") ? dic["EPD.SetConfig"] : null;
 
-                         if (string.IsNullOrEmpty(recipeStep.EndPointConfig))
 
-                         {
 
-                             if (recipeStep.EndBy == "EndByEndPoint")
 
-                             {
 
-                                 EV.PostWarningLog("System", "EndPoint is empty");
 
-                                 return false;
 
-                             }
 
-                             recipeStep.EndPointConfig = SC.GetStringValue("System.EndPoint.EndPointDefaultValue");
 
-                         }
 
-                         else
 
-                         {
 
-                             if (!ParseEPD(recipeStep.EndPointConfig, out EPDConfig config))
 
-                             {
 
-                                 EV.PostWarningLog("System", "EndPoint config is not valid");
 
-                                 return false;
 
-                             }
 
-                             recipeStep.FaultIfNoEPDTrigger = config.FaultIfNoEPDTrigger;
 
-                         }
 
-                     }
 
-                     //dic.Remove("Ramp");
 
-                     dic.Remove("StepNo");
 
-                     dic.Remove("Name");
 
-                     dic.Remove("Loop");
 
-                     dic.Remove("Time");
 
-                     dic.Remove("EndBy");
 
-                     //dic.Remove("EndValue");
 
-                     dic.Remove("Rf.SetPowerOnTime");
 
-                     foreach (string key in dic.Keys)
 
-                         recipeStep.RecipeCommands.Add(key, dic[key]);
 
-                 }
 
-             }
 
-             catch (Exception ex)
 
-             {
 
-                 LOG.Write(ex);
 
-                 return false;
 
-             }
 
-             return true;
 
-         }
 
-         private static bool ParseEPD(string config, out EPDConfig epdConfig)
 
-         {
 
-             epdConfig = new EPDConfig();
 
-             try
 
-             {
 
-                 epdConfig.nParameterCount = 1;
 
-                 string[] items = config.Split(';');
 
-                 foreach (var item in items)
 
-                 {
 
-                     if (string.IsNullOrEmpty(item))
 
-                         continue;
 
-                     string[] pairs = item.Split('=');
 
-                     if (pairs.Length != 2)
 
-                         continue;
 
-                     switch (pairs[0])
 
-                     {
 
-                         case "ExposureTime":
 
-                             epdConfig.Columns[0].nCCDExposureTime = int.Parse(pairs[1]);
 
-                             break;
 
-                         case "WaveLengthA":
 
-                             epdConfig.Columns[0].nWaveLength[0] = ushort.Parse(pairs[1]);
 
-                             break;
 
-                         case "BinningA":
 
-                             epdConfig.Columns[0].nBinning[0] = ushort.Parse(pairs[1]);
 
-                             break;
 
-                         case "WaveLengthB":
 
-                             epdConfig.Columns[0].nWaveLength[1] = ushort.Parse(pairs[1]);
 
-                             break;
 
-                         case "BinningB":
 
-                             epdConfig.Columns[0].nBinning[1] = ushort.Parse(pairs[1]);
 
-                             break;
 
-                         case "WaveLengthC":
 
-                             epdConfig.Columns[0].nWaveLength[2] = ushort.Parse(pairs[1]);
 
-                             break;
 
-                         case "BinningC":
 
-                             epdConfig.Columns[0].nBinning[2] = ushort.Parse(pairs[1]);
 
-                             break;
 
-                         case "WaveLengthD":
 
-                             epdConfig.Columns[0].nWaveLength[3] = ushort.Parse(pairs[1]);
 
-                             break;
 
-                         case "BinningD":
 
-                             epdConfig.Columns[0].nBinning[3] = ushort.Parse(pairs[1]);
 
-                             break;
 
-                         case "Fd":
 
-                             epdConfig.Columns[0].cFunc = pairs[1];
 
-                             break;
 
-                         case "PrefilterTime":
 
-                             epdConfig.Columns[0].nPreFilterTime = int.Parse(pairs[1]);
 
-                             break;
 
-                         case "PostfilterTime":
 
-                             epdConfig.Columns[0].nPostFilterTime = int.Parse(pairs[1]);
 
-                             break;
 
-                         case "AlgorithmType":
 
-                             epdConfig.Columns[0].algorithmType = MapType(pairs[1]);
 
-                             break;
 
-                         case "Criteria":
 
-                             epdConfig.Columns[0].nCriteria = float.Parse(pairs[1]);
 
-                             break;
 
-                         case "DelayTime":
 
-                             epdConfig.Columns[0].nDelayTime = int.Parse(pairs[1]);
 
-                             break;
 
-                         case "ValidationTime":
 
-                             epdConfig.Columns[0].nValidationTime = int.Parse(pairs[1]);
 
-                             break;
 
-                         case "ValidationValue":
 
-                             epdConfig.Columns[0].nValidationValue = int.Parse(pairs[1]);
 
-                             break;
 
-                         case "TimeWindow":
 
-                             epdConfig.Columns[0].nTimeWindow = int.Parse(pairs[1]);
 
-                             break;
 
-                         case "MinimalTime":
 
-                             epdConfig.Columns[0].nMinimalTime = int.Parse(pairs[1]);
 
-                             break;
 
-                         case "PostponeTime":
 
-                             epdConfig.Columns[0].nPostponeTime = int.Parse(pairs[1]);
 
-                             break;
 
-                         case "Control":
 
-                             epdConfig.Columns[0].bControl = Convert.ToBoolean(pairs[1]);
 
-                             break;
 
-                         case "Normalization":
 
-                             epdConfig.Columns[0].bNormalization = Convert.ToBoolean(pairs[1]);
 
-                             break;
 
-                         case "EnablePostponePercent":
 
-                             epdConfig.Columns[0].bPostponePercent = Convert.ToBoolean(pairs[1]);
 
-                             break;
 
-                         case "EnableCriterialPercent":
 
-                             epdConfig.Columns[0].bCriteriaPercent = Convert.ToBoolean(pairs[1]);
 
-                             break;
 
-                         case "EnableEventTrigger":
 
-                             epdConfig.Columns[0].bEvtTrigger = Convert.ToBoolean(pairs[1]);
 
-                             break;
 
-                         case "IsFaultIfNoTrigger":
 
-                             epdConfig.FaultIfNoEPDTrigger = Convert.ToBoolean(pairs[1]);
 
-                             break;
 
-                     }
 
-                 }
 
-                 return true;
 
-             }
 
-             catch (Exception ex)
 
-             {
 
-                 LOG.Write(ex);
 
-                 EV.PostMessage("System", EventEnum.DefaultAlarm, "EPD config input not valid, ", ex.Message);
 
-                 return false;
 
-             }
 
-              
 
-         }
 
-         private static AlgorithmType MapType(string type)
 
-         {
 
-             switch (type)
 
-             {
 
-                 case "Unknown": return AlgorithmType.ALG_NONE;
 
-                 case "Above_ABS_Value": return AlgorithmType.ALG_RISE_VALUE;
 
-                 case "Below_ABS_Value": return AlgorithmType.ALG_FALL_VALUE;
 
-                 case "Drop_Percent": return AlgorithmType.ALG_FALL_PERCENT;
 
-                 case "Up_Percent": return AlgorithmType.ALG_RISE_PERCENT;
 
-                 case "Range_In": return AlgorithmType.ALG_RANGE_IN;
 
-                 case "Gradient": return AlgorithmType.ALG_GRADIENT;
 
-                 case "Peek": return AlgorithmType.ALG_PEAK;
 
-                 case "Valley": return AlgorithmType.ALG_VALLEY;
 
-                 case "Min_Drop_Percent": return AlgorithmType.ALG_MIN_FALL_PERCENT;
 
-                 case "Min_Up_Percent": return AlgorithmType.ALG_MIN_RISE_PERCENT;
 
-                 case "Max_Drop_Percent": return AlgorithmType.ALG_MAX_FALL_PERCENT;
 
-                 case "Max_Up_Percent": return AlgorithmType.ALG_MAX_RISE_PERCENT;
 
-                 case "Rise_Fall": return AlgorithmType.ALG_RISE_FALL;
 
-                 case "Fall_Rise": return AlgorithmType.ALG_FALL_RISE;
 
-             }
 
-             return AlgorithmType.ALG_NONE;
 
-         }
 
-     }
 
- }
 
 
  |