Sic07/Modules/SicPM2/RecipeRoutine/PMMacroRoutine.cs

947 lines
38 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Collections.Generic;
using System.Diagnostics;
using Aitex.Core.Common;
using Aitex.Core.Common.DeviceData;
using Aitex.Core.RT.Device;
using Aitex.Core.RT.Device.Devices;
using Aitex.Core.RT.Event;
using Aitex.Core.RT.Log;
using Aitex.Core.RT.OperationCenter;
using Aitex.Core.RT.Routine;
using Aitex.Core.RT.SCCore;
using Aitex.Core.Util;
using MECF.Framework.Common.Equipment;
using MECF.Framework.Common.SubstrateTrackings;
using SicPM2.RecipeExecutions;
using SicPM2.Routines;
namespace SicPM2.RecipeRoutine
{
public enum RecipeContinueMode
{
None,
WaferReturnAndJobStop,
RecipeCompleted,
StepContinue,
StepRestart,
RecipeRestart,
NextStep,
}
public enum RoutineType
{
DefaultRoutine,
AtmRoutine,
VacRoutine,
ProcessIdleRoutine,
PumpRoutine,
VentRoutine,
PurgeRoutine,
CleanRoutine,
ExchangeMORoutine,
IsolationRoutine,
LeakCheckRoutine,
AbortRoutine
}
public partial class PMMacroRoutine : PMBaseRoutine
{
enum RoutineStep
{
WaitProcess,
}
enum RecipeRunningState
{
Error,
RecipeCompleted,
ExecStep,
TimeWait,
ConditionWait,
StepCompleted,
Paused,
}
private object _recipeLocker = new object();
private RecipeRunningState _state = RecipeRunningState.ExecStep;
private RecipeRunningState _pausedState = RecipeRunningState.ExecStep;
private DeviceTimer _estimatedTimeCalcTimer = new DeviceTimer();//用于定时计算工艺程序估计的结束时间
private double _curStepElpasedTimeBeforePaused;
private double _curStepElpasedTimeBeforePaused2;
//前序所有步总的时间
private double _preStepTotalTime;
public RecipeContinueMode ContinueAction { get; set; }
public DateTime _recipeStartTime
{
get;
private set;
}
public string CurrentRecipeContent { get; private set; }
private int _currentStepNumber;
private int _dummyStepCount;
public int CurStepTotalLoopCount
{
get;
private set;
}
public double CurStepTotalTime
{
get
{
if (PmDevice.RecipeRunningInfo.RecipeStepList == null || PmDevice.RecipeRunningInfo.RecipeStepList.Count == 0 || _state == RecipeRunningState.RecipeCompleted || _state == RecipeRunningState.Error)
return 0;
return PmDevice.RecipeRunningInfo.RecipeStepList[_currentStepNumber].StepTime * 1000;
}
}
public int CurrentLoopCount
{
get;
private set;
}
public int CurStartLoopStep;
private DeviceTimer _stepTimer = new DeviceTimer();
private DeviceTimer _stepTimer2 = new DeviceTimer();
private DeviceTimer _recipeTimer = new DeviceTimer();
public bool IsPaused
{
private set;
get;
}
private double CurStepLeftTime
{
get
{
return _stepTimer.GetTotalTime() - _stepTimer.GetElapseTime();
}
}
public double EstimatedTotalLeftTime
{
get;
private set;
}
private RecipeDBCallback _dbCallback;
private Fdc _fdc;
private int _currentStepIndex = 99;
private IoInterLock _pmInterLock;
private string _recipeName;
private RoutineType _routineType;
#region Parse
private bool _isPSUHeaterJumpMode;
private bool _isSCRHeaterJumpMode;
private bool _isMFCJumpMode;
#endregion
public PMMacroRoutine(ModuleName module, PM2Module pm1) : base(module, pm1)
{
Module = module.ToString();
Name = "Routine";
_dbCallback = new RecipeDBCallback();
_fdc = new Fdc(Module);
_pmInterLock = DEVICE.GetDevice<IoInterLock>($"{Module}.PMInterLock");
}
public void Init(string recipeName, RoutineType routineType = RoutineType.DefaultRoutine)
{
_recipeName = recipeName;
_routineType = routineType;
}
public bool SetRoutineRunning(bool eValue,out string reason)
{
reason = string.Empty;
if(_routineType == RoutineType.ProcessIdleRoutine)
{
if (!_pmInterLock.SetPMProcessIdleRunning(eValue, out reason))
{
return false;
}
}
else if (_routineType == RoutineType.CleanRoutine)
{
if (!_pmInterLock.SetPMCleanRoutineRunning(eValue, out reason))
{
return false;
}
}
else if (_routineType == RoutineType.PurgeRoutine)
{
if (!_pmInterLock.SetPMPurgeRoutineRunning(eValue, out reason))
{
return false;
}
}
else if (_routineType == RoutineType.PumpRoutine)
{
if (!_pmInterLock.SetPMPumpRoutineRunning(eValue, out reason))
{
return false;
}
}
else if (_routineType == RoutineType.VentRoutine)
{
if (!_pmInterLock.SetPMVentRoutineRunning(eValue, out reason))
{
return false;
}
}
else if (_routineType == RoutineType.ExchangeMORoutine)
{
if (!_pmInterLock.SetPMExchangeMoRoutineRunning(eValue, out reason))
{
return false;
}
}
else if (_routineType == RoutineType.VacRoutine)
{
}
else if (_routineType == RoutineType.AtmRoutine)
{
}
else
{
if (!_pmInterLock.SetPMProcessRunning(eValue, out reason))
{
return false;
}
}
return true;
}
public override Result Start(params object[] param)
{
Reset();
//解析Recipe
if (!RecipeParser.Parse(_recipeName, Module, out var recipeHead, out var recipeSteps, out string reason))
{
Stop($"Load recipe {_recipeName} failed, {reason}");
return Result.FAIL;
}
if(!SetRoutineRunning(true,out reason))
{
EV.PostAlarmLog(Module, $"can not run Routine, {reason}");
return Result.FAIL;
}
if (_routineType == RoutineType.PurgeRoutine)
{
_pmInterLock.DoLidCloseRoutineSucceed = false;
}
else if (_routineType == RoutineType.CleanRoutine)
{
_pmInterLock.DoLidOpenRoutineSucceed = false;
}
//先打开加热
PmDevice.SetHeatEnable(true);
_currentStepIndex = 99;
//设置当前Step/当前循环步/当前总循环步为0
_currentStepNumber = 0;
CurStartLoopStep = 0;
CurrentLoopCount = CurrentLoopCount = 0;
_preStepTotalTime = 0;
_dummyStepCount = 0;
_estimatedTimeCalcTimer.Start(1000);
PmDevice.RecipeRunningInfo.RecipeName = _recipeName;
PmDevice.RecipeRunningInfo.Head = recipeHead;
PmDevice.RecipeRunningInfo.RecipeStepList = recipeSteps;
PmDevice.RecipeRunningInfo.InnerId = Guid.NewGuid();
PmDevice.RecipeRunningInfo.BeginTime = DateTime.Now;
PmDevice.RecipeRunningInfo.TotalTime = CalcRecipeTime();
_state = RecipeRunningState.ExecStep;
_recipeTimer.Start(int.MaxValue);
_dbCallback.RecipeStart(PmDevice.Module, 0, PmDevice.RecipeRunningInfo.InnerId.ToString(), PmDevice.RecipeRunningInfo.RecipeName);
_dbCallback.RecipeUpdateStatus(PmDevice.RecipeRunningInfo.InnerId.ToString(), "InProcess");
WaferManager.Instance.UpdateWaferProcessStatus(ModuleHelper.Converter(Module), 0, EnumWaferProcessStatus.InProcess);
_fdc.Reset();
Notify($"Start");
return Result.RUN;
}
public override Result Monitor()
{
if (!PmDevice.CheckEnableRunProcess(out string reason))
{
EV.PostAlarmLog(Module, reason);
return Result.FAIL;
}
MonitorRecipeEndTime();
MonitorRecipeRunInfo();
lock (_recipeLocker)
{
try
{
switch (_state)
{
case RecipeRunningState.ExecStep:
{
PmDevice.ResetToleranceChecker();
if (ContinueAction != RecipeContinueMode.StepContinue)
{
_curStepElpasedTimeBeforePaused = 0;
_curStepElpasedTimeBeforePaused2 = 0;
}
ContinueAction = RecipeContinueMode.None;
if (PmDevice.RecipeRunningInfo.RecipeStepList[_currentStepNumber].IsLoopStartStep)
{
CurStartLoopStep = _currentStepNumber;
CurStepTotalLoopCount = PmDevice.RecipeRunningInfo.RecipeStepList[_currentStepNumber].LoopCount;
}
_stepTimer.Start(PmDevice.RecipeRunningInfo.RecipeStepList[_currentStepNumber].StepTime * 1000 - _curStepElpasedTimeBeforePaused);
if (!_stepTimer2.IsIdle())
{
_curStepElpasedTimeBeforePaused2 += _stepTimer2.GetElapseTime();
_stepTimer2.Stop();
}
_stepTimer2.Start(int.MaxValue);
Notify($"Running step {_currentStepNumber + 1} : {PmDevice.RecipeRunningInfo.RecipeStepList[_currentStepNumber].StepName}");
if (PmDevice.RecipeRunningInfo.RecipeStepList[_currentStepNumber].IsDummyStep)
{
_dummyStepCount++;
}
//执行工艺程序命令
foreach (var recipeCmd in PmDevice.RecipeRunningInfo.RecipeStepList[_currentStepNumber].RecipeCommands.Keys)
{
if (recipeCmd == "SusHeaterSetMode")
{
if (PmDevice.RecipeRunningInfo.RecipeStepList[_currentStepNumber].RecipeCommands[recipeCmd] == "Jump")
_isPSUHeaterJumpMode = true;
else
_isPSUHeaterJumpMode = false;
continue;
}
if (recipeCmd == "WWHeaterSetMode")
{
if (PmDevice.RecipeRunningInfo.RecipeStepList[_currentStepNumber].RecipeCommands[recipeCmd] == "Jump")
_isSCRHeaterJumpMode = true;
else
_isSCRHeaterJumpMode = false;
continue;
}
if (recipeCmd == "FlowSetMode")
{
if (PmDevice.RecipeRunningInfo.RecipeStepList[_currentStepNumber].RecipeCommands[recipeCmd] == "Jump")
_isMFCJumpMode = true;
else
_isMFCJumpMode = false;
continue;
}
if (IsCmdSkip(recipeCmd)) // 不是注册的方法,需要跳过
continue;
if (!OP.CanDoOperation($"{Module}.{recipeCmd}", out reason, PmDevice.RecipeRunningInfo.RecipeStepList[_currentStepNumber].RecipeCommands[recipeCmd]))
{
EV.PostAlarmLog(Module, $"Can not execute {recipeCmd}, {reason}");
return Result.FAIL;
}
else
{
int time = (int)PmDevice.RecipeRunningInfo.RecipeStepList[_currentStepNumber].StepTime * 1000;
if (recipeCmd.StartsWith("TC1") && _isPSUHeaterJumpMode)
{
time = 1;
}
if (recipeCmd.StartsWith("TC2") && _isSCRHeaterJumpMode)
{
time = 1;
}
if (recipeCmd.StartsWith("Mfc") && recipeCmd.EndsWith(".Ramp") && !PmDevice.RecipeRunningInfo.RecipeStepList[_currentStepNumber].IsDummyStep)
{
if (_isMFCJumpMode)
{
time = 1;
}
}
if ((recipeCmd == "TV.SetPressure"
|| recipeCmd == "PMServo.SetActualSpeed"
|| recipeCmd.StartsWith("Pressure") && recipeCmd.EndsWith(".Ramp")
|| recipeCmd.StartsWith("Mfc") && recipeCmd.EndsWith(".Ramp"))
&& !PmDevice.RecipeRunningInfo.RecipeStepList[_currentStepNumber].IsDummyStep)
{
if (_currentStepNumber >= 1)
{
int previousStepNumber = _currentStepNumber - 1;
if (PmDevice.RecipeRunningInfo.RecipeStepList[previousStepNumber].IsDummyStep)
previousStepNumber = _currentStepNumber - 2;
if (PmDevice.RecipeRunningInfo.RecipeStepList[previousStepNumber].RecipeCommands.ContainsKey(recipeCmd))
{
string previousValue = PmDevice.RecipeRunningInfo.RecipeStepList[previousStepNumber].RecipeCommands[recipeCmd];
string currentValue = PmDevice.RecipeRunningInfo.RecipeStepList[_currentStepNumber].RecipeCommands[recipeCmd];
if (previousValue == currentValue)
{
time = 1;
}
}
}
}
if (recipeCmd.EndsWith(AITValveOperation.GVTurnValve)) // 阀门
{
OP.DoOperation($"{Module}.{recipeCmd}", PmDevice.RecipeRunningInfo.RecipeStepList[_currentStepNumber].RecipeCommands[recipeCmd]);
}
else
{
OP.DoOperation($"{Module}.{recipeCmd}", out string reason1, time, PmDevice.RecipeRunningInfo.RecipeStepList[_currentStepNumber].RecipeCommands[recipeCmd]);
}
}
}
if (PmDevice.RecipeRunningInfo.RecipeStepList[_currentStepNumber].EndBy == EnumEndByCondition.ByTime)
_state = RecipeRunningState.TimeWait;
else
_state = RecipeRunningState.ConditionWait;
_dbCallback.RecipeStepStart(PmDevice.RecipeRunningInfo.InnerId.ToString(), _currentStepNumber, PmDevice.RecipeRunningInfo.RecipeStepList[_currentStepNumber].StepName, (float)PmDevice.RecipeRunningInfo.RecipeStepList[_currentStepNumber].StepTime);
_fdc.Start(PmDevice.RecipeRunningInfo.RecipeStepList[_currentStepNumber].RecipeCommands);
}
break;
case RecipeRunningState.TimeWait:
{
if (IsPaused)
{
_state = RecipeRunningState.Paused;
}
if (_stepTimer.IsTimeout())
{
_state = RecipeRunningState.StepCompleted;
}
}
break;
case RecipeRunningState.ConditionWait:
{
//如果暂停,则进入暂停状态
if (IsPaused)
{
_state = RecipeRunningState.Paused;
}
//设置的压力
double.TryParse(PmDevice.RecipeRunningInfo.RecipeStepList[_currentStepNumber].RecipeCommands["TV.SetPressure"], out double setPressure);
//实时反馈的压力
double feedBackPressure = DEVICE.GetDevice<IoPressure>($"{Module}.PT1").FeedBack;
double _pmPressureMaxDiff = SC.GetValue<double>($"PM.{Module}.ThrottlePressureMaxDiff");
if(Math.Abs(setPressure - feedBackPressure) <= _pmPressureMaxDiff)
{
_state = RecipeRunningState.StepCompleted;
}
}
break;
case RecipeRunningState.Paused:
PmDevice.PauseRecipe(out reason);
if (!_stepTimer.IsIdle())
{
_curStepElpasedTimeBeforePaused += _stepTimer.GetElapseTime();
_stepTimer.Stop();
}
switch (ContinueAction)
{
case RecipeContinueMode.None:
break;
case RecipeContinueMode.WaferReturnAndJobStop:
//Singleton<RouteManager>.Instance.CheckToPostMessage((int)RouteManager.MSG.StopJob);
_state = RecipeRunningState.Error;
break;
case RecipeContinueMode.RecipeCompleted:
_state = RecipeRunningState.RecipeCompleted;
break;
case RecipeContinueMode.StepContinue:
_state = RecipeRunningState.ExecStep;
break;
case RecipeContinueMode.StepRestart:
_state = RecipeRunningState.ExecStep;
break;
case RecipeContinueMode.RecipeRestart:
_currentStepNumber = 0;
_state = RecipeRunningState.ExecStep;
break;
case RecipeContinueMode.NextStep:
_state = RecipeRunningState.StepCompleted;
break;
}
break;
case RecipeRunningState.StepCompleted:
{
_preStepTotalTime += CurStepTotalTime/1000;
//放在前面stepnumber后面会被更新
_stepTimer2.Stop();
_dbCallback.RecipeStepEnd(PmDevice.RecipeRunningInfo.InnerId.ToString(), _currentStepNumber, _fdc.DataList);
_fdc.Stop();
if (PmDevice.RecipeRunningInfo.RecipeStepList[_currentStepNumber].IsLoopEndStep)
{
CurrentLoopCount++;
if (CurrentLoopCount >= CurStepTotalLoopCount)
{
CurrentLoopCount = CurStepTotalLoopCount = 0;
CurStartLoopStep = 0;
_currentStepNumber++;
}
else
{
_currentStepNumber = CurStartLoopStep;
}
}
else
{
_currentStepNumber++;
}
//判断最后一步是否执行完
if (_currentStepNumber >= PmDevice.RecipeRunningInfo.RecipeStepList.Count)
{
_currentStepNumber = PmDevice.RecipeRunningInfo.RecipeStepList.Count - 1;
_state = RecipeRunningState.RecipeCompleted;
}
else
{
_state = RecipeRunningState.ExecStep;
}
}
break;
case RecipeRunningState.RecipeCompleted:
{
_recipeTimer.Stop();
if (!SetRoutineRunning(false, out reason))
{
EV.PostAlarmLog(Module, $"can not run Process, {reason}");
return Result.FAIL;
}
//设置Succeed状态
if(_routineType == RoutineType.PurgeRoutine)
{
_pmInterLock.SetLidOpenRoutineSucceed(true, out reason);
}
else if (_routineType == RoutineType.CleanRoutine)
{
_pmInterLock.SetLidClosedRoutineSucceed(true, out reason);
}
//设置当前Step/当前循环步/当前总循环步为0
_currentStepNumber = 0;
CurStartLoopStep = 0;
CurrentLoopCount = CurrentLoopCount = 0;
Notify("Finished");
return Result.DONE;
}
case RecipeRunningState.Error:
{
if (!SetRoutineRunning(false, out reason))
{
EV.PostAlarmLog(Module, $"can not run Process, {reason}");
return Result.FAIL;
}
return Result.DONE;
}
default:
break;
}
}
catch (Exception ex)
{
PmDevice.SetHeaterStopRamp();
PmDevice.SetMfcStopRamp(PmDevice.GetMfcListByGroupName(MfcGroupName.All));
PmDevice.SetRotationStopRamp();
if (!SetRoutineRunning(false, out reason))
{
EV.PostAlarmLog(Module, $"can not run Process, {reason}");
return Result.FAIL;
}
LOG.Write(ex);
return Result.FAIL;
}
}
return Result.RUN;
}
private void MonitorRecipeRunInfo()
{
PmDevice.RecipeRunningInfo.StepNumber = _currentStepNumber + 1 - _dummyStepCount; //CurStepNum start from 0, ignore dummy step
PmDevice.RecipeRunningInfo.StepName = PmDevice.RecipeRunningInfo.RecipeStepList[_currentStepNumber].StepName;
PmDevice.RecipeRunningInfo.StepTime = PmDevice.RecipeRunningInfo.RecipeStepList[_currentStepNumber].StepTime;
PmDevice.RecipeRunningInfo.StepElapseTime = _stepTimer.IsIdle() ? _curStepElpasedTimeBeforePaused / 1000 : (_stepTimer.GetElapseTime() + _curStepElpasedTimeBeforePaused) / 1000;
PmDevice.RecipeRunningInfo.TotalElapseTime = CalcElapseRecipeTime();
PmDevice.RecipeRunningInfo.StepElapseTime2 = _stepTimer2.IsIdle() ? _curStepElpasedTimeBeforePaused2 / 1000 : (_stepTimer2.GetElapseTime() + _curStepElpasedTimeBeforePaused2) / 1000;
PmDevice.RecipeRunningInfo.TotalElapseTime2 = _recipeTimer.GetElapseTime() / 1000;
if (_currentStepIndex != PmDevice.RecipeRunningInfo.StepNumber)
{
Notify($"Start Recipe: Step:{PmDevice.RecipeRunningInfo.StepNumber} Name:{PmDevice.RecipeRunningInfo.StepName} ");
_currentStepIndex = PmDevice.RecipeRunningInfo.StepNumber;
}
}
public override void Abort()
{
_state = RecipeRunningState.RecipeCompleted;
_dbCallback.RecipeFailed(PmDevice.RecipeRunningInfo.InnerId.ToString());
_fdc.Stop();
PmDevice.RecipeRunningInfo.StepName = string.Empty;
PmDevice.RecipeRunningInfo.StepNumber = 0;
PmDevice.RecipeRunningInfo.StepTime = 0;
PmDevice.RecipeRunningInfo.StepElapseTime = 0;
PmDevice.RecipeRunningInfo.TotalTime = 0;
PmDevice.RecipeRunningInfo.TotalElapseTime = 0;
if (!SetRoutineRunning(false, out string reason))
{
EV.PostAlarmLog(Module, $"can not run Process, {reason}");
}
//根据Routine类型执行Abort
SetRoutineAbort();
base.Abort();
}
private List<string> _lstGroup1 = new List<string>() { "V46", "V46s", "V73" };
private List<string> _lstGroup2 = new List<string>() { "V46", "V46s" };
private List<string> _lstGroup3 = new List<string>() { "V43", "V43s", "V45" };
//默认为TMA换源参数
private int mfc7Or10 = 7;
private int mfc8Or12 = 8;
private int mfc11 = 11;
private int pc2Or3 = 2;
public void SetRoutineAbort()
{
if (_routineType == RoutineType.ProcessIdleRoutine)
{
PmDevice._ioThrottleValve.StopRamp();
PmDevice.SetMfcStopRamp(PmDevice.GetMfcListByGroupName(MfcGroupName.All));
PmDevice.SetHeaterStopRamp();
PmDevice.SetRotationStopRamp();
PmDevice.SetRotationServo(0, 0);
}
else if (_routineType == RoutineType.CleanRoutine)
{
PmDevice._ioThrottleValve.StopRamp();
PmDevice.SetMfcStopRamp(PmDevice.GetMfcListByGroupName(MfcGroupName.All));
PmDevice.SetRotationServo(0, 0);
}
else if (_routineType == RoutineType.PurgeRoutine)
{
PmDevice._ioThrottleValve.StopRamp();
PmDevice.SetMfcStopRamp(PmDevice.GetMfcListByGroupName(MfcGroupName.All));
PmDevice.SetRotationServo(0, 0);
}
else if (_routineType == RoutineType.PumpRoutine)
{
PmDevice.SetRotationServo(0, 0);
}
else if (_routineType == RoutineType.VentRoutine)
{
PmDevice._ioThrottleValve.StopRamp();
PmDevice.SetMfcStopRamp(PmDevice.GetMfcListByGroupName(MfcGroupName.All));
PmDevice.SetRotationServo(0, 0);
}
else if (_routineType == RoutineType.ExchangeMORoutine)
{
PmDevice.SetIoValue(_lstGroup1, false);
PmDevice.SetIoValue(_lstGroup2, false);
PmDevice.SetMfcValueToDefault(new List<int> { mfc7Or10 });
PmDevice.SetMfcValueToDefault(new List<int> { mfc8Or12 });
PmDevice.SetMfcValueToDefault(new List<int> { mfc11 });
PmDevice.SetPCValueToDefault(new List<int> { pc2Or3 });
PmDevice.SetRotationServo(0, 0);
}
else if (_routineType == RoutineType.VacRoutine)
{
PmDevice.SetRotationServo(0, 0);
}
}
public void ExitProcess()
{
if (_state == RecipeRunningState.RecipeCompleted)
{
_dbCallback.RecipeComplete(PmDevice.RecipeRunningInfo.InnerId.ToString());
_fdc.Stop();
}
else
{
_dbCallback.RecipeFailed(PmDevice.RecipeRunningInfo.InnerId.ToString());
_fdc.Stop();
}
}
public void PauseRecipe()
{
if (_state != RecipeRunningState.TimeWait && _state != RecipeRunningState.ConditionWait)
return;
if (!IsPaused)
{
IsPaused = true;
_pausedState = _state;
_state = RecipeRunningState.Paused;
}
}
public void SkipCurrentRecipeStep()
{
if (_state == RecipeRunningState.ConditionWait || _state == RecipeRunningState.TimeWait)
{
_state = RecipeRunningState.StepCompleted;
}
}
protected int CalcRecipeTime()
{
double total = 0;
for (int i = 0; i < PmDevice.RecipeRunningInfo.RecipeStepList.Count; i++)
{
if (!PmDevice.RecipeRunningInfo.RecipeStepList[i].IsDummyStep) // 不统计虚拟Step的时间
{
int loopTimes = PmDevice.RecipeRunningInfo.RecipeStepList[i].LoopCount == 0 ? 1 : PmDevice.RecipeRunningInfo.RecipeStepList[i].LoopCount;
total += PmDevice.RecipeRunningInfo.RecipeStepList[i].StepTime * loopTimes;
}
}
return (int)total;
}
protected int CalcElapseRecipeTime()
{
double total = 0;
//for (int i = 0; i < _currentStepNumber; i++)
//{
// if (!PMDevice.RecipeRunningInfo.RecipeStepList[i].IsDummyStep) // 不统计虚拟Step的时间
// {
// total += PMDevice.RecipeRunningInfo.RecipeStepList[i].StepTime;
// }
//}
total = _preStepTotalTime;
total += PmDevice.RecipeRunningInfo.StepElapseTime;
return (int)total;
}
protected void MonitorRecipeEndTime()
{
try
{
if (!_estimatedTimeCalcTimer.IsTimeout())
return;
_estimatedTimeCalcTimer.Start(1000);
EstimatedTotalLeftTime = 0;
if (_state == RecipeRunningState.RecipeCompleted)
return;
if (!(_currentStepNumber >= 0 && _currentStepNumber <= PmDevice.RecipeRunningInfo.RecipeStepList.Count - 1))
return;
if (CurStepLeftTime > 0)
{
EstimatedTotalLeftTime = CurStepLeftTime;
}
int nextBegin = _currentStepNumber;
bool IsInLoop = false;
int iNum1 = 0;
int iNum2 = 0;
//int j=i;
for (int j = _currentStepNumber; j < PmDevice.RecipeRunningInfo.RecipeStepList.Count; j++)
{
if (PmDevice.RecipeRunningInfo.RecipeStepList[j].IsLoopEndStep)
{
iNum2 = j;
IsInLoop = true;
break;
}
else if (j > _currentStepNumber && PmDevice.RecipeRunningInfo.RecipeStepList[j].IsLoopStartStep)
{
IsInLoop = false;
break;
}
}
if (IsInLoop)
{
iNum1 = _currentStepNumber;
for (int j = _currentStepNumber; j >= 0; j--)
{
if (PmDevice.RecipeRunningInfo.RecipeStepList[j].IsLoopStartStep)
{
iNum1 = j;
break;
}
}
for (int j = _currentStepNumber + 1; j <= iNum2; j++)
{
EstimatedTotalLeftTime += PmDevice.RecipeRunningInfo.RecipeStepList[j].StepTime * 1000 * (PmDevice.RecipeRunningInfo.RecipeStepList[iNum1].LoopCount - CurrentLoopCount + 1);
}
for (int j = iNum1; j <= _currentStepNumber; j++)
{
EstimatedTotalLeftTime += PmDevice.RecipeRunningInfo.RecipeStepList[j].StepTime * 1000 * (PmDevice.RecipeRunningInfo.RecipeStepList[iNum1].LoopCount - CurrentLoopCount);
}
nextBegin = iNum2 + 1;
}
else
{
nextBegin++;
}
for (int j = nextBegin; j < PmDevice.RecipeRunningInfo.RecipeStepList.Count; j++)
{
if (PmDevice.RecipeRunningInfo.RecipeStepList[j].IsLoopStartStep)
{
//j=i;
iNum1 = j;
iNum2 = j + 1;
double lr1 = 0;
for (int m = j; m < PmDevice.RecipeRunningInfo.RecipeStepList.Count; m++)
{
lr1 += PmDevice.RecipeRunningInfo.RecipeStepList[m].StepTime * 1000;
if (PmDevice.RecipeRunningInfo.RecipeStepList[m].IsLoopEndStep)
{
iNum2 = m;
break;
}
}
EstimatedTotalLeftTime += lr1 * PmDevice.RecipeRunningInfo.RecipeStepList[iNum1].LoopCount;
j = iNum2;
}
else
{
EstimatedTotalLeftTime += PmDevice.RecipeRunningInfo.RecipeStepList[j].StepTime * 1000;
}
}
}
catch (Exception ex)
{
LOG.Write(ex);
}
}
public void SetContinue(string continueMode)
{
switch (continueMode)
{
case "Step continue":
ContinueAction = RecipeContinueMode.StepContinue;
break;
case "Step restart":
ContinueAction = RecipeContinueMode.StepRestart;
break;
case "Next step":
ContinueAction = RecipeContinueMode.NextStep;
break;
case "Recipe restart":
ContinueAction = RecipeContinueMode.RecipeRestart;
break;
case "Recipe complete":
ContinueAction = RecipeContinueMode.RecipeCompleted;
break;
case "Wafer return and job stop":
ContinueAction = RecipeContinueMode.WaferReturnAndJobStop;
break;
}
IsPaused = false;
PmDevice.ResetToleranceChecker();
}
}
}