using Aitex.Core.RT.Event; using Aitex.Core.RT.Routine; using Aitex.Core.RT.SCCore; using Aitex.Core.Util; using Caliburn.Micro.Core; using FurnaceRT.Equipments.PMs; using FurnaceRT.Equipments.Systems; using MECF.Framework.Common.Equipment; using MECF.Framework.Common.SubstrateTrackings; using System; namespace FurnaceRT.Equipments.FIMSs { public class FIMSLoadRoutine : ModuleRoutine, IRoutine { enum RoutineStep { Load, Delay, CheckLoadFinish, } private int _timeout; private FIMSModule _fimsModule; private PMModule _pmModule; private bool _isNeedN2Purge; public FIMSLoadRoutine(FIMSModule fimsModule) { Module = fimsModule.Module.ToString(); _fimsModule = fimsModule; Name = "Load"; _pmModule = Singleton.Instance.Modules[ModuleName.PM1] as PMModule; } public Result Init(bool isNeedN2Purge) { _isNeedN2Purge = isNeedN2Purge; return Result.DONE; } public Result Start(params object[] objs) { Reset(); _timeout = SC.GetValue($"FIMS.{Module}.MotionTimeout"); if (!Singleton.Instance.IsAutoMode && !Singleton.Instance.IsReturnWafer) { if (!_fimsModule.SensorWaferRobotEX1AxisHomePosition.Value) { _fimsModule.LoadFailAlarm.Set($"wafer robot EX1 axis not at home position"); return Result.FAIL; } if (!_fimsModule.SensorWaferRobotEX2AxisHomePosition.Value) { _fimsModule.LoadFailAlarm.Set($"wafer robot EX2 axis not at home position"); return Result.FAIL; } } if (_isNeedN2Purge) { if (!(Singleton.Instance.Modules[ModuleName.PM1] as PMModule).FIMSLoadCheckLAO2(out string reason)) { _fimsModule.LoadFailAlarm.Set(reason); return Result.FAIL; } _pmModule?.SetN2PurgeParameters(); } _pmModule?.SetN2PurgeProcess(_isNeedN2Purge); if (_fimsModule.FIMSDevice.IsLoadCompleted) { EV.PostInfoLog(Module, $"{Module} already at load position"); _fimsModule.FIMSDevice.IsLoadCompleted = true; _fimsModule.FIMSDevice.IsUnloadCompleted = false; return Result.DONE; } if (SC.ContainsItem("PM1.N2Purge.FOUPOpenerStableWaitTime")) { _timeout = (int)SC.GetValue("PM1.N2Purge.FOUPOpenerStableWaitTime"); } _fimsModule.FIMSDevice.IsLoadCompleted = false; _fimsModule.FIMSDevice.IsUnloadCompleted = false; Notify($"{_fimsModule.Name} {Name} start"); return Result.RUN; } public override Result Monitor() { try { PauseRountine(_fimsModule.FIMSDevice.IsPause); if (_fimsModule.FIMSDevice.IsPause) return Result.RUN; Load((int)RoutineStep.Load, _timeout); Delay((int)RoutineStep.Delay, 3); CheckLoadFinish((int)RoutineStep.CheckLoadFinish, _timeout); } catch (RoutineBreakException) { return Result.RUN; } catch (RoutineFaildException) { _fimsModule.Stop(); return Result.FAIL; } _pmModule?.SetN2PurgeProcess(false); _fimsModule.FIMSDevice.IsLoadCompleted = true; _fimsModule.Stop(); Notify($"{_fimsModule.Name} {Name} finished"); return Result.DONE; } public void Abort() { _fimsModule.Stop(); } private void Load(int id, int timeout) { Tuple ret = ExecuteAndWait(id, () => { Notify($"{Module} load"); if (!_fimsModule.FIMSDevice.Load(out string reason)) { Stop(reason); return false; } return true; }, () => { return true; }, timeout * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { throw (new RoutineFaildException()); } else if (ret.Item2 == Result.TIMEOUT) //timeout { _fimsModule.LoadTimeoutAlarm.Set($"can not complete in {timeout} seconds"); throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } private void CheckLoadFinish(int id, int timeout) { Tuple ret = ExecuteAndWait(id, () => { Notify($"Check {Module} load finish"); return true; }, () => { if (_fimsModule.FIMSDevice.IsPLCLoadCompleted && !_fimsModule.FIMSDevice.IsRunning) { if (_fimsModule.IsWaferOnRobot) { _fimsModule.LoadFailAlarm.Set($"The wafer on {Module} has shifted"); _pmModule?.SetN2PurgeProcess(false); return false; } return true; } return false; }, timeout * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { throw (new RoutineFaildException()); } else if (ret.Item2 == Result.TIMEOUT) //timeout { _fimsModule.LoadTimeoutAlarm.Set($"can not complete in {timeout} seconds"); throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } } }