810 lines
27 KiB
C#
810 lines
27 KiB
C#
using System;
|
||
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.SubstrateTrackings;
|
||
using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Aligners.HwAligner;
|
||
using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.EFEM;
|
||
using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Robots;
|
||
using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Robots.RobotBase;
|
||
using static MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Robots.RobotBase.RobotBaseDevice;
|
||
using IoInterLock = SicModules.Devices.IoInterLock;
|
||
|
||
namespace SicModules.EFEMs.Routines.Base
|
||
{
|
||
public class EfemBaseRoutine : ModuleRoutine, IRoutine
|
||
{
|
||
private RobotBaseDevice _waferRobot = null;
|
||
private RobotBaseDevice _trayRobot = null;
|
||
private IEFEM _efemDevice;
|
||
|
||
public IoSensor _loadTrayHomeSensor; //Tray定位
|
||
public IoSensor _loadWaferPlaced; //上下对射,检测Wafer有无
|
||
public IoSensor _loadTrayPresence; //检测托盘有无
|
||
public IoSensor _cassAL6Inch; //6寸检测
|
||
public IoSensor _cassAR6Inch; //6寸检测
|
||
public IoSensor _cassBL6Inch; //6寸检测
|
||
|
||
public IoSensor _cassALWaferConvex; //凸片检测
|
||
public IoSensor _cassARWaferConvex; //凸片检测
|
||
public IoSensor _cassBLWaferConvex; //凸片检测
|
||
private IoInterLock _tmIoInterLock;
|
||
|
||
public IoLift4 _llLift;
|
||
public IoClaw _loadWaferClaw;
|
||
public IoLift4 _unLoadLift;
|
||
public IoClaw _unLoadWaferClaw;
|
||
|
||
private HwAlignerGuide _alignerDevice = null;
|
||
|
||
protected RobotBaseDevice WaferRobot
|
||
{
|
||
get { return _waferRobot; }
|
||
}
|
||
|
||
protected RobotBaseDevice TrayRobot
|
||
{
|
||
get { return _trayRobot; }
|
||
}
|
||
|
||
protected IEFEM EfemDevice
|
||
{
|
||
get { return _efemDevice; }
|
||
}
|
||
|
||
public EfemBaseRoutine() : base(ModuleName.EFEM.ToString())
|
||
{
|
||
_waferRobot = DEVICE.GetDevice<SicWaferRobot>($"WaferRobot.WaferRobot");
|
||
_trayRobot = DEVICE.GetDevice<SicTrayRobot>($"TrayRobot.TrayRobot");
|
||
_efemDevice = DEVICE.GetDevice<SicEFEM>($"EFEM.EFEM");
|
||
_loadTrayHomeSensor = DEVICE.GetDevice<IoSensor>($"TM.LoadTrayHomeSensor");
|
||
_alignerDevice = DEVICE.GetDevice<HwAlignerGuide>($"Aligner.HiWinAligner");
|
||
_loadWaferPlaced = DEVICE.GetDevice<IoSensor>($"TM.LLWaferPlaced");
|
||
_loadTrayPresence = DEVICE.GetDevice<IoSensor>($"TM.LLTrayPresence");
|
||
_cassBLWaferConvex = DEVICE.GetDevice<IoSensor>($"TM.CassBLWaferConvexSensor");
|
||
_cassALWaferConvex = DEVICE.GetDevice<IoSensor>($"TM.CassALWaferConvexSensor");
|
||
_cassARWaferConvex = DEVICE.GetDevice<IoSensor>($"TM.CassARWaferConvexSensor");
|
||
_cassAL6Inch = DEVICE.GetDevice<IoSensor>($"TM.CassALInch6Sensor");
|
||
_cassAR6Inch = DEVICE.GetDevice<IoSensor>($"TM.CassARInch6Sensor");
|
||
_cassBL6Inch = DEVICE.GetDevice<IoSensor>($"TM.CassBLInch6Sensor");
|
||
_tmIoInterLock = DEVICE.GetDevice<IoInterLock>("TM.IoInterLock");
|
||
|
||
_llLift= DEVICE.GetDevice<IoLift4>($"LoadLock.LLLift");
|
||
_unLoadLift= DEVICE.GetDevice<IoLift4>($"UnLoad.UnLoadLift");
|
||
|
||
_loadWaferClaw = DEVICE.GetDevice<IoClaw>($"LoadLock.LLWaferClaw");
|
||
_unLoadWaferClaw = DEVICE.GetDevice<IoClaw>($"UnLoad.UnLoadWaferClaw");
|
||
}
|
||
|
||
protected void CheckTraySensor(int id)
|
||
{
|
||
Tuple<bool, Result> ret = Execute(id, () =>
|
||
{
|
||
if (SC.GetValue<bool>($"System.IsSimulatorMode"))
|
||
{
|
||
return true;
|
||
}
|
||
return _loadTrayPresence.Value;
|
||
});
|
||
if (ret.Item1)
|
||
{
|
||
if (ret.Item2 == Result.FAIL)
|
||
{
|
||
Stop($"Sensor[DI-32] check no tray");
|
||
throw (new RoutineFaildException());
|
||
}
|
||
else
|
||
throw (new RoutineBreakException());
|
||
}
|
||
}
|
||
|
||
protected void ClearRobortExtendToDO(int id)
|
||
{
|
||
Tuple<bool, Result> ret = Execute(id, () =>
|
||
{
|
||
Notify("Clear RobortExtendTO DO");
|
||
_tmIoInterLock.DoATMRobotExtendLoaLSideEnable = false;
|
||
_tmIoInterLock.DoATMRobotExtendLoaRSideEnable = false;
|
||
_tmIoInterLock.DoATMRobotExtendUnloadEnable = false;
|
||
return true;
|
||
});
|
||
|
||
}
|
||
|
||
protected void Pick(int id, RobotBaseDevice robot, ModuleName source, int slot, int timeout)
|
||
{
|
||
Tuple<bool, Result> ret = ExecuteAndWait(id, () =>
|
||
{
|
||
Notify($"Pick from {source} {slot + 1} use Blade1 ");
|
||
if (!robot.Pick(MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Robots.RobotArmEnum.Blade1, 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}");
|
||
robot.Abort();
|
||
throw (new RoutineFaildException());
|
||
}
|
||
else if (ret.Item2 == Result.TIMEOUT) //timeout
|
||
{
|
||
robot.Abort();
|
||
Stop(string.Format("pick timeout, can not complete in {0} seconds", timeout));
|
||
throw (new RoutineFaildException());
|
||
}
|
||
else
|
||
throw (new RoutineBreakException());
|
||
}
|
||
}
|
||
|
||
protected void ExtendForPick(int id, RobotBaseDevice robot, ModuleName source, int slot, int timeout)
|
||
{
|
||
Tuple<bool, Result> ret = ExecuteAndWait(id, () =>
|
||
{
|
||
Notify($"ExtendForPick from {source} {slot + 1} use Blade1 ");
|
||
if (!robot.CheckToPostMessage(RobotMsg.ExtendForPick, RobotArmEnum.Blade1, 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($"ExtendForPick failed, error {robot.ErrorCode}");
|
||
robot.Abort();
|
||
throw (new RoutineFaildException());
|
||
}
|
||
else if (ret.Item2 == Result.TIMEOUT) //timeout
|
||
{
|
||
Stop(string.Format("ExtendForPick timeout, can not complete in {0} seconds", timeout));
|
||
robot.Abort();
|
||
throw (new RoutineFaildException());
|
||
}
|
||
else
|
||
throw (new RoutineBreakException());
|
||
}
|
||
}
|
||
|
||
protected void ExtendForPlace(int id, RobotBaseDevice robot, ModuleName source, int slot, int timeout)
|
||
{
|
||
Tuple<bool, Result> ret = ExecuteAndWait(id, () =>
|
||
{
|
||
Notify($"ExtendForPlace to {source} {slot + 1} use Blade1 ");
|
||
if (!robot.CheckToPostMessage(RobotMsg.ExtendForPlace, MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Robots.RobotArmEnum.Blade1, 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($"ExtendForPlace failed, error {robot.ErrorCode}");
|
||
robot.Abort();
|
||
throw (new RoutineFaildException());
|
||
}
|
||
else if (ret.Item2 == Result.TIMEOUT) //timeout
|
||
{
|
||
Stop(string.Format("ExtendForPlace timeout, can not complete in {0} seconds", timeout));
|
||
robot.Abort();
|
||
throw (new RoutineFaildException());
|
||
}
|
||
else
|
||
throw (new RoutineBreakException());
|
||
}
|
||
}
|
||
|
||
protected void RobotActionComplete(int id, RobotBaseDevice robot, int timeout)
|
||
{
|
||
Tuple<bool, Result> ret = ExecuteAndWait(id, () =>
|
||
{
|
||
Notify($"Robot Action Complete ");
|
||
if (!robot.CheckToPostMessage(RobotMsg.ActionDone))
|
||
{
|
||
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($"Robot Action failed, error {robot.ErrorCode}");
|
||
robot.Abort();
|
||
throw (new RoutineFaildException());
|
||
}
|
||
else if (ret.Item2 == Result.TIMEOUT) //timeout
|
||
{
|
||
Stop(string.Format("Robot Action timeout, can not complete in {0} seconds", timeout));
|
||
robot.Abort();
|
||
throw (new RoutineFaildException());
|
||
}
|
||
else
|
||
throw (new RoutineBreakException());
|
||
}
|
||
}
|
||
|
||
protected void Place(int id, RobotBaseDevice robot, ModuleName source, int slot, int timeout)
|
||
{
|
||
Tuple<bool, Result> ret = ExecuteAndWait(id, () =>
|
||
{
|
||
Notify($"Place wafer to {source} {slot + 1} use Blade1 ");
|
||
if (!robot.Place(MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Robots.RobotArmEnum.Blade1, 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($"Place failed, error {robot.ErrorCode}");
|
||
robot.Abort();
|
||
throw (new RoutineFaildException());
|
||
}
|
||
else if (ret.Item2 == Result.TIMEOUT) //timeout
|
||
{
|
||
robot.Abort();
|
||
Stop(string.Format("Place timeout, can not complete in {0} seconds", timeout));
|
||
throw (new RoutineFaildException());
|
||
}
|
||
else
|
||
throw (new RoutineBreakException());
|
||
}
|
||
}
|
||
|
||
protected void CheckWaferStatuBeforePick(int id, RobotBaseDevice robot, int timeout)
|
||
{
|
||
Tuple<bool, Result> ret = ExecuteAndWait(id, () =>
|
||
{
|
||
Notify($"Check Wafer Status Before Pick");
|
||
if (!robot.ExecuteCommand(new object[] { true }))
|
||
{
|
||
robot.IsBusy = false;
|
||
return false;
|
||
}
|
||
|
||
return true;
|
||
|
||
}, () =>
|
||
{
|
||
if (robot.IsReady())
|
||
{
|
||
if (WaferManager.Instance.CheckHasWafer(robot.Name, 0))
|
||
{
|
||
EV.PostWarningLog(ModuleName.EFEM.ToString(), "Robot Check Has Wafer!");
|
||
return null;
|
||
}
|
||
return true;
|
||
}
|
||
return false;
|
||
|
||
}, timeout * 1000);
|
||
|
||
if (ret.Item1)
|
||
{
|
||
if (ret.Item2 == Result.FAIL)
|
||
{
|
||
Stop($"Place failed, error {robot.ErrorCode}");
|
||
robot.Abort();
|
||
throw (new RoutineFaildException());
|
||
}
|
||
else if (ret.Item2 == Result.TIMEOUT) //timeout
|
||
{
|
||
robot.Abort();
|
||
Stop(string.Format("Place timeout, can not complete in {0} seconds", timeout));
|
||
throw (new RoutineFaildException());
|
||
}
|
||
else
|
||
throw (new RoutineBreakException());
|
||
}
|
||
}
|
||
|
||
protected void CheckWaferStatuAfterPlace(int id, RobotBaseDevice robot,int timeout)
|
||
{
|
||
Tuple<bool, Result> ret = ExecuteAndWait(id, () =>
|
||
{
|
||
Notify($"Check Wafer Status After Place");
|
||
if (!robot.ExecuteCommand(new object[] { true}))
|
||
{
|
||
robot.IsBusy = false;
|
||
return false;
|
||
}
|
||
|
||
return true;
|
||
|
||
}, () =>
|
||
{
|
||
if (robot.IsReady())
|
||
{
|
||
if (WaferManager.Instance.CheckHasWafer(robot.Name, 0))
|
||
{
|
||
EV.PostWarningLog(ModuleName.EFEM.ToString(), "Place Finished and Robot Check Has Wafer!");
|
||
return null;
|
||
}
|
||
return true;
|
||
|
||
}
|
||
return false;
|
||
|
||
}, timeout * 1000);
|
||
|
||
if (ret.Item1)
|
||
{
|
||
if (ret.Item2 == Result.FAIL)
|
||
{
|
||
Stop($"Place failed, error {robot.ErrorCode}");
|
||
robot.Abort();
|
||
throw (new RoutineFaildException());
|
||
}
|
||
else if (ret.Item2 == Result.TIMEOUT) //timeout
|
||
{
|
||
robot.Abort();
|
||
Stop(string.Format("Place timeout, can not complete in {0} seconds", timeout));
|
||
throw (new RoutineFaildException());
|
||
}
|
||
else
|
||
throw (new RoutineBreakException());
|
||
}
|
||
}
|
||
|
||
|
||
protected void CheckTrayStatuBeforePick(int id, RobotBaseDevice robot, int timeout)
|
||
{
|
||
Tuple<bool, Result> ret = ExecuteAndWait(id, () =>
|
||
{
|
||
Notify($"Check Tray Status Before Pick");
|
||
if (!robot.ExecuteCommand(new object[] { true }))
|
||
{
|
||
robot.IsBusy = false;
|
||
return false;
|
||
}
|
||
|
||
return true;
|
||
|
||
}, () =>
|
||
{
|
||
if (robot.IsReady())
|
||
{
|
||
if (WaferManager.Instance.CheckHasTray(ModuleHelper.Converter(robot.Name), 0))
|
||
{
|
||
EV.PostWarningLog(ModuleName.EFEM.ToString(), "Robot Check Has Tray!");
|
||
return null;
|
||
}
|
||
return true;
|
||
|
||
}
|
||
return false;
|
||
|
||
}, timeout * 1000);
|
||
|
||
if (ret.Item1)
|
||
{
|
||
if (ret.Item2 == Result.FAIL)
|
||
{
|
||
Stop($"Place failed, error {robot.ErrorCode}");
|
||
robot.Abort();
|
||
throw (new RoutineFaildException());
|
||
}
|
||
else if (ret.Item2 == Result.TIMEOUT) //timeout
|
||
{
|
||
robot.Abort();
|
||
Stop(string.Format("Place timeout, can not complete in {0} seconds", timeout));
|
||
throw (new RoutineFaildException());
|
||
}
|
||
else
|
||
throw (new RoutineBreakException());
|
||
}
|
||
}
|
||
|
||
protected void Map(int id, RobotBaseDevice robot, ModuleName source, int timeout)
|
||
{
|
||
Tuple<bool, Result> ret = ExecuteAndWait(id, () =>
|
||
{
|
||
Notify($"Mapping wafer {source}");
|
||
if (!robot.WaferMapping(source))
|
||
{
|
||
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($"Mapping failed, error {robot.ErrorCode}");
|
||
robot.Abort();
|
||
throw (new RoutineFaildException());
|
||
}
|
||
else if (ret.Item2 == Result.TIMEOUT) //timeout
|
||
{
|
||
robot.Abort();
|
||
Stop(string.Format("Mapping 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<bool, Result> ret = ExecuteAndWait(id, () =>
|
||
{
|
||
Notify($"{robot.Name} 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)
|
||
{
|
||
robot.Abort();
|
||
Stop($"{robot.Name} timeout, can not complete in {timeout} seconds");
|
||
throw (new RoutineFaildException());
|
||
}
|
||
else
|
||
throw (new RoutineBreakException());
|
||
}
|
||
}
|
||
|
||
|
||
public void RobotHomeExcute(int id, RobotBaseDevice robot, int timeout)
|
||
{
|
||
Tuple<bool, Result> ret = Execute(id, () =>
|
||
{
|
||
Notify($"{robot.Name} Execute home");
|
||
if (!robot.Home(null))
|
||
{
|
||
EV.PostAlarmLog(Module, $"{robot.Name} Can not home robot");
|
||
return false;
|
||
}
|
||
|
||
return true;
|
||
});
|
||
|
||
if (ret.Item1)
|
||
{
|
||
if (ret.Item2 == Result.FAIL)
|
||
{
|
||
throw (new RoutineFaildException());
|
||
}
|
||
else if (ret.Item2 == Result.TIMEOUT) //timeout
|
||
{
|
||
robot.Abort();
|
||
Stop($"{robot.Name} home timeout over {timeout} seconds");
|
||
throw (new RoutineFaildException());
|
||
}
|
||
else
|
||
throw (new RoutineBreakException());
|
||
}
|
||
}
|
||
|
||
//关闭Aligner真空
|
||
protected void CloseVacuum(int id, int timeout)
|
||
{
|
||
Tuple<bool, Result> ret = ExecuteAndWait(id, () =>
|
||
{
|
||
Notify($"Close Vacuum");
|
||
_alignerDevice.Set("CVF", "CVF");
|
||
|
||
return true;
|
||
}, () =>
|
||
{
|
||
return !_alignerDevice.IsBusy;
|
||
|
||
}, timeout * 1000);
|
||
|
||
if (ret.Item1)
|
||
{
|
||
if (ret.Item2 == Result.FAIL)
|
||
{
|
||
throw (new RoutineFaildException());
|
||
}
|
||
else if (ret.Item2 == Result.TIMEOUT) //timeout
|
||
{
|
||
Stop($"Aligner Close Vacuum Timeout, over {timeout} seconds");
|
||
throw (new RoutineFaildException());
|
||
}
|
||
else
|
||
throw (new RoutineBreakException());
|
||
}
|
||
}
|
||
|
||
//Aligner移动到测量中心
|
||
protected void AlignerMoveToMeasure(int id, int timeout)
|
||
{
|
||
Tuple<bool, Result> ret = ExecuteAndWait(id, () =>
|
||
{
|
||
Notify($"Move to Measure position");
|
||
_alignerDevice.Set("MTM", "MTM");
|
||
return true;
|
||
}, () =>
|
||
{
|
||
return !_alignerDevice.IsBusy;
|
||
|
||
}, timeout * 1000);
|
||
|
||
if (ret.Item1)
|
||
{
|
||
if (ret.Item2 == Result.FAIL)
|
||
{
|
||
throw (new RoutineFaildException());
|
||
}
|
||
else if (ret.Item2 == Result.TIMEOUT)
|
||
{
|
||
Stop($"Aligner Move to Measure position Timeout, over {timeout} seconds");
|
||
throw (new RoutineFaildException());
|
||
}
|
||
else
|
||
throw (new RoutineBreakException());
|
||
}
|
||
}
|
||
|
||
//检查是否有Wafer
|
||
protected void CheckHaveWafer(int id, int timeout)
|
||
{
|
||
Tuple<bool, Result> ret = ExecuteAndWait(id, () =>
|
||
{
|
||
Notify($"check wafer exist or not");
|
||
|
||
_alignerDevice.Set("DOC", "DOC");
|
||
return true;
|
||
}, () =>
|
||
{
|
||
if (!_alignerDevice.IsBusy)
|
||
{
|
||
if (_alignerDevice.HaveWafer)
|
||
{
|
||
Stop($"Check result : aligner have wafer, can not place to aligner");
|
||
return null;
|
||
}
|
||
else
|
||
{
|
||
return true;
|
||
}
|
||
}
|
||
|
||
return false;
|
||
|
||
}, timeout * 1000);
|
||
|
||
if (ret.Item1)
|
||
{
|
||
if (ret.Item2 == Result.FAIL)
|
||
{
|
||
throw (new RoutineFaildException());
|
||
}
|
||
else if (ret.Item2 == Result.TIMEOUT)
|
||
{
|
||
Stop($"Aligner Check Wafer Timeout, over {timeout} seconds");
|
||
throw (new RoutineFaildException());
|
||
}
|
||
else
|
||
throw (new RoutineBreakException());
|
||
}
|
||
}
|
||
|
||
protected void SetWaferRobortExtendToDO(int id, ModuleName target, int timeout)
|
||
{
|
||
Tuple<bool, Result> ret = ExecuteAndWait(id, () =>
|
||
{
|
||
Notify("Set RobortExtendTO DO");
|
||
|
||
_tmIoInterLock.DoATMRobotExtendLoaLSideEnable = false;
|
||
_tmIoInterLock.DoATMRobotExtendLoaRSideEnable = false;
|
||
_tmIoInterLock.DoATMRobotExtendUnloadEnable = false;
|
||
|
||
if (ModuleHelper.IsLoadLock(target) || target == ModuleName.Load)
|
||
{
|
||
if (!_tmIoInterLock.SetWaferRobotExtendLoadEnable(true, out string reasen))
|
||
{
|
||
Notify(reasen);
|
||
return false;
|
||
}
|
||
}
|
||
else if (target == ModuleName.UnLoad)
|
||
{
|
||
if (!_tmIoInterLock.SetWaferRobotExtendUnLoadEnable(true, out string reasen))
|
||
{
|
||
Notify(reasen);
|
||
return false;
|
||
}
|
||
}
|
||
return true;
|
||
|
||
}, () =>
|
||
{
|
||
if (ModuleHelper.IsLoadLock(target) || target == ModuleName.Load)
|
||
{
|
||
return _tmIoInterLock.DiATMRobotExtendLoadLSideEnableFB;
|
||
}
|
||
else if (target == ModuleName.UnLoad)
|
||
{
|
||
return _tmIoInterLock.DiATMRobotExtendUnloadEnableFB;
|
||
}
|
||
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());
|
||
}
|
||
}
|
||
|
||
protected void SetTrayRobortExtendToDO(int id, ModuleName target, int timeout)
|
||
{
|
||
Tuple<bool, Result> ret = ExecuteAndWait(id, () =>
|
||
{
|
||
Notify("Set RobortExtendTO DO");
|
||
|
||
_tmIoInterLock.DoATMRobotExtendLoaLSideEnable = false;
|
||
_tmIoInterLock.DoATMRobotExtendLoaRSideEnable = false;
|
||
_tmIoInterLock.DoATMRobotExtendUnloadEnable = false;
|
||
|
||
if (ModuleHelper.IsLoadLock(target) || target == ModuleName.Load)
|
||
{
|
||
if (!_tmIoInterLock.SetTrayRobotExtendLoadEnable(true, out string reasen))
|
||
{
|
||
Notify(reasen);
|
||
return false;
|
||
}
|
||
}
|
||
return true;
|
||
|
||
}, () =>
|
||
{
|
||
if (ModuleHelper.IsLoadLock(target) || target == ModuleName.Load)
|
||
{
|
||
return _tmIoInterLock.DiATMRobotExtendLoadRSideEnableFB;
|
||
}
|
||
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());
|
||
}
|
||
}
|
||
|
||
protected void CheckLoadTrayPresence(int id)
|
||
{
|
||
Tuple<bool, Result> ret = Execute(id, () =>
|
||
{
|
||
if (SC.GetValue<bool>("LoadLock.TrayPresenceCheckEnable"))
|
||
{
|
||
if (!_loadTrayPresence.Value)
|
||
{
|
||
EV.PostAlarmLog(Module, $"check load Tray Presence sensor false,no Tray in load");
|
||
return false;
|
||
}
|
||
}
|
||
|
||
return true;
|
||
});
|
||
|
||
if (ret.Item1)
|
||
{
|
||
if (ret.Item2 == Result.FAIL)
|
||
{
|
||
throw (new RoutineFaildException());
|
||
}
|
||
else
|
||
throw (new RoutineBreakException());
|
||
}
|
||
}
|
||
|
||
|
||
}
|
||
}
|