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 MECF.Framework.Common.Schedulers; using System.Collections.Generic; using Venus_RT.Devices.EFEM; namespace Venus_RT.Modules.EFEM { class EfemPickRoutine : ModuleRoutineBase, IRoutine { private enum PickStep { WaitModuleReady, Picking1, Picking2, End, } private int _moveTimeout = 20 * 1000; private ModuleName _targetModule = ModuleName.System; int _targetSlot; int _targetSlot2; Hand _hand; Hand _hand2; EfemBase _efem; bool _bDoublePick = false; public EfemPickRoutine(EfemBase efem) : base(ModuleName.EfemRobot) { _efem = efem; } public RState Start(params object[] objs) { if (!_efem.IsHomed) { LOG.Write(eEvent.ERR_EFEM_COMMON_FAILED, Module, $"EFEM is not homed, please home it first"); return RState.Failed; } _bDoublePick = false; var pickItem = (Queue)objs[0]; _targetModule = pickItem.Peek().SourceModule; _targetSlot = pickItem.Peek().SourceSlot; _hand = pickItem.Peek().RobotHand; if(WaferManager.Instance.CheckHasWafer(ModuleName.EfemRobot, (int)_hand)) { LOG.Write(eEvent.ERR_EFEM_ROBOT, Module, $"Efem robot arm{_hand} already has a wafer, cannot do the pick action"); return RState.Failed; } if(WaferManager.Instance.CheckNoWafer(_targetModule, _targetSlot)) { LOG.Write(eEvent.ERR_EFEM_ROBOT, Module, $"The target slot: {_targetModule}{_targetSlot} has no wafer, cannot do the pick action"); return RState.Failed; } if(pickItem.Count >= 2) { if(!ModuleHelper.IsLoadPort(_targetModule)) { LOG.Write(eEvent.ERR_EFEM_ROBOT, Module, $"Wrong double pick command, target is not loadport"); return RState.Failed; } _hand2 = _hand != Hand.Blade1 ? Hand.Blade1 : Hand.Blade2; if (WaferManager.Instance.CheckHasWafer(ModuleName.EfemRobot, (int)_hand2)) { LOG.Write(eEvent.ERR_EFEM_ROBOT, Module, $"Efem robot arm{_hand2} already has a wafer, cannot do the double pick action"); return RState.Failed; } _targetSlot2 = pickItem.ToArray()[1].SourceSlot; if (WaferManager.Instance.CheckNoWafer(_targetModule, _targetSlot2)) { LOG.Write(eEvent.ERR_EFEM_ROBOT, Module, $"The target slot: {_targetModule}{_targetSlot2} has no wafer, cannot do the double pick action"); return RState.Failed; } _bDoublePick = true; } _moveTimeout = SC.GetValue($"EFEM.MotionTimeout") * 1000; return Runner.Start(Module, $"Pick from {_targetModule}"); } public RState Monitor() { if(_bDoublePick) { Runner.Wait((int)PickStep.WaitModuleReady, WaitModuleReady) .Run((int)PickStep.Picking1, Pick1, Pick1Done, _moveTimeout) .Run((int)PickStep.Picking2, Pick2, Pick2Done, _moveTimeout) .End((int)PickStep.End, ActionDone); } else { Runner.Wait((int)PickStep.WaitModuleReady, WaitModuleReady) .Run((int)PickStep.Picking1, Pick1, Pick1Done, _moveTimeout) .End((int)PickStep.End, ActionDone); } return Runner.Status; } public void Abort() { _efem.Halt(); } private bool WaitModuleReady() { return true; } private bool Pick1() { return _efem.Pick(_targetModule, _targetSlot, _hand); } private bool Pick1Done() { if (_efem.Status == RState.End) { WaferManager.Instance.WaferMoved(_targetModule, _targetSlot, ModuleName.EfemRobot, (int)_hand); return true; } else if (_efem.Status != RState.Running) { LOG.Write(eEvent.ERR_EFEM_ROBOT, Module, $"Efem robot picking failed: {_efem.Status}"); return true; } return false; } private bool Pick2() { return _efem.Pick(_targetModule, _targetSlot2, _hand2); } private bool Pick2Done() { if (_efem.Status == RState.End) { WaferManager.Instance.WaferMoved(_targetModule, _targetSlot2, ModuleName.EfemRobot, (int)_hand2); return true; } else if (_efem.Status != RState.Running) { LOG.Write(eEvent.ERR_EFEM_ROBOT, Module, $"Efem robot picking failed: {_efem.Status}"); return true; } return false; } private bool ActionDone() { return true; } } }