using Aitex.Core.RT.Fsm; using Aitex.Core.RT.Routine; using Aitex.Core.Util; using MECF.Framework.Common.Equipment; using MECF.Framework.Common.Schedulers; using CyberX8_Core; using CyberX8_RT.Modules.PUF; using CyberX8_RT.Modules; using CyberX8_RT.Schedulers.EfemRobot; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using CyberX8_RT.Modules.Loader; using Aitex.Core.RT.Log; using MECF.Framework.Common.SubstrateTrackings; using Aitex.Core.Common; using MECF.Framework.Common.Utilities; using CyberX8_RT.Devices.AXIS; using Aitex.Core.RT.Device; using CyberX8_RT.Dispatch; using MECF.Framework.Common.RecipeCenter; namespace CyberX8_RT.Schedulers.Puf { public class SchedulerPuf : SchedulerModule { private enum OperationStep { None, ReadyForSwap, WaitForLoaderUnloadComplete, Swap, CheckSwapComplete, GotoRobotForPick, WaitForRobotPick, PufBackToPark, CheckParkComplete } #region 内部变量 private PUFEntity _pufEntity; private LoaderEntity _loaderEntity; private OperationStep _currentOperation; private EfemEntity _efemEntity; private bool _forward = false; private bool _isProductionWafer = false; #endregion #region 属性 /// /// 是否空闲 /// public override bool IsIdle { get { return _state == RState.End; } } /// /// 是否错误 /// public override bool IsError { get { return _state == RState.Failed || _state == RState.Timeout; } } #endregion /// /// 构造函数 /// /// public SchedulerPuf(ModuleName moduleName) : base(moduleName.ToString()) { _efemEntity = Singleton.Instance.EFEM; _pufEntity = Singleton.Instance.GetModule(moduleName.ToString()); _loaderEntity = Singleton.Instance.GetModule(ModuleName.Loader1.ToString()); } /// /// 执行 /// /// /// public override bool RunProcess(object recipe, object parameter, List syncMessages) { _isProductionWafer = false; _forward = (bool)parameter; if (_forward) { _currentOperation = OperationStep.ReadyForSwap; //B面是否有片 if (WaferManager.Instance.CheckHasWafer(Module, 1)) { _state = RState.Running; return _pufEntity.CheckToPostMessage(eEvent.ERR_PUF, Module.ToString(), (int)PUFMSG.ReadyForSwap); } return false; } else { _currentOperation = OperationStep.None; return true; } } /// /// 监控执行 /// /// public override bool MonitorProcess(SchedulerSequence schedulerSequence, bool hasMatchWafer) { //当前状态为ReadyForSwap if (_currentOperation == OperationStep.ReadyForSwap) { //若Puf已经完成ReadyForSwap动作,状态变更为WaitForSwap if (_pufEntity.State == (int)PUFSTATE.WaitForSwap) { //当前操作变量为WaitFor LoaderUnload Complete _currentOperation = OperationStep.WaitForLoaderUnloadComplete; LOG.WriteLog(eEvent.INFO_PUF, Module.ToString(), "Current Operation is WaitForLoaderUnloadComplete"); } } else if (_currentOperation == OperationStep.WaitForLoaderUnloadComplete) { //Loader Entity Unload all if (CheckDualPufStateCanExecuteLoaderUnloadAll(hasMatchWafer)) { PostLoaderEntityUnloadAllSide(); } } //puf 进行Swap else if(_currentOperation==OperationStep.Swap) { bool result = _pufEntity.CheckToPostMessage(eEvent.ERR_PUF, Module.ToString(), (int)PUFMSG.Swap); if(result) { _currentOperation = OperationStep.CheckSwapComplete; LOG.WriteLog(eEvent.INFO_PUF, Module.ToString(), "Current Operation is CheckSwapComplete"); } } else if(_currentOperation==OperationStep.CheckSwapComplete) { //puf完成Swap后运动至Robot让Robot取片 PostPufEntityGotoRobotForPick(); } else if(_currentOperation==OperationStep.GotoRobotForPick) { //Efem 将Dummy片运输至Dummy Casstete PostEfemRobotTransferToDummyCassete(); } else if(_currentOperation==OperationStep.WaitForRobotPick) { //等待Efem Robot完成传片 if (RobotMoveHelper.Instance.IsBusy) { RobotMoveHelper.Instance.Monitor(Module.ToString()); } if(RobotMoveHelper.Instance.IsPickCompleted) { _currentOperation = OperationStep.PufBackToPark; LOG.WriteLog(eEvent.INFO_PUF, Module.ToString(), "Current Operation is PufBackToBack"); } } else if(_currentOperation==OperationStep.PufBackToPark) { if (RobotMoveHelper.Instance.IsBusy) { RobotMoveHelper.Instance.Monitor(Module.ToString()); } //Puf运动至Park安全位置 bool result = _pufEntity.CheckToPostMessage(eEvent.ERR_PUF, Module.ToString(), (int)PUFMSG.RobotPickComplete); if (result) { _currentOperation = OperationStep.CheckParkComplete; LOG.WriteLog(eEvent.INFO_PUF, Module.ToString(), "Current Operation is CheckParkComplete"); } } else if(_currentOperation==OperationStep.CheckParkComplete) { if (RobotMoveHelper.Instance.IsBusy) { RobotMoveHelper.Instance.Monitor(Module.ToString()); } //判定Puf运动是否完成 if (_pufEntity.IsIdle&&RobotMoveHelper.Instance.IsIdle) { _state = RState.End; } } return false; } /// /// 检验Dual puf 是不是都处于WaitForSwap 状态,保证Loader可以UnloadAll /// /// private bool CheckDualPufStateCanExecuteLoaderUnloadAll(bool hasMatchWafer) { bool puf1ready = true; if(ModuleHelper.IsInstalled(ModuleName.PUF1)) { PUFEntity puf1Entity = Singleton.Instance.GetModule(ModuleName.PUF1.ToString()); if(hasMatchWafer) { //B面有Wafer if (WaferManager.Instance.CheckHasWafer(ModuleName.PUF1,1)) { puf1ready = puf1Entity.State == (int)PUFSTATE.WaitForSwap; } else { puf1ready = false; } } else { //任务仅一片Wafer,同时模块为PUF2 if(Module==ModuleName.PUF2) { puf1ready = puf1Entity.IsIdle; } } } if(!puf1ready) { return false; } bool puf2ready = true; if (ModuleHelper.IsInstalled(ModuleName.PUF2)) { PUFEntity puf2Entity = Singleton.Instance.GetModule(ModuleName.PUF2.ToString()); if(hasMatchWafer) { //B面有Wafer if (WaferManager.Instance.CheckHasWafer(ModuleName.PUF2, 1)) { puf2ready = puf2Entity.State == (int)PUFSTATE.WaitForSwap; } else { puf2ready = false; } } else { //任务仅一片Wafer,同时模块为PUF1 if (Module == ModuleName.PUF1) { puf2ready = puf2Entity.IsIdle; } } } if(!puf2ready) { return false; } //Loader中没有WaferHolder if(_loaderEntity.WaferHolderInfo==null) { return false; } if (_loaderEntity.State == (int)LOADERSTATE.WaitForUnload) { JetAxisBase _loadTransporterGantryAxis = DEVICE.GetDevice($"{ModuleName.Transporter2}.Gantry"); if (_loadTransporterGantryAxis != null && !_loadTransporterGantryAxis.JudgeCompareTargetStation("Loader", "Right")) { return false; } } return true; } /// /// LoaderEntity Unload All /// private void PostLoaderEntityUnloadAllSide() { //当前loader状态机为WaitForUnload if (_loaderEntity.State == (int)LOADERSTATE.WaitForUnload&&_currentOperation==OperationStep.WaitForLoaderUnloadComplete) { //触发loaderEntity UnloadAll _loaderEntity.CheckToPostMessage(eEvent.WARN_LOADER, ModuleName.Loader1.ToString(), (int)LoaderMSG.UnloadAll); } //若Loader Unload操作完成,状态变更为WaitForLoad,puf操作变更为Swap else if (_loaderEntity.State == (int)LOADERSTATE.WaitForLoad) { _currentOperation = OperationStep.Swap; LOG.WriteLog(eEvent.INFO_PUF, Module.ToString(), "Current Operation is Swap"); } else if (_loaderEntity.State == (int)LOADERSTATE.Unloading) { return; } //else //{ // LOG.WriteLog(eEvent.ERR_PUF, Module.ToString(), $"Loader1 Current State {(LOADERSTATE)_loaderEntity.State} is not avaible"); // _state = RState.Failed; //} } /// /// PUF Entity运动至Robot准备让robot pick /// private void PostPufEntityGotoRobotForPick() { if (_pufEntity.Module == ModuleName.PUF2) { if (_pufEntity.State == (int)PUFSTATE.AferSwapParkStation) { bool result = _pufEntity.CheckToPostMessage(eEvent.ERR_PUF, Module.ToString(), (int)PUFMSG.ReadyForRobotPick); if (result) { NotifyWaferTaskSchedulerLoaderComplete(); _currentOperation = OperationStep.GotoRobotForPick; LOG.WriteLog(eEvent.INFO_PUF, Module.ToString(), "Current Operation is GotoRobotForPick"); } } } else { if (_pufEntity.State == (int)PUFSTATE.AferSwapParkStation) { JetAxisBase loaderRotationAxis = DEVICE.GetDevice($"{ModuleName.Loader1}.Rotation"); if (loaderRotationAxis != null && loaderRotationAxis.CheckPositionIsInStation(loaderRotationAxis.MotionData.MotorPosition, "TRNPA")) { if (_loaderEntity.State == (int)LOADERSTATE.Loading || _loaderEntity.IsIdle) { bool result = _pufEntity.CheckToPostMessage(eEvent.ERR_PUF, Module.ToString(), (int)PUFMSG.ReadyForRobotPick); if (result) { NotifyWaferTaskSchedulerLoaderComplete(); _currentOperation = OperationStep.GotoRobotForPick; LOG.WriteLog(eEvent.INFO_PUF, Module.ToString(), "Current Operation is GotoRobotForPick"); } } } } } } /// /// 通知Wafer对应的SchedulerLoader工序已经完成 /// private void NotifyWaferTaskSchedulerLoaderComplete() { //puf A面是否存在Wafer if (WaferManager.Instance.CheckHasWafer(_pufEntity.Module, 0)) { WaferInfo waferInfo = WaferManager.Instance.GetWafer(_pufEntity.Module, 0); if (waferInfo!=null&&waferInfo.WaferType==WaferType.Production) { _isProductionWafer = true; WaferTask waferTask = WaferTaskManager.Instance.GetWaferTask(waferInfo.WaferID); if (waferTask!=null) { waferTask.UpdateLoaderSchedulerSequenceComplete(); } } } } /// /// 将Dummy片移动至Dummy Cassete /// private void PostEfemRobotTransferToDummyCassete() { if (_pufEntity.State == (int)PUFSTATE.WaitForRobotPick) { //生产片待EfemRobot取完片进行PufBackToPark状态 if (_isProductionWafer) { bool hasWafer = WaferManager.Instance.CheckHasWafer(_pufEntity.Module, 0); if (!hasWafer) { _currentOperation = OperationStep.PufBackToPark; LOG.WriteLog(eEvent.INFO_PUF, Module.ToString(), "Current Operation is PufBackToPark"); } } else { //A面Wafer WaferInfo waferInfo = WaferManager.Instance.GetWafer(_pufEntity.Module, 0); if (waferInfo == null) { return; } //Dummy片 if (waferInfo.WaferType == WaferType.Assit) { if (_efemEntity.IsIdle) { var result = SchedulerSequenceManager.Instance.GetAvaibleDummySlots(); if (result.moduleName != ModuleName.Unknown) { MoveItem moveItem = new MoveItem(_pufEntity.Module, 0, result.moduleName, result.slot, Aitex.Sorter.Common.Hand.Blade1); if(RobotMoveHelper.Instance.IsIdle) { RobotMoveHelper.Instance.Start(moveItem,Module.ToString()); _currentOperation = OperationStep.WaitForRobotPick; LOG.WriteLog(eEvent.INFO_PUF, Module.ToString(), "Current Operation is WaitForRobotPick"); } } else { LOG.WriteBackgroundLog(eEvent.WARN_PUF, Module.ToString(), "dummy slot is empty"); } } else { LOG.WriteBackgroundLog(eEvent.WARN_PUF, Module.ToString(), $"wafer {waferInfo.WaferID} efem is not idle"); } } else { LOG.WriteBackgroundLog(eEvent.WARN_PUF, Module.ToString(), $"wafer {waferInfo.WaferID} is not dummy wafer"); } } } } /// /// 检验前置条件 /// /// /// /// public override bool CheckPrecondition(List schedulerSequences, int sequenceIndex, object parameter, string materialId, ref string reason) { if (_state == RState.Running) { reason = "scheduler module is already running"; return false; } if (_pufEntity==null) { reason = "Puf entity is null"; return false; } bool forward=(bool)parameter; if(forward) { if (_pufEntity.State == (int)PUFSTATE.WaitForRobotPlace) { return true; } else { reason = $"{_pufEntity.Module} forward,but state is not WaitForRobotPlace"; return false; } } else { if (_pufEntity.State == (int)PUFSTATE.WaitForRobotPick) { return true; } else { reason = $"{_pufEntity.Module} backward,but state is not WaitForRobotPick"; return false; } } } /// /// 获取可用资源 /// /// /// /// public override bool GetAvaibleMaterial(int sequenceIndex, object parameter) { return true; } } }