using System; using System.Collections.Generic; using System.Diagnostics; using System.Text; using System.Threading.Tasks; using MECF.Framework.Common.Equipment; using VirgoRT.Scheduler; using MECF.Framework.Common.Schedulers; using MECF.Framework.Common.SubstrateTrackings; using Aitex.Core.RT.SCCore; using Aitex.Core.Util; using Aitex.Core.RT.DataCenter; namespace VirgoRT.Modules.Schedulers { public class SchedulerBuffer : SchedulerModule { private readonly int _MAX_SLOT = SC.GetValue("EFEM.Buffer.SlotNumber"); public override bool IsAvailable { get { return CheckTaskDone(); } } public SchedulerBuffer(ModuleName buffer) : base(buffer.ToString()) { EventWaferArrived += WaferArrived; } private void WaferArrived(object sender, EventArgs e) { var eArgs = e as WaferMoveArgs; WaferArriveTicks[eArgs.DstSlot] = DateTime.Now.Ticks; } private DeviceTimer _timerCooling = new DeviceTimer(); private float _paramCoolingTime = 0; public override bool Cooling(int coolingTime) { _task = TaskType.Cooling; LogTaskStart(_task, $"Cooling {coolingTime} seconds"); _paramCoolingTime = coolingTime; _timerCooling.Start(_paramCoolingTime * 1000); return true; } private DeviceTimer _timerCooling1 = new DeviceTimer(); private int _paramCoolingTime1 = 0; private DeviceTimer _timerCooling2 = new DeviceTimer(); private int _paramCoolingTime2 = 0; public override bool Cooling(int coolingTime, int slot, bool isType = true) { LogTaskStart(_task, $"Cooling {coolingTime} seconds by slot {slot + 1}"); if(slot == 0) { if(isType) _task = TaskType.Cooling1; _paramCoolingTime1 = coolingTime; _timerCooling1.Start(_paramCoolingTime1 * 1000); } else { if(isType) _task = TaskType.Cooling2; _paramCoolingTime2 = coolingTime; _timerCooling2.Start(_paramCoolingTime2 * 1000); } return true; } public override int GetCoolingTime(int slot) { if(slot == 0) { var ms = _paramCoolingTime1 * 1000 - _timerCooling1.GetElapseTime(); if (ms < 0) ms = 0; return (int)ms / 1000; } else if(slot == 1) { var ms = _paramCoolingTime2 * 1000 - _timerCooling2.GetElapseTime(); if (ms < 0) ms = 0; return (int)ms / 1000; } return 0; } public bool CheckTaskDone() { bool ret = false; switch (_task) { case TaskType.None: ret = true; break; case TaskType.Cooling: ret = _timerCooling.IsTimeout(); break; case TaskType.Cooling1: ret = _timerCooling1.IsTimeout(); break; case TaskType.Cooling2: ret = _timerCooling2.IsTimeout(); break; } if (ret && _task != TaskType.None) { LogTaskDone(_task, ""); _task = TaskType.None; } return ret; } public override SlotItem GetReadyOutSlot() { double maxDelay = 0; SlotItem item = new SlotItem(ModuleName.System, -1); if (AutoTransfer_T.GetSystemInnerWaferCount() >= AutoTransfer_T.SystemInternalWaferCount) return item; for (int i = 0; i < _MAX_SLOT; i++) { var wafer = WaferManager.Instance.GetWafer(Module, i); if (wafer.IsEmpty || wafer.ProcessJob == null || wafer.ProcessJob.Sequence == null || wafer.NextSequenceStep > wafer.ProcessJob.Sequence.Steps.Count) // wafer.NextSequenceStep already increased after wafer arrive continue; if(i == 0) { if (_timerCooling1.IsTimeout()) { item.Module = Module; item.Slot = i; return item; } else continue; } if (i == 1) { if (_timerCooling2.IsTimeout()) { item.Module = Module; item.Slot = i; return item; } else continue; } if (!wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep - 1].StepParameter.ContainsKey("CoolingTime")) // parameter name may change continue; float stayTime; if (!float.TryParse((string)wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep - 1].StepParameter["CoolingTime"], out stayTime)) continue; long elapsedTicks = DateTime.Now.Ticks - WaferArriveTicks[i]; TimeSpan elapsedSpan = new TimeSpan(elapsedTicks); double delay = elapsedSpan.TotalSeconds - stayTime; if (delay > maxDelay) { maxDelay = delay; item.Module = Module; item.Slot = i; } } return item; } } }