using System; using Aitex.Core.Common; using Aitex.Core.RT.Event; using Aitex.Core.RT.Routine; using Aitex.Core.RT.SCCore; using Aitex.Core.Util; using Aitex.Sorter.Common; using MECF.Framework.Common.Equipment; using MECF.Framework.Common.Routine; using MECF.Framework.Common.Schedulers; using MECF.Framework.Common.SubstrateTrackings; using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.PMs; using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Robots; using MECF.Framework.RT.EquipmentLibrary.LogicUnits; using MECF.Framework.RT.ModuleLibrary.AlignerModules; using MECF.Framework.RT.ModuleLibrary.PMModules; using MECF.Framework.RT.ModuleLibrary.SystemModules; namespace JetEfemLib.Efems { public class EfemPickRoutine : ModuleRoutineBase, IStepRoutine { enum RoutineStep { CheckBeforePick, PickWafer, CheckBeforePick2, PickWafer2, PostTransfer, PrepareTransfer, PickExtend, PickRetract, LiftMove, End, } private int _pickTimeout; private ModuleName _source; private int _sourceSlot; private Hand _hand; private bool _autoHand; private EfemModule _robotModule; private ITransferTarget _target; private int _postTransferTimeout; private WaferSize _waferSize = WaferSize.WS0; public EfemPickRoutine(EfemModule robotModule) : base(ModuleName.EFEM.ToString()) { Name = "Pick"; _robotModule = robotModule; } public RState Start(params object[] objs) { if (!_robotModule.EfemDevice.IsInitialized) { EV.PostAlarmLog(Module, $"EFEM is not homed, please home it first"); return RState.Failed; } _pickTimeout = SC.GetValue("EFEM.EfemRobot.PickTimeout"); Reset(); if (_autoHand) { if (WaferManager.Instance.CheckNoWafer(ModuleName.EfemRobot, 0)) { _hand = Hand.Blade1; } else if (WaferManager.Instance.CheckNoWafer(ModuleName.EfemRobot, 1)) { _hand = Hand.Blade2; } else { EV.PostWarningLog(Module, $"Can not pick, Robot both arm has wafer"); return RState.Failed; } } if (_hand == Hand.Both) { if (!SC.GetValueOrDefault("EFEM.EfemRobot.LowerBladeEnable")) { EV.PostAlarmLog(Module, $"Can not pick, Lower Blade is Disabled"); return RState.Failed; } if (!SC.GetValueOrDefault("EFEM.EfemRobot.UpperBladeEnable")) { EV.PostAlarmLog(Module, $"Can not pick, Upper Blade is Disabled"); return RState.Failed; } if (WaferManager.Instance.GetWafers(_source).Length < 2) { EV.PostWarningLog(Module, $"Can not pick use both arm, Only one slot at {_source}"); return RState.Failed; } if (!WaferManager.Instance.CheckHasWafer(_source, _sourceSlot)) { EV.PostWarningLog(Module, $"Can not pick, No wafer at {_source}, {_sourceSlot + 1}"); return RState.Failed; } if (!WaferManager.Instance.CheckHasWafer(_source, _sourceSlot + 1)) { EV.PostWarningLog(Module, $"Can not pick, No wafer at {_source}, {_sourceSlot + 1 + 1}"); return RState.Failed; } if (!WaferManager.Instance.CheckNoWafer(Module, (int)Hand.Blade1)) { EV.PostWarningLog(Module, $"Can not pick, Robot arm 1 has wafer"); return RState.Failed; } if (!WaferManager.Instance.CheckNoWafer(Module, (int)Hand.Blade2)) { EV.PostWarningLog(Module, $"Can not pick, Robot arm 2 has wafer"); return RState.Failed; } } else { if (_hand == Hand.Blade1 && !SC.GetValueOrDefault("EFEM.EfemRobot.LowerBladeEnable")) { EV.PostAlarmLog(Module, $"Can not pick, Lower Blade is Disabled"); return RState.Failed; } if (_hand == Hand.Blade2 && !SC.GetValueOrDefault("EFEM.EfemRobot.UpperBladeEnable")) { EV.PostAlarmLog(Module, $"Can not pick, Upper Blade is Disabled"); return RState.Failed; } if (!WaferManager.Instance.CheckHasWafer(_source, _sourceSlot)) { EV.PostWarningLog(Module, $"Can not pick, No wafer at {_source}, {_sourceSlot + 1}"); return RState.Failed; } if (!WaferManager.Instance.CheckNoWafer(Module, (int)_hand)) { EV.PostWarningLog(Module, $"Can not pick, Robot arm {(int)_hand + 1} has wafer"); return RState.Failed; } } _waferSize = WaferManager.Instance.GetWafer(_source, _sourceSlot).Size; Notify($"Start, Pick from {_source} slot {_sourceSlot + 1}, by {_hand}"); return Runner.Start(ModuleName.EFEM.ToString(), Name); } public void Init(ModuleName source, int slot, Hand hand) { _autoHand = false; _source = source; _sourceSlot = slot; _hand = hand; if (ModuleHelper.IsPm(source)) _postTransferTimeout = SC.GetValue($"PM.PostTransferTimeout"); _target = EquipmentManager.Modules[source] as ITransferTarget; } public void Init(ModuleName source, int slot) { _autoHand = true; _source = source; _sourceSlot = slot; if (ModuleHelper.IsPm(source)) _postTransferTimeout = SC.GetValue($"PM.PostTransferTimeout"); _target = EquipmentManager.Modules[source] as ITransferTarget; } public void Abort() { if (_target != null) { _target.NoteTransferStop(ModuleName.EfemRobot, Hand.Blade1, 0, EnumTransferType.Pick); } _target = null; Notify("Abort"); } public RState Monitor() { if (_hand == Hand.Both) { Runner.Run(RoutineStep.PrepareTransfer, PrepareTransfer, CheckPrepareTransfer, _postTransferTimeout * 1000) .Wait(RoutineStep.CheckBeforePick, HOFs.Apply(CheckBeforePick, _source, _sourceSlot, Hand.Blade1)) .Run(RoutineStep.PickWafer, HOFs.Apply(PickWafer, _source, _sourceSlot, Hand.Blade1), CheckPickWafer, _pickTimeout * 1000) .Wait(RoutineStep.CheckBeforePick2, HOFs.Apply(CheckBeforePick, _source, _sourceSlot + 1, Hand.Blade2)) .Run(RoutineStep.PickWafer2, HOFs.Apply(PickWafer, _source, _sourceSlot + 1, Hand.Blade2), CheckPickWafer, _pickTimeout * 1000) .Run(RoutineStep.PostTransfer, PostTransfer, CheckPostTransfer, _postTransferTimeout * 1000) .Run(RoutineStep.LiftMove, LiftMove, CheckLiftMove, _pickTimeout * 1000) .End(RoutineStep.End, NullFun, _delay_0s); } else { Runner.Run(RoutineStep.PrepareTransfer, PrepareTransfer, CheckPrepareTransfer, _postTransferTimeout * 1000) .Wait(RoutineStep.CheckBeforePick, HOFs.Apply(CheckBeforePick, _source, _sourceSlot, _hand)) .Run(RoutineStep.PickWafer, HOFs.Apply(PickWafer, _source, _sourceSlot, _hand), CheckPickWafer, _pickTimeout * 1000) .Run(RoutineStep.PostTransfer, PostTransfer, CheckPostTransfer, _postTransferTimeout * 1000) .Run(RoutineStep.LiftMove, LiftMove, CheckLiftMove, _pickTimeout * 1000) .End(RoutineStep.End, NullFun, _delay_0s); } if (Runner.Status == RState.End) { _target.NoteTransferStop(ModuleName.EfemRobot, Hand.Blade1, 0, EnumTransferType.Pick); Notify($"Finish, Pick from {_source} slot {_sourceSlot + 1}, by {_hand}"); } return Runner.Status; } bool PrepareTransfer() { if(ModuleHelper.IsPm(_source) && !_target.CheckReadyForTransfer(ModuleName.EfemRobot, _hand, _sourceSlot, EnumTransferType.Pick, out _)) { var pm = _target as PMModuleBase; var type = EnumTransferType.Pick; Notify($"{pm.Name} Prepare transfer "); if (!pm.PrepareTransfer(ModuleName.EfemRobot, Hand.Blade1, new int[] { 0 }, type, 0, 0, false, out string reason)) { Stop(reason); return false; } return true; } return true; } bool CheckPrepareTransfer() { if (ModuleHelper.IsPm(_source) && !_target.CheckReadyForTransfer(ModuleName.EfemRobot, _hand, _sourceSlot, EnumTransferType.Pick, out _)) { var pm = _target as PMModuleBase; return !pm.IsError && pm.IsReady && pm.IsPrepareTransferReady(EnumTransferType.Pick, (EnumDualPM)(_sourceSlot + 1), _waferSize); ; } return true; } bool CheckBeforePick(ModuleName source, int slot, Hand blade) { Notify("Check pick is enabled"); string reason = string.Empty; if (!_target.CheckReadyForTransfer(ModuleName.EfemRobot, _hand, _sourceSlot, EnumTransferType.Pick, out reason)) { Stop(reason); return false; } if (blade == Hand.Blade1) { if (!WaferManager.Instance.CheckHasWafer(source, slot)) { Stop("Source no wafer"); return false; } if (!WaferManager.Instance.CheckNoWafer(ModuleName.EfemRobot, 0)) { Stop("Blade has wafer"); return false; } } else if (blade == Hand.Blade2) { if (!WaferManager.Instance.CheckHasWafer(source, slot)) { Stop("Source no wafer"); return false; } if (!WaferManager.Instance.CheckNoWafer(ModuleName.EfemRobot, 1)) { Stop("Blade has wafer"); return false; } } else { for (int i = 0; i < 2; i++) { if (!WaferManager.Instance.CheckHasWafer(source, slot + i)) { Stop("Source no wafer"); return false; } if (!WaferManager.Instance.CheckNoWafer(ModuleName.EfemRobot, i)) { Stop("Blade has wafer"); return false; } } } return true; } bool PickWafer(ModuleName chamber, int slot, Hand hand) { Notify("robot execute pick command"); _target.NoteTransferStart(ModuleName.EfemRobot, hand, slot, EnumTransferType.Pick); string reason; if (!_robotModule.RobotDevice.Pick(chamber, hand, slot, out reason)) { Stop(reason); return false; } return true; } bool CheckPickWafer() { return !_robotModule.RobotDevice.IsError && _robotModule.RobotDevice.IsIdle; } bool PostTransfer() { if(ModuleHelper.IsPm(_source)) { var pm = _target as PMModuleBase; var type = EnumTransferType.Pick; Notify($"{pm.Name} post transfer "); if (!pm.PostTransfer(ModuleName.EfemRobot, _hand, new int[] { _sourceSlot }, type, out string reason)) { Stop(reason); return false; } return true; } return true; } bool CheckPostTransfer() { if (ModuleHelper.IsPm(_source)) { var pm = _target as PMModuleBase; return !pm.IsError && pm.IsReady; } return true; } bool LiftMove() { if(ModuleHelper.IsCooling(_source) || ModuleHelper.IsAligner(_source)) { var aligner = _target as AlignerModuleBase; Notify($"{aligner.Name} lift pin up "); //if (!pm.ChamberLiftPin.MoveUp(out string reason)) //{ // Stop(reason); // return false; //} return aligner.Lift(true); } return true; } bool CheckLiftMove() { if (ModuleHelper.IsCooling(_source) || ModuleHelper.IsAligner(_source)) { var aligner = _target as AlignerModuleBase; return aligner.IsReady; } return true; } } }