using System; using System.Collections.Generic; using Aitex.Core.Common; using Aitex.Core.RT.Device; using Aitex.Core.RT.Device.Devices; using Aitex.Core.RT.Device.Unit; using Aitex.Core.RT.Event; using Aitex.Core.RT.Routine; using Aitex.Core.RT.SCCore; using MECF.Framework.Common.Equipment; using MECF.Framework.Common.Schedulers; using MECF.Framework.Common.SubstrateTrackings; using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Aligners; using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.PMs; using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Robots; using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Robots.RobotBase; using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.TMs; using SicModules.Devices; namespace SicModules.TMs { public class TMBaseRoutine : ModuleRoutine, IRoutine { public bool IsPicking = false; //机械手是否在Pick和Place过程中,在此过程中Abort不停止机械手动作 protected RobotBaseDevice RobotDevice { get { return _robot; } } protected TM TMDevice { get { return _tm; } } protected IoLift4 LoadLift { get { return _loadLift; } } protected IoLift4 UnLoadLift { get { return _unLoadLift; } } protected bool _isATMMode; private RobotBaseDevice _robot = null; private RobotBaseDevice _casseteRobot = null; private TM _tm = null; protected IoSensor SensorLLTrayPresence = null; protected IoSensor SensorUnloadWaferPresence = null; protected IoSensor SensorBufferHighWaferPresence = null; protected IoSensor SensorBufferMiddleWaferPresence = null; protected IoSensor SensorBufferLowWaferPresence = null; private IoInterLockEx _tmIoInterLock; //传盘后PM腔检查Tray是否放好Sensor public IoSensor _reactorSuspectorCheckPM1; public IoSensor _reactorSuspectorCheckPM2; private IoLift4 _loadLift; private IoLift4 _unLoadLift; public TMBaseRoutine() : base(ModuleName.TM.ToString()) { Module = ModuleName.TM.ToString(); _robot = DEVICE.GetDevice($"{ModuleName.TMRobot}.{ModuleName.TMRobot}"); _tm = DEVICE.GetDevice($"{ModuleName.System}.{ModuleName.TM}"); _isATMMode = SC.GetValue("System.IsATMMode"); SensorLLTrayPresence = DEVICE.GetDevice($"{ModuleName.TM}.LLTrayPresence"); SensorUnloadWaferPresence = DEVICE.GetDevice($"{ModuleName.TM}.UnLoadWaferPlaced"); SensorBufferHighWaferPresence = DEVICE.GetDevice($"{ModuleName.TM}.BufferWaferHigh"); SensorBufferMiddleWaferPresence = DEVICE.GetDevice($"{ModuleName.TM}.BufferWaferMiddle"); SensorBufferLowWaferPresence = DEVICE.GetDevice($"{ModuleName.TM}.BufferWaferLow"); _tmIoInterLock = DEVICE.GetDevice("TM.IoInterLock"); _loadLift = DEVICE.GetDevice($"{ModuleName.LoadLock}.LLLift"); _unLoadLift = DEVICE.GetDevice($"{ModuleName.UnLoad}.UnLoadLift"); _reactorSuspectorCheckPM1 = DEVICE.GetDevice($"PM1.SensorReactorSuspectorCheck"); _reactorSuspectorCheckPM2 = DEVICE.GetDevice($"PM2.SensorReactorSuspectorCheck"); } public virtual Result Start(params object[] objs) { return Result.DONE; } public virtual Result Monitor() { return Result.DONE; } public virtual void Abort() { _tm.SetAllValvesClose(out string reason); } /// /// this method should be call just after check load /// /// protected void UpdateWaferInfoByRobotSensor(int id, RobotBaseDevice robot) { Tuple ret = Execute(id, () => { Notify($"Update wafer info by robot wafer present"); if (robot.IsWaferPresenceOnBlade1 && WaferManager.Instance.CheckNoTray(ModuleHelper.Converter(robot.Module), 0)) { EV.PostInfoLog(Module, "TM Robot sensor found wafer on blade 1"); WaferManager.Instance.CreateWafer(ModuleHelper.Converter(robot.Module), 0, WaferStatus.Normal); } if (!robot.IsWaferPresenceOnBlade1 && WaferManager.Instance.CheckHasTray(ModuleHelper.Converter(robot.Module), 0)) { EV.PostInfoLog(Module, "TM Robot sensor no wafer on blade 1"); WaferManager.Instance.DeleteWafer(ModuleHelper.Converter(robot.Module), 0); } if (robot.IsWaferPresenceOnBlade2 && WaferManager.Instance.CheckNoTray(ModuleHelper.Converter(robot.Module), 1)) { EV.PostInfoLog(Module, "TM Robot sensor found wafer on blade 2"); WaferManager.Instance.CreateWafer(ModuleHelper.Converter(robot.Module), 1, WaferStatus.Normal); } if (!robot.IsWaferPresenceOnBlade2 && WaferManager.Instance.CheckHasTray(ModuleHelper.Converter(robot.Module), 1)) { EV.PostInfoLog(Module, "TM Robot sensor no wafer on blade 2"); WaferManager.Instance.DeleteWafer(ModuleHelper.Converter(robot.Module), 1); } return true; }); if (ret.Item1) { throw (new RoutineBreakException()); } } protected void UpdateWaferInfoDueHandoff(int id, ModuleName moduleFrom, int slotFrom, ModuleName moduleTo, int slotTo) { Tuple ret = Execute(id, () => { Notify($"Update wafer info because of handoff"); WaferManager.Instance.WaferMoved(moduleFrom, slotFrom, moduleTo, slotTo); return true; }); if (ret.Item1) { throw (new RoutineBreakException()); } } protected void ClearRobortExtendToDO(int id) { Tuple ret = Execute(id, () => { Notify("Clear RobortExtendTO DO"); _tmIoInterLock.DoVacRobotExtenLLEnable = false; _tmIoInterLock.DoVacRobotExtendBufferEnable = false; _tmIoInterLock.DoVacRobotExtendPMAEnable = false; _tmIoInterLock.DoVacRobotExtendPMBEnable = false; _tmIoInterLock.DoVacRobotExtendUnloadEnable = false; return true; }); } protected void WaitPMReadySensor(int id, ModuleName md, int timeout) { Tuple ret = ExecuteAndWait(id, () => { return true; }, () => { if (ModuleHelper.IsPm(md)) { if(md == ModuleName.PM1) { return _tmIoInterLock.DoRectorAATMTransferReady || _tmIoInterLock.DoRectorAProcessTransferReady; } else { return _tmIoInterLock.DoRectorBATMTransferReady || _tmIoInterLock.DoRectorBProcessTransferReady; } } else { return true; } }, timeout * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { throw (new RoutineFaildException()); } else if (ret.Item2 == Result.TIMEOUT) //timeout { Stop($"Wait ReactorATMTransferReady or RectorProcessTransferReady timeout over {timeout} seconds"); throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } /// /// 发送DO信号 /// /// protected void SetRobortExtendToDO(int id, ModuleName target, int timeout) { Tuple ret = ExecuteAndWait(id, () => { Notify("Set RobortExtendTO DO"); _tmIoInterLock.DoVacRobotExtendBufferEnable = false; _tmIoInterLock.DoVacRobotExtendPMAEnable = false; _tmIoInterLock.DoVacRobotExtendPMBEnable = false; _tmIoInterLock.DoVacRobotExtendUnloadEnable = false; _tmIoInterLock.DoVacRobotExtenLLEnable = false; if (ModuleHelper.IsLoadLock(target) || target == ModuleName.Load) { if (!_tmIoInterLock.SetRobotExtenLLEnable(true, out string reasen)) { Notify(reasen); return false; } } else if (target == ModuleName.UnLoad) { if (!_tmIoInterLock.SetRobotExtendUnLoadEnable(true, out string reasen)) { Notify(reasen); return false; } } else if (ModuleHelper.IsBuffer(target)) { if (!_tmIoInterLock.SetRobotExtendBufferEnable(true, out string reasen)) { Notify(reasen); return false; } } else if (target == ModuleName.PMA || target == ModuleName.PM1) { if (!_tmIoInterLock.SetRobotExtendPMAEnable(true, out string reasen)) { Notify(reasen); return false; } } else if (target == ModuleName.PMB || target == ModuleName.PM2) { if (!_tmIoInterLock.SetRobotExtendPMBEnable(true, out string reasen)) { Notify(reasen); return false; } } return true; }, () => { if (ModuleHelper.IsLoadLock(target) || target == ModuleName.Load) { return _tmIoInterLock.DiVacRobotExtenLLEnableFB; } else if (target == ModuleName.UnLoad) { return _tmIoInterLock.DiVacRobotExtendUnloadEnableFB; } else if (ModuleHelper.IsBuffer(target)) { return _tmIoInterLock.DiVacRobotExtendBufferEnableFB; } else if (target == ModuleName.PMA || target == ModuleName.PM1) { return _tmIoInterLock.DiVacRobotExtendPMAEnableFB; } else if (target == ModuleName.PMB || target == ModuleName.PM2) { return _tmIoInterLock.DiVacRobotExtendPMBEnableFB; } return true; }, timeout * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { throw (new RoutineFaildException()); } else if (ret.Item2 == Result.TIMEOUT) //timeout { Stop($"Set Robot extend to Do timeout over {timeout} seconds"); throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } public void RobotRequestWaferPresent(int id, RobotBaseDevice robot, RobotArmEnum arm, int timeout) { Tuple ret = ExecuteAndWait(id, () => { Notify("request wafer present"); List parm = new List() { "QueryWaferPresent", arm }; if (!robot.ReadParameter(parm.ToArray())) { EV.PostAlarmLog(Module, $"Can not request wafer present"); return false; } return true; }, () => { if (robot.IsReady()) { return true; } return false; }, timeout * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { throw (new RoutineFaildException()); } else if (ret.Item2 == Result.TIMEOUT) //timeout { Stop($"timeout over {timeout} seconds"); throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } public void RobotRequestWaferAWCData(int id, RobotBaseDevice robot, int timeout) { Tuple ret = ExecuteAndWait(id, () => { Notify("request wafer AWC Data"); List parm = new List() { "QueryWaferCentData" }; if (!robot.ReadParameter(parm.ToArray())) { EV.PostAlarmLog(Module, $"Can not request wafer AWC Data"); return false; } return true; }, () => { if (robot.IsReady()) { return true; } return false; }, timeout * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { Stop("robot error"); throw (new RoutineFaildException()); } else if (ret.Item2 == Result.TIMEOUT) //timeout { Stop($"timeout over {timeout} seconds"); throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } protected void CheckWaferInfoByRobotRQ(int id, RobotBaseDevice robot, RobotArmEnum hand, int timeOut) { string strMessage = ""; Tuple ret = Wait(id, () => { if (SC.GetValue("System.IsSimulatorMode")) return true; if (hand == RobotArmEnum.Blade1 || hand == RobotArmEnum.Both) { if (!robot.IsWaferPresenceOnBlade1 && WaferManager.Instance.CheckHasTray(ModuleHelper.Converter(robot.Module), 0)) { strMessage = "Robort sensor no wafer and UI have tray!"; return false; } if (robot.IsWaferPresenceOnBlade1 && !WaferManager.Instance.CheckHasTray(ModuleHelper.Converter(robot.Module), 0)) { strMessage = "Robort sensor have wafer and UI no tray!"; return false; } } if (hand == RobotArmEnum.Blade2 || hand == RobotArmEnum.Both) { if (robot.IsWaferPresenceOnBlade2 && !WaferManager.Instance.CheckHasTray(ModuleHelper.Converter(robot.Module), 1)) { EV.PostWarningLog(Module, "TM Robot sensor found wafer on blade 2"); return false; } if (!robot.IsWaferPresenceOnBlade2 && !WaferManager.Instance.CheckHasTray(ModuleHelper.Converter(robot.Module), 1)) { EV.PostWarningLog(Module, "TM Robot sensor no wafer on blade 2"); return false; } } return true; }, timeOut); if (ret.Item1) { if (ret.Item2 == Result.TIMEOUT) { Stop($"check wafer info failed." + strMessage); throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } protected void CheckReactorSuspector(int id,ModuleName module) { Tuple ret = Execute(id, () => { if (SC.GetValue($"PM.{module.ToString()}.ReactorSuspectorCheckEnable")) { if(module == ModuleName.PM1) { if (_reactorSuspectorCheckPM1.Value) { EV.PostAlarmLog(Module, $"check {module.ToString()} suspector sensor have tray"); return false; } } else { if (_reactorSuspectorCheckPM2.Value) { EV.PostAlarmLog(Module, $"check {module.ToString()} suspector sensor have tray"); return false; } } } return true; }); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } protected void CheckWaferInfoByRobotSensor(int id, RobotBaseDevice robot, RobotArmEnum hand, int timeOut) { Notify($"check wafer info by robot sensor present"); string strMessage = ""; Tuple ret = Wait(id, () => { if (SC.GetValue("System.IsSimulatorMode")) return true; if (hand == RobotArmEnum.Blade1 || hand == RobotArmEnum.Both) { if (!robot.IsWaferPresenceOnBlade1 && WaferManager.Instance.CheckHasWafer(robot.Module, 0)) { strMessage = "Robort sensor no wafer and UI have wafer!!"; return false; } if (robot.IsWaferPresenceOnBlade1 && WaferManager.Instance.CheckNoWafer(robot.Module, 0)) { strMessage = "Robort sensor have wafer and UI no wafer!!"; return false; } } if (hand == RobotArmEnum.Blade2 || hand == RobotArmEnum.Both) { if (robot.IsWaferPresenceOnBlade2 && WaferManager.Instance.CheckNoWafer(robot.Module, 1)) { EV.PostWarningLog(Module, "TM Robot sensor found wafer on blade 2"); return false; } if (!robot.IsWaferPresenceOnBlade2 && WaferManager.Instance.CheckHasWafer(robot.Module, 1)) { EV.PostWarningLog(Module, "TM Robot sensor no wafer on blade 2"); return false; } } return true; }, timeOut); if (ret.Item1) { if (ret.Item2 == Result.TIMEOUT) { Stop($"check wafer info failed.." + strMessage); throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } protected void WaitSlitValveOpenInterlock(int id, IoSlitValve slitValve, int timeout) { Tuple ret = Wait(id, () => { return slitValve != null; }, timeout * 1000); if (ret.Item1) { if (ret.Item2 == Result.TIMEOUT) //timeout { Stop($"wait {slitValve.Name} open timeout, over {timeout} seconds"); throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } protected void WaitSlitValveCloseInterlock(int id, IoSlitValve slitValve, int timeout) { Tuple ret = Wait(id, () => { return slitValve == null; }, timeout * 1000); if (ret.Item1) { if (ret.Item2 == Result.TIMEOUT) //timeout { Stop($"wait {slitValve.Name} close timeout, over {timeout} seconds"); throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } protected void QueryOffset(int id, AlignerBase aligner, int timeout) { //Tuple ret = ExecuteAndWait(id, () => //{ // Notify($"Query {Module} offset"); // string reason; // if (!aligner.QueryOffset(out reason)) // { // Stop(reason); // return false; // } // return true; //}, () => //{ // if (aligner.IsIdle) // { // EV.PostInfoLog(aligner.Module, $"{aligner.Module} offset RO={aligner.RadialOffset} TO={aligner.ThetaOffset}"); // 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()); //} } protected void PickEx(int id, RobotBaseDevice robot, ModuleName source, int slot, RobotArmEnum hand, float ro, float to, int timeout) { Tuple ret = ExecuteAndWait(id, () => { Notify($"PickEX from {source} {slot + 1} use {(hand == RobotArmEnum.Blade1 ? "Blade1" : "Blade2")} RO={ro} TO={to}"); if (!robot.PickEx(hand, source.ToString(), slot, ro, to)) { robot.IsBusy = false; return false; } return true; }, () => { if (robot.IsReady()) return true; return false; }, timeout * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { Stop($"Pick failed, error {robot.ErrorCode}"); throw (new RoutineFaildException()); } else if (ret.Item2 == Result.TIMEOUT) //timeout { Stop(string.Format("pick timeout, can not complete in {0} seconds", timeout)); throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } protected void Pick(int id, RobotBaseDevice robot, ModuleName source, int slot, RobotArmEnum hand, int timeout) { Tuple ret = ExecuteAndWait(id, () => { IsPicking = true; Notify($"Pick from {source} {slot + 1} use {(hand == RobotArmEnum.Blade1 ? "Blade1" : "Blade2")}"); if (!robot.Pick(hand, source.ToString(), slot)) { robot.IsBusy = false; return false; } return true; }, () => { if (robot.IsReady()) return true; return false; }, timeout * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { Stop($"Pick failed, error {robot.ErrorCode}"); throw (new RoutineFaildException()); } else if (ret.Item2 == Result.TIMEOUT) //timeout { Stop(string.Format("pick timeout, can not complete in {0} seconds", timeout)); throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } public void PickExtend(int id, RobotBaseDevice robot, ModuleName source, int slot, RobotArmEnum hand, int timeout) { Tuple ret = ExecuteAndWait(id, () => { Notify($"Pick extend to {source} {slot + 1} use {(hand == RobotArmEnum.Blade1 ? "Blade1" : "Blade2")}"); List para = new List() { "ExtendForPick", hand, source, slot, false, true }; if (!robot.GoTo(para.ToArray())) { robot.IsBusy = false; return false; } return true; }, () => { if (robot.IsReady()) return true; return false; }, timeout * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { Stop($"Pick extend failed, error {robot.ErrorCode}"); 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 PickRetract(int id, RobotBaseDevice robot, ModuleName source, int slot, RobotArmEnum hand, int timeout) { Tuple ret = ExecuteAndWait(id, () => { Notify("send command to device"); List para = new List() { "RetractFromPick", hand, source, slot, true, true }; if (!robot.GoTo(para.ToArray())) { robot.IsBusy = false; return false; } return true; }, () => { if (robot.IsReady()) return true; return false; }, timeout * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { Stop($"Pick retract failed, error {robot.ErrorCode}"); 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 CheckBeforePick(int id, ModuleName source, int slot, RobotArmEnum blade) { Tuple ret = Execute(id, () => { Notify("Check pick condition"); string reason = string.Empty; if (!RobotDevice.IsReady()) { Stop("robot is not Ready."); return false; } if (blade == RobotArmEnum.Blade1) { if (!WaferManager.Instance.CheckHasWafer(source, slot) && !WaferManager.Instance.CheckHasTray(source, slot)) { Stop("Source no wafer"); return false; } if (!WaferManager.Instance.CheckNoWafer(Module, 0)) { Stop("Blade has wafer"); return false; } } else if (blade == RobotArmEnum.Blade2) { if (!WaferManager.Instance.CheckHasWafer(source, slot)) { Stop("Source no wafer"); return false; } if (!WaferManager.Instance.CheckNoWafer(Module, 1)) { Stop("Blade has wafer"); return false; } } else { for (int i = 0; i < 2; i++) { if (!WaferManager.Instance.CheckHasWafer(source, slot + i)) { Stop("Source no wafer"); return false; } if (!WaferManager.Instance.CheckNoWafer(Module, i)) { Stop("Blade has wafer"); return false; } } } return true; }); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { throw (new RoutineFaildException()); } } } public void CheckBeforeExtend(int id, ModuleName target, int slot, RobotArmEnum blade) { Tuple ret = Execute(id, () => { Notify("Check extend condition"); string reason = string.Empty; if (RobotDevice.IsReady()) { Stop("robot is not Ready."); return false; } return true; }); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { throw (new RoutineFaildException()); } } } public void Extend(int id, RobotBaseDevice robot, ModuleName source, int slot, RobotArmEnum hand, int timeout) { Tuple ret = ExecuteAndWait(id, () => { Notify("send extend command to device"); List para = new List() { hand, source, slot, false, true }; if (!robot.GoTo(para.ToArray())) { return false; } return true; }, () => { if (robot.IsReady()) return true; return false; }, timeout * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { Stop($"Extend failed, error {robot.ErrorCode}"); 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 Retract(int id, RobotBaseDevice robot, ModuleName source, int slot, RobotArmEnum hand, int timeout) { Tuple ret = ExecuteAndWait(id, () => { Notify("send retract command to device"); List para = new List() { hand, source, slot, true, true }; if (!robot.GoTo(para.ToArray())) { return false; } return true; }, () => { if (robot.IsReady()) return true; return false; }, timeout * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { Stop($"Retract failed, error {robot.ErrorCode}"); 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()); } } //protected void SetShutter(int id, CoralPM pm, bool isOpen, int timeout) //{ // Tuple ret = ExecuteAndWait(id, () => // { // Notify($"Set shutter {(isOpen ? "open" : "close")}"); // if (!pm.SetShutter(isOpen, out string reason)) // { // Stop($"{pm.Name} {reason}"); // return false; // } // return true; // }, () => // { // if (isOpen && pm.CheckShutterDown()) // { // return true; // } // if (!isOpen && pm.CheckShutterUp()) // { // return true; // } // return false; // }, timeout * 1000); // if (ret.Item1) // { // if (ret.Item2 == Result.FAIL) // { // Stop($"{pm.Name} error"); // throw (new RoutineFaildException()); // } // else if (ret.Item2 == Result.TIMEOUT) //timeout // { // Stop($"{pm.Name} shutter operate timeout, over {timeout} seconds"); // throw (new RoutineFaildException()); // } // else // throw (new RoutineBreakException()); // } //} protected void PrepareTransfer(int id, PM pm, EnumTransferType type, int timeout) { Tuple ret = ExecuteAndWait(id, () => { string reason = ""; Notify($"Run {pm.Name} prepare transfer "); pm.PrepareTransfer(type, out reason); return true; }, () => { if (pm.IsError) { return null; } return pm.IsIdle && pm.CheckEnableTransfer(type, out string reason); }, timeout * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { Stop($"{pm.Name} error"); throw (new RoutineFaildException()); } else if (ret.Item2 == Result.TIMEOUT) //timeout { Stop($"{pm.Name} prepare transfer timeout, over {timeout} seconds"); throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } protected void PrepareTransferNotWait(int id, PM pm, EnumTransferType type, int timeout) { Tuple ret = ExecuteAndWait(id, () => { string reason = ""; Notify($"Run {pm.Name} prepare transfer "); pm.PrepareTransfer(type, out reason); return true; }, () => { return true; }, timeout * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { Stop($"{pm.Name} error"); throw (new RoutineFaildException()); } else if (ret.Item2 == Result.TIMEOUT) //timeout { Stop($"{pm.Name} prepare transfer timeout, over {timeout} seconds"); throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } protected void CheckTransferPrepared(int id, PM pm, EnumTransferType type, int timeout) { Tuple ret = ExecuteAndWait(id, () => { Notify($"Check {pm.Name} transfer prepared"); return true; }, () => { if (pm.IsError) { return null; } return pm.IsIdle && pm.CheckEnableTransfer(type, out string reason); }, timeout * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { throw (new RoutineFaildException()); } else if (ret.Item2 == Result.TIMEOUT) //timeout { Stop($"{pm.Name} prepare transfer timeout, over {timeout} seconds"); throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } public void TransferHandoff(int id, PM pm, EnumTransferType type, int timeout) { Tuple ret = ExecuteAndWait(id, () => { Notify("send handoff command to device"); pm.TransferHandoff(type); return true; }, () => { if (pm.IsError) { return null; } return pm.IsIdle && pm.CheckHandoff(type); }, timeout * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { Stop($"{pm.Name} error"); throw (new RoutineFaildException()); } else if (ret.Item2 == Result.TIMEOUT) //timeout { Stop($"{pm.Name} transfer handoff timeout, over {timeout} seconds"); throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } //public void PostTransfer(int id, PMEntity pmEntity, PM pm, EnumTransferType type, int timeout) //{ // Tuple ret = ExecuteAndWait(id, () => // { // Notify($"Run {pm.Name} post transfer "); // pmEntity.InvokePostTransfer(type); // return true; // }, () => // { // if (pm.IsError) // { // return null; // } // return pm.IsIdle && pm.CheckPostTransfer(type); // }, timeout * 1000); // if (ret.Item1) // { // if (ret.Item2 == Result.FAIL) // { // Stop($"{pm.Name} error"); // throw (new RoutineFaildException()); // } // else if (ret.Item2 == Result.TIMEOUT) //timeout // { // Stop($"{pm.Name} post transfer timeout, over {timeout} seconds"); // throw (new RoutineFaildException()); // } // else // throw (new RoutineBreakException()); // } //} public void CheckBeforePlace(int id, ModuleName target, int slot, RobotArmEnum blade) { Tuple ret = Execute(id, () => { Notify("Check place condition"); string reason = string.Empty; if (!RobotDevice.IsReady()) { Stop("robot is not Ready."); return false; } if (blade == RobotArmEnum.Blade1) { if (target != ModuleName.LoadLock && target != ModuleName.Load) { if (WaferManager.Instance.CheckHasWafer(target, slot)) { Stop($"Target {target}.{slot + 1} has wafer"); return false; } } if (WaferManager.Instance.CheckHasTray(target, slot)) { Stop($"Target {target}.{slot + 1} has tray"); return false; } if (!WaferManager.Instance.CheckHasWafer(Module, 0) && !WaferManager.Instance.CheckHasTray(ModuleHelper.Converter(Module), 0)) { Stop("Blade no wafer"); return false; } } else if (blade == RobotArmEnum.Blade2) { if (!WaferManager.Instance.CheckNoWafer(target, slot)) { Stop($"Target {target}.{slot + 1} has wafer"); return false; } if (!WaferManager.Instance.CheckHasWafer(Module, 1)) { Stop("Blade no wafer"); return false; } } else { for (int i = 0; i < 2; i++) { if (!WaferManager.Instance.CheckNoWafer(target, slot + i)) { Stop("Target has wafer"); return false; } if (!WaferManager.Instance.CheckHasWafer(Module, i)) { Stop("Blade no wafer"); return false; } } } return true; }); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { throw (new RoutineFaildException()); } } } public void Place(int id, RobotBaseDevice robot, ModuleName target, int slot, RobotArmEnum hand, int timeout) { Tuple ret = ExecuteAndWait(id, () => { IsPicking = true; Notify($"Place to {target} {slot + 1} use {(hand == RobotArmEnum.Blade1 ? "Blade1" : "Blade2")}"); if (!robot.Place(hand, target.ToString(), slot)) { robot.IsBusy = false; return false; } return true; }, () => { if (robot.IsReady()) return true; if (robot.IsError) return null; return false; }, timeout * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { Stop($"Place failed, error {robot.ErrorCode}"); throw (new RoutineFaildException()); } else if (ret.Item2 == Result.TIMEOUT) //timeout { Stop(string.Format("place timeout, can not complete in {0} seconds", timeout)); throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } public void PlaceExtend(int id, RobotBaseDevice robot, ModuleName source, int slot, RobotArmEnum hand, int timeout) { Tuple ret = ExecuteAndWait(id, () => { Notify($"Place extend to {source} {slot + 1} use {(hand == RobotArmEnum.Blade1 ? "Blade1" : "Blade2")}"); List para = new List() { "ExtendForPlace", hand, source, slot, false, true }; if (!robot.GoTo(para.ToArray())) { robot.IsBusy = false; return false; } return true; }, () => { if (robot.IsReady()) return true; return false; }, timeout * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { Stop($"Place extend failed, error {robot.ErrorCode}"); 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 PlaceRetract(int id, RobotBaseDevice robot, ModuleName source, int slot, RobotArmEnum hand, int timeout) { Tuple ret = ExecuteAndWait(id, () => { Notify("place retract"); List para = new List() { "RetractFromPlace", hand, source, slot, true, true }; if (!robot.GoTo(para.ToArray())) { robot.IsBusy = false; return false; } return true; }, () => { if (robot.IsReady()) return true; return false; }, timeout * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { Stop($"Place retract failed, error {robot.ErrorCode}"); 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()); } } protected void RobotGotoNotWait(int id, RobotBaseDevice robot, ModuleName source, int slot, RobotArmEnum hand, int timeout) { Tuple ret = ExecuteAndWait(id, () => { Notify($"Goto {source} {slot + 1} use {(hand == RobotArmEnum.Blade1 ? "Blade1" : "Blade2")}"); List para = new List() { "GoTo", hand, source, slot, true, true }; if (!robot.GoTo(para.ToArray())) { robot.IsBusy = false; return false; } return true; }, () => { return true; }, timeout * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { Stop($"Goto failed, error {robot.ErrorCode}"); 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()); } } protected void CheckRobotReady(int id, RobotBaseDevice robot, int timeout) { Tuple ret = ExecuteAndWait(id, () => { Notify($"Check robot ready"); return true; }, () => { if (robot.IsReady()) return true; return false; }, timeout * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { 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 CloseTMVent(int id) { Tuple ret = Execute(id, () => { Notify($"Close {TMDevice.Name} vent valve"); if (!TMDevice.SetFastVentValve(false, out string reason)) { Stop(reason); return false; } return true; }); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } public void OpenBufferVent(int id) { Tuple ret = Execute(id, () => { Notify($"Open Buffer vent valve"); if (!TMDevice.SetBufferVentValve(true, out string reason)) { Stop(reason); return false; } return true; }); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } public void CloseBufferVent(int id) { Tuple ret = Execute(id, () => { Notify($"Close Buffer vent valve"); if (!TMDevice.SetBufferVentValve(false, out string reason)) { Stop(reason); return false; } return true; }); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } public void OpenSlowPump(int id, TM tm, double basePressure, int timeout) { Tuple ret = ExecuteAndWait(id, () => { Notify($"Open {tm.Name} slow pump valve"); if (!tm.SetSlowPumpValve(true, out string reason)) { Stop(reason); return false; } return true; }, () => { return tm.ChamberPressure <= basePressure; }, timeout * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { throw (new RoutineFaildException()); } else if (ret.Item2 == Result.TIMEOUT) //timeout { tm.SetFastPumpValve(false, out string _); Stop($"{tm.Name} pressure can not pump to {basePressure} in {timeout} seconds"); throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } public void CloseSlowPump(int id, TM tm) { Tuple ret = Execute(id, () => { Notify($"Close {tm.Name} pump valves"); if (!_tm.SetSlowPumpValve(false, out string reason)) { Stop(reason); return false; } return true; }); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } public void OpenFastPump(int id, TM tm, double basePressure, int timeout) { Tuple ret = ExecuteAndWait(id, () => { Notify($"Open {tm.Name} pump valve"); if (!tm.SetFastPumpValve(true, out string reason)) { Stop(reason); return false; } return true; }, () => { return tm.ChamberPressure <= basePressure; }, timeout * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { throw (new RoutineFaildException()); } else if (ret.Item2 == Result.TIMEOUT) //timeout { tm.SetFastPumpValve(false, out string _); Stop($"{tm.Name} pressure can not pump to {basePressure} in {timeout} seconds"); throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } public void CloseFastPump(int id, TM tm) { Tuple ret = Execute(id, () => { Notify($"Close {tm.Name} pump valves"); if (!_tm.SetFastPumpValve(false, out string reason)) { Stop(reason); return false; } return true; }); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } public void CloseFastPump(int id) { Tuple ret = Execute(id, () => { Notify($"Close {TMDevice.Name} Fast pump valve"); if (!TMDevice.SetFastPumpValve(false, out string reason)) { Stop(reason); return false; } return true; }); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } public void CloseSlowPump(int id) { Tuple ret = Execute(id, () => { Notify($"Close {TMDevice.Name} Slow pump valve"); if (!TMDevice.SetSlowPumpValve(false, out string reason)) { Stop(reason); return false; } return true; }); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } public void SetMFCToSetPoint(int id, IoMFC _mfc, double setPoint) { Tuple ret = Execute(id, () => { Notify($"Set MFC value to default"); _mfc.Ramp(setPoint, 0); return true; }); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } public void OpenFastVent(int id, TM tm, double basePressure, int timeout) { Tuple ret = ExecuteAndWait(id, () => { Notify($"Open {tm.Name} slow vent valve"); if (!tm.SetFastVentValve(true, out string reason)) { Stop(reason); return false; } return true; }, () => { return tm.ChamberPressure >= basePressure; }, timeout * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { throw (new RoutineFaildException()); } else if (ret.Item2 == Result.TIMEOUT) //timeout { tm.SetFastVentValve(false, out string _); Stop($"{tm.Name} pressure can not vent to {basePressure} in {timeout} seconds"); throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } public void OpenSlowVent(int id, TM tm, double basePressure, int timeout) { Tuple ret = ExecuteAndWait(id, () => { Notify($"Open {tm.Name} slow vent valve"); if (!tm.SetSlowVentValve(true, out string reason)) { Stop(reason); return false; } return true; }, () => { return tm.ChamberPressure >= basePressure; }, timeout * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { throw (new RoutineFaildException()); } else if (ret.Item2 == Result.TIMEOUT) //timeout { tm.SetFastVentValve(false, out string _); Stop($"{tm.Name} pressure can not vent to {basePressure} in {timeout} seconds"); throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } public void CloseSlowVentValve(int id, TM tm) { Tuple ret = Execute(id, () => { Notify($"Close {tm.Name} fast pump valve"); if (!tm.SetSlowVentValve(false, out string reason)) { Stop(reason); return false; } return true; }); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } } }