using Aitex.Core.RT.Routine; using Aitex.Core.RT.SCCore; using Aitex.Sorter.Common; using CyberX8_RT.Devices; using MECF.Framework.Common.Jobs; using MECF.Framework.Common.Routine; using MECF.Framework.Common.Equipment; using MECF.Framework.Common.SubstrateTrackings; using CyberX8_Core; using Aitex.Core.RT.Log; using Aitex.Core.Util; using MECF.Framework.Common.Schedulers; using System.Collections.Generic; using CyberX8_RT.Devices.EFEM; namespace CyberX8_RT.Modules.EFEM { class EfemSwapRoutine : ModuleRoutineBase, IRoutine { private enum SwapStep { WaitModuleReady, ModulePrepare, OpenSlitDoor, MoveWafer, WaitMaferMoved, CloseSlitDoor, NotifyDone, } private readonly EfemBase _efem; private int _moveTimeout = 20 * 1000; Queue _actionList = new Queue(); MoveItem _currentAction; private int _actionCount = 0; private int _autoPumpOptInWafer = 4; private int _autoPumpOptOutWafer = 0; private bool _bAutoMode = true; public EfemSwapRoutine(EfemBase efem) : base(ModuleName.EfemRobot) { _efem = efem; Name = "Swap"; } 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; } _actionList.Clear(); foreach (var item in (Queue)objs[0]) { _actionList.Enqueue(new MoveItem(item.SourceModule, item.SourceSlot, item.DestinationModule, item.DestinationSlot, item.RobotHand)); } var firtItem = _actionList.Peek(); _moveTimeout = SC.GetValue("EFEM.MotionTimeout") * 1000; _autoPumpOptInWafer = SC.GetValue("EFEM.LLAutoPumpInWaferOpt"); _autoPumpOptOutWafer = SC.GetValue("EFEM.LLAutoPumpOutWaferOpt"); _bAutoMode = Singleton.Instance.IsAutoMode; _actionCount = _actionList.Count; return Runner.Start(Module, $"EFEM Swap with"); } public RState Monitor() { Runner.LoopStart(SwapStep.MoveWafer, loopName(), _actionCount, MoveWafer) .LoopEnd(SwapStep.WaitMaferMoved, NullFun, WaitWaferMoved, _moveTimeout); return Runner.Status; } private bool ModulePrepare() { return true; } private string loopName() { return "EFEM Swap"; } private bool VerifyWaferExistence(MoveItem item) { if (WaferManager.Instance.CheckHasWafer(item.DestinationModule, item.DestinationSlot)) { LOG.Write(eEvent.ERR_EFEM_ROBOT, Module, $"Cannot move wafer as desitination {item.DestinationModule},{item.DestinationSlot} already a wafer: "); return false; } if (WaferManager.Instance.CheckNoWafer(item.SourceModule, item.SourceSlot)) { LOG.Write(eEvent.ERR_EFEM_ROBOT, Module, $"Cannot move wafer as source {item.SourceModule}, {item.SourceSlot} has no wafer"); return false; } return true; } private bool MoveWafer() { if(_actionList.Count <= 0) { Runner.Stop("no action"); return true; } _currentAction = _actionList.Dequeue(); if (!VerifyWaferExistence(_currentAction)) return false; var wafer = WaferManager.Instance.GetWafer(_currentAction.SourceModule, _currentAction.SourceSlot); LOG.Write(eEvent.EV_EFEM_ROBOT, ModuleName.EfemRobot, $"{wafer.WaferOrigin} will be move from {_currentAction.SourceModule} {_currentAction.SourceSlot + 1} to {_currentAction.DestinationModule} {_currentAction.DestinationSlot + 1}"); return false; } private bool WaitWaferMoved() { if (_efem.Status == RState.Running) { return false; } else if (_efem.Status == RState.End) { WaferManager.Instance.WaferMoved(_currentAction.SourceModule, _currentAction.SourceSlot, _currentAction.DestinationModule, _currentAction.DestinationSlot); return true; } else { Runner.Stop($"EFEM Robot moving wafer failed, {_efem.Status}"); return true; } } public void Abort() { _efem.Halt(); } } }