using System; using Aitex.Core.Common; using Aitex.Core.RT.Device; using Aitex.Core.RT.Event; using Aitex.Core.RT.Routine; using Aitex.Core.RT.SCCore; using Aitex.Sorter.Common; using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Robot; using MECF.Framework.Common.Equipment; using MECF.Framework.Common.SubstrateTrackings; using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.LoadPorts; using Aitex.Sorter.RT.SorterCommonFrame.Modules; using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Robots.RobotBase; using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Aligners.AlignersBase; using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Robots; using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.LoadPorts.LoadPortBase; using System.Threading; using Aitex.Core.RT.Log; using Aitex.Core.Util; using Aitex.Sorter.RT.SorterCommonFrame.SorterJobControl; using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Flipper.FlipperBase; namespace Aitex.Sorter.RT.SorterCommonFrame.Routines { public class EfemPickRoutine : CommonRoutineSorter, IRoutine { enum Pick { ReleaseAligner, QueryState, WaitLastMotion, WaitAlignerReady, TurnReady, WaitTurnReady, TurnTo0, WaitTurnTo0, CheckBeforePick, GoPickPosition, WaitGotoPos, PickWafer, WaitPick, UnGrip, WaitUngrip, RobotRetract, WaitRobotRetract, CheckAfterPick, TurnBack, WaitTurnBack, Finish, } private int _timeout = 0; public EfemPickRoutine(string module, string name) { Module = module; Name =name; } public bool Initalize() { Reset(); IsRoutineActive = false; return true; } public ModuleName Source { get; set; } public int Slot { get; set; } public Hand Blade { get; set; } public ModuleName RobotModulename { get; set; } = ModuleName.Robot; private bool _isNeedWaitTurnOverIdle; private bool _isNeedReleasePA; public Result Start(params object[] objs) { Reset(); Robot = DEVICE.GetDevice(RobotModulename.ToString()); Aligner = DEVICE.GetDevice(ModuleName.Aligner.ToString()); _timeout = Robot.RobotCommandTimeout; if (Blade == Hand.Blade1 || Blade == Hand.Blade2) { if (WaferManager.Instance.CheckHasWafer(RobotModulename, (int)Blade)) { EV.PostAlarmLog(ModuleName.System.ToString(), $"Can not {Name}, there's wafer on {Blade}."); return Result.FAIL; } } if (Blade == Hand.Both) { if (WaferManager.Instance.CheckHasWafer(RobotModulename, 0)) { EV.PostAlarmLog(ModuleName.System.ToString(), $"Can not {Name}, there's wafer on lower arm."); return Result.FAIL; } if (WaferManager.Instance.CheckHasWafer(RobotModulename, 1)) { EV.PostAlarmLog(ModuleName.System.ToString(), $"Can not {Name}, there's wafer on upper arm."); return Result.FAIL; } } FixedTurnOverPosition = SC.ContainsItem("Process.FixedTurnOverPosition") ? SC.GetValue("Process.FixedTurnOverPosition") : true; if (Source == ModuleName.TurnOverStation && !_ioTurnOver.IsPlacement) { EV.PostAlarmLog(ModuleName.System.ToString(), $"Can not {Name}, destination no wafer."); return Result.FAIL; } if (!ModuleHelper.IsTurnOverStation(Source) && Source != ModuleName.Aligner) { if (!RobotOffsetConfig.Instance.GetPickOffset(Source, ref _offsetX, ref _offsetY, ref _offsetZ, out string reason)) { EV.PostWarningLog(ModuleName.System.ToString(), $"Can not {Name}, {reason}"); return Result.FAIL; } } else { _offsetX = 0; _offsetY = 0; _offsetY = 0; } if(ModuleHelper.IsAligner(Source)) { if (!DEVICE.GetDevice(Source.ToString()).IsReady()) { EV.PostAlarmLog(ModuleName.System.ToString(), "Aligner is not ready"); return Result.FAIL; } _isNeedReleasePA = Aligner.IsNeedRelease; } if (ModuleHelper.IsLoadPort(Source)) { var lp = DEVICE.GetDevice(Source.ToString()); if(lp.IsForbidAccessSlotAboveWafer() && Slot>0 && WaferManager.Instance.CheckHasWafer(Source,Slot-1)) { EV.PostAlarmLog(ModuleName.System.ToString(), "Access dennied to the slot above wafer."); return Result.FAIL; } string reason; if(!lp.IsEnableTransferWafer(out reason)) { EV.PostAlarmLog(ModuleName.System.ToString(), $"{Source} is not ready to transfer wafer:{reason}."); return Result.FAIL; } var wafer = WaferManager.Instance.GetWafer(Source, Slot); if(ModuleHelper.IsLoadPort((ModuleName)wafer.DestinationStation)) { if(!Singleton.Instance.CheckCarrierAccessPermit(Source, (ModuleName)wafer.DestinationStation)) { EV.PostAlarmLog("System", $"Can't start pick routine: carrier access dennied."); return Result.FAIL; } } } if (ModuleHelper.IsTurnOverStation(Source) && !_ioTurnOver.IsReady) { _isNeedWaitTurnOverIdle = true; } else _isNeedWaitTurnOverIdle = false; if (ModuleHelper.IsTurnOverStation(Source)) { _isTurnOverOn0deg = _ioTurnOver.CurrentFlipperPosition == FlipperPosEnum.FrontSide; } EV.PostInfoLog("System",$"Start picking wafer from station:{Source} slot:{Slot+1} with blade {Blade}"); IsRoutineActive = true; return Monitor(); } private bool _isTurnOverOn0deg; public Result Monitor() { if (!IsRoutineActive) return Result.DONE; var ret = MonitorRoutine(); if (ret == Result.FAIL) { Initalize(); IsRoutineActive = false; } if (ret == Result.DONE) { IsRoutineActive = false; } return ret; } private Result MonitorRoutine() { try { if (!ModuleHelper.IsTurnOverStation(Source)) { if (ModuleHelper.IsAligner(Source) && _isNeedReleasePA) { RtReleaseAligner((int)Pick.ReleaseAligner, Notify, Stop); if (ExecuteResult.Item1) { if (ExecuteResult.Item2 == Result.RUN) return Result.RUN; if (ExecuteResult.Item2 == Result.FAIL) return Result.FAIL; if (ExecuteResult.Item2 == Result.TIMEOUT) return Result.FAIL; if (ExecuteResult.Item2 == Result.DONE) return Result.RUN; } RtWaitAlignerMotion((int)Pick.WaitAlignerReady, Aligner, "Wait Aligner Ready", _timeout, Notify, Stop); if (ExecuteResult.Item1) { if (ExecuteResult.Item2 == Result.RUN) return Result.RUN; if (ExecuteResult.Item2 == Result.FAIL) return Result.FAIL; if (ExecuteResult.Item2 == Result.TIMEOUT) return Result.FAIL; if (ExecuteResult.Item2 == Result.DONE) return Result.RUN; } } RtPickWafer((int)Pick.PickWafer, "Start pick wafer", Source, Slot, Blade, _timeout, _offsetX, _offsetY, _offsetZ, Notify, Stop); if (ExecuteResult.Item1) { if (ExecuteResult.Item2 == Result.RUN) return Result.RUN; if (ExecuteResult.Item2 == Result.FAIL) return Result.FAIL; if (ExecuteResult.Item2 == Result.TIMEOUT) return Result.FAIL; if (ExecuteResult.Item2 == Result.DONE) return Result.RUN; } } else { if (_isNeedWaitTurnOverIdle) { RtWaitTurnOverMotion((int)Pick.WaitTurnReady, _ioTurnOver, _ioTurnOver.TimelimitAction, Notify, Stop); if (ExecuteResult.Item1) { if (ExecuteResult.Item2 == Result.RUN) return Result.RUN; if (ExecuteResult.Item2 == Result.FAIL) return Result.FAIL; if (ExecuteResult.Item2 == Result.TIMEOUT) return Result.FAIL; if (ExecuteResult.Item2 == Result.DONE) return Result.RUN; } } if (FixedTurnOverPosition) { if (_isTurnOverOn0deg) { RtTurnOverTurn((int)Pick.TurnTo0, Notify, Stop); if (ExecuteResult.Item1) { if (ExecuteResult.Item2 == Result.RUN) return Result.RUN; if (ExecuteResult.Item2 == Result.FAIL) return Result.FAIL; if (ExecuteResult.Item2 == Result.TIMEOUT) return Result.FAIL; if (ExecuteResult.Item2 == Result.DONE) return Result.RUN; } RtWaitTurnOverTurnTo180((int)Pick.WaitTurnTo0, _ioTurnOver, _ioTurnOver.TimelimitAction, Notify, Stop); if (ExecuteResult.Item1) { if (ExecuteResult.Item2 == Result.RUN) return Result.RUN; if (ExecuteResult.Item2 == Result.FAIL) return Result.FAIL; if (ExecuteResult.Item2 == Result.TIMEOUT) return Result.FAIL; if (ExecuteResult.Item2 == Result.DONE) return Result.RUN; } } RtRobotArmGoReadyForPickFromTurnOver((int)Pick.GoPickPosition, Source, Slot, Blade, _timeout, Notify, Stop, GetWaferOffsetForTurnOverOn180()); if (ExecuteResult.Item1) { if (ExecuteResult.Item2 == Result.RUN) return Result.RUN; if (ExecuteResult.Item2 == Result.FAIL) return Result.FAIL; if (ExecuteResult.Item2 == Result.TIMEOUT) return Result.FAIL; if (ExecuteResult.Item2 == Result.DONE) return Result.RUN; } RtTurnOverUnGripWafer((int)Pick.UnGrip, Notify, Stop); if (ExecuteResult.Item1) { if (ExecuteResult.Item2 == Result.RUN) return Result.RUN; if (ExecuteResult.Item2 == Result.FAIL) return Result.FAIL; if (ExecuteResult.Item2 == Result.TIMEOUT) return Result.FAIL; if (ExecuteResult.Item2 == Result.DONE) return Result.RUN; } RtWaitTurnOverUnGrip((int)Pick.WaitUngrip, _ioTurnOver, _ioTurnOver.TimelimitAction, Notify, Stop); if (ExecuteResult.Item1) { if (ExecuteResult.Item2 == Result.RUN) return Result.RUN; if (ExecuteResult.Item2 == Result.FAIL) return Result.FAIL; if (ExecuteResult.Item2 == Result.TIMEOUT) return Result.FAIL; if (ExecuteResult.Item2 == Result.DONE) return Result.RUN; } RtPickWaferFromTurnOver((int)Pick.RobotRetract, Source, Slot, Blade, _timeout, Notify, Stop, GetWaferOffsetForTurnOverOn180()); if (ExecuteResult.Item1) { if (ExecuteResult.Item2 == Result.RUN) return Result.RUN; if (ExecuteResult.Item2 == Result.FAIL) return Result.FAIL; if (ExecuteResult.Item2 == Result.TIMEOUT) return Result.FAIL; if (ExecuteResult.Item2 == Result.DONE) return Result.RUN; } RtTurnOverTurnBack((int)Pick.TurnBack, Notify, Stop); if (ExecuteResult.Item1) { if (ExecuteResult.Item2 == Result.RUN) return Result.RUN; if (ExecuteResult.Item2 == Result.FAIL) return Result.FAIL; if (ExecuteResult.Item2 == Result.TIMEOUT) return Result.FAIL; if (ExecuteResult.Item2 == Result.DONE) return Result.RUN; } } else { if (_isTurnOverOn0deg) { RtRobotArmGoReadyForPickFromTurnOver((int)Pick.GoPickPosition, Source, Slot, Blade, _timeout, Notify, Stop); if (ExecuteResult.Item1) { if (ExecuteResult.Item2 == Result.RUN) return Result.RUN; if (ExecuteResult.Item2 == Result.FAIL) return Result.FAIL; if (ExecuteResult.Item2 == Result.TIMEOUT) return Result.FAIL; if (ExecuteResult.Item2 == Result.DONE) return Result.RUN; } RtTurnOverUnGripWafer((int)Pick.UnGrip, Notify, Stop); if (ExecuteResult.Item1) { if (ExecuteResult.Item2 == Result.RUN) return Result.RUN; if (ExecuteResult.Item2 == Result.FAIL) return Result.FAIL; if (ExecuteResult.Item2 == Result.TIMEOUT) return Result.FAIL; if (ExecuteResult.Item2 == Result.DONE) return Result.RUN; } RtWaitTurnOverUnGrip((int)Pick.WaitUngrip, _ioTurnOver, _ioTurnOver.TimelimitAction, Notify, Stop); if (ExecuteResult.Item1) { if (ExecuteResult.Item2 == Result.RUN) return Result.RUN; if (ExecuteResult.Item2 == Result.FAIL) return Result.FAIL; if (ExecuteResult.Item2 == Result.TIMEOUT) return Result.FAIL; if (ExecuteResult.Item2 == Result.DONE) return Result.RUN; } RtPickWaferFromTurnOver((int)Pick.RobotRetract, Source, Slot, Blade, _timeout, Notify, Stop); if (ExecuteResult.Item1) { if (ExecuteResult.Item2 == Result.RUN) return Result.RUN; if (ExecuteResult.Item2 == Result.FAIL) return Result.FAIL; if (ExecuteResult.Item2 == Result.TIMEOUT) return Result.FAIL; if (ExecuteResult.Item2 == Result.DONE) return Result.RUN; } } else { RtRobotArmGoReadyForPickFromTurnOver((int)Pick.GoPickPosition, Source, Slot, Blade, _timeout, Notify, Stop, GetWaferOffsetForTurnOverOn180()); if (ExecuteResult.Item1) { if (ExecuteResult.Item2 == Result.RUN) return Result.RUN; if (ExecuteResult.Item2 == Result.FAIL) return Result.FAIL; if (ExecuteResult.Item2 == Result.TIMEOUT) return Result.FAIL; if (ExecuteResult.Item2 == Result.DONE) return Result.RUN; } RtTurnOverUnGripWafer((int)Pick.UnGrip, Notify, Stop); if (ExecuteResult.Item1) { if (ExecuteResult.Item2 == Result.RUN) return Result.RUN; if (ExecuteResult.Item2 == Result.FAIL) return Result.FAIL; if (ExecuteResult.Item2 == Result.TIMEOUT) return Result.FAIL; if (ExecuteResult.Item2 == Result.DONE) return Result.RUN; } RtWaitTurnOverUnGrip((int)Pick.WaitUngrip, _ioTurnOver, _ioTurnOver.TimelimitAction, Notify, Stop); if (ExecuteResult.Item1) { if (ExecuteResult.Item2 == Result.RUN) return Result.RUN; if (ExecuteResult.Item2 == Result.FAIL) return Result.FAIL; if (ExecuteResult.Item2 == Result.TIMEOUT) return Result.FAIL; if (ExecuteResult.Item2 == Result.DONE) return Result.RUN; } RtPickWaferFromTurnOver((int)Pick.RobotRetract, Source, Slot, Blade, _timeout, Notify, Stop, GetWaferOffsetForTurnOverOn180()); if (ExecuteResult.Item1) { if (ExecuteResult.Item2 == Result.RUN) return Result.RUN; if (ExecuteResult.Item2 == Result.FAIL) return Result.FAIL; if (ExecuteResult.Item2 == Result.TIMEOUT) return Result.FAIL; if (ExecuteResult.Item2 == Result.DONE) return Result.RUN; } } } } RtUpdateWaferSingleStepProcessState((int)Pick.Finish, "Update wafer single step process state", RobotModulename, 0, Blade, EnumWaferProcessStatus.Idle, Notify, Stop); if (ExecuteResult.Item1) { if (ExecuteResult.Item2 == Result.RUN) return Result.RUN; if (ExecuteResult.Item2 == Result.FAIL) return Result.FAIL; if (ExecuteResult.Item2 == Result.TIMEOUT) return Result.FAIL; if (ExecuteResult.Item2 == Result.DONE) return Result.DONE; } EV.PostInfoLog("System", $"Complete picking wafer from station:{Source} slot:{Slot + 1} with blade {Blade}."); IsRoutineActive = false; return Result.DONE; } catch (Exception ex) { EV.PostAlarmLog("System", $"Failed to pick wafer from station:{Source} slot:{Slot + 1} with blade {Blade}."); LOG.Write(ex); IsRoutineActive = false; return Result.FAIL; } } } }