using System;
using System.Threading;
namespace SA_LTT.Module
{
public class PreAligner : ComPort
{
public enum ErrorCode
{
None,
PinUpError,
PinDownError,
VaccumError,
NoWafer,
WaferLimitErrorAfterAlign,
NotFoundNotch,
StageLimitError = 9,
InvalidAlignCommand,
ChuckArrangeError,
WaferAlignCCDOver,
WaferLimitErrorBeforeAlign,
RetractHome = 16,
WaferExist,
CCDModuleError = 30,
AlignerTypeError = 50,
CommandError = 999,
}
private Equipment _equipment;
private Thread t_statusUpdate;
private Thread t_commandWriteRead;
private string _version;
private double _positionX;
private double _positionY;
private double _positionT;
private bool _isWaferExist;
private bool _isVacuumOn;
private bool _isHome;
private bool _isAlignRun;
private bool _lockCheck;
private object _thisLock = new object();
private int waitTime = 100;
public ErrorCode error;
private SequenceTimer _timer = new SequenceTimer();
public string Version
{
get
{
return _version;
}
set
{
_version = value;
}
}
public double PositionX
{
get
{
return _positionX;
}
set
{
_positionX = value;
}
}
public double PositionY
{
get
{
return _positionY;
}
set
{
_positionY = value;
}
}
public double PositionT
{
get
{
return _positionT;
}
set
{
_positionT = value;
}
}
public bool IsHome
{
get
{
return _isHome;
}
set
{
_isHome = value;
}
}
public bool IsWaferExist
{
get
{
return _isWaferExist;
}
set
{
_isWaferExist = value;
}
}
public bool IsVacuumOn
{
get
{
return _isVacuumOn;
}
set
{
_isVacuumOn = value;
}
}
public bool IsAlignRun
{
get
{
return _isAlignRun;
}
set
{
_isAlignRun = value;
}
}
public bool IsRunEnable
{
get
{
if(IsOpen && (t_commandWriteRead == null || t_commandWriteRead.ThreadState == ThreadState.Stopped))
{
return true;
}
else
{
return false;
}
}
}
public PreAligner(Equipment equipment)
{
serialPort.PortName = "COM4";
serialPort.DataBits = 8;
serialPort.Parity = System.IO.Ports.Parity.None;
serialPort.StopBits = System.IO.Ports.StopBits.One;
serialPort.BaudRate = 19200;
ReceiveWaitSeconds = 0.1;
Terminator = null;
_equipment = equipment;
error = ErrorCode.None;
t_statusUpdate = new Thread(statusUpdate);
t_statusUpdate.Start();
}
public void statusUpdate()
{
while (_equipment.IsDisposed == false)
{
try
{
Thread.Sleep(waitTime);
if (IsOpen)
{
if (IsRunEnable)
{
ReadPosition();
ReadStatus();
}
}
else
{
if (_equipment.alarmManager.OccurredAlarms.Exists(x => x.Code == AlarmCode.AL_0051_PRE_ALIGNER_DISCONNECTED))
{
}
else
{
if (Open() == false)
{
_equipment.alarmManager.Occur(AlarmCode.AL_0051_PRE_ALIGNER_DISCONNECTED);
}
else
{
if (ReadVersion() == false)
{
Close();
}
else
{
//Home();
}
}
}
}
}
catch (Exception e)
{
EquipmentLogManager.Instance.WriteExceptionLog(e.StackTrace);
}
}
}
public void Align(double angle)
{
if (IsRunEnable == false) return;
t_commandWriteRead = new Thread(() =>
{
lock (_thisLock)
{
while (_lockCheck)
Monitor.Wait(_thisLock);
try
{
_lockCheck = true;
IsAlignRun = true;
if (angle < 0)
{
angle = 0;
}
else if (angle > 359.999)
{
angle = 359.999;
}
string str = WriteRead($"ALIGN {angle:f3}");
string str1 = Read(10);
//ALIGN 90.000\rEND\r
string[] datas = str.Split('\r');
if (datas.Length == 3 && datas[1].Contains("ERR"))
{
string errorCode = datas[1].Split(' ')[1];
error = (ErrorCode)Enum.Parse(typeof(ErrorCode), errorCode);
SetAlarmCode(error);
}
datas = str1.Split('\r');
if (datas.Length == 3 && datas[1].Contains("ERR"))
{
string errorCode = datas[1].Split(' ')[1];
error = (ErrorCode)Enum.Parse(typeof(ErrorCode), errorCode);
SetAlarmCode(error);
}
Thread.Sleep(100);
string log = WriteRead($"RQ POSITION");
EquipmentLogManager.Instance.WritePreAlignLog("Result : " + log.Replace('\r', ' '));
Thread.Sleep(waitTime);
}
catch (Exception e)
{
EquipmentLogManager.Instance.WriteExceptionLog(e.StackTrace);
}
finally
{
IsAlignRun = false;
_lockCheck = false;
Monitor.Pulse(_thisLock);
}
}
}
);
t_commandWriteRead.Start();
}
///
/// 얼라인 이후에 각도 변경
///
///
public void Again(double angle)
{
if (IsRunEnable == false) return;
t_commandWriteRead = new Thread(() =>
{
lock (_thisLock)
{
while (_lockCheck)
Monitor.Wait(_thisLock);
try
{
_lockCheck = true;
IsAlignRun = true;
if (angle < 0)
{
angle = 0;
}
else if (angle > 359.999)
{
angle = 359.999;
}
string str = WriteRead($"AGAIN {angle:f3}");
string[] datas = str.Split('\r');
if (datas.Length == 3 && datas[1].Contains("ERR"))
{
error = (ErrorCode)Enum.Parse(typeof(ErrorCode), datas[1].Split(' ')[1]);
SetAlarmCode(error);
}
Thread.Sleep(waitTime);
//AGAIN 0.000\rEND\r
}
catch (Exception e)
{
EquipmentLogManager.Instance.WriteExceptionLog(e.StackTrace);
}
finally
{
IsAlignRun = false;
_lockCheck = false;
Monitor.Pulse(_thisLock);
}
}
});
t_commandWriteRead.Start();
}
public bool ReadVersion()
{
lock (_thisLock)
{
while (_lockCheck)
Monitor.Wait(_thisLock);
try
{
_lockCheck = true;
string receivedData = WriteRead($"VER");
string[] datas = receivedData.Split('\r');
if (datas.Length == 3)
{
Version = datas[1];
return true;
}
else
{
return false;
}
}
catch (Exception e)
{
EquipmentLogManager.Instance.WriteExceptionLog(e.StackTrace);
return false;
}
finally
{
_lockCheck = false;
Monitor.Pulse(_thisLock);
}
}
}
public void Home()
{
if (IsRunEnable == false) return;
t_commandWriteRead = new Thread(() =>
{
lock (_thisLock)
{
while (_lockCheck)
Monitor.Wait(_thisLock);
try
{
_lockCheck = true;
string str = WriteRead($"HOME");
str = Read(20);
//HOME\rEND\r
Thread.Sleep(waitTime);
}
catch (Exception e)
{
EquipmentLogManager.Instance.WriteExceptionLog(e.StackTrace);
}
finally
{
_lockCheck = false;
Monitor.Pulse(_thisLock);
}
}
});
t_commandWriteRead.Start();
}
public void VacuumOn()
{
if (IsRunEnable == false) return;
t_commandWriteRead = new Thread(() =>
{
lock (_thisLock)
{
while (_lockCheck)
Monitor.Wait(_thisLock);
try
{
_lockCheck = true;
string str = WriteRead($"VAC ON");
str = Read(5);
string[] datas = str.Split('\r');
if (datas.Length == 3 && datas[1].Contains("ERR"))
{
error = (ErrorCode)Enum.Parse(typeof(ErrorCode), datas[1].Split(' ')[1]);
SetAlarmCode(error);
}
Thread.Sleep(waitTime);
}
catch (Exception e)
{
EquipmentLogManager.Instance.WriteExceptionLog(e.StackTrace);
}
finally
{
_lockCheck = false;
Monitor.Pulse(_thisLock);
}
}
});
t_commandWriteRead.Start();
}
public void VacuumOff()
{
if (IsRunEnable == false) return;
t_commandWriteRead = new Thread(() =>
{
lock (_thisLock)
{
while (_lockCheck)
Monitor.Wait(_thisLock);
try
{
_lockCheck = true;
string str = WriteRead($"VAC OFF");
string[] datas = str.Split('\r');
if (datas.Length == 3 && datas[1].Contains("ERR"))
{
error = (ErrorCode)Enum.Parse(typeof(ErrorCode), datas[1].Split(' ')[1]);
SetAlarmCode(error);
}
Thread.Sleep(waitTime);
}
catch (Exception e)
{
EquipmentLogManager.Instance.WriteExceptionLog(e.StackTrace);
}
finally
{
_lockCheck = false;
Monitor.Pulse(_thisLock);
}
}
});
t_commandWriteRead.Start();
}
public void PinUp()
{
if (IsRunEnable == false) return;
t_commandWriteRead = new Thread(() =>
{
t_commandWriteRead.Start();
lock (_thisLock)
{
while (_lockCheck)
Monitor.Wait(_thisLock);
try
{
_lockCheck = true;
string str = WriteRead($"PIN UP");
//PIN UP\r
Thread.Sleep(waitTime);
}
catch (Exception e)
{
EquipmentLogManager.Instance.WriteExceptionLog(e.StackTrace);
}
finally
{
_lockCheck = false;
Monitor.Pulse(_thisLock);
}
}
});
}
public void PinDown()
{
if (IsRunEnable == false) return;
t_commandWriteRead = new Thread(() =>
{
lock (_thisLock)
{
while (_lockCheck)
Monitor.Wait(_thisLock);
try
{
_lockCheck = true;
string str = WriteRead($"PIN DN");
//PIN DN\r
Thread.Sleep(waitTime);
}
catch (Exception e)
{
EquipmentLogManager.Instance.WriteExceptionLog(e.StackTrace);
}
finally
{
_lockCheck = false;
Monitor.Pulse(_thisLock);
}
}
});
t_commandWriteRead.Start();
}
public void ReadStatus()
{
lock (_thisLock)
{
while (_lockCheck)
Monitor.Wait(_thisLock);
try
{
_lockCheck = true;
string str = WriteRead($"STATUS");
//STATUS\r[0:ON 1:OFF] VAC:1 WF1:1 WF2:0 START:1 CLR:1 HOME:1 IN4:1 RUN:1 WAF:0 VAC:1 ALM:0\r
string[] datas = str.Split('\r');
if(datas.Length == 3)
{
string[] status = datas[1].Split(' ');
IsHome = status[7].Split(':')[1] == "0" ? true : false;
IsWaferExist = status[10].Split(':')[1] == "0" ? true : false;
IsVacuumOn = status[11].Split(':')[1] == "0" ? true : false;
}
Thread.Sleep(waitTime);
}
catch (Exception e)
{
EquipmentLogManager.Instance.WriteExceptionLog(e.StackTrace);
}
finally
{
_lockCheck = false;
Monitor.Pulse(_thisLock);
}
}
}
public void ReadLog()
{
string str = WriteRead($"RQ LOG");
}
public void ReadAlarmCode()
{
if (IsRunEnable == false) return;
t_commandWriteRead = new Thread(() =>
{
});
t_commandWriteRead.Start();
lock (_thisLock)
{
while (_lockCheck)
Monitor.Wait(_thisLock);
try
{
_lockCheck = true;
string str = WriteRead($"ALARM CODE");
str = Read(20);
//ALARM CODE\rNO_ALARM\r
Thread.Sleep(waitTime);
}
catch (Exception e)
{
EquipmentLogManager.Instance.WriteExceptionLog(e.StackTrace);
}
finally
{
_lockCheck = false;
Monitor.Pulse(_thisLock);
}
}
}
public void ReadPinStatus()
{
if (IsRunEnable == false) return;
t_commandWriteRead = new Thread(() =>
{
});
t_commandWriteRead.Start();
lock (_thisLock)
{
while (_lockCheck)
Monitor.Wait(_thisLock);
try
{
_lockCheck = true;
string str = WriteRead($"RQ PIN");
//RQ PIN\r
Thread.Sleep(waitTime);
}
catch (Exception e)
{
EquipmentLogManager.Instance.WriteExceptionLog(e.StackTrace);
}
finally
{
_lockCheck = false;
Monitor.Pulse(_thisLock);
}
}
}
public void ReadWaferStatus()
{
if (IsRunEnable == false) return;
t_commandWriteRead = new Thread(() =>
{
});
t_commandWriteRead.Start();
lock (_thisLock)
{
while (_lockCheck)
Monitor.Wait(_thisLock);
try
{
_lockCheck = true;
string str = WriteRead($"RQ WAFER");
//RQ WAFER\r
Thread.Sleep(waitTime);
}
catch (Exception e)
{
EquipmentLogManager.Instance.WriteExceptionLog(e.StackTrace);
}
finally
{
_lockCheck = false;
Monitor.Pulse(_thisLock);
}
}
}
public void ReadVaccumStatus()
{
if (IsRunEnable == false) return;
t_commandWriteRead = new Thread(() =>
{
});
t_commandWriteRead.Start();
lock (_thisLock)
{
while (_lockCheck)
Monitor.Wait(_thisLock);
try
{
_lockCheck = true;
string str = WriteRead($"RQ VAC");
//RQ VAC\r[OFF]\r
Thread.Sleep(waitTime);
}
catch (Exception e)
{
EquipmentLogManager.Instance.WriteExceptionLog(e.StackTrace);
}
finally
{
_lockCheck = false;
Monitor.Pulse(_thisLock);
}
}
}
public void ReadParameter()
{
lock (_thisLock)
{
while (_lockCheck)
Monitor.Wait(_thisLock);
try
{
_lockCheck = true;
string str = WriteRead($"RQ PARA");
str = Read(3);
//"RQ PARA\r\rVER 1.2(DX)-01\rTYPE 1\rDEEP 0.6\rDEEX 1.5\rRETRY 5\rSET 000.00\rOFFSET +000.000\rWIDTH 5\rWAFER SIZE 300\rBASE LENGTH 142\rLOOP 1\rRESET 1\rLOG 1\rVAC KEEP 0\rRESPONSE 1\rWP 0\rDIST"
Thread.Sleep(waitTime);
}
catch (Exception e)
{
EquipmentLogManager.Instance.WriteExceptionLog(e.StackTrace);
}
finally
{
_lockCheck = false;
Monitor.Pulse(_thisLock);
}
}
}
public void ReadPosition()
{
lock (_thisLock)
{
while (_lockCheck)
Monitor.Wait(_thisLock);
try
{
_lockCheck = true;
string receivedData = WriteRead("RQ POSITION");
string[] datas = receivedData.Split('\r');
if (datas.Length == 3)
{
string[] positions = datas[1].Split(' ');
PositionX = double.Parse(positions[1]);
PositionY = double.Parse(positions[2]);
PositionT = double.Parse(positions[3]);
}
else
{
}
Thread.Sleep(waitTime);
}
catch (Exception e)
{
EquipmentLogManager.Instance.WriteExceptionLog(e.StackTrace);
}
finally
{
_lockCheck = false;
Monitor.Pulse(_thisLock);
}
}
}
public void Center()
{
if (IsRunEnable == false) return;
t_commandWriteRead = new Thread(() =>
{
lock (_thisLock)
{
while (_lockCheck)
Monitor.Wait(_thisLock);
try
{
_lockCheck = true;
string str = WriteRead($"CENTER");
string[] datas = str.Split('\r');
if (datas.Length == 3 && datas[1].Contains("ERR"))
{
error = (ErrorCode)Enum.Parse(typeof(ErrorCode), datas[1].Split(' ')[1]);
SetAlarmCode(error);
}
Thread.Sleep(waitTime);
}
catch (Exception e)
{
EquipmentLogManager.Instance.WriteExceptionLog(e.StackTrace);
}
finally
{
_lockCheck = false;
Monitor.Pulse(_thisLock);
}
}
});
t_commandWriteRead.Start();
}
public void SetAlignOffset(double offset)
{
lock (_thisLock)
{
while (_lockCheck)
Monitor.Wait(_thisLock);
try
{
_lockCheck = true;
string str = WriteRead($"OFFSET {offset:3f}");
Thread.Sleep(waitTime);
}
catch (Exception e)
{
EquipmentLogManager.Instance.WriteExceptionLog(e.StackTrace);
}
finally
{
_lockCheck = false;
Monitor.Pulse(_thisLock);
}
}
}
//===================================================================
public new bool Write(string command)
{
string data = base.WriteRead(command + "\r");
if (data != string.Empty)
{
return true;
}
else
{
return false;
}
}
public new string WriteRead(string command)
{
string receivedData = string.Empty;
receivedData = base.WriteRead(command + "\r");
if (receivedData.StartsWith(command.Split(' ')[0]))
{
return receivedData;
}
else
{
if (receivedData.Contains("ERR"))
{
string errorCode = receivedData.Split(' ')[1].Replace("\r", "");
if (Enum.TryParse(errorCode, out error))
{
SetAlarmCode(error);
}
//Error 추가.
}
return "-1";
}
}
public bool WriteRead(string command, out string receivedData)
{
string data = base.WriteRead(command + '\r');
if (data.StartsWith(command.Split(' ')[0]))
{
receivedData = data.Remove(0, command.Split(' ')[0].Length).Replace("\r", "");
return true;
}
else
{
receivedData = string.Empty;
return false;
}
}
private void SetAlarmCode(ErrorCode errorCode)
{
EquipmentLogManager.Instance.WritePreAlignLog($"Error Code : {(int)errorCode} : {errorCode.ToString()}");
switch (errorCode)
{
case ErrorCode.PinUpError:
{
_equipment.alarmManager.Occur(AlarmCode.AL_0500_PREALIGNER_PIN_UP_ERROR);
break;
}
case ErrorCode.PinDownError:
{
_equipment.alarmManager.Occur(AlarmCode.AL_0501_PREALIGNER_PIN_DOWN_ERROR);
break;
}
case ErrorCode.VaccumError:
{
_equipment.alarmManager.Occur(AlarmCode.AL_0502_PREALIGNER_VACCUM_ERROR);
break;
}
case ErrorCode.NoWafer:
{
_equipment.alarmManager.Occur(AlarmCode.AL_0503_PREALIGNER_NO_WAFER);
break;
}
case ErrorCode.WaferLimitErrorAfterAlign:
{
_equipment.alarmManager.Occur(AlarmCode.AL_0504_PREALIGNER_WAFER_LIMIT_ERROR_AFTER_ALIGN);
break;
}
case ErrorCode.NotFoundNotch:
{
_equipment.alarmManager.Occur(AlarmCode.AL_0505_PREALIGNER_NOT_FOUND_NOTCH);
break;
}
case ErrorCode.StageLimitError:
{
_equipment.alarmManager.Occur(AlarmCode.AL_0506_PREALIGNER_STAGE_LIMIT_ERROR);
break;
}
case ErrorCode.InvalidAlignCommand:
{
_equipment.alarmManager.Occur(AlarmCode.AL_0507_PREALIGNER_INVALID_ALIGN_COMMAND);
break;
}
case ErrorCode.ChuckArrangeError:
{
_equipment.alarmManager.Occur(AlarmCode.AL_0508_PREALIGNER_CHUCK_ARRANGE_ERROR);
break;
}
case ErrorCode.WaferAlignCCDOver:
{
_equipment.alarmManager.Occur(AlarmCode.AL_0509_PREALIGNER_WAFER_ALIGN_CCD_OVER);
break;
}
case ErrorCode.WaferLimitErrorBeforeAlign:
{
_equipment.alarmManager.Occur(AlarmCode.AL_0510_PREALIGNER_WAFER_LIMIT_ERROR_BEFORE_ALIGN);
break;
}
case ErrorCode.RetractHome:
{
_equipment.alarmManager.Occur(AlarmCode.AL_0511_PREALIGNER_RETRACT_HOME);
break;
}
case ErrorCode.WaferExist:
{
_equipment.alarmManager.Occur(AlarmCode.AL_0512_PREALIGNER_WAFER_EXIST);
break;
}
case ErrorCode.CCDModuleError:
{
_equipment.alarmManager.Occur(AlarmCode.AL_0513_PREALIGNER_CCD_MODULE_ERROR);
break;
}
case ErrorCode.AlignerTypeError:
{
_equipment.alarmManager.Occur(AlarmCode.AL_0514_PREALIGNER_ALIGNER_TYPE_ERROR);
break;
}
case ErrorCode.CommandError:
{
_equipment.alarmManager.Occur(AlarmCode.AL_0515_PREALIGNER_COMMAND_ERROR);
break;
}
}
}
}
}