using Aitex.Core.Common;
using Aitex.Core.RT.Log;
using Aitex.Core.RT.Routine;
using Aitex.Core.RT.SCCore;
using Aitex.Core.Util;
using Aitex.Sorter.Common;
using CyberX8_Core;
using CyberX8_RT.Devices.EFEM;
using CyberX8_RT.Modules.LPs;
using MECF.Framework.Common.Beckhoff.Station;
using MECF.Framework.Common.Equipment;
using MECF.Framework.Common.Schedulers;
using MECF.Framework.Common.SubstrateTrackings;
using MECF.Framework.Common.Utilities;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CyberX8_RT.Modules.EFEM
{
public class RobotCycleRoutine : ModuleRoutineBase, IRoutine
{
private enum RobotCycleStep
{
LPCycleStrat,
PickFromLP,
PickFromLPCheck,
PlaceToAligner,
PlaceToAlignerCheck,
AlignAction,
AlignCompleteCheck,
PickFromAligner,
PickFromAlignerCheck,
PlaceToDummy,
PlaceToDummyCheck,
PickFromDummy,
PickFromDummyCheck,
PlaceToSrd,
PlaceToSrdCheck,
PickFromSrd,
PickFromSrdCheck,
PlaceToLP,
PlaceToLPCheck,
LPCycleEnd,
End
}
EfemBase _efem;
///
/// 当前Cycle选中的LP里面的Wafer数量
///
private int _waferCount;
private EfemPickRoutine _efemPickRoutine;
private EfemPlaceRoutine _efemPlaceRoutine;
private EFEMAlignRoutine _efemAlignRoutine;
private ModuleName _targetLP;
private ModuleName _targetAligner;
private ModuleName _targetDummy;
private ModuleName _targetSrd;
private Queue _lpToAlignerMoveItem = new Queue();
private Queue _alignerToDummyMoveItem = new Queue();
private Queue _alignerToSrdMoveItem = new Queue();
private Queue _dummyToLpMoveItem = new Queue();
private Queue _dummyToSrdMoveItem = new Queue();
private Queue _srdToLpMoveItem = new Queue();
private Queue _lpWaferIndex = new Queue(); //记录有LP有Wafer的slot号
private int _moveTimeout = 20 * 1000;
private int _dummySlotNumber = 0;
private object[] alignerParamater;
public RobotCycleRoutine(EfemBase efem) : base(ModuleName.EfemRobot)
{
_efem = efem;
_efemPickRoutine = new EfemPickRoutine(efem);
_efemPlaceRoutine = new EfemPlaceRoutine(efem);
_efemAlignRoutine = new EFEMAlignRoutine(efem);
}
public RState Start(params object[] objs)
{
_lpWaferIndex.Clear();//初始化LP 有wafer的slot号
_waferCount = 0; //初始化wafercount的数量
alignerParamater = new object[3];//初始化Align参数
alignerParamater[0] = ModuleName.Aligner1;
alignerParamater[1] = 0;
if (objs.Length >= 6)
{
_targetLP = (ModuleName)objs[0];
_targetAligner = (ModuleName)objs[1];
_targetDummy = (ModuleName)objs[2];
_targetSrd = (ModuleName)objs[3];
alignerParamater[2] = (int)objs[5];
}
else
{
return RState.Failed;
}
if (!CheckPreCondition()) //检验前提条件
{
return RState.Failed;
}
_moveTimeout = SC.GetValue($"EFEM.MotionTimeout") * 1000;
MoveItem lpToAlignerMoveItem = new MoveItem //LP To Aligner
{
SourceModule = _targetLP,
SourceSlot = _lpWaferIndex.Dequeue(),
DestinationModule = ModuleName.Aligner1,
DestinationSlot = 0,
RobotHand = 0 //表示blade1
};
_lpToAlignerMoveItem.Enqueue(lpToAlignerMoveItem);
MoveItem alignerToDummyMoveItem = new MoveItem //Aligner To Dummy
{
SourceModule = ModuleName.Aligner1,
SourceSlot = 0,
DestinationModule = _targetDummy,
DestinationSlot = 0,
RobotHand = 0
};
_alignerToDummyMoveItem.Enqueue(alignerToDummyMoveItem);
MoveItem alignerToSrdMoveItem = new MoveItem //Aligner To Srd
{
SourceModule = ModuleName.Aligner1,
SourceSlot = 0,
DestinationModule = _targetSrd,
DestinationSlot = 0,
RobotHand = 0
};
_alignerToSrdMoveItem.Enqueue(alignerToSrdMoveItem);
MoveItem dummyToLpMoveItem = new MoveItem //Dummy To LP
{
SourceModule = _targetDummy,
SourceSlot = 0,
DestinationModule = _targetLP,
DestinationSlot = _lpToAlignerMoveItem.Peek().SourceSlot, //放回原来LP的slot位置
RobotHand = 0
};
_dummyToLpMoveItem.Enqueue(dummyToLpMoveItem);
MoveItem dummyToSrdMoveItem = new MoveItem //Dummy To Srd
{
SourceModule = _targetDummy,
SourceSlot = 0,
DestinationModule = _targetSrd,
DestinationSlot = 0,
RobotHand = 0
};
_dummyToSrdMoveItem.Enqueue(dummyToSrdMoveItem);
MoveItem srdToLpMoveItem = new MoveItem //SRD To LP
{
DestinationModule = _targetLP,
DestinationSlot = _lpToAlignerMoveItem.Peek().SourceSlot, //放回原来LP的slot位置
RobotHand = 0
};
_srdToLpMoveItem.Enqueue(srdToLpMoveItem);
return Runner.Start(Module, "Robot Cycle start");
}
public RState Monitor()
{
Runner.LoopStart(RobotCycleStep.LPCycleStrat, "LP Cycle Start", _waferCount, NullFun, _delay_1ms)
.LoopRun(RobotCycleStep.PickFromLP, () => { return _efemPickRoutine.Start(_lpToAlignerMoveItem) == RState.Running; }, _delay_1ms)
.LoopRunWithStopStatus(RobotCycleStep.PickFromLPCheck, () => { return CommonFunction.CheckRoutineEndState(_efemPickRoutine); },
() => CheckRoutineStopStatus(_efemPickRoutine, "Efem pick from LP failed"))
.LoopRun(RobotCycleStep.PlaceToAligner, () => { return _efemPlaceRoutine.Start(_lpToAlignerMoveItem) == RState.Running; }, _delay_1ms)
.LoopRunWithStopStatus(RobotCycleStep.PlaceToAlignerCheck, () => { return CommonFunction.CheckRoutineEndState(_efemPlaceRoutine); },
() => CheckRoutineStopStatus(_efemPlaceRoutine, "Efem place to aligner failed"))
.LoopRun(RobotCycleStep.AlignAction, () => { return _efemAlignRoutine.Start(alignerParamater) == RState.Running; }, _delay_1ms)
.LoopRunWithStopStatus(RobotCycleStep.AlignCompleteCheck, () => { return CommonFunction.CheckRoutineEndState(_efemAlignRoutine); },
() => CheckRoutineStopStatus(_efemAlignRoutine, "Efem aligner Action failed"))
.LoopRun(RobotCycleStep.PickFromAligner, () => { return _efemPickRoutine.Start(_alignerToDummyMoveItem) == RState.Running; }, _delay_1ms)
.LoopRunWithStopStatus(RobotCycleStep.PickFromAlignerCheck, () => { return CommonFunction.CheckRoutineEndState(_efemPickRoutine); },
() => CheckRoutineStopStatus(_efemPickRoutine, "Efem pick from aligner failed"))
//从Aligner到dummy
.LoopRunIf(RobotCycleStep.PlaceToDummy, _targetDummy != ModuleName.Unknown, () => { return _efemPlaceRoutine.Start(_alignerToDummyMoveItem) == RState.Running; }, _delay_1ms)
.LoopRunIfWithStopStatus(RobotCycleStep.PlaceToDummyCheck, _targetDummy != ModuleName.Unknown,() => { return CommonFunction.CheckRoutineEndState(_efemPlaceRoutine); },
() => CheckRoutineStopStatus(_efemPlaceRoutine, "Efem place to dummy failed"))
.LoopRunIf(RobotCycleStep.PickFromDummy, _targetDummy != ModuleName.Unknown, () => { return _efemPickRoutine.Start(_dummyToLpMoveItem) == RState.Running; }, _delay_1ms)
.LoopRunIfWithStopStatus(RobotCycleStep.PickFromDummyCheck, _targetDummy != ModuleName.Unknown,() => { return CommonFunction.CheckRoutineEndState(_efemPickRoutine); },
() => CheckRoutineStopStatus(_efemPickRoutine, "Efem pick from dummy failed"))
//从Aligner到SRD的
.LoopRunIf(RobotCycleStep.PlaceToSrd, _targetSrd != ModuleName.Unknown && _targetDummy==ModuleName.Unknown, () => { return _efemPlaceRoutine.Start(_alignerToSrdMoveItem) == RState.Running; }, _delay_1ms)
.LoopRunIfWithStopStatus(RobotCycleStep.PlaceToSrdCheck, _targetSrd != ModuleName.Unknown && _targetDummy == ModuleName.Unknown, () => { return CommonFunction.CheckRoutineEndState(_efemPlaceRoutine); },
() => CheckRoutineStopStatus(_efemPlaceRoutine, "Efem place to srd failed"))
.LoopRunIf(RobotCycleStep.PickFromSrd, _targetSrd != ModuleName.Unknown && _targetDummy == ModuleName.Unknown, () => { return _efemPickRoutine.Start(_alignerToSrdMoveItem) == RState.Running; }, _delay_1ms)
.LoopRunIfWithStopStatus(RobotCycleStep.PickFromSrdCheck, _targetSrd != ModuleName.Unknown && _targetDummy == ModuleName.Unknown, () => { return CommonFunction.CheckRoutineEndState(_efemPickRoutine); },
() => CheckRoutineStopStatus(_efemPickRoutine, "Efem pick from srd failed"))
//从dummy到SRD的
.LoopRunIf(RobotCycleStep.PlaceToSrd, _targetSrd != ModuleName.Unknown && _targetDummy != ModuleName.Unknown, () => { return _efemPlaceRoutine.Start(_dummyToSrdMoveItem) == RState.Running; }, _delay_1ms)
.LoopRunIfWithStopStatus(RobotCycleStep.PlaceToSrdCheck, _targetSrd != ModuleName.Unknown && _targetDummy != ModuleName.Unknown, () => { return CommonFunction.CheckRoutineEndState(_efemPlaceRoutine); },
() => CheckRoutineStopStatus(_efemPlaceRoutine, "Efem place to srd failed"))
.LoopRunIf(RobotCycleStep.PickFromSrd, _targetSrd != ModuleName.Unknown && _targetDummy != ModuleName.Unknown, () => { return _efemPickRoutine.Start(_dummyToSrdMoveItem) == RState.Running; }, _delay_1ms)
.LoopRunIfWithStopStatus(RobotCycleStep.PickFromSrdCheck, _targetSrd != ModuleName.Unknown && _targetDummy != ModuleName.Unknown, () => { return CommonFunction.CheckRoutineEndState(_efemPickRoutine); },
() => CheckRoutineStopStatus(_efemPickRoutine, "Efem pick from srd failed"))
//从Dummy回LP
.LoopRunIf(RobotCycleStep.PlaceToLP, _targetDummy != ModuleName.Unknown && _targetSrd == ModuleName.Unknown, () => { return _efemPlaceRoutine.Start(_dummyToLpMoveItem) == RState.Running; }, _delay_1ms)
.LoopRunIfWithStopStatus(RobotCycleStep.PlaceToLPCheck, _targetDummy != ModuleName.Unknown && _targetSrd == ModuleName.Unknown, () => { return CommonFunction.CheckRoutineEndState(_efemPlaceRoutine); },
() => CheckRoutineStopStatus(_efemPlaceRoutine, "Efem place to LP failed"))
//从SRD回LP
.LoopRunIf(RobotCycleStep.PlaceToLP, _targetSrd != ModuleName.Unknown, () => { return _efemPlaceRoutine.Start(_srdToLpMoveItem) == RState.Running; }, _delay_1ms)
.LoopRunIfWithStopStatus(RobotCycleStep.PlaceToLPCheck, _targetSrd != ModuleName.Unknown, () => { return CommonFunction.CheckRoutineEndState(_efemPlaceRoutine); },
() => CheckRoutineStopStatus(_efemPlaceRoutine, "Efem place to LP failed"))
.LoopEnd(RobotCycleStep.LPCycleEnd, UpdateMoveItem, _delay_1ms)
.End(RobotCycleStep.End, ClearMoveItem, _delay_1ms);
return Runner.Status;
}
public void Abort()
{
_efem.Halt();
}
#region 功能方法
private bool CheckPreCondition()
{
if (WaferManager.Instance.CheckHasWafer(ModuleName.EfemRobot, 0))
{
Stop($"Efem robot arm already has a wafer, cannot do the RobotCycle action");
return false;
}
//LoadPort状态判断
if (ModuleHelper.IsLoadPort(_targetLP) && ModuleHelper.IsInstalled(_targetLP))
{
Loadport loadPort = GetLoadPort(_targetLP);
if (loadPort == null)
{
Stop($"{_targetLP} is null");
return false;
}
WaferInfo[] waferInfos = WaferManager.Instance.GetWafers(_targetLP);
for (int i = 0; i < waferInfos.Length; i++)
{
if (waferInfos[i] != null && !waferInfos[i].IsEmpty)
{
_waferCount++;
_lpWaferIndex.Enqueue(i);
}
}
if (_waferCount < 1)
{
Stop($"there is no wafer in {_targetLP}");
return false;
}
}
else if(ModuleHelper.IsLoadPort(_targetLP) && !ModuleHelper.IsInstalled(_targetLP))
{
Stop($"{_targetLP} is not installed");
return false;
}
//Aligner状态判断
//if (!ModuleHelper.IsInstalled(_targetAligner))
//{
// Stop($"{_targetAligner} is not installed");
// return false;
//}
//Dummy状态判断
if (!ModuleHelper.IsInstalled(_targetDummy))
{
Stop($"{_targetDummy} is not installed");
return false;
}
//若dummy存在wafer,需要人工处理
DummyDevice dummyDevice = Singleton.Instance.EFEM.GetDummyDevice(_targetDummy - ModuleName.Dummy1);
if(dummyDevice != null)
{
if (!dummyDevice.HasCassette)
{
Stop($"{_targetDummy} dose not have cassette");
return false;
}
WaferInfo[] waferInfos = WaferManager.Instance.GetWafers(_targetDummy);
if(waferInfos.Length > 0)
{
_dummySlotNumber = waferInfos.Length;
foreach (var item in waferInfos)
{
if (item != null && !item.IsEmpty)
{
Stop($"There are wafers inside the {_targetDummy},cannot do the RobotCycle action");
return false;
}
}
}
}
return true;
}
private Loadport GetLoadPort(ModuleName station)
{
LoadPortModule loadPortModule = Singleton.Instance.EFEM.GetLoadportModule(station - ModuleName.LP1);
return loadPortModule.LPDevice;
}
private bool CheckRoutineStopStatus(IRoutine routine, string error)
{
bool result = CommonFunction.CheckRoutineStopState(routine);
if (result)
{
Stop( $"{error}");
}
return result;
}
//更新取放dummy的位置
private bool UpdateMoveItem()
{
if (_lpWaferIndex.Count > 0)
{
_lpToAlignerMoveItem.Peek().SourceSlot = _lpWaferIndex.Dequeue(); //更新从LP取片的位置
if (_targetDummy != ModuleName.Unknown)
{
_alignerToDummyMoveItem.Peek().DestinationSlot = (_alignerToDummyMoveItem.Peek().DestinationSlot + 1) % _dummySlotNumber; //更新放到Dummy的位置
_dummyToLpMoveItem.Peek().SourceSlot = (_dummyToLpMoveItem.Peek().SourceSlot + 1) % _dummySlotNumber; //更新从dummy取片的位置,送回LP
_dummyToSrdMoveItem.Peek().SourceSlot = (_dummyToSrdMoveItem.Peek().SourceSlot + 1) % _dummySlotNumber;//更新从dummy取片的位置,送到Srd
}
_dummyToLpMoveItem.Peek().DestinationSlot = _lpToAlignerMoveItem.Peek().SourceSlot;//更新从dummy放回LP的位置。
_srdToLpMoveItem.Peek().DestinationSlot = _lpToAlignerMoveItem.Peek().SourceSlot;//更新从srd放回LP的位置。
}
return true;
}
//清除MoveItem
private bool ClearMoveItem()
{
_lpToAlignerMoveItem.Clear();
_alignerToDummyMoveItem.Clear();
_alignerToSrdMoveItem.Clear();
_dummyToLpMoveItem.Clear();
_dummyToSrdMoveItem.Clear();
_srdToLpMoveItem.Clear();
return true;
}
#endregion
}
}