using Aitex.Core.RT.Log; using Aitex.Core.RT.Routine; using MECF.Framework.Common.RecipeCenter; using MECF.Framework.Common.Routine; using CyberX8_Core; using CyberX8_RT.Devices.AXIS; using CyberX8_RT.Devices.SRD; using System; using System.Collections.Generic; using MECF.Framework.Common.Utilities; using MECF.Framework.Common.CommonData; using MECF.Framework.Common.CommonData.SRD; using Aitex.Core.RT.SCCore; using Aitex.Core.RT.Device; using CyberX8_RT.Devices.Facilities; using Aitex.Core.Util; using CyberX8_RT.Modules.Transporter; using MECF.Framework.Common.WaferHolder; namespace CyberX8_RT.Modules.SRD { public class SRDProcessRecipeRoutine : RoutineBase, IRoutine { #region 常量 private const int LOTTRACK_TIME = 1000; #endregion private enum SRDProcessState { Ready, RunWafer, Unloading, End, InitialRunWaferStateMachine, InitialUnloadingStateMachine, CheckRunWaferStateMachineInitialStatus, CheckUnloadingStateMachineInitialStatus, StartRunWaferStateMachine, StartUnloadingStateMachine, CycleRun, CycleEnd } #region 内部变量 /// /// 次数 /// private int _cycleCount = 0; /// /// Rotation Axis /// private JetAxisBase _rotationAxis; /// /// Arm Axis /// private JetAxisBase _armAxis; /// /// SRD Recipe /// private SrdRecipe _srdRecipe; /// /// 设备对象 /// private SrdCommonDevice _srdCommonDevice; /// /// Run wafer Recipe Routine /// private SRDRunWaferRecipeRoutine _runWaferRecipRoutine; /// /// Unload Routine /// private SRDUnloadRoutine _unloadRoutine; /// /// lock track time /// private DateTime _lotTackTime = DateTime.Now; /// /// LotTrack数据 /// private List _datas = new List(); /// /// LotTrack文件头数据 /// private LotTrackFileHeaderCommonData _header = new LotTrackFileHeaderCommonData(); /// /// Facilities /// private SystemFacilities _facilities; #endregion #region 属性 /// /// 当前子状态机 /// public string CurrentStateMachine { get { return GetCurrentStateMachine(); } } /// /// 当前cycle次数 /// public int AchievedCycle { get { return Runner.LoopCounter; } } /// /// 是否正在用水 /// public bool IsUsingWater { get { return _runWaferRecipRoutine.IsUsingWater; } } /// /// LotTrack数据 /// public List SRDLotTrackDatas { get { return _datas; } } /// /// LotTrack文件头数据 /// public LotTrackFileHeaderCommonData SRDLotTrackHeaderDatas { get { return _header; } } #endregion /// /// 构造函数 /// /// public SRDProcessRecipeRoutine(string module, JetAxisBase rotationAxis, JetAxisBase armAxis, SrdCommonDevice srdCommon) : base(module) { _rotationAxis = rotationAxis; _armAxis = armAxis; _srdCommonDevice = srdCommon; _runWaferRecipRoutine = new SRDRunWaferRecipeRoutine(module); _unloadRoutine= new SRDUnloadRoutine(module); } /// /// 取消 /// public void Abort() { if(_unloadRoutine.Monitor() == RState.Running) { _unloadRoutine.Abort(); } if (_runWaferRecipRoutine.Monitor() == RState.Running) { _runWaferRecipRoutine.Abort(); } Runner.Stop("Manual Abort"); if (_srdCommonDevice != null) { _srdCommonDevice.EnterErrorOperation(); } } /// /// 监控 /// /// /// public RState Monitor() { LottrackRecord(); Runner.LoopStart(SRDProcessState.Ready, "Process Recipe Start", _cycleCount, NullFun, _delay_1ms) .LoopRun(SRDProcessState.StartRunWaferStateMachine, () => { return StartRunWaferRecipeStateMachine(); }, _delay_1ms) .LoopRunWithStopStatus(SRDProcessState.RunWafer, CheckRunWaferRecipeStateCompleteState, CheckRunWaferRecipeStateErrorState) .LoopRun(SRDProcessState.StartUnloadingStateMachine, () => { return StartUnloadingStateMachine(); }, _delay_1ms) .LoopRunWithStopStatus(SRDProcessState.Unloading, CheckUnloadingStateCompleteState, CheckUnloadingStateErrorState) .LoopEnd(SRDProcessState.CycleEnd, NullFun, _delay_1ms) .End(SRDProcessState.End, NullFun, _delay_1ms); return Runner.Status; } /// /// 启动 /// /// /// /// public RState Start(params object[] objects) { _srdRecipe = objects[0] as SrdRecipe; if (_srdRecipe == null) { LOG.WriteLog(eEvent.ERR_SRD, Module.ToString(), " recipe is null"); return RState.Failed; } _cycleCount = (int)objects[1]; if (_cycleCount == 0) { return RState.End; } _header.SoftWareVersion = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString(); _header.Recipe = $"{_srdRecipe.Ppid}.srd.rcp"; if (SC.ContainsItem("System.ToolID")) _header.ToolID = SC.GetStringValue("System.ToolID"); _facilities = DEVICE.GetDevice("System.Facilities"); if (_facilities == null) { LOG.WriteLog(eEvent.ERR_SRD, Module, "Facility is null"); return RState.Failed; } _datas.Clear(); _lotTackTime = DateTime.Now; return Runner.Start(Module, "Process Recipe"); } #region RunWaferStateMatcine /// /// 启动状态机 /// /// /// private bool StartRunWaferRecipeStateMachine() { bool result = _runWaferRecipRoutine.Start(_srdRecipe)==RState.Running; if (result) { LOG.WriteLog(eEvent.INFO_SRD, Module.ToString(), $"Start Run Wafer State Machine, recipe[{_srdRecipe.Ppid}] times[{_cycleCount + 1}]"); } else { NotifyError(eEvent.ERR_SRD, _runWaferRecipRoutine.ErrorMsg, 0); } return result; } /// /// 检验RunWafer状态机完成情况 /// /// private bool CheckRunWaferRecipeStateCompleteState() { return CommonFunction.CheckRoutineEndState(_runWaferRecipRoutine); } /// /// 检验RunWafer状态机错误情况 /// /// private bool CheckRunWaferRecipeStateErrorState() { bool result = CommonFunction.CheckRoutineStopState(_runWaferRecipRoutine); if (result) { AddLotTrackData(); if (_srdCommonDevice != null) { _srdCommonDevice.EnterErrorOperation(); } NotifyError(eEvent.ERR_SRD, _runWaferRecipRoutine.ErrorMsg, 0); } return result; } #endregion #region UnloadingStateMatcine /// /// 启动状态机 /// /// /// private bool StartUnloadingStateMachine() { bool result= _unloadRoutine.Start() == RState.Running; if (!result) { NotifyError(eEvent.ERR_SRD,_unloadRoutine.ErrorMsg, 0); } return result; } /// /// 检验Unloading状态机完成情况 /// /// private bool CheckUnloadingStateCompleteState() { return CommonFunction.CheckRoutineEndState(_unloadRoutine); } /// /// 检验Unloading状态机错误情况 /// /// private bool CheckUnloadingStateErrorState() { bool result= CommonFunction.CheckRoutineStopState(_unloadRoutine); if (result) { AddLotTrackData(); NotifyError(eEvent.ERR_SRD, _unloadRoutine.ErrorMsg, 0); } return result; } /// /// 停止unloading状态机 /// /// private bool StopUnloadingStateMachine() { //_unloadingStateMachine.Stop(); if (_rotationAxis.IsRun) { _rotationAxis.StopPositionOperation(); } if (_armAxis.IsRun) { _armAxis.StopPositionOperation(); } return true; } #endregion /// /// 获取当前子状态机 /// private string GetCurrentStateMachine() { string result; if(Runner.CurrentStep.ToString() == "Ready") { result = "Ready"; } else if(Runner.CurrentStep.ToString().Contains("RunWafer")) { result = _runWaferRecipRoutine.CurrentStep; } else if(Runner.CurrentStep.ToString().Contains("Unloading")) { result = _unloadRoutine.CurrentStep; } else { result = "End"; } return result; } /// /// 记录Lottrack /// private void LottrackRecord() { //记录Lottrack if (DateTime.Now.Subtract(_lotTackTime).TotalMilliseconds >= LOTTRACK_TIME) { AddLotTrackData(); _lotTackTime = DateTime.Now; } } /// /// 获取Lot Track数据 /// /// private void AddLotTrackData() { SRDLotTrackData data = new SRDLotTrackData(); data.TimeStamp = DateTime.Now; data.StateMachine = GetCurrentStateMachine(); data.ArmPosition = _armAxis.MotionData.MotorPosition; data.WaterPressure = _srdCommonDevice.CommonData.WaterPressure; data.WaferPresence = $"{_srdCommonDevice.WaferPresence}:{_srdCommonDevice.CommonData.WaferPresence}"; data.ChuckVacuumOn = _srdCommonDevice.CommonData.ChuckVacuum; data.ChuckVacuumPressure = _srdCommonDevice.CommonData.VacuumValue; data.ArmTorque = _armAxis.MotionData.ActualTorque; data.SpinTorque = _rotationAxis.MotionData.ActualTorque; data.RotationSpeed = _rotationAxis.MotionData.ActualVelocity; data.N2BelowOn = false; data.WaterAbove = _srdCommonDevice.CommonData.WaterAbove; data.WaterBelow = _srdCommonDevice.CommonData.WaterBelow; data.ExhaustOn = _srdCommonDevice.CommonData.ExhaustOn; data.LoaderDIEnable = _facilities.LoaderDiEnable; data.WaterFlow = 0; _datas.Add(data); } /// /// 重试 /// /// public RState Retry(int step) { List preStepIds = new List(); return Runner.Retry(SRDProcessState.Ready, preStepIds, Module, "RunRecipe Retry"); } /// /// 检验前面完成状态 /// /// public bool CheckCompleteCondition(int index) { if (_armAxis.IsRun) { NotifyError(eEvent.ERR_SRD, "Arm axis is run", 0); return false; } if (!_armAxis.IsHomed) { NotifyError(eEvent.ERR_SRD, "Arm axis is not homed", 0); return false; } if (_rotationAxis.IsRun) { NotifyError(eEvent.ERR_SRD, "Rotation axis is run", 0); return false; } if (!_rotationAxis.IsHomed) { NotifyError(eEvent.ERR_SRD, "Rotation axis is not homed", 0); return false; } if (!_srdCommonDevice.CommonData.ChuckVacuum) { NotifyError(eEvent.ERR_SRD, "Vacuum is not released", 0); return false; } if (!_srdCommonDevice.CommonData.DoorOpened) { NotifyError(eEvent.ERR_SRD, "Door is not opened", 0); return false; } return true; } } }