using Aitex.Core.RT.Routine; using Aitex.Core.RT.SCCore; using Aitex.Sorter.Common; using Venus_RT.Devices; using MECF.Framework.Common.Routine; using MECF.Framework.Common.Equipment; using MECF.Framework.Common.SubstrateTrackings; using Venus_Core; using Aitex.Core.RT.Log; using Aitex.Core.Util; using System.Collections.Generic; using System.Linq; using Venus_RT.Modules.Schedulers; using Venus_RT.Scheduler; using System; using MECF.Framework.Common.Schedulers; using Aitex.Core.RT.Fsm; namespace Venus_RT.Modules { class TMCycle : ModuleRoutineBase, IRoutine { enum TMCycleStep { Start, ReturnBack, Cycling, End, } private bool IsModuleAvailable(ModuleName module) => dictSchedulers.Keys.Contains(module) && dictSchedulers[module].IsAvailable; List tmCycleRoutine = new List() { ModuleName.LLA, ModuleName.PMA, ModuleName.PMB, ModuleName.LLB }; int cycleCount = 1000; ModuleName _sourceModule = ModuleName.LLA; ModuleName _destinationModule = ModuleName.LLB; int _sourceSlotNumber = 4; int _destinationSlotNumber = 4; SchedulerTMRobot _TMRobot = (SchedulerTMRobot)Singleton.Instance.GetScheduler(ModuleName.TMRobot); private readonly int INVALID_SLOT = -1; Dictionary dictSchedulers = new Dictionary(); Queue _ReturnWafers = new Queue(); Queue _runningItems = new Queue(); Queue _CycleWafers = new Queue(); public int? CycleIndex; public TMCycle() : base(ModuleName.System) { Name = "TM Cycle"; void _initMoudle(ModuleName name, SchedulerModule sche) { if (ModuleHelper.IsInstalled(name)) { dictSchedulers[name] = sche; } } _initMoudle(ModuleName.LLA, new SchedulerLoadLock(ModuleName.LLA)); _initMoudle(ModuleName.LLB, new SchedulerLoadLock(ModuleName.LLB)); _initMoudle(ModuleName.PMA, new SchedulerPM(ModuleName.PMA)); _initMoudle(ModuleName.PMB, new SchedulerPM(ModuleName.PMB)); _initMoudle(ModuleName.PMC, new SchedulerPM(ModuleName.PMC)); _initMoudle(ModuleName.PMD, new SchedulerPM(ModuleName.PMD)); } public RState Start(params object[] objs) { CycleIndex = 0; if (objs.Length == 2) { var modules = ((string[])objs[0]).ToList(); if (modules.Count >= 2) tmCycleRoutine.Clear(); foreach(var mod in modules) { try { ModuleName module = ModuleHelper.Converter(mod); tmCycleRoutine.Add(module); } catch { LOG.Write(eEvent.ERR_ROUTER, "TMCycle", $"Invalid module string: {mod}"); return RState.Failed; } } cycleCount = (int)objs[1]; } return Runner.Start(Module, Name); } public RState Monitor() { Runner.Run(TMCycleStep.Start, NullFun) .LoopStart(TMCycleStep.ReturnBack, "Cycle", cycleCount, StartReturn, ReturnBack) .LoopEnd(TMCycleStep.Cycling, StartCycle, Cycling) .End(TMCycleStep.End, NullFun, _delay_50ms); return Runner.Status; } private bool StartReturn() { CycleIndex += 1; _destinationModule = tmCycleRoutine.Last(); _destinationSlotNumber = SC.GetValue($"{_destinationModule}.SlotNumber"); _sourceModule = tmCycleRoutine.First(); _sourceSlotNumber = SC.GetValue($"{_sourceModule}.SlotNumber"); _ReturnWafers.Clear(); for(int i = 0; i < _destinationSlotNumber; i++) { if(WaferManager.Instance.CheckHasWafer(_destinationModule, i)) { _ReturnWafers.Enqueue(new MoveItem(_destinationModule, i, _sourceModule, INVALID_SLOT, Hand.None)); } } return true; } List GetReadyInSlot(ModuleName module, int slotCount) { List slots = new List(); for (int i = 0; i < slotCount; i++) { if (WaferManager.Instance.CheckNoWafer(module, i)) slots.Add(i); if (slots.Count >= 2) return slots; } return slots; } List GetReadyOutSlot(ModuleName module, int slotCount) { List slots = new List(); for (int i = 0; i < slotCount; i++) { if (WaferManager.Instance.CheckHasWafer(module, i)) slots.Add(i); if (slots.Count >= 2) return slots; } return slots; } List GetReadyOutPMs() { List outpm = new List(); foreach(var module in tmCycleRoutine) { if(ModuleHelper.IsPm(module)) { if(IsModuleAvailable(module) && WaferManager.Instance.CheckHasWafer(module, 0)) { outpm.Add(module); if (outpm.Count >= 2) break; } } } return outpm; } List GetReadyInPMs() { List inpm = new List(); foreach (var module in tmCycleRoutine) { if (ModuleHelper.IsPm(module)) { if (IsModuleAvailable(module) && WaferManager.Instance.CheckNoWafer(module, 0)) { inpm.Add(module); if (inpm.Count >= 3) break; } } } return inpm; } private bool ReturnBack() { var t1 = IsModuleAvailable(_sourceModule); var t2 = IsModuleAvailable(_destinationModule); var t3 = _TMRobot.IsAvailable; if (IsModuleAvailable(_sourceModule) && IsModuleAvailable(_destinationModule) && _TMRobot.IsAvailable) { var InSlots = GetReadyInSlot(_sourceModule, _sourceSlotNumber); var OutSlots = GetReadyOutSlot(_destinationModule, _destinationSlotNumber); if (InSlots.Count == 0 || OutSlots.Count == 0) return true; Queue items = new Queue(); for(int i = 0; i < Math.Min(InSlots.Count, OutSlots.Count); i++) { items.Enqueue(new MoveItem(_destinationModule, OutSlots[i], _sourceModule, InSlots[i], (Hand)i)); } if(items.Count > 0) { _TMRobot.PostMoveItems(items.ToArray()); } } return false; } private bool ModuleHasWafer(ModuleName mod, int nSlots) { for(int i= 0; i< nSlots; i++) { if (WaferManager.Instance.CheckHasWafer(mod, i)) return true; } return false; } private bool PMsHasWafers() { foreach (var module in tmCycleRoutine) { if (ModuleHelper.IsPm(module) && ModuleHelper.IsInstalled(module)) { if (WaferManager.Instance.CheckHasWafer(module, 0)) return true; } } return false; } private bool IsPMsAvailabe() { foreach (var module in tmCycleRoutine) { if (ModuleHelper.IsPm(module)&&ModuleHelper.IsInstalled(module)) { if (!IsModuleAvailable(module)) return false; } } return true; } private bool Cycling() { if(IsPMsAvailabe() && IsModuleAvailable(_destinationModule) && IsModuleAvailable(_sourceModule) && _TMRobot.IsAvailable) { if (!PMsHasWafers() && _TMRobot.IsAvailable && _CycleWafers.Count == 0) return true; if(PMsHasWafers()) { var pmSlots = GetReadyOutPMs(); var inSlots = GetReadyInSlot(_destinationModule, _destinationSlotNumber); for(int i = 0; i < Math.Min(pmSlots.Count, inSlots.Count); i++) { _runningItems.Enqueue(new MoveItem(pmSlots[i], 0, _destinationModule, inSlots[i], Hand.Both)); } } else { var InPMs = GetReadyInPMs(); if(_CycleWafers.Count > 0 && InPMs.Count >= 1) { var item = _CycleWafers.Dequeue(); _runningItems.Enqueue(new MoveItem(item.SourceModule, item.SourceSlot, InPMs[0], 0, Hand.Both)); } if(_CycleWafers.Count > 0 && InPMs.Count >= 2) { var item = _CycleWafers.Dequeue(); _runningItems.Enqueue(new MoveItem(item.SourceModule, item.SourceSlot, InPMs[1], 0, Hand.Both)); } } if (_runningItems.Count > 0) { if (_TMRobot.PostMoveItems(_runningItems.ToArray())) _runningItems.Clear(); } } return false; } private bool StartCycle() { _CycleWafers.Clear(); for(int i = 0; i< _sourceSlotNumber; i++) { if (WaferManager.Instance.CheckHasWafer(_sourceModule, i)) _CycleWafers.Enqueue(new MoveItem(_sourceModule, i, _destinationModule, INVALID_SLOT, Hand.None)); } return true; } public void Abort() { CycleIndex = null; _TMRobot._entityTaskToken = (int)FSM_MSG.NONE; } } }