using System; using System.Collections.Generic; using System.Security.AccessControl; using Aitex.Core.Common; using Aitex.Core.RT.Device; using Aitex.Core.RT.Event; using Aitex.Core.RT.Routine; using Aitex.Core.RT.SCCore; using Aitex.Core.Util; using Aitex.Sorter.Common; using Aitex.Sorter.RT.Module; using Aitex.Sorter.RT.SorterCommonFrame.Routines; using MECF.Framework.Common.Equipment; using MECF.Framework.Common.SubstrateTrackings; using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.LoadPorts; namespace Aitex.Sorter.RT.SorterCommonFrame.Modules { public class SingleMoveManager : IMoveManager { public event Action OnMoveError; public Hand Blade { get; set; } public int TaskCount { get { return tasks.Count; } } public bool IsPaused { get { return !_pause; } } public int WaferCompleted { get { int count = tasks.Count; int completed = lastTaskCount - count; lastTaskCount = count; return completed; } } private PickRoutine pickRoutine = null; private PlaceRoutine placeRoutine = null; private AlignRoutine alignRoutine = null; private List tasks = new List(); private IRoutine _robotRoutine = null; private AlignRoutine _alignerRoutine = null; private MoveTask task1 = null; private int lastTaskCount = 0; private bool _verifyFail = false; private bool _pause = true; public SingleMoveManager() { pickRoutine = new PickRoutine("System", "PickRoutine"); pickRoutine.Initalize(); placeRoutine = new PlaceRoutine("System", "PlaceRoutine"); placeRoutine.Initalize(); alignRoutine = new AlignRoutine("System", "AlignRoutine"); alignRoutine.Initalize(); } public bool Initialize() { return true; } public bool Pause() { _pause = true; return true; } public bool Resume() { _pause = false; return true; } public bool Stop() { tasks.Clear(); if (task1 != null) tasks.Add(task1); _pause = false; return true; } public bool Start(List tasks) { _robotRoutine = null; _alignerRoutine = null; this.tasks = tasks; _pause = false; bool bCheck = true; foreach (MoveTask task in tasks) { if (IsSwap(task)) { string reason = string.Format("single arm can't support swap operation. {0}:{1} ---> {2}:{3}.", ((ModuleName)task.SourceStaion).ToString(), task.SourceSlot, ((ModuleName)task.DestStaion).ToString(), task.DestSlot); EV.PostMessage(ModuleName.System.ToString(),EventEnum.DefaultWarning, reason); bCheck = false; } } if (!bCheck) return false; foreach (MoveTask task in tasks) { WaferManager.Instance.UpdateWaferProcessStatus(task.WaferID, ProcessStatus.Wait); task.WaferID = WaferManager.Instance.GetWaferID(task.SourceStaion, task.SourceSlot); } newTask(); if (task1 == null) { return true; } _robotRoutine = null; _alignerRoutine = null; lastTaskCount = tasks.Count; return true; } private void newTask() { if (tasks.Count > 0) task1 = tasks[0]; if (task1 != null) { WaferManager.Instance.UpdateWaferProcessStatus(task1.WaferID, ProcessStatus.Busy); } } private bool IsSwap(MoveTask task) { if ((task.DestStaion == task.SourceStaion) && (task.DestSlot == task.SourceSlot)) return false; return WaferManager.Instance.CheckHasWafer(task.DestStaion, task.DestSlot); } public bool Monitor(object[] objs) { Result ret = Result.RUN; if (tasks.Count == 0 && task1 == null) { return true; //completed } if (task1 == null) { if (!_pause) newTask(); } if (_alignerRoutine != null) { ret = _alignerRoutine.Monitor(); if (ret == Result.DONE) { _alignerRoutine = null; AlignCompleted(); return false; } else if (ret == Result.FAIL) { WaferManager.Instance.UpdateWaferProcessStatus(ModuleName.Robot, 0, ProcessStatus.Failed); WaferManager.Instance.UpdateWaferProcessStatus(ModuleName.Robot, 1, ProcessStatus.Failed); WaferManager.Instance.UpdateWaferProcessStatus(ModuleName.Aligner, 0, ProcessStatus.Failed); NotifyError("Aligner", "Aligner Error"); return true; //failed } } if (_robotRoutine != null) { ret = _robotRoutine.Monitor(); if (ret == Result.DONE) { _robotRoutine = null; return false; } else if (ret == Result.FAIL) { WaferManager.Instance.UpdateWaferProcessStatus(ModuleName.Robot, 0, ProcessStatus.Failed); WaferManager.Instance.UpdateWaferProcessStatus(ModuleName.Robot, 1, ProcessStatus.Failed); WaferManager.Instance.UpdateWaferProcessStatus(ModuleName.Aligner, 0, ProcessStatus.Failed); NotifyError("Robot", "Robot Error"); return true; //failed } } else { if (!_pause) { IRoutine rountine = NextRoutine(); if (rountine != null) { rountine.Start(); _robotRoutine = rountine; } } } return false; } public Result Monitor() { Result ret = Result.RUN; if (tasks.Count == 0 && task1 == null) { return Result.DONE; //completed } if (task1 == null) { if (!_pause) newTask(); } if (_alignerRoutine != null) { ret = _alignerRoutine.Monitor(); if (ret == Result.DONE) { _alignerRoutine = null; AlignCompleted(); return Result.RUN; } else if (ret == Result.FAIL) { WaferManager.Instance.UpdateWaferProcessStatus(ModuleName.Robot, 0, ProcessStatus.Failed); WaferManager.Instance.UpdateWaferProcessStatus(ModuleName.Robot, 1, ProcessStatus.Failed); WaferManager.Instance.UpdateWaferProcessStatus(ModuleName.Aligner, 0, ProcessStatus.Failed); NotifyError("Aligner", "Aligner Error"); return Result.FAIL; //failed } else if (ret == Result.VERIFYFAIL) { // _alignerRoutine = null; if (SC.ContainsItem(SorterCommon.ScPathName.Process_LMMismatchHandle)) switch (SC.GetValue(SorterCommon.ScPathName.Process_LMMismatchHandle)) { case 2: task1.DestStaion = task1.SourceStaion; task1.DestSlot = task1.SourceSlot; WaferManager.Instance.UpdateWaferProcessStatus(ModuleName.Aligner, 0, ProcessStatus.Failed); _verifyFail = true; break; case 3: ModuleName handleLp; if (SC.ContainsItem(SorterCommon.ScPathName.Process_MismatchCollectPort)) { handleLp = ModuleHelper.Converter(SC.GetStringValue(SorterCommon.ScPathName.Process_MismatchCollectPort)); if (!ModuleHelper.IsLoadPort(handleLp)) break; //handleLp = ModuleName.LP1; } else break; task1.DestStaion = handleLp; int startSlot = SC.ContainsItem("LoadPort." + handleLp.ToString() + "StartSlot") ? SC.GetValue("LoadPort." + handleLp.ToString() + "StartSlot") : 1; if (startSlot > 25 || startSlot < 1) startSlot = 1; int endSlot = SC.ContainsItem("LoadPort." + handleLp.ToString() + "EndSlot") ? SC.GetValue("LoadPort." + handleLp.ToString() + "EndSlot") : 25; if (endSlot > 25 || endSlot < 1) endSlot = 25; WaferManager.Instance.UpdateWaferProcessStatus(ModuleName.Aligner, 0, ProcessStatus.Failed); _verifyFail = true; var emptySlot = DEVICE.GetDevice(handleLp.ToString()).GetEmptySlot(); foreach(int slot in emptySlot) { if (slot < startSlot || slot > endSlot) emptySlot.Remove(slot); } if (emptySlot.Count != 0) { if (SC.ContainsItem("Process.PlaceFromTopOnHostLPMode") && SC.GetValue("Process.PlaceFromTopOnHostLPMode")) { task1.DestSlot = emptySlot[emptySlot.Count - 1]; } else { task1.DestSlot = emptySlot[0]; } break; } else { Singleton.Instance.PostMsg(RouteManagerSorter.MSG.PauseRecipe); EV.PostWarningLog(handleLp.ToString(), $"{handleLp} is full."); break; } } //AlignCompleted(); _alignerRoutine.PostAlignValue = SC.ContainsItem("Aligner." + task1.DestStaion + "PostAlignAngle") ? SC.GetValue("Aligner." + task1.DestStaion + "PostAlignAngle") : 0; return Result.RUN; } } if (_robotRoutine != null) { ret = _robotRoutine.Monitor(); if (ret == Result.DONE) { _robotRoutine = null; return Result.RUN; } else if (ret == Result.FAIL) { WaferManager.Instance.UpdateWaferProcessStatus(ModuleName.Robot, 0, ProcessStatus.Failed); WaferManager.Instance.UpdateWaferProcessStatus(ModuleName.Robot, 1, ProcessStatus.Failed); WaferManager.Instance.UpdateWaferProcessStatus(ModuleName.Aligner, 0, ProcessStatus.Failed); NotifyError("Robot", "Robot Error"); return Result.FAIL; //failed } } else { if (!_pause) { IRoutine rountine = NextRoutine(); if (rountine != null) { rountine.Start(); _robotRoutine = rountine; } } } return Result.RUN; } private void AlignCompleted() { if (task1 != null) { if (task1.Step == MoveStep.WaitAligner) { task1.Step = MoveStep.PickFromAligner; } } } private IRoutine NextRoutine() { IRoutine routine = null; if (task1.Step == MoveStep.PickFromSource) { pickRoutine.Source = task1.SourceStaion; pickRoutine.Slot = task1.SourceSlot; pickRoutine.Blade = GetEmptyHand(); task1.Blade = pickRoutine.Blade; routine = pickRoutine; if (PassTurnOver(task1.option) && PassAligner(task1.option)) { task1.Step = MoveStep.PlaceToAligner; } else if(PassTurnOver(task1.option)) { task1.Step = MoveStep.PlaceToTurnOver; } else if (PassAligner(task1.option)) { task1.Step = MoveStep.PlaceToAligner; } else { task1.Step = MoveStep.PlaceToDest; } } else if (task1.Step == MoveStep.PlaceToTurnOver) { placeRoutine.Station = ModuleName.TurnOverStation; placeRoutine.Slot = 0; placeRoutine.Blade = task1.Blade; task1.Step = MoveStep.PickFromTurnOver; routine = placeRoutine; } else if (task1.Step == MoveStep.PlaceToAligner) { placeRoutine.Station = ModuleName.Aligner; placeRoutine.Slot = 0; placeRoutine.Blade = task1.Blade; task1.Step = MoveStep.Aligning; routine = placeRoutine; } else if (task1.Step == MoveStep.Aligning) { alignRoutine.Option = task1.option; alignRoutine.Notch = task1.Notch; alignRoutine.IsVerifyAny = task1.VerifyAny; alignRoutine.IsVerifyLM1 = task1.VerifyLaserMaker; alignRoutine.StrLaserMark1 = task1.LaserMaker; alignRoutine.IsVerifyLM2 = task1.VerifyT7Code; alignRoutine.StrLaserMark2 = task1.T7Code; alignRoutine.PostAlignValue = SC.ContainsItem("Aligner." + task1.DestStaion + "PostAlignAngle") ? SC.GetValue("Aligner." + task1.DestStaion + "PostAlignAngle") : 0; _alignerRoutine = alignRoutine; _alignerRoutine.Start(); task1.Step = MoveStep.WaitAligner; } else if (task1.Step == MoveStep.PickFromTurnOver) { pickRoutine.Source = ModuleName.TurnOverStation; pickRoutine.Slot = 0; pickRoutine.Blade = task1.Blade; task1.Step = MoveStep.PlaceToDest; routine = pickRoutine; } else if (task1.Step == MoveStep.PickFromAligner) { if (_alignerRoutine == null) //aligning completed { if (PassTurnOver(task1.option)) { pickRoutine.Source = ModuleName.Aligner; pickRoutine.Slot = 0; pickRoutine.Blade = task1.Blade; task1.Step = MoveStep.PlaceToTurnOver; routine = pickRoutine; } else { pickRoutine.Source = ModuleName.Aligner; pickRoutine.Slot = 0; pickRoutine.Blade = task1.Blade; task1.Step = MoveStep.PlaceToDest; routine = pickRoutine; } } } else if (task1.Step == MoveStep.PlaceToDest) { placeRoutine.Station = task1.DestStaion; placeRoutine.Slot = task1.DestSlot; placeRoutine.Blade = task1.Blade; task1.Step = MoveStep.Completed; routine = placeRoutine; } else if (task1.Step == MoveStep.Completed) { if (_verifyFail) { WaferManager.Instance.UpdateWaferProcessStatus(task1.DestStaion, task1.DestSlot, ProcessStatus.Failed); _verifyFail = false; } else WaferManager.Instance.UpdateWaferProcessStatus(task1.DestStaion, task1.DestSlot, ProcessStatus.Completed); tasks.Remove(task1); task1 = GetNextTask(); } return routine; } private bool PassAligner(MoveOption option) { return (((option & MoveOption.Align) == MoveOption.Align) || ((option & MoveOption.ReadID) == MoveOption.ReadID) || ((option & MoveOption.ReadID2) == MoveOption.ReadID2)); } private bool PassTurnOver(MoveOption option) { return (option & MoveOption.Turnover) == MoveOption.Turnover; } private Hand GetEmptyHand() { return this.Blade; /* if (!WaferManager.Instance.CheckWafer(UnitName.Robot, 0, WaferStatus.Normal)) { return Hand.Blade1; } if (!WaferManager.Instance.CheckWafer(UnitName.Robot, 1, WaferStatus.Normal)) { return Hand.Blade2; } */ //return Hand.Blade1; } private MoveTask GetNextTask() { MoveTask newTask = null; if (tasks.Count > 0) newTask = tasks[0]; if (newTask != null) { WaferManager.Instance.UpdateWaferProcessStatus(newTask.WaferID, ProcessStatus.Busy); } return newTask; } //private void PostMsg(RouteManager.MSG msg, params object[] objs) //{ // Singleton.Instance.PostMsg(msg, objs); //} private void NotifyError(string module, string message) { if (OnMoveError != null) { OnMoveError(new MoveErrorArgument(module, message)); } } } }