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, PreRotation, PickPrepare, PickExtend, DropDownWafer, PickDelay, PickRetract, PlacePrepare, PlaceExtend, LiftUpWafer, PlaceDelay, PlaceRetract, NotifyDone, } private enum SwapWithHeaterStep { WaitPMReady, PreRotation, PickPrepare, Picking, PlacePrepare, Placing, NotifyDone, } private readonly JetTM _JetTM; private readonly ITransferRobot _robot; private int _swapingTimeout = 120 * 1000; private int _placeDelayTime = 0; private int _pickDelayTime = 0; private ModuleName _targetModule; private PMEntity _pmModule; private int _targetSlot; private Hand _pickHand; private Hand _placeHand; public MFPMSwapRoutine(JetTM tm, ITransferRobot robot) : base(ModuleName.TMRobot) { _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.TMRobot, (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.TMRobot, (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 + 1} has no wafer"); return RState.Failed; } Reset(); _swapingTimeout = SC.GetValue($"TM.SwapTimeout") * 1000; _pickDelayTime = SC.GetValue($"{_targetModule}.PickDelayTime"); _placeDelayTime = SC.GetValue($"{_targetModule}.PlaceDelayTime"); return Runner.Start(Module, $"Swap with {_targetModule}"); } public RState Monitor() { //Runner.Wait(SwapStep.WaitPMReady, () => _pmModule.IsIdle, _delay_60s) // .RunIf(SwapStep.PreRotation, _JetTM.PreRotateModules.ContainsKey(_targetModule), RotateArm, WaitRotateDone) // .Run(SwapStep.PickPrepare, PickPrepare, IsModuleReadyForPick) // .Run(SwapStep.PickExtend, PickExtend, WaitRobotExtendDone) // .Run(SwapStep.DropDownWafer, NotifyPMPickWafer, WaitPMWaferDropDown) // .Delay(SwapStep.PickDelay, _pickDelayTime) // .Run(SwapStep.PickRetract, PickRetract, WaitRobotRetractDone) // .Run(SwapStep.PlacePrepare, PlacePrepare, IsModuleReadyForPlace) // .Run(SwapStep.PlaceExtend, PlaceExtend, WaitRobotExtendDone) // .Run(SwapStep.LiftUpWafer, NotifyLiftUpWafer, WaitPMWaferLiftUp) // .Delay(SwapStep.PlaceDelay, _placeDelayTime) // .Run(SwapStep.PlaceRetract, PlaceRetract, WaitRobotRetractDone) // .End(SwapStep.NotifyDone, NotifyPMDone, _delay_50ms); switch (_pmModule.ChamberType) { case JetChamber.Venus: case JetChamber.Kepler2300: Runner.Wait(SwapStep.WaitPMReady, () => _pmModule.IsIdle, _delay_60s) .RunIf(SwapStep.PreRotation, _JetTM.PreRotateModules.ContainsKey(_targetModule), RotateArm, WaitRotateDone) .Run(SwapStep.PickPrepare, PickPrepare, IsModuleReadyForPick) .Run(SwapStep.PickExtend, PickExtend, WaitRobotExtendDone) .Run(SwapStep.DropDownWafer, NotifyPMPickWafer, WaitPMWaferDropDown) .Delay(SwapStep.PickDelay, _pickDelayTime) .Run(SwapStep.PickRetract, PickRetract, WaitRobotRetractDone) .Run(SwapStep.PlacePrepare, PlacePrepare, IsModuleReadyForPlace) .Run(SwapStep.PlaceExtend, PlaceExtend, WaitRobotExtendDone) .Run(SwapStep.LiftUpWafer, NotifyLiftUpWafer, WaitPMWaferLiftUp) .Delay(SwapStep.PlaceDelay, _placeDelayTime) .Run(SwapStep.PlaceRetract, PlaceRetract, WaitRobotRetractDone) .End(SwapStep.NotifyDone, NotifyPMDone, _delay_50ms); break; case JetChamber.Kepler2200A: Runner.Wait(SwapStep.WaitPMReady, () => _pmModule.IsIdle, _delay_60s) .RunIf(SwapStep.PreRotation, _JetTM.PreRotateModules.ContainsKey(_targetModule), RotateArm, WaitRotateDone) .Run(SwapStep.PickPrepare, PickPrepare, IsModuleReadyForPick) .Run(SwapWithHeaterStep.Picking, Picking, WaitPickDone) .Run(SwapWithHeaterStep.PlacePrepare, PlacePrepare, IsModuleReadyForPlace) .Run(SwapWithHeaterStep.Placing, Placing, WaitPlaceDone) .End(SwapStep.NotifyDone, NotifyPMDone, _delay_50ms); break; } 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 Picking() { return _robot.Pick(_targetModule, _targetSlot, _pickHand); } private bool WaitPickDone() { if (_robot.Status == RState.Running) { return false; } else if (_robot.Status == RState.End) { //WaferManager.Instance.WaferMoved(ModuleName.TM, (int)_hand, _targetModule, _targetSlot); WaferManager.Instance.WaferMoved(_targetModule, _targetSlot, ModuleName.TMRobot, (int)_pickHand); return true; } else { Runner.Stop($"TM Robot Picking failed, {_robot.Status}"); return true; } } private bool Placing() { return _robot.Place(_targetModule, _targetSlot, _placeHand); } private bool WaitPlaceDone() { if (_robot.Status == RState.Running) { return false; } else if (_robot.Status == RState.End) { WaferManager.Instance.WaferMoved(ModuleName.TMRobot, (int)_placeHand, _targetModule, _targetSlot); return true; } else { Runner.Stop($"TM Robot Place failed, {_robot.Status}"); return true; } } private bool RotateArm() { _pmModule.PostMsg(PMEntity.MSG.PreparePick); // Notify PM to Serv pressure in advance for throughput enhancement return _robot.Goto(_JetTM.PreRotateModules[_targetModule], 0, _placeHand); } private bool WaitRotateDone() { if (_robot.Status == RState.Running) { return false; } else if (_robot.Status == RState.End) { return true; } else { Runner.Stop($"TM Robot Rotate Arm 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.TMRobot, (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.TMRobot, (int)_placeHand, _targetModule, _targetSlot); return true; } return false; } private bool NotifyPMDone() { _pmModule.PostMsg(PMEntity.MSG.PlaceReady); return true; } public void Abort() { _robot.Halt(); } } }