using System; using Aitex.Core.Common; using Aitex.Core.RT.Device; using Aitex.Core.RT.Event; using Aitex.Core.RT.Log; using Aitex.Core.RT.Routine; using Aitex.Core.RT.SCCore; using FutureEfemLib.Efems; using MECF.Framework.Common.Equipment; using MECF.Framework.Common.SubstrateTrackings; using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.LoadPorts; using MECF.Framework.RT.ModuleLibrary.SystemModules; namespace FutureEfemLib.LPs { class LoadPortLoadRoutine : ModuleRoutine, IRoutine { enum RoutineStep { Clamp, Dock, OpenDoor, QueryStatus1, WaitRobotIdle, Map, GetWaferInfo, QueryStatus2, } private int _timeout = 0; LoadPort _lp = null; private LoadPortModule _lpModule; private EfemModule _efem; public LoadPortLoadRoutine(LoadPortModule lpModule) { _lpModule = lpModule; _efem = EquipmentManager.Modules[ModuleName.EFEM] as EfemModule; Module = lpModule.Module; Name = "Load"; _lp = DEVICE.GetDevice($"{Module}"); } public bool Initalize() { return true; } public Result Start(params object[] objs) { Reset(); _timeout = SC.GetValue("EFEM.LoadPort.HomeTimeout"); var waferSize = _lp.GetCurrentWaferSize(); if (waferSize != WaferSize.WS8 && waferSize != WaferSize.WS12) { EV.PostWarningLog(Module, $"{Module} get wafer size abnormal, can not load"); return Result.FAIL; } if (!_lp.IsPresent || !_lp.IsPlacement) { EV.PostWarningLog(Module, $"{Module} not found carrier, can not load"); return Result.FAIL; } Notify($"Start"); return Result.RUN; } public Result Monitor() { try { Clamp((int)RoutineStep.Clamp, _lp, _timeout); //Dock((int)RoutineStep.Dock, _lp, _timeout); OpenDoor((int)RoutineStep.OpenDoor, _lp, _timeout); //if (_lp.GetCurrentWaferSize()!=WaferSize.WS12) //{ // QueryStatus((int)RoutineStep.QueryStatus1, _lp, _timeout); // WaitRobotIdle((int)RoutineStep.WaitRobotIdle, _lp, _timeout); // Map((int)RoutineStep.Map, _lp, _timeout); //} if (_lp.GetCurrentWaferSize() == WaferSize.WS12) { QueryMapInfo((int)RoutineStep.GetWaferInfo, _lp, _timeout); } QueryStatus((int)RoutineStep.QueryStatus2, _lp, _timeout); } catch (RoutineBreakException) { return Result.RUN; } catch (RoutineFaildException ex) { LOG.Write(ex); return Result.FAIL; } Notify("Finished"); return Result.DONE; } public void OpenDoor(int id, LoadPort lp, int timeout) { Tuple ret = ExecuteAndWait(id, () => { Notify($"Start OpenDoorAndMap {lp.Name}"); string reason; if (!lp.OpenDoor(out reason)) { Stop(reason); return false; } return true; }, () => { if (_lp.Error) return false; if (_lp.IsBusy) return false; return true; }, timeout * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { Stop(string.Format("failed.")); throw (new RoutineFaildException()); } else if (ret.Item2 == Result.TIMEOUT) //timeout { Stop(string.Format("timeout, can not complete in {0} seconds", timeout)); throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } public void Dock(int id, LoadPort lp, int timeout) { Tuple ret = ExecuteAndWait(id, () => { Notify($"Start Dock {lp.Name}"); string reason; if (!lp.Dock(out reason)) { Stop(reason); return false; } return true; }, () => { if (_lp.Error) return false; if (_lp.IsBusy) return false; return true; }, timeout * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { Stop(string.Format("failed.")); throw (new RoutineFaildException()); } else if (ret.Item2 == Result.TIMEOUT) //timeout { Stop(string.Format("timeout, can not complete in {0} seconds", timeout)); throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } public void WaitRobotIdle(int id, LoadPort lp, int timeout) { Tuple ret = Wait(id, () => { if(WaferManager.Instance.CheckHasWafer(ModuleName.EfemRobot,0)) return false; if(_efem.IsBusy) return false; if (_lp.Error) return false; if (_lp.IsBusy) return false; if (_efem.RobotDevice.IsError) return null; if (_efem.RobotDevice.IsIdle) return true; return false; }, timeout * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { Stop(string.Format("failed.")); throw (new RoutineFaildException()); } else if (ret.Item2 == Result.TIMEOUT) //timeout { Stop(string.Format("timeout, can not complete in {0} seconds", timeout)); throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } public void Map(int id, LoadPort lp, int timeout) { Tuple ret = ExecuteAndWait(id, () => { Notify($"Start map {lp.Name}"); string reason; if (!_efem.RobotDevice.Map(ModuleHelper.Converter(_lp.Module), 0, out reason)) { Stop(reason); return false; } return true; }, () => { if (_efem.RobotDevice.IsError) return false; if (_efem.RobotDevice.IsIdle) return true; return false; }, timeout * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { Stop(string.Format("failed.")); throw (new RoutineFaildException()); } else if (ret.Item2 == Result.TIMEOUT) //timeout { Stop(string.Format("timeout, can not complete in {0} seconds", timeout)); throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } public void Clamp(int id, LoadPort lp, int timeout) { Tuple ret = ExecuteAndWait(id, () => { Notify($"Start clamp {lp.Name}"); string reason; if (!lp.Clamp(out reason)) { Stop(reason); return false; } return true; }, () => { if (_lp.Error) return false; if (_lp.IsBusy) return false; return true; }, timeout * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { Stop(string.Format("failed.")); throw (new RoutineFaildException()); } else if (ret.Item2 == Result.TIMEOUT) //timeout { Stop(string.Format("timeout, can not complete in {0} seconds", timeout)); throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } public void QueryMapInfo(int id, LoadPort lp, int timeout) { Tuple ret = ExecuteAndWait(id, () => { Notify($"Start to get wafer info {lp.Name}"); //string reason; if (!lp.GetMapInfo(out string reason)) { Stop(reason); return false; } return true; }, () => { if (_lp.Error) return false; if (_lp.IsBusy) return false; return true; }, timeout * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { Stop(string.Format("failed.")); throw (new RoutineFaildException()); } else if (ret.Item2 == Result.TIMEOUT) //timeout { Stop(string.Format("timeout, can not complete in {0} seconds", timeout)); throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } public void QueryStatus(int id, LoadPort lp, int timeout) { Tuple ret = ExecuteAndWait(id, () => { Notify($"Start query status {lp.Name}"); string reason; if (!lp.QueryState(out reason)) { Stop(reason); return false; } return true; }, () => { if (_lp.Error) return false; if (_lp.IsBusy) return false; return true; }, timeout * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { Stop(string.Format("Query status failed.")); throw (new RoutineFaildException()); } else if (ret.Item2 == Result.TIMEOUT) //timeout { Stop(string.Format("Home timeout, can not complete in {0} seconds", timeout)); throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } public void Abort() { } } }