using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Text; using System.Threading.Tasks; using Aitex.Core.Common; using Aitex.Core.RT.Device; using Aitex.Core.RT.Event; using Aitex.Core.RT.Fsm; using Aitex.Core.RT.Log; using Aitex.Core.RT.SCCore; using Aitex.Core.Util; using Aitex.Sorter.Common; using EfemDualSchedulerLib.Schedulers; using MECF.Framework.Common.Equipment; using MECF.Framework.Common.Schedulers; using MECF.Framework.Common.SubstrateTrackings; using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.LoadLocks; using MECF.Framework.RT.ModuleLibrary.BufferModules; using MECF.Framework.RT.ModuleLibrary.LLModules; using MECF.Framework.RT.ModuleLibrary.SystemModules; namespace EfemDualSchedulerLib.Schedulers { public class SchedulerLoadLock : SchedulerModule { public override bool IsAvailable { get { return _loadLock.IsReady && _loadLock.IsOnline && CheckTaskDone(); } } public override bool IsOnline { get { return _loadLock.IsOnline; } } public override bool IsError { get { return _loadLock.IsError; } } private LoadLockModuleBase _loadLock; public LoadLockModuleBase Entity { get { return _loadLock; } } private ModuleName _taskRobot; private int[] _taskSlot; private int _entityTaskToken = (int)FSM_MSG.NONE; private bool _isATM; private long[] _slotDelayTime; private EnumTransferType TransferType { get; set; } public SchedulerLoadLock(ModuleName module) : base(module.ToString()) { _loadLock = EquipmentManager.Modules[module] as LoadLockModuleBase; _isATM = SC.IsATMMode; _slotDelayTime = new long[_loadLock.SlotCount]; } void OnFieldChanged(object sender, string name, object fieldValue) { if (name == nameof(_loadLock.IsOnline)) { bool v = (bool)fieldValue; if (!v && _task != TaskType.None) { LOG.Warning($"{Module} abort {_task} since offline"); _task = TaskType.None; } } } public void Reset() { _task = TaskType.None; } public override bool PrepareTransfer(ModuleName robot, EnumTransferType type, int[] slot) { _task = TaskType.PrepareTransfer; _taskRobot = robot; _taskSlot = slot; TransferType = type; _loadLock.PrepareTransfer(robot, Hand.Blade1, slot, type, out string reason); Array.ForEach(slot,p=> LogTaskStart(_task, $"{robot} {type} slot {p + 1}")); return _entityTaskToken != (int)FSM_MSG.NONE; } internal bool CheckAtAtm() { //LoadLock deviceLL = DEVICE.GetDevice(_module); //return deviceLL.CheckAtm(); return true; } internal bool CheckAtVacuum() { //LoadLock deviceLL = DEVICE.GetDevice(_module); //return deviceLL.CheckVacuum(); return true; } public override bool IsReadyForPick(ModuleName robot, Hand hand, int slot) { if (!_loadLock.CheckReadyForTransfer(robot, hand, slot, EnumTransferType.Pick, out string reason)) return false; if(_slotDelayTime[slot] != -1) { if (_slotDelayTime[slot] > GetTickCount()) return false; } return WaferManager.Instance.CheckHasWafer(ModuleHelper.Converter(_module), slot); } public override bool IsReadyForPlace(ModuleName robot, Hand hand, int slot) { if (!_loadLock.CheckReadyForTransfer(robot, hand, slot, EnumTransferType.Place, out string reason)) return false; return WaferManager.Instance.CheckNoWafer(ModuleHelper.Converter(_module), slot); } public override bool IsReadyForPlace(ModuleName robot, Hand hand, int slot, bool isNeedPair) { if (!_loadLock.CheckReadyForTransfer(robot, hand, slot, EnumTransferType.Place, out string reason)) return false; var checkNoWafer = WaferManager.Instance.CheckNoWafer(ModuleHelper.Converter(_module), slot); if(SC.IsDoubleFork && checkNoWafer && robot == ModuleName.EfemRobot && isNeedPair) { for(int i= 5;i > slot;i--) { var wafer1 = WaferManager.Instance.GetWafer(ModuleHelper.Converter(_module), i); if(wafer1 != null && !wafer1.IsEmpty) { var nextSlot = (i % 2 > 0) ? i - 1 : i + 1; var nextWafer = WaferManager.Instance.GetWafer(ModuleHelper.Converter(_module), nextSlot); if (nextWafer != null && !nextWafer.IsEmpty) continue; var targetWafer = WaferManager.Instance.GetWafer(robot, (int)hand); if ((targetWafer.ProcessJob !=null && wafer1.ProcessJob != null) && (targetWafer.ProcessJob.Sequence != null && wafer1.ProcessJob.Sequence != null) && (wafer1.ProcessState == EnumWaferProcessStatus.Idle) && (targetWafer.ProcessJob.Sequence.Name == wafer1.ProcessJob.Sequence.Name) && slot != nextSlot) return false; } } var leftOrRightSlot = (slot % 2 > 0) ? slot - 1 : slot + 1; checkNoWafer = WaferManager.Instance.CheckNoWafer(ModuleHelper.Converter(_module), leftOrRightSlot); if(!checkNoWafer) { var wafer0 = WaferManager.Instance.GetWafer(robot, (int)hand); var wafer1 = WaferManager.Instance.GetWafer(ModuleHelper.Converter(_module), leftOrRightSlot); checkNoWafer = (wafer1.ProcessJob==null || wafer0.ProcessJob == null) || ((wafer1.ProcessJob != null && wafer0.ProcessJob != null) && (wafer1.ProcessState == EnumWaferProcessStatus.Idle) && (wafer1.ProcessJob.Sequence != null && wafer0.ProcessJob.Sequence != null) && (wafer1.ProcessJob.Sequence.Name == wafer0.ProcessJob.Sequence.Name)); } } return checkNoWafer; } public override bool Cooling(int coolingTime) { _task = TaskType.Cooling; //_entityTaskToken = _loadLock.InvokeCooling(coolingTime); LogTaskStart(_task, $"{Module} cooling {coolingTime} seconds"); return _entityTaskToken != (int)FSM_MSG.NONE; } private long GetTickCount() { //毫秒 return DateTime.Now.Ticks / 10000; } public override bool PostTransfer(ModuleName ll, EnumTransferType type, int slot) { var waferDelayTime = SC.GetValueOrDefault("System.Scheduler.WaferDelayTime"); var wafer = WaferManager.Instance.GetWafer(ll, slot); if (_isATM || waferDelayTime == 0 || wafer.ProcessState == EnumWaferProcessStatus.Idle) _slotDelayTime[slot] = -1; else { _slotDelayTime[slot] = waferDelayTime * 1000 + GetTickCount(); EV.PostInfoLog(Module.ToString(), $"{ll} Delay {waferDelayTime} seconds at slot {slot + 1}"); } return true; } public bool Monitor() { return true; } public bool CheckTaskDone() { bool ret = false; switch (_task) { case TaskType.None: ret = true; break; case TaskType.PrepareTransfer: //ret = _loadLock.CheckReadyForTransfer(_taskRobot, TransferType); break; case TaskType.PreCooling: //ret = _loadLock.IsPreCoolingDone(); break; } if (ret && _task != TaskType.None) { LogTaskDone(_task, ""); _task = TaskType.None; } return ret; } } }