288 lines
10 KiB
C#
288 lines
10 KiB
C#
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;
|
||
|
||
// int count = (_waferTempDataList.Count - 1) / _waferNum ;//分区数计算,最后一个数据是托盘的,所以减一,
|
||
// if ((_waferTempDataList.Count - 1) % _waferNum != 0)//分区数量不是整数,温度不解析防呆,
|
||
// return waferTemps;
|
||
|
||
// for (int i = 0; i < _waferNum; i++) //Wafer温度只取每个晶圆的第一个设置的中心温度
|
||
// {
|
||
// var index = i * count;
|
||
// waferTemps[i] = _waferTempDataList[index].Temp;//直接使用第一个中心温度作为中心温度
|
||
|
||
// //要求不判断中心点,只用第一个分区温度
|
||
// //for (int j = index; j < index + count ; j++)
|
||
// //{
|
||
// // if(_waferTempDataList[j].ZoneNum==0)
|
||
// // {
|
||
// // waferTemps[i] = _waferTempDataList[j].Temp;//有中心温度设置,获取第一个中心温度作为晶圆温度
|
||
// // break;
|
||
// // }
|
||
// //}
|
||
// }
|
||
|
||
// return waferTemps;
|
||
//}
|
||
|
||
public double[] GetWaferTemp()
|
||
{
|
||
double[] waferTemps = Enumerable.Repeat(_minTemp, _waferNum).ToArray();
|
||
if (_waferTempDataList.Count < _waferNum)
|
||
return waferTemps;
|
||
|
||
//这届
|
||
for (int i = 0; i < _waferNum; i++) //只有前面几个温度数据,才是需要统计的
|
||
{
|
||
waferTemps[i] = _waferTempDataList[i].Temp;
|
||
}
|
||
|
||
//_waferTempDataList[i].CalZone
|
||
//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作为提示
|
||
//}
|
||
|
||
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;
|
||
}
|
||
}
|
||
} |