using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Aitex.Core.RT.Fsm; using Aitex.Core.RT.Log; using Aitex.Core.Util; using Aitex.Sorter.Common; using MECF.Framework.Common.Schedulers; using MECF.Framework.Common.Equipment; using MECF.Framework.Common.SubstrateTrackings; using Venus_RT.Modules; using Venus_Core; namespace Venus_RT.Scheduler { class SchedulerItem { public EfemEntity.MSG MoveType { get; set; } public ModuleName target { get; set; } public Queue moveList { get; set; } public RState Status { get; set; } } public class SchedulerEfemRobot : SchedulerModule { public override bool IsAvailable { get { return _entity.IsIdle && /*(_entity.IsOnline || !Singleton.Instance.IsAutoMode) &&*/ CheckTaskDone() && RunSchedulers(); } } public override bool IsOnline { get { return _entity.IsOnline; } } public override bool IsError { get { return _entity.IsError; } } public override bool IsIdle { get { return _entity.IsIdle; } } public RState RobotStatus { get { return _entity.RobotStatus; } } private EfemEntity _entity = null; private SchedulerItem _currentScheduler = null; private int _entityTaskToken = (int)FSM_MSG.NONE; public ModuleName PreviousTarget { get; set; } public SchedulerEfemRobot() : base(ModuleName.EfemRobot.ToString()) { _entity = Singleton.Instance.EFEM; PreviousTarget = ModuleName.System; } public bool Goto(ModuleName target, int slot ) { _entityTaskToken = _entity.InvokeGoto(target, slot ); PreviousTarget = target; LogTaskStart(_task, $"Robot goto {target}.{slot + 1}"); return true; } public bool Map(ModuleName destination ) { _entityTaskToken = _entity.InvokeMap(destination.ToString()); LogTaskStart(_task, $"{Module} mapping"); PreviousTarget = destination; return true; } public bool Monitor() { return true; } public bool CheckTaskDone() { bool ret = false; switch (_entityTaskToken) { case (int)FSM_MSG.NONE: ret = true; break; case (int)EfemEntity.MSG.Pick: case (int)EfemEntity.MSG.Place: case (int)EfemEntity.MSG.Swap: ret = IsAllWafersArrived(); break; case (int)EfemEntity.MSG.Map: ret = _entity.CheckAcked(_entityTaskToken) && _entity.IsIdle; break; case (int)EfemEntity.MSG.Goto: ret = _entity.CheckAcked(_entityTaskToken) && _entity.IsIdle; break; case (int)EfemEntity.MSG.Align: ret = _entity.CheckAcked(_entityTaskToken) && _entity.IsIdle; break; } if (ret && _task != TaskType.None) { LogTaskDone(_task, ""); _task = TaskType.None; } return ret; } public bool PostMoveItems(MoveItem[] items) { foreach (var item in items) { LOG.Write(eEvent.EV_ROUTER, ModuleName.EfemRobot, $"Post Moving Item: {item.SourceModule} Slot {item.SourceSlot + 1} => {item.DestinationModule} Slot {item.DestinationSlot + 1}"); } if (ModuleHelper.IsLoadLock(items.First().Module)) { _currentScheduler = new SchedulerItem(); _currentScheduler.MoveType = EfemEntity.MSG.Swap; _currentScheduler.target = items.First().Module; _currentScheduler.Status = RState.Init; _currentScheduler.moveList = new Queue(items); } else { _currentScheduler = new SchedulerItem(); _currentScheduler.MoveType = items.First().TransferType == EnumMoveType.Pick ? EfemEntity.MSG.Pick : EfemEntity.MSG.Place; _currentScheduler.target = items.First().Module; _currentScheduler.Status = RState.Init; _currentScheduler.moveList = new Queue(items); } RunSchedulers(); return true; } bool RunSchedulers() { if (_currentScheduler == null) return true; if (_entity.IsIdle) { if(_currentScheduler.Status == RState.Init) { foreach (var item in _currentScheduler.moveList) { LOG.Write(eEvent.EV_EFEM_ROBOT, ModuleName.EfemRobot, $"EFEM Robot Moving Items: {item.SourceModule} Slot {item.SourceSlot + 1} => {item.DestinationModule} Slot {item.DestinationSlot + 1}"); } if (_entity.CheckToPostMessage((int)_currentScheduler.MoveType, _currentScheduler.moveList)) { _currentScheduler.Status = RState.Running; _entityTaskToken = (int)_currentScheduler.MoveType; } else _entityTaskToken = (int)FSM_MSG.NONE; } else if(_currentScheduler.Status == RState.Running) { if (IsAllWafersArrived()) { if( _entityTaskToken == (int)EfemEntity.MSG.Pick || _entityTaskToken == (int)EfemEntity.MSG.Place || _entityTaskToken == (int)EfemEntity.MSG.Swap) { _entityTaskToken = (int)FSM_MSG.NONE; } _currentScheduler.Status = RState.End; } } } return _currentScheduler.Status == RState.End; } private bool IsAllWafersArrived() { foreach(var item in _currentScheduler.moveList) { if (WaferManager.Instance.CheckNoWafer(item.DestinationModule, item.DestinationSlot)) return false; } return true; } public override void ResetTask() { base.ResetTask(); _entityTaskToken = (int)FSM_MSG.NONE; if(_currentScheduler != null) { _currentScheduler.moveList.Clear(); _currentScheduler.Status = RState.End; } } public override bool Align(float angle) { _task = TaskType.Align; LogTaskStart(_task, $"Aligning"); _entityTaskToken = _entity.InvokeAlign(ModuleName.Aligner1.ToString(),0, angle); return _entityTaskToken == (int)EfemEntity.MSG.Align; } } }