using Aitex.Core.RT.Event; using Aitex.Core.RT.Routine; using Aitex.Core.RT.SCCore; using Aitex.Core.Util; 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 FIMSUnloadRoutine : ModuleRoutine, IRoutine { enum RoutineStep { Unload, Delay, CheckUnloadFinish, } private int _timeout; private FIMSModule _fimsModule; private PMModule _pmModule; private bool _isNeedN2Purge; public FIMSUnloadRoutine(FIMSModule fimsModule) { Module = fimsModule.Module.ToString(); _fimsModule = fimsModule; Name = "Unload"; _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 (_fimsModule.FIMSDevice.IsUnloadCompleted) { EV.PostInfoLog(Module, $"{Module} already at unload position"); _fimsModule.FIMSDevice.IsLoadCompleted = false; _fimsModule.FIMSDevice.IsUnloadCompleted = true; return Result.DONE; } if (!Singleton.Instance.IsAutoMode && !Singleton.Instance.IsReturnWafer) { if (!_fimsModule.SensorWaferRobotEX1AxisHomePosition.Value) { _fimsModule.UnloadFailAlarm.Set($"wafer robot EX1 axis not at home position"); return Result.FAIL; } if (!_fimsModule.SensorWaferRobotEX2AxisHomePosition.Value) { _fimsModule.UnloadFailAlarm.Set($"wafer robot EX2 axis not at home position"); return Result.FAIL; } } //if (_fimsModule.FIMSDevice.DoorOpenCloseStatus == Devices.DeviceStatus.Open && _fimsModule.IsWaferOnRobot) //{ // _fimsModule.UnloadFailAlarm.Set($"wafer robot inside {Module}"); // return Result.FAIL; //} Notify($"{_fimsModule.Name} {Name} start"); _fimsModule.FIMSDevice.IsLoadCompleted = false; _fimsModule.FIMSDevice.IsUnloadCompleted = false; if (SC.ContainsItem("PM1.N2Purge.FOUPOpenerStableWaitTime")) { _timeout = (int)SC.GetValue("PM1.N2Purge.FOUPOpenerStableWaitTime"); } if (_fimsModule.FIMSDevice.DoorOpenCloseStatus == Devices.DeviceStatus.Close && _fimsModule.IsWaferOnRobot) { _fimsModule.UnloadFailAlarm.Set($"The wafer on {Module} has shifted"); return Result.FAIL; } if (_isNeedN2Purge) _pmModule?.SetN2PurgeParameters(); _pmModule?.SetN2PurgeFIMS1O2CheckEnable(ModuleHelper.Converter(Module), _isNeedN2Purge); return Result.RUN; } public override Result Monitor() { try { PauseRountine(_fimsModule.FIMSDevice.IsPause); if (_fimsModule.FIMSDevice.IsPause) return Result.RUN; Unload((int)RoutineStep.Unload, _timeout); Delay((int)RoutineStep.Delay, 3); CheckUnloadFinish((int)RoutineStep.CheckUnloadFinish, _timeout); } catch (RoutineBreakException) { return Result.RUN; } catch (RoutineFaildException) { _pmModule?.SetN2PurgeFIMS1O2CheckEnable(ModuleHelper.Converter(Module), false); _fimsModule.Stop(); return Result.FAIL; } _pmModule?.SetN2PurgeFIMS1O2CheckEnable(ModuleHelper.Converter(Module), false); _fimsModule.FIMSDevice.IsUnloadCompleted = true; _fimsModule.Stop(); Notify($"{_fimsModule.Name} {Name} finished"); return Result.DONE; } public void Abort() { _fimsModule.Stop(); } private void Unload(int id, int timeout) { Tuple ret = ExecuteAndWait(id, () => { Notify($"{Module} unload"); if (!_fimsModule.FIMSDevice.Unload(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.UnloadTimeoutAlarm.Set($"can not complete in {timeout} seconds"); throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } private void CheckUnloadFinish(int id, int timeout) { Tuple ret = ExecuteAndWait(id, () => { Notify($"Check {Module} unload finish"); return true; }, () => { return _fimsModule.FIMSDevice.IsPLCUnloadCompleted && !_fimsModule.FIMSDevice.IsRunning; }, timeout * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { throw (new RoutineFaildException()); } else if (ret.Item2 == Result.TIMEOUT) //timeout { _fimsModule.UnloadTimeoutAlarm.Set($"can not complete in {timeout} seconds"); throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } } }