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;
}
}
}