Sic08/Modules/Mainframe/PMs/Routines/EditableRoutine/PMEditableRoutine.cs

946 lines
38 KiB
C#
Raw Normal View History

2023-03-28 13:24:11 +08:00
using System;
using System.Collections.Generic;
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;
2023-04-13 15:35:13 +08:00
using SicModules.PMs.RecipeExecutions;
using SicModules.PMs.Routines.Base;
2023-03-28 13:24:11 +08:00
namespace SicModules.PMs.Routines.EditableRoutine
2023-03-28 13:24:11 +08:00
{
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 PMEditableRoutine : PMBaseRoutine
2023-03-28 13:24:11 +08:00
{
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 PMEditableRoutine(ModuleName module, PMModule pm1) : base(module, pm1)
2023-03-28 13:24:11 +08:00
{
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 (!EditableRoutineParser.Parse(_recipeName, Module, out var recipeHead, out var recipeSteps, out string reason))
2023-03-28 13:24:11 +08:00
{
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");
2023-08-10 15:56:27 +08:00
WaferManager.Instance.UpdateWaferProcessStatus(ModuleHelper.Converter(Module), 0, WaferProcessStatus.InProcess);
2023-03-28 13:24:11 +08:00
_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();
}
}
}