MoS2/Framework/MECF.Framework.RT.EquipmentLibrary/HardwareUnits/Temps/AKunTriggerTemp/AKunTriggerChannelWaferTempData.cs

258 lines
8.8 KiB
C#
Raw Normal View History

2026-08-18 14:04:28 +08:00
using Aitex.Core.RT.DataCenter;
using System;
using System.Collections.Generic;
using System.Linq;
namespace MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Temps
{
public enum DataType
{
Wafer,
Tray,
}
/// <summary>
/// 测温点位置
/// </summary>
public enum EnumZoneNum
{
Center,
CenterEdge,
Edge
}
public class AKunTriggerChannelWaferTempData
{
/// <summary>
/// 创建通道对应的单个晶圆温度对象
/// </summary>
/// <param name="waferNum">晶圆编号</param>
/// <param name="ch">测温设备通道编号</param>
/// <param name="name">当前晶圆对象的名称Wafer or Tray,测温对象也能反馈Tray温度</param>
public AKunTriggerChannelWaferTempData(int waferNum, int ch = 1, string name = "Wafer")
{
Detector = ch;
WaferNum = waferNum;
WaferName = $"CH{Detector}.{name}{waferNum}"; //eg: CH1.Wafer1 CH1.Wafer2 CH2.Wafer1 CH2.Wafer2
}
/// <summary>
/// 通道编号默认为1
/// </summary>
public int Detector { get; set; }
public string WaferName { get; set; }
public int WaferNum { get; set; }
public DataType Type { get; set; }
public double Temp { get; set; }
public int ZoneNum { get; set; }
public EnumZoneNum ZoneNumSelect { get; set; }
/// <summary>
/// 0表示无效晶圆代表Dummy晶圆或者空位此位置的温度不能参与STC控温
/// </summary>
public int PocketNum { get; set; }
/// <summary>
/// The reflection of 404nm
/// </summary>
public double Reflect1 { get; set; }
/// <summary>
/// The reflection of 633nm.
/// </summary>
public double Reflect2 { get; set; }
/// <summary>
/// The reflection of 950nm.
/// </summary>
public double Reflect3 { get; set; }
public double Curvature { get; set; }
/// <summary>
/// false不参与控温晶圆温度是否参与区域计算不放片或者放Dummy时不参与区域计算
/// </summary>
public bool CalZone { get; set; }
public void UpData(AKunTriggerChannelWaferTempData newData)
{
// 确保传入的 newData 对象不为空
if (newData == null)
{
throw new ArgumentNullException(nameof(newData));
}
Detector = newData.Detector;
WaferNum = newData.WaferNum;
Temp = newData.Temp;
ZoneNum = newData.ZoneNum;
ZoneNumSelect = newData.ZoneNumSelect;
Reflect1 = newData.Reflect1;
Curvature = newData.Curvature;
}
}
public class AKunTriggerTempDataManager(int waferNum, double minTemp)
{
private readonly int _waferNum = waferNum;
private double _minTemp = minTemp;
private List<AKunTriggerChannelWaferTempData> _waferTempDataList = new();
private static readonly object _lock = new object();
#region
public bool ProcessReceivedData(string tcpReceive)
{
lock (_lock)
{
List<AKunTriggerChannelWaferTempData> tempDataList = new List<AKunTriggerChannelWaferTempData>();
AKunTriggerChannelWaferTempData aKunChWaferTempData;
string[] keyValuePairs = tcpReceive.Split('\0');
for (int i = 0; i < keyValuePairs.Length - 1; i++)
{
aKunChWaferTempData = new AKunTriggerChannelWaferTempData(-999);
string[] keyValues = keyValuePairs[i].Split(',');
foreach (string pair in keyValues)
{
string[] keyValue = pair.Split('=');
switch (keyValue[0])
{
case "Detector":
aKunChWaferTempData.Detector = int.Parse(keyValue[1]);
break;
case "PocketNum":
aKunChWaferTempData.PocketNum = int.Parse(keyValue[1]);
break;
case "WaferNum":
aKunChWaferTempData.WaferNum = int.Parse(keyValue[1]);
break;
case "CalZone":
aKunChWaferTempData.CalZone = int.Parse(keyValue[1]) == 1;
break;
case "TTemp":
aKunChWaferTempData.Temp = double.Parse(keyValue[1]);
break;
case "ZoneNum":
aKunChWaferTempData.ZoneNum = int.Parse(keyValue[1]);
aKunChWaferTempData.ZoneNumSelect =
(EnumZoneNum)Enum.Parse(typeof(EnumZoneNum), keyValue[1]);
break;
case "Reflec1":
aKunChWaferTempData.Reflect1 = double.Parse(keyValue[1]);
break;
case "Reflec2":
aKunChWaferTempData.Reflect2 = double.Parse(keyValue[1]);
break;
case "Reflec3":
aKunChWaferTempData.Reflect3 = double.Parse(keyValue[1]);
break;
case "Curvature":
aKunChWaferTempData.Curvature = double.Parse(keyValue[1]);
break;
}
}
if (aKunChWaferTempData.WaferNum == -999)
return true;
tempDataList.Add(aKunChWaferTempData);
}
_waferTempDataList = tempDataList;
return true;
}
}
public bool[] GetCalZone()
{
bool[] calZone = new bool[_waferNum];
if (_waferTempDataList.Count < _waferNum)
return calZone;
for (int i = 0; i < _waferNum; i++) //只有前面几个数据,是需要统计是否参与计算
{
calZone[i] = _waferTempDataList[i].CalZone;
}
return calZone;
}
public double[] GetWaferTemp()
{
double[] waferTemps = Enumerable.Repeat(_minTemp, _waferNum).ToArray();
if (_waferTempDataList.Count < _waferNum)
return waferTemps;
2026-08-20 09:10:12 +08:00
//for (int i = 0; i < _waferNum; i++) //只有前面几个温度数据,才是需要统计的
2026-08-18 14:04:28 +08:00
//{
2026-08-20 09:10:12 +08:00
// waferTemps[i] = _waferTempDataList[i].Temp;
2026-08-18 14:04:28 +08:00
//}
2026-08-20 09:10:12 +08:00
for (int i = 0; i < _waferNum; i++)
{
//根据编号,获取同一分区所有温度数据
var tempCaches = _waferTempDataList.Where(item => item.PocketNum == i + 1);
if (tempCaches != null && tempCaches.Count() > 0)
{
//同一分区所有温度数据查找第一个CalZone为true的温度数据
var matchedItem = tempCaches.Where(item => item.CalZone).FirstOrDefault();
if (matchedItem != null)
waferTemps[i] = matchedItem.Temp;
else
waferTemps[i] = tempCaches.First().Temp;//未设置CalZone为true使用当前分区第一个数据作为默认温度值
}
else
waferTemps[i] = -1;//没有分区温度是乱的无法解析,使用-1作为提示
}
2026-08-18 14:04:28 +08:00
return waferTemps;
}
public double GetTrayTemp()
{
if (_waferTempDataList.Count == 0)
return _minTemp;
return _waferTempDataList[_waferTempDataList.Count - 1].Temp; //最后一个数据才是Tray温度
}
#endregion
public List<double[]> GetReflectValue()
{
List<double[]> reflectList = Enumerable.Range(0, _waferNum)
.Select(_ => new double[3]) // 每个数组默认元素为 0
.ToList();
if (_waferTempDataList.Count < _waferNum)
return reflectList;
for (int i = 0; i < _waferNum; i++) //只有前面几个反射率数据,才是需要统计的
{
var data = _waferTempDataList[i];
reflectList.Add([data.Reflect1, data.Reflect2, data.Reflect3]);
}
return reflectList;
}
}
}