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 EfemTransferRoutine : CommonRoutineSorter, IRoutine { enum Transfer { ReleaseAligner, QueryState, WaitLastMotion, WaitAlignerReady, TurnReady, WaitTurnReady, TurnTo0, WaitTurnTo0, CheckBeforePick, GoPickPosition, WaitGotoPos, PickWafer, WaitPick, UnGrip, WaitUngrip, RobotRetract, WaitRobotRetract, CheckAfterPick, TurnBack, WaitTurnBack, PlaceSetAlignerWaferSize, PlaceRaiseAligner, PlaceWafer, Finish, } private int _timeout = 0; public EfemTransferRoutine(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 ModuleName Destination { get; set; } public int DestSlot { get; set; } public Hand PickBlade { get; set; } public Hand PlaceBlade { get; set; } private WaferSize _currentWaferSize; public ModuleName RobotModulename { get; set; } = ModuleName.Robot; private bool _isNeedWaitTurnOverIdle; private bool _isNeedReleasePA; private bool _isNeedToCheckAlginerWaferSize; private bool _isNeedAlignerPrepare; public Result Start(params object[] objs) { Reset(); Robot = DEVICE.GetDevice(RobotModulename.ToString()); Aligner = DEVICE.GetDevice(ModuleName.Aligner.ToString()); _timeout = Robot.RobotCommandTimeout; if (PickBlade == Hand.Blade1 || PickBlade == Hand.Blade2) { if (WaferManager.Instance.CheckHasWafer(RobotModulename, (int)PickBlade)) { EV.PostAlarmLog(ModuleName.System.ToString(), $"Can not {Name}, there's wafer on {PickBlade}."); return Result.FAIL; } } if (PickBlade == 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; } } if(PickBlade != PlaceBlade) { if (PlaceBlade == Hand.Blade1 || PlaceBlade == Hand.Blade2) { if (!WaferManager.Instance.CheckHasWafer(RobotModulename, (int)PlaceBlade)) { EV.PostAlarmLog(ModuleName.System.ToString(), $"Can not {Name}, there's no wafer on {PlaceBlade}."); 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; } if (ModuleHelper.IsAligner(Destination)) { if (!DEVICE.GetDevice(Destination.ToString()).IsReady()) { EV.PostAlarmLog(Destination.ToString(), $"{Destination} is not ready."); return Result.FAIL; } if (DEVICE.GetDevice(Destination.ToString()).IsWaferPresent(0)) { EV.PostAlarmLog(Destination.ToString(), $"{Destination} wafer present."); return Result.FAIL; } _isNeedAlignerPrepare = Aligner.IsNeedPrepareBeforePlaceWafer(); _currentWaferSize = WaferManager.Instance.GetWaferSize(Source, Slot); _isNeedToCheckAlginerWaferSize = Aligner.IsNeedChangeWaferSize(_currentWaferSize); } EV.PostInfoLog("System",$"Start transfer wafer from station:{Source} slot:{Slot+1} to {Destination} slot:{DestSlot+1} with pickk blade:{PickBlade} and place blade:{PlaceBlade}"); 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)Transfer.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)Transfer.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)Transfer.PickWafer, "Start pick wafer", Source, Slot, PickBlade, _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)Transfer.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)Transfer.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)Transfer.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)Transfer.GoPickPosition, Source, Slot, PickBlade, _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)Transfer.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)Transfer.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)Transfer.RobotRetract, Source, Slot, PickBlade, _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)Transfer.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)Transfer.GoPickPosition, Source, Slot, PickBlade, _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)Transfer.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)Transfer.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)Transfer.RobotRetract, Source, Slot, PickBlade, _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)Transfer.GoPickPosition, Source, Slot, PickBlade, _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)Transfer.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)Transfer.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)Transfer.RobotRetract, Source, Slot, PickBlade, _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; } } } } if (ModuleHelper.IsAligner(Destination) && _isNeedToCheckAlginerWaferSize) { RtAlignerSetWaferSize((int)Transfer.PlaceSetAlignerWaferSize, _currentWaferSize, _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.DONE; } } if (ModuleHelper.IsAligner(Destination) && _isNeedAlignerPrepare) { RtAlignerPrepareAccept((int)Transfer.PlaceRaiseAligner, _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.DONE; } } RtPlaceWafer((int)Transfer.PlaceWafer, "Place wafer", Destination, DestSlot, PlaceBlade, _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.DONE; } RtUpdateWaferSingleStepProcessState((int)Transfer.Finish, "Update wafer single step process state", Destination, DestSlot, PlaceBlade, 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 transfer wafer from station:{Source} slot:{Slot + 1} to {Destination} slot:{DestSlot}" + $"with blade {PlaceBlade}."); IsRoutineActive = false; return Result.DONE; } catch (Exception ex) { EV.PostAlarmLog("System", $"Failed to transfer wafer from station:{Source} slot:{Slot + 1} with blade {PickBlade}."); LOG.Write(ex); IsRoutineActive = false; return Result.FAIL; } } } }