using Aitex.Core.RT.Routine; using Aitex.Core.RT.SCCore; using Aitex.Sorter.Common; using Venus_RT.Devices; using MECF.Framework.Common.Routine; using MECF.Framework.Common.Equipment; using MECF.Framework.Common.SubstrateTrackings; using Venus_Core; using Aitex.Core.RT.Log; using Aitex.Core.Util; using Venus_RT.Modules.PMs; using MECF.Framework.Common.Schedulers; using System.Collections.Generic; namespace Venus_RT.Modules.TM { class MFPMSwapRoutine : ModuleRoutineBase, IRoutine { private enum SwapStep { WaitPMReady, PickPrepare, PickExtend, DropDownWafer, PickRetract, PlacePrepare, PlaceExtend, LiftUpWafer, PlaceRetract, NotifyDone, } private readonly JetTM _JetTM; private readonly ITransferRobot _robot; private int _swapingTimeout = 120 * 1000; private ModuleName _targetModule; private PMEntity _pmModule; int _targetSlot; Hand _pickHand; Hand _placeHand; public MFPMSwapRoutine(JetTM tm, ITransferRobot robot) : base(ModuleName.TM) { _JetTM = tm; _robot = robot; Name = "Swap with PM"; } public RState Start(params object[] objs) { if (!_robot.IsHomed) { LOG.Write(eEvent.ERR_TM, Module, $"TM Robot is not homed, please home it first"); return RState.Failed; } var swapItem = (Queue)objs[0]; _targetModule = swapItem.Peek().SourceModule; _targetSlot = swapItem.Peek().SourceSlot; _pickHand = swapItem.Peek().RobotHand; _placeHand = _pickHand == Hand.Blade2 ? Hand.Blade1 : Hand.Blade2; if (ModuleHelper.IsPm(_targetModule) && ModuleHelper.IsInstalled(_targetModule)) { _pmModule = Singleton.Instance.GetPM(_targetModule); } else { LOG.Write(eEvent.ERR_TM, Module, $"Invalid target module : {_targetModule} for swap action"); return RState.Failed; } if (WaferManager.Instance.CheckNoWafer(ModuleName.TM, (int)_placeHand)) { LOG.Write(eEvent.ERR_TM, Module, $"Cannot Swap Wafer as TM Robot Arm: {_placeHand} has no wafer"); return RState.Failed; } if (WaferManager.Instance.CheckHasWafer(ModuleName.TM, (int)_pickHand)) { LOG.Write(eEvent.ERR_TM, Module, $"Cannot Swap Wafer as TM Robot Arm: {_pickHand} has a wafer"); return RState.Failed; } if (WaferManager.Instance.CheckNoWafer(_targetModule, _targetSlot)) { LOG.Write(eEvent.ERR_TM, Module, $"Cannot Swap Wafer as {_targetModule} Slot {_targetSlot} has no wafer"); return RState.Failed; } Reset(); _swapingTimeout = SC.GetValue($"{Module}.SwapTimeout") * 1000; return Runner.Start(Module, $"Swap with {_targetModule}"); } public RState Monitor() { Runner.Wait((int)SwapStep.WaitPMReady, () => _pmModule.IsIdle, _delay_60s) .Run((int)SwapStep.PickPrepare, PickPrepare, IsModuleReadyForPick) .Run((int)SwapStep.PickExtend, PickExtend, WaitRobotExtendDone) .Run((int)SwapStep.DropDownWafer, NotifyPMPickWafer, WaitPMWaferDropDown) .Run((int)SwapStep.PickRetract, PickRetract, WaitRobotRetractDone) .Run((int)SwapStep.PlacePrepare, PlacePrepare, IsModuleReadyForPlace) .Run((int)SwapStep.PlaceExtend, PlaceExtend, WaitRobotExtendDone) .Run((int)SwapStep.LiftUpWafer, NotifyLiftUpWafer, WaitPMWaferLiftUp) .Run((int)SwapStep.PlaceRetract, PlaceRetract, WaitRobotRetractDone) .End((int)SwapStep.NotifyDone, NotifyPMDone, _delay_50ms); return Runner.Status; } private bool PickPrepare() { _pmModule.PostMsg(PMEntity.MSG.PreparePick); return true; } private bool IsModuleReadyForPick() { return _pmModule.Status == PMEntity.PMStatus.Ready_For_Pick && _pmModule.IsSlitDoorOpen; } private bool PickExtend() { return _robot.PickExtend(_targetModule, _targetSlot, _pickHand); } private bool PickRetract() { return _robot.PickRetract(_targetModule, _targetSlot, _pickHand); } private bool PlacePrepare() { _pmModule.PostMsg(PMEntity.MSG.PreparePlace); return true; } private bool IsModuleReadyForPlace() { return _pmModule.Status == PMEntity.PMStatus.Ready_For_Place && _pmModule.IsSlitDoorOpen; } private bool PlaceExtend() { return _robot.PlaceExtend(_targetModule, _targetSlot, _placeHand); } private bool PlaceRetract() { return _robot.PlaceRetract(_targetModule, _targetSlot, _placeHand); } private bool WaitRobotExtendDone() { if (_robot.Status == RState.Running) { return false; } else if (_robot.Status == RState.End) { return true; } else { Runner.Stop($"TM Robot Place Extend failed, {_robot.Status}"); return true; } } private bool NotifyPMPickWafer() { _pmModule.PostMsg(PMEntity.MSG.DropDownWafer); return true; } private bool WaitPMWaferDropDown() { if (_pmModule.Status == PMEntity.PMStatus.Exchange_Ready) { WaferManager.Instance.WaferMoved(_targetModule, _targetSlot, ModuleName.TM, (int)_pickHand); return true; } return false; } private bool WaitRobotRetractDone() { if (_robot.Status == RState.Running) { return false; } else if (_robot.Status == RState.End) { return true; } else { Runner.Stop($"TM Robot Swap Retract failed, {_robot.Status}"); return true; } } private bool NotifyLiftUpWafer() { _pmModule.PostMsg(PMEntity.MSG.LiftUpWafer); return true; } private bool WaitPMWaferLiftUp() { if(_pmModule.Status == PMEntity.PMStatus.Exchange_Ready) { WaferManager.Instance.WaferMoved(ModuleName.TM, (int)_placeHand, _targetModule, _targetSlot); return true; } return false; } private bool NotifyPMDone() { _pmModule.PostMsg(PMEntity.MSG.PlaceReady); return true; } public void Abort() { _robot.Halt(); } } }