using System; using System.Collections.Generic; using System.IO.Ports; using System.Linq; using System.Text; using Aitex.Core.Common.DeviceData; using Aitex.Core.RT.Device; using Aitex.Core.RT.Device.Unit; using Aitex.Core.RT.Event; using Aitex.Core.RT.Log; using Aitex.Core.RT.OperationCenter; using Aitex.Core.RT.SCCore; using Aitex.Core.Util; using MECF.Framework.Common.Communications; using MECF.Framework.Common.Device.Bases; using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Common; using Newtonsoft.Json; using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Robots.RobotBase; using MECF.Framework.Common.Equipment; using MECF.Framework.Common.SubstrateTrackings; using System.Threading; using Aitex.Core.Common; using Aitex.Core.RT.DataCenter; using System.Text.RegularExpressions; using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Aligners.AlignersBase; using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Robots.JEL; using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Robots; namespace MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Aligners.JelAligner { public class JelAlignerWithOcrCylinder : JelAligner, IConnection { /* SAL3262HV model: for 2-inch to 6-inch wafer SAL3362HV model: for 3-inch to 6-inch wafer SAL3482HV model: for 4-inch to 8-inch wafer SAL38C3HV model: for 8-inch to 12-inch wafer*/ public JelAlignerWithOcrCylinder(string module, string name, string scRoot, IoSensor[] dis, IoTrigger[] dos,WaferSize[] sizes, int alignerType = 0, string robotModel = "") : base(module, name,scRoot,null,null,alignerType,robotModel) { isSimulatorMode = SC.ContainsItem("System.IsSimulatorMode") ? SC.GetValue("System.IsSimulatorMode") : false; _robotModel = robotModel; _scRoot = scRoot; _diWaferPresent = dis[0]; _diOcrOnWaferSize1 = dis[1]; _diOcrOnWaferSize2 = dis[2]; _doOcrToWaferSize1 = dos[0]; _doOcrToWaferSize2 = dos[1]; _size1 = sizes[0]; _size2 = sizes[1]; DEVICE.Register(String.Format("{0}.{1}", Name, "OcrMoveTo6Inch"), (out string reason, int time, object[] param) => { _doOcrToWaferSize1.SetTrigger(true,out _); _doOcrToWaferSize2.SetTrigger(false, out _); reason = string.Format("{0} {1}", Name, "MoveTo6Inch"); return true; }); DEVICE.Register(String.Format("{0}.{1}", Name, "OcrMoveTo8Inch"), (out string reason, int time, object[] param) => { _doOcrToWaferSize1.SetTrigger(false, out _); _doOcrToWaferSize2.SetTrigger(true, out _); reason = string.Format("{0} {1}", Name, "MoveTo8Inch"); return true; }); } private IoSensor _diOcrOnWaferSize1; private IoSensor _diOcrOnWaferSize2; private IoTrigger _doOcrToWaferSize1; private IoTrigger _doOcrToWaferSize2; private IoSensor _diWaferPresent; private WaferSize _size1; private WaferSize _size2; public override bool OnTimer() { try { if (!_connection.IsConnected || _connection.IsCommunicationError) { lock (_locker) { _lstMoveHandler.Clear(); } _trigRetryConnect.CLK = !_connection.IsConnected; if (_trigRetryConnect.Q) { _connection.SetPortAddress(SC.GetStringValue($"{_scRoot}.{Name}.PortName")); if (!_connection.Connect()) { EV.PostAlarmLog(Module, $"Can not connect with {_connection.Address}, {Module}.{Name}"); } else { } } return true; } HandlerBase handler = null; DateTime dtstart = DateTime.Now; lock (_locker) { while (_lstMoveHandler.Count > 0 && _lstMonitorHandler.Count == 0) { if (!_connection.IsBusy) { if (YAxisAndThetaAxisStatus == JelAxisStatus.NormalEnd && XAxisStatus == JelAxisStatus.NormalEnd) { handler = _lstMoveHandler.First.Value; _connection.Execute(handler); _lstMoveHandler.RemoveFirst(); } else { _connection.Execute(new JelAlignerReadHandler(this, "")); } } else { _connection.MonitorTimeout(); _trigCommunicationError.CLK = _connection.IsCommunicationError; if (_trigCommunicationError.Q) { _lstMoveHandler.Clear(); OnError($"{Module}.{Name} communication error, {_connection.LastCommunicationError}"); } } if (DateTime.Now - dtstart > TimeSpan.FromSeconds(150)) { _lstMonitorHandler.Clear(); _lstMoveHandler.Clear(); OnError("Robot action timeout"); } } while (_lstMonitorHandler.Count > 0) { if (!_connection.IsBusy) { handler = _lstMonitorHandler.First.Value; _connection.Execute(handler); _lstMonitorHandler.RemoveFirst(); } if (DateTime.Now - dtstart > TimeSpan.FromSeconds(150)) { _lstMonitorHandler.Clear(); _lstMoveHandler.Clear(); OnError("Robot action timeout"); } } } } catch (Exception ex) { LOG.Write(ex); } return true; } private int _bodyNumber; private string _robotModel; //T-00902H //public int BodyNumber { get => _bodyNumber; } private string _address = ""; //public string Address { get => _address; } private bool isSimulatorMode; private string _scRoot; private PeriodicJob _thread; //protected JelAlignerConnection _connection; private R_TRIG _trigError = new R_TRIG(); private R_TRIG _trigCommunicationError = new R_TRIG(); private R_TRIG _trigRetryConnect = new R_TRIG(); private R_TRIG _trigActionDone = new R_TRIG(); private LinkedList _lstMoveHandler = new LinkedList(); private LinkedList _lstMonitorHandler = new LinkedList(); private bool _isAligned; private bool _isOnHomedPostion; //public int TimelimitAlginerHome { get; private set; } //public int TimelimitForAlignWafer { get; private set; } private object _locker = new object(); private bool _enableLog; #region ParseHandler #endregion public override bool IsNeedChangeWaferSize(WaferSize wz) { return wz != GetCurrentWaferSize(); } protected override bool fReset(object[] param) { if (!_connection.IsConnected) { _enableLog = SC.GetValue($"{_scRoot}.{Name}.EnableLogMessage"); _bodyNumber = SC.GetValue($"{_scRoot}.{Name}.BodyNumber"); PortName = SC.GetStringValue($"{_scRoot}.{Name}.PortName"); //TimelimitAlginerHome = SC.GetValue($"{_scRoot}.{Name}.TimeLimitAlignerHome"); //TimelimitForAlignWafer = SC.GetValue($"{_scRoot}.{Name}.TimeLimitForAlignWafer"); _connection = new JelAlignerConnection(PortName); if (_connection.Connect()) { EV.PostInfoLog(Module, $"{Module}.{Name} connected"); } } _trigError.RST = true; _connection.SetCommunicationError(false, ""); _trigCommunicationError.RST = true; _enableLog = SC.GetValue($"{_scRoot}.{Name}.EnableLogMessage"); _connection.EnableLog(_enableLog); _trigRetryConnect.RST = true; _lstMoveHandler.Clear(); _lstMonitorHandler.Clear(); _connection.ForceClear(); lock (_locker) { _lstMonitorHandler.AddLast(new JelAlignerRawCommandHandler(this, $"${BodyNumber}RD\r")); _lstMonitorHandler.AddLast(new JelAlignerReadHandler(this, "")); _lstMonitorHandler.AddLast(new JelAlignerReadHandler(this, "WIS1")); } return true; } protected override bool fMonitorReset(object[] param) { _isAligned = false; return true; } protected override bool fStartInit(object[] param) { lock (_locker) { int alignspeed = AlginerSpeedSetPoint * 8191 / 100; _lstMoveHandler.AddLast(new JelAlignerMoveHandler(this, "W0")); _lstMoveHandler.AddLast(new JelAlignerReadHandler(this, "")); _lstMoveHandler.AddLast(new JelAlignerSetHandler(this, "WSP", alignspeed.ToString())); _lstMoveHandler.AddLast(new JelAlignerMoveHandler(this, "WU")); _lstMoveHandler.AddLast(new JelAlignerReadHandler(this, "")); _lstMoveHandler.AddLast(new JelAlignerMoveHandler(this, "WUC")); _lstMoveHandler.AddLast(new JelAlignerReadHandler(this, "")); _lstMoveHandler.AddLast(new JelAlignerMoveHandler(this, "WT")); _lstMoveHandler.AddLast(new JelAlignerReadHandler(this, "")); } _isAligned = false; _isOnHomedPostion = false; _dtActionStart = DateTime.Now; return true; } public override WaferSize GetCurrentWaferSize() { if (!_diOcrOnWaferSize1.Value && _diOcrOnWaferSize2.Value && _doOcrToWaferSize1.Value && !_doOcrToWaferSize2.Value) return _size1; if (_diOcrOnWaferSize1.Value && !_diOcrOnWaferSize2.Value && !_doOcrToWaferSize1.Value && _doOcrToWaferSize2.Value) return _size2; return WaferSize.WS0; } private DateTime _dtActionStart; protected override bool fMonitorInit(object[] param) { _isAligned = false; if (DateTime.Now - _dtActionStart > TimeSpan.FromSeconds((double)TimelimitAlginerHome)) OnError("Init timeout"); if (_lstMoveHandler.Count == 0 && !_connection.IsBusy && XAxisStatus == JelAxisStatus.NormalEnd && YAxisAndThetaAxisStatus == JelAxisStatus.NormalEnd) { IsBusy = false; _isOnHomedPostion = true; if (IsWaferPresent(0) && WaferManager.Instance.CheckNoWafer(RobotModuleName, 0)) { WaferManager.Instance.CreateWafer(RobotModuleName, 0, WaferStatus.Normal, GetCurrentWaferSize()); } if (!IsWaferPresent(0) && WaferManager.Instance.CheckHasWafer(RobotModuleName, 0)) { EV.PostAlarmLog("System", $"There's no phisical wafer on {RobotModuleName},but it has wafer information on."); //WaferManager.Instance.DeleteWafer(RobotModuleName, 0); } return true; } if (_lstMoveHandler.Count == 0 && !_connection.IsBusy) _connection.Execute(new JelAlignerReadHandler(this, "")); return false; } protected override bool fStartHome(object[] param) { lock (_locker) { int alignspeed = AlginerSpeedSetPoint * 8191 / 100; _lstMoveHandler.AddLast(new JelAlignerMoveHandler(this, "W0")); _lstMoveHandler.AddLast(new JelAlignerReadHandler(this, "")); _lstMoveHandler.AddLast(new JelAlignerSetHandler(this, "WSP", alignspeed.ToString())); _lstMoveHandler.AddLast(new JelAlignerMoveHandler(this, "WU")); _lstMoveHandler.AddLast(new JelAlignerReadHandler(this, "")); _lstMoveHandler.AddLast(new JelAlignerMoveHandler(this, "WUC")); _lstMoveHandler.AddLast(new JelAlignerReadHandler(this, "")); _lstMoveHandler.AddLast(new JelAlignerMoveHandler(this, "WT")); _lstMoveHandler.AddLast(new JelAlignerReadHandler(this, "")); } _isAligned = false; _dtActionStart = DateTime.Now; return true; } protected override bool fMonitorHome(object[] param) { if (DateTime.Now - _dtActionStart > TimeSpan.FromSeconds((double)TimelimitAlginerHome)) OnError("Home timeout"); if (_lstMoveHandler.Count == 0 && !_connection.IsBusy && XAxisStatus == JelAxisStatus.NormalEnd && YAxisAndThetaAxisStatus == JelAxisStatus.NormalEnd) { IsBusy = false; _isOnHomedPostion = true; return true; } if (_lstMoveHandler.Count == 0 && !_connection.IsBusy) _connection.Execute(new JelAlignerReadHandler(this, "")); return false; } public override bool IsReady() { return AlignerState == AlignerStateEnum.Idle && !IsBusy; } public override bool IsWaferPresent(int slotindex) { if (_diWaferPresent != null) return _diWaferPresent.Value; return WaferManager.Instance.CheckHasWafer(RobotModuleName, slotindex); } public override bool IsNeedPrepareBeforePlaceWafer() { return !_isOnHomedPostion; } protected override bool fStartLiftup(object[] param) //Ungrip { _dtActionStart = DateTime.Now; lock (_locker) { _lstMoveHandler.AddLast(new JelAlignerMoveHandler(this, "WU")); _lstMoveHandler.AddLast(new JelAlignerReadHandler(this, "")); } return true; } protected override bool fMonitorLiftup(object[] param) { if (DateTime.Now - _dtActionStart > TimeSpan.FromSeconds(TimelimitForAlignWafer)) OnError("Aligner lift up timeout"); if (_lstMoveHandler.Count == 0 && !_connection.IsBusy && XAxisStatus == JelAxisStatus.NormalEnd && YAxisAndThetaAxisStatus == JelAxisStatus.NormalEnd) { IsBusy = false; _isAligned = false; _isOnHomedPostion = false; return true; } if (_lstMoveHandler.Count == 0 && !_connection.IsBusy) _connection.Execute(new JelAlignerReadHandler(this, "")); return false; } protected override bool fStartLiftdown(object[] param) { _dtActionStart = DateTime.Now; lock (_locker) { _lstMoveHandler.AddLast(new JelAlignerMoveHandler(this, "WD")); _lstMoveHandler.AddLast(new JelAlignerReadHandler(this, "")); } return true; } protected override bool fMonitorLiftdown(object[] param) { if (DateTime.Now - _dtActionStart > TimeSpan.FromSeconds(TimelimitForAlignWafer)) OnError("Aligner lift down timeout"); if (_lstMoveHandler.Count == 0 && !_connection.IsBusy && XAxisStatus == JelAxisStatus.NormalEnd && YAxisAndThetaAxisStatus == JelAxisStatus.NormalEnd) { IsBusy = false; _isAligned = true; _isOnHomedPostion = false; return true; } if (_lstMoveHandler.Count == 0 && !_connection.IsBusy) _connection.Execute(new JelAlignerReadHandler(this, "")); return false; } protected override bool fStartAlign(object[] param) { //WaferSize wz = WaferManager.Instance.GetWaferSize(RobotModuleName, 0); //if (wz != GetCurrentWaferSize()) //{ // EV.PostAlarmLog("System", "Wafer size is not match, can't do alignment"); // return false; //} _isOnHomedPostion = false; double aligneangle = (double)param[0]; while (aligneangle < 0 || aligneangle > 360) { if (aligneangle < 0) aligneangle += 360; if (aligneangle > 360) aligneangle -= 360; } //int speed = SC.GetValue($"{_scRoot}.{Name}.AlignSpeed"); int intangle = (int)(aligneangle * 76799 / 360); CurrentNotch = aligneangle; lock (_locker) { _lstMoveHandler.AddLast(new JelAlignerMoveHandler(this, "WC")); //Close grip _lstMoveHandler.AddLast(new JelAlignerReadHandler(this, "")); _lstMoveHandler.AddLast(new JelAlignerMoveHandler(this, "WD")); //Align _lstMoveHandler.AddLast(new JelAlignerReadHandler(this, "")); //_lstMoveHandler.AddLast(new JelAlignerMoveHandler(this, "WA")); //Move down //_lstMoveHandler.AddLast(new JelAlignerReadHandler(this, "")); _lstMoveHandler.AddLast(new JelAlignerSetHandler(this, "WOP", intangle.ToString())); _lstMoveHandler.AddLast(new JelAlignerMoveHandler(this, "WOF")); _lstMoveHandler.AddLast(new JelAlignerReadHandler(this, "")); _lstMoveHandler.AddLast(new JelAlignerMoveHandler(this, "WU")); //Move Up _lstMoveHandler.AddLast(new JelAlignerReadHandler(this, "")); _lstMoveHandler.AddLast(new JelAlignerMoveHandler(this, "WUC")); //Ungrip _lstMoveHandler.AddLast(new JelAlignerReadHandler(this, "")); _lstMoveHandler.AddLast(new JelAlignerMoveHandler(this, "WT")); _lstMoveHandler.AddLast(new JelAlignerReadHandler(this, "")); } _dtActionStart = DateTime.Now; return true; } protected override bool fMonitorAligning(object[] param) { if (DateTime.Now - _dtActionStart > TimeSpan.FromSeconds(TimelimitForAlignWafer)) OnError("Alignment timeout"); if (_lstMoveHandler.Count == 0 && !_connection.IsBusy && XAxisStatus == JelAxisStatus.NormalEnd && YAxisAndThetaAxisStatus == JelAxisStatus.NormalEnd) { IsBusy = false; _isOnHomedPostion = true; return true; } if (_lstMoveHandler.Count == 0 && !_connection.IsBusy) _connection.Execute(new JelAlignerReadHandler(this, "")); return false; } protected override bool fStop(object[] param) { return true; } protected override bool FsmAbort(object[] param) { return true; } protected override bool fClear(object[] param) { return true; } protected override bool fStartReadData(object[] param) { return true; } protected override bool fStartSetParameters(object[] param) { _dtActionStart = DateTime.Now; _currentSetParameter = param[0].ToString(); switch (_currentSetParameter) { case "WaferSize": if (GetWaferState() != RobotArmWaferStateEnum.Absent) { EV.PostAlarmLog("System", "Can't set wafersize when wafer is not absent"); return false; } _currentSetWaferSize = (WaferSize)param[1]; if (WaferManager.Instance.CheckHasWafer(RobotModuleName, 0)) { WaferManager.Instance.UpdateWaferSize(RobotModuleName, 0, _currentSetWaferSize); } string strpara; switch (_currentSetWaferSize) { case WaferSize.WS2: case WaferSize.WS3: case WaferSize.WS4: case WaferSize.WS5: case WaferSize.WS6: case WaferSize.WS8: strpara = _currentSetWaferSize.ToString().Replace("WS", ""); break; case WaferSize.WS12: strpara = "9"; break; default: return false; } if(_currentSetWaferSize == _size1) { _doOcrToWaferSize1.SetTrigger(true, out _); _doOcrToWaferSize2.SetTrigger(false, out _); } if (_currentSetWaferSize == _size2) { _doOcrToWaferSize2.SetTrigger(true, out _); _doOcrToWaferSize1.SetTrigger(false, out _); } lock (_locker) { _lstMonitorHandler.AddLast(new JelAlignerMoveHandler(this, "WAS", strpara)); _lstMonitorHandler.AddLast(new JelAlignerReadHandler(this, "WAS")); } break; } return true; } private string _currentSetParameter; private WaferSize _currentSetWaferSize = WaferSize.WS0; protected override bool fMonitorSetParamter(object[] param) { IsBusy = false; if (DateTime.Now - _dtActionStart > TimeSpan.FromSeconds(TimelimitForAlignWafer)) OnError("Set parameter timeout"); switch (_currentSetParameter) { case "WaferSize": if (_lstMonitorHandler.Count == 0 && _lstMoveHandler.Count == 0 && !_connection.IsBusy) { if (_currentSetWaferSize != Size) { OnError($"Fail to set wafer size,set:{_currentSetWaferSize},return:{Size}"); } if(_currentSetWaferSize != GetCurrentWaferSize()) { return false; } return true; } break; } return false; } protected override bool fStartUnGrip(object[] param) { lock (_locker) { _lstMoveHandler.AddLast(new JelAlignerMoveHandler(this, "WDF")); _lstMoveHandler.AddLast(new JelAlignerReadHandler(this, "")); } _diStartUngrip = DateTime.Now; return true; } private DateTime _diStartUngrip; protected override bool fMonitorUnGrip(object[] param) { if (DateTime.Now - _diStartUngrip > TimeSpan.FromSeconds(10)) OnError("UnGrip timeout"); if (_lstMoveHandler.Count == 0 && !_connection.IsBusy && XAxisStatus == JelAxisStatus.NormalEnd && YAxisAndThetaAxisStatus == JelAxisStatus.NormalEnd) { IsBusy = false; return true; } if (_lstMoveHandler.Count == 0 && !_connection.IsBusy) _connection.Execute(new JelAlignerReadHandler(this, "")); return false; } protected override bool fStartGrip(object[] param) { lock (_locker) { _lstMoveHandler.AddLast(new JelAlignerMoveHandler(this, "WUC")); _lstMoveHandler.AddLast(new JelAlignerReadHandler(this, "")); } _diStartUngrip = DateTime.Now; return true; } protected override bool fMonitorGrip(object[] param) { if (DateTime.Now - _diStartUngrip > TimeSpan.FromSeconds(10)) OnError("Grip timeout"); if (_lstMoveHandler.Count == 0 && !_connection.IsBusy) { if (XAxisStatus == JelAxisStatus.NormalEnd && YAxisAndThetaAxisStatus == JelAxisStatus.NormalEnd) { IsBusy = false; return true; } else { _connection.Execute(new JelAlignerReadHandler(this, "")); } } return false; } protected override bool fResetToReady(object[] param) { return true; } protected override bool fError(object[] param) { return true; } public override void OnError(string errortext) { _isAligned = false; _isOnHomedPostion = false; _lstMonitorHandler.Clear(); _lstMoveHandler.Clear(); base.OnError(errortext); } public override bool IsNeedRelease { get => !_isOnHomedPostion; } protected override bool fStartPrepareAccept(object[] param) { _dtActionStart = DateTime.Now; lock (_locker) { _lstMoveHandler.AddLast(new JelAlignerMoveHandler(this, "WU")); _lstMoveHandler.AddLast(new JelAlignerReadHandler(this, "")); _lstMoveHandler.AddLast(new JelAlignerMoveHandler(this, "WUC")); _lstMoveHandler.AddLast(new JelAlignerReadHandler(this, "")); _lstMoveHandler.AddLast(new JelAlignerMoveHandler(this, "WT")); _lstMoveHandler.AddLast(new JelAlignerReadHandler(this, "")); } return true; } protected override bool fMonitorPrepareAccept(object[] param) { if (DateTime.Now - _dtActionStart > TimeSpan.FromSeconds((double)TimelimitAlginerHome)) OnError("Home timeout"); if (_lstMoveHandler.Count == 0 && !_connection.IsBusy && XAxisStatus == JelAxisStatus.NormalEnd && YAxisAndThetaAxisStatus == JelAxisStatus.NormalEnd) { IsBusy = false; _isAligned = false; _isOnHomedPostion = true; return true; } if (_lstMoveHandler.Count == 0 && !_connection.IsBusy) _connection.Execute(new JelAlignerReadHandler(this, "")); return false; } } }