using System; using System.Collections.Generic; using Aitex.Core.Common; using Aitex.Core.RT.Event; using Aitex.Core.RT.Routine; using EFEM.RT.Routines; using Aitex.Sorter.Common; using MECF.Framework.Common.Equipment; using MECF.Framework.Common.SubstrateTrackings; using Aitex.Sorter.RT.Module; namespace EFEM.RT.Modules { public class SingleArmMoveManager : IMoveManager { private IRoutine _alignerRoutine; private bool _pause = true; private IRoutine _robotRoutine; private readonly AlignRoutine alignRoutine; private int lastTaskCount; private readonly PickRoutine pickRoutine; private readonly PlaceRoutine placeRoutine; private MoveTask task1; private List tasks = new List(); public SingleArmMoveManager() { pickRoutine = new PickRoutine("System", "PickWafer"); pickRoutine.Initalize(); placeRoutine = new PlaceRoutine("System", "PlaceWafer"); placeRoutine.Initalize(); alignRoutine = new AlignRoutine("System", "Alignment"); alignRoutine.Initalize(); } public Hand Blade { get; set; } public event Action OnMoveError; public int TaskCount => tasks.Count; public bool IsPaused => !_pause; public int WaferCompleted { get { var count = tasks.Count; var completed = lastTaskCount - count; lastTaskCount = count; return completed; } } 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; var bCheck = true; var isSameStation = false || tasks[0].SourceStaion == tasks[tasks.Count - 1].DestStaion; for (var i = 0; i < tasks.Count; i++) if (!(tasks[i].DestStaion == tasks[tasks.Count - 1].DestStaion && isSameStation)) if (IsSwap(tasks[i])) { var reason = string.Format("single arm can't support swap operation. {0}:{1} ---> {2}:{3}.", tasks[i].SourceStaion.ToString(), tasks[i].SourceSlot, tasks[i].DestStaion.ToString(), tasks[i].DestSlot); EV.PostMessage(ModuleName.System.ToString(), EventEnum.DefaultWarning, reason); bCheck = false; } if (!bCheck) return false; foreach (var task in tasks) { WaferManager.Instance.UpdateWaferProcessStatus(task.SourceStaion, task.SourceSlot, EnumWaferProcessStatus.Wait);//(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; } public bool Monitor(object[] objs) { var 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; } 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; } 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) { var rountine = NextRoutine(); if (rountine != null) { ret = rountine.Start(); if (ret == Result.FAIL) { WaferManager.Instance.UpdateWaferProcessStatus(ModuleName.Robot, 0, ProcessStatus.Failed); WaferManager.Instance.UpdateWaferProcessStatus(ModuleName.Robot, 1, ProcessStatus.Failed); NotifyError("Robot", "Robot Error"); return true; } _robotRoutine = rountine; } } } return false; } public Result Monitor() { var 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; } if (ret == Result.FAIL) { WaferManager.Instance.UpdateWaferProcessStatus(ModuleName.Robot, 0, EnumWaferProcessStatus.Failed); WaferManager.Instance.UpdateWaferProcessStatus(ModuleName.Robot, 1, EnumWaferProcessStatus.Failed); WaferManager.Instance.UpdateWaferProcessStatus(ModuleName.Aligner, 0, EnumWaferProcessStatus.Failed); NotifyError("Aligner", "Aligner Error"); return Result.FAIL; //failed } } if (_robotRoutine != null) { ret = _robotRoutine.Monitor(); if (ret == Result.DONE) { _robotRoutine = null; IRoutine rountine = NextRoutine(); if (rountine != null) { if (rountine.Start() == Result.FAIL) { WaferManager.Instance.UpdateWaferProcessStatus(ModuleName.Robot, 0, EnumWaferProcessStatus.Failed); WaferManager.Instance.UpdateWaferProcessStatus(ModuleName.Robot, 1, EnumWaferProcessStatus.Failed); WaferManager.Instance.UpdateWaferProcessStatus(ModuleName.Aligner, 0, EnumWaferProcessStatus.Failed); NotifyError("Robot", "Robot Error"); return Result.FAIL; } else { _robotRoutine = rountine; return _robotRoutine.Monitor(); } } return Result.RUN; } if (ret == Result.FAIL) { WaferManager.Instance.UpdateWaferProcessStatus(ModuleName.Robot, 0, EnumWaferProcessStatus.Failed); WaferManager.Instance.UpdateWaferProcessStatus(ModuleName.Robot, 1, EnumWaferProcessStatus.Failed); WaferManager.Instance.UpdateWaferProcessStatus(ModuleName.Aligner, 0, EnumWaferProcessStatus.Failed); NotifyError("Robot", "Robot Error"); return Result.FAIL; //failed } } else { if (!_pause) { IRoutine rountine = NextRoutine(); if (rountine != null) { if (rountine.Start() == Result.FAIL) { WaferManager.Instance.UpdateWaferProcessStatus(ModuleName.Robot, 0, EnumWaferProcessStatus.Failed); WaferManager.Instance.UpdateWaferProcessStatus(ModuleName.Robot, 1, EnumWaferProcessStatus.Failed); WaferManager.Instance.UpdateWaferProcessStatus(ModuleName.Aligner, 0, EnumWaferProcessStatus.Failed); NotifyError("Robot", "Robot Error"); return Result.FAIL; } else { _robotRoutine = rountine; return _robotRoutine.Monitor(); } } return Result.RUN; } } return Result.RUN; } public bool Initialize() { return true; } private void newTask() { if (tasks.Count > 0) task1 = tasks[0]; if (task1 != null) WaferManager.Instance.UpdateWaferProcessStatus(task1.SourceStaion, task1.SourceSlot, EnumWaferProcessStatus.Wait); //(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); } 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(); pickRoutine.WaitForPickTime = task1.DelayTimeBeforePick; task1.Blade = pickRoutine.Blade; routine = pickRoutine; if (PassAligner(task1.option)) task1.Step = MoveStep.PlaceToAligner; else task1.Step = MoveStep.PlaceToDest; } 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.VerifyAny = task1.VerifyAny; alignRoutine.VerifyLaserMaker = task1.VerifyLaserMaker; alignRoutine.LaserMaker = task1.LaserMaker; alignRoutine.VerifyT7Code = task1.VerifyT7Code; alignRoutine.T7Code = task1.T7Code; _alignerRoutine = alignRoutine; _alignerRoutine.Start(); task1.Step = MoveStep.WaitAligner; } else if (task1.Step == MoveStep.PickFromAligner) { if (_alignerRoutine == null) //aligning completed { 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) { 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 Hand GetEmptyHand() { return 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.SourceStaion, newTask.SourceSlot, EnumWaferProcessStatus.Wait);//(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)); } } }