using Aitex.Core.Common; using Aitex.Core.RT.Log; using Aitex.Core.RT.SCCore; using Aitex.Core.Util; using Aitex.Sorter.Common; using MECF.Framework.Common.Equipment; using MECF.Framework.Common.SubstrateTrackings; using MECF.Framework.RT.ModuleLibrary.EfemModules; using MECF.Framework.RT.ModuleLibrary.SystemModules; using MECF.Framework.RT.ModuleLibrary.TMModules; namespace EfemDualSchedulerLib.Schedulers { public class SchedulerEFEM : SchedulerModule { public override bool IsAvailable { get { return _efem.IsReady && _efem.IsOnline && CheckTaskDone(); } } public override bool IsOnline { get { return _efem.IsOnline; } } public override bool IsError { get { return _efem.IsError; } } public bool Blade1Enable { get => SC.GetValueOrDefault($"Efem.EfemRobot.LowerBladeEnable"); } public bool Blade2Enable { get => SC.GetValueOrDefault($"Efem.EfemRobot.UpperBladeEnable"); } private EfemModuleBase _efem = null; private Hand _hand; private Hand _taskSwapPickHand; private Hand _taskSwapPlaceHand; private int _taskSwapPickSlot; private int _taskSwapPlaceSlot; public ModuleName PreviousTarget { get; set; } public SchedulerEFEM(EfemModuleBase moduleDevice) : base(ModuleName.EFEM.ToString()) { _efem = moduleDevice; PreviousTarget = ModuleName.System; } public override void ResetTask() { base.ResetTask(); PreviousTarget = ModuleName.System; } public override WaferInfo GetWaferInfo(int slot) { return WaferManager.Instance.GetWafer(ModuleName.EfemRobot, slot); } public override bool HasWafer(int slot) { return WaferManager.Instance.CheckHasWafer(ModuleName.EfemRobot, slot); } public override bool NoWafer(int slot) { return WaferManager.Instance.CheckNoWafer(ModuleName.EfemRobot, slot); } public override bool CheckWaferNextStepIsThisModule(ModuleName module, int slot) { if (!WaferManager.Instance.CheckHasWafer(module, slot)) return false; WaferInfo wafer = WaferManager.Instance.GetWafer(module, slot); if (wafer.ProcessJob == null || wafer.ProcessJob.Sequence == null) return false; if (wafer.NextSequenceStep >= wafer.ProcessJob.Sequence.Steps.Count) return false; if (!wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepModules.Contains(ModuleName.EfemRobot)) return false; return true; } public override bool CheckWaferNextStepIsThisModuleSlot(ModuleName module, int slot, int thisSlot) { if (!WaferManager.Instance.CheckHasWafer(module, slot)) return false; WaferInfo wafer = WaferManager.Instance.GetWafer(module, slot); if (wafer.ProcessJob == null || wafer.ProcessJob.Sequence == null) return false; if (wafer.NextSequenceStep >= wafer.ProcessJob.Sequence.Steps.Count) return false; if (!wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepModules.Contains(ModuleName.EfemRobot)) return false; if (!wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepParameter["SlotSelection"].ToString().Contains(thisSlot.ToString())) return false; return true; } public bool IsReadyForPick(Hand blade) { return WaferManager.Instance.CheckNoWafer(ModuleName.EfemRobot, (int)blade); } public bool IsReadyForPlace(Hand blade) { return WaferManager.Instance.CheckHasWafer(ModuleName.EfemRobot, (int)blade); } public bool Pick(ModuleName source, int slot, Hand hand) { _task = TaskType.Pick; _hand = hand; if (!_efem.Pick(source, hand, slot, out string reason)) { LOG.Write(reason); } PreviousTarget = source; LogTaskStart(_task, $"{source}.{slot + 1}=>{Module}.{hand}"); return true; } public bool Place(ModuleName destination, int slot, Hand hand) { _task = TaskType.Place; _hand = hand; if (!_efem.Place(destination, hand, slot, out string reason)) { LOG.Write(reason); } PreviousTarget = destination; LogTaskStart(_task, $"{Module}.{hand}=>{destination}.{slot + 1}"); return true; } public bool Map(ModuleName destination) { _task = TaskType.Map; if (!_efem.Map(destination, out string reason)) { LOG.Write(reason); } PreviousTarget = destination; LogTaskStart(_task, $"mapping {Module}"); return true; } public bool PickAndPlace(ModuleName target, int pickSlot, int placeSlot, Hand pickHand, Hand placeHand) { PreviousTarget = target; _task = TaskType.PickAndPlace; _taskSwapPickHand = pickHand; _taskSwapPlaceHand = placeHand; _taskSwapPickSlot = pickSlot; _taskSwapPlaceSlot = placeSlot; LogTaskStart(_task, $" {target}.{pickSlot + 1}=>{Module}.{pickHand} && {Module}.{placeHand}=>{target}.{placeSlot + 1}"); return _efem.PickAndPlace(target, pickHand, pickSlot, target, placeHand, placeSlot, out _); } public bool Goto(ModuleName target, int slot, Hand hand) { PreviousTarget = target; _task = TaskType.Goto; if (!_efem.Goto(target, hand, slot, out string reason)) { LOG.Write(reason); } LogTaskStart(_task, $"robot {hand} goto {target}, slot {slot + 1}"); return true; } public bool CheckTaskDone() { bool ret = false; switch (_task) { case TaskType.None: ret = true; break; case TaskType.Pick: if (_hand == Hand.Both) { ret = WaferManager.Instance.CheckHasWafer(ModuleName.EfemRobot, (int)Hand.Blade1) && WaferManager.Instance.CheckHasWafer(ModuleName.EfemRobot, (int)Hand.Blade2); } else { ret = WaferManager.Instance.CheckHasWafer(ModuleName.EfemRobot, (int)_hand); } break; case TaskType.Place: if (_hand == Hand.Both) { ret = WaferManager.Instance.CheckNoWafer(ModuleName.EfemRobot, (int)Hand.Blade1) && WaferManager.Instance.CheckNoWafer(ModuleName.EfemRobot, (int)Hand.Blade2); } else { ret = WaferManager.Instance.CheckNoWafer(ModuleName.EfemRobot, (int)_hand); } break; case TaskType.Map: ret = _efem.IsReady; break; case TaskType.Goto: ret = _efem.IsReady; break; case TaskType.PickAndPlace: ret = WaferManager.Instance.CheckHasWafer(ModuleName.EfemRobot, (int)_taskSwapPickHand) && WaferManager.Instance.CheckNoWafer(ModuleName.EfemRobot, (int)_taskSwapPlaceHand); break; } if (ret && _task != TaskType.None) { LogTaskDone(_task, ""); _task = TaskType.None; } return ret; } } }