using System; using System.Collections.Generic; using System.Linq; using Aitex.Core.Common; using Aitex.Core.RT.Routine; using Aitex.Core.RT.SCCore; using Aitex.Sorter.Common; using Aitex.Core.RT.Log; using Aitex.Core.Util; using Aitex.Core.RT.DataCenter; using Aitex.Core.RT.RecipeCenter; using Aitex.Core.RT.Fsm; using MECF.Framework.Common.Jobs; using MECF.Framework.Common.Routine; using MECF.Framework.Common.Equipment; using MECF.Framework.Common.SubstrateTrackings; using MECF.Framework.Common.Schedulers; using MECF.Framework.Common.DBCore; using CyberX8_Core; using CyberX8_RT.Schedulers; using CyberX8_RT.Schedulers.EfemRobot; namespace CyberX8_RT.Modules { public class ManualTransfer : IRoutine { SchedulerEfemRobot _efemRobot = (SchedulerEfemRobot)SchedulerManager.Instance.GetScheduler(ModuleName.EfemRobot); private Queue _moveTaskQueue = new Queue(); private MoveItem _move_item = new MoveItem(ModuleName.System, 0, ModuleName.System, 0, Hand.None); private MoveItem _current_item = new MoveItem(ModuleName.System, 0, ModuleName.System, 0, Hand.None); private Guid _wafer_id; private R_TRIG _wafer_arrive_trig = new R_TRIG(); private MovingStatus _moving_status = MovingStatus.Idle; private int _tmRobotSingleArmOption = 0; private int _efemRobotSingleArmOption = 0; public ManualTransfer() { _tmRobotSingleArmOption = SC.GetValue("TM.SingleArmOption"); _efemRobotSingleArmOption = SC.GetValue("EFEM.SingleArmOption"); } public RState Start(params object[] objs) { // RESET _moveTaskQueue.Clear(); _moving_status = MovingStatus.Idle; _wafer_arrive_trig.RST = true ; _move_item.SourceModule = (ModuleName)objs[0]; _move_item.SourceSlot = (int)objs[1]; _move_item.DestinationModule = (ModuleName)objs[2]; _move_item.DestinationSlot = (int)objs[3]; _wafer_id = WaferManager.Instance.GetWafer(_move_item.SourceModule, _move_item.SourceSlot).InnerId; if (!CheckSingleArmOption(_move_item.DestinationModule, _move_item.DestinationSlot)) return RState.Failed; if (!CheckSingleArmOption(_move_item.SourceModule, _move_item.SourceSlot)) return RState.Failed; if(ModuleHelper.IsEFEMRobot(_move_item.SourceModule)) { _moveTaskQueue.Enqueue(new MoveItem(_move_item.SourceModule, _move_item.SourceSlot, _move_item.DestinationModule, _move_item.DestinationSlot, (Hand)_move_item.SourceSlot)); } else if (ModuleHelper.IsEFEMRobot(_move_item.DestinationModule)) { _moveTaskQueue.Enqueue(new MoveItem(_move_item.SourceModule, _move_item.SourceSlot, _move_item.DestinationModule, _move_item.DestinationSlot, (Hand)_move_item.DestinationSlot)); } else { Hand hand = SelectEfemRobotFreeHand(); if (hand == Hand.None) { LOG.Write(eEvent.WARN_ROUTER, ModuleName.EfemRobot, "No free efem robot arm for wafer move."); return RState.Failed; } _moveTaskQueue.Enqueue(new MoveItem(_move_item.SourceModule, _move_item.SourceSlot, ModuleName.EfemRobot, (int)hand, hand)); _moveTaskQueue.Enqueue(new MoveItem(ModuleName.EfemRobot, (int)hand, _move_item.DestinationModule, _move_item.DestinationSlot, hand)); } _current_item = _moveTaskQueue.Dequeue(); _moving_status = MovingStatus.Waiting; return RState.Running; } public RState Monitor() { return MoveWaferForward(); } public void Abort() { } public void Clear() { _moveTaskQueue.Clear(); SchedulerManager.Instance.GetScheduler(ModuleName.EfemRobot).ResetTask(); } private RState MoveWaferForward() { switch(_moving_status) { case MovingStatus.Waiting: { if(IsCurrentModuleReady()) { // Post current item _efemRobot.PostMoveItems(new MoveItem[1] { _current_item }); _moving_status = MovingStatus.Moving; } } break; case MovingStatus.Moving: { _wafer_arrive_trig.CLK = IsArriveCurrentTarget(); if (_wafer_arrive_trig.Q) { _moving_status = MovingStatus.Idle; } } break; case MovingStatus.Idle: { if(IsCurrentModuleReady()) { if(_moveTaskQueue.Count > 0) { _current_item = _moveTaskQueue.Dequeue(); _moving_status = MovingStatus.Waiting; } } break; } } return TransferStatus(); } private bool IsArriveCurrentTarget() { var wafer = WaferManager.Instance.GetWafer(_current_item.DestinationModule, _current_item.DestinationSlot); return !wafer.IsEmpty && wafer.InnerId == _wafer_id; } private bool IsCurrentModuleReady() { return (_efemRobot.IsAvailable) && _isModuleReady(_current_item.SourceModule) && _isModuleReady(_current_item.DestinationModule); } private bool IsTransferError() { return (_efemRobot.IsError) || _isModuleError(_current_item.SourceModule) || _isModuleError(_current_item.DestinationModule); } private bool _isModuleReady(ModuleName module) { return SchedulerManager.Instance.GetScheduler(module).IsAvailable; } private bool _isModuleError(ModuleName module) { return SchedulerManager.Instance.GetScheduler(module).IsError; } private Hand SelectEfemRobotFreeHand() { if (WaferManager.Instance.CheckNoWafer(ModuleName.EfemRobot, 0)) return Hand.Blade1; else if (WaferManager.Instance.CheckNoWafer(ModuleName.EfemRobot, 1)) return Hand.Blade2; else return Hand.None; } private RState TransferStatus() { if (IsTransferError()) return RState.Failed; if (IsCurrentModuleReady() && _moveTaskQueue.Count == 0 && _moving_status == MovingStatus.Idle) return RState.End; return RState.Running; } private bool CheckSingleArmOption(ModuleName robot, int slot) { if(ModuleHelper.IsEFEMRobot(robot)) { if (_efemRobotSingleArmOption != 0 && _efemRobotSingleArmOption != slot + 1) { LOG.Write(eEvent.ERR_ROUTER, ModuleName.EfemRobot, $"Cannot move the wafer as EFEM Robot {(Hand)slot} is disabled."); return false; } } return true; } public int GetSingleArmOption(ModuleName robot) { return _efemRobotSingleArmOption; } } public class ReturnAllWafer : IRoutine { private List _moduleList = new List { ModuleName.EfemRobot, ModuleName.Aligner1, ModuleName.Aligner, ModuleName.PMA, ModuleName.PMB, ModuleName.PMC, ModuleName.PMD }; private ManualTransfer _manualTransfer; private Queue _returnTaskQueue = new Queue(); private MoveItem _current_item; public ReturnAllWafer(ManualTransfer manualTransfer) { _manualTransfer = manualTransfer; } public RState Start(params object[] objs) { SchedulerManager.Instance.GetScheduler(ModuleName.EfemRobot).ResetTask(); foreach(var mod in _moduleList) { if (ModuleHelper.IsInstalled(mod) && SchedulerManager.Instance.GetScheduler(mod).IsAvailable) { if (ModuleHelper.IsEFEMRobot(mod)) { if (_manualTransfer.GetSingleArmOption(mod) != 2) PushWaferToReturnQueqe(mod, 0); if (_manualTransfer.GetSingleArmOption(mod) != 1) PushWaferToReturnQueqe(mod, 1); } else { PushWaferToReturnQueqe(mod, 0); } } } if (_returnTaskQueue.Count == 0) return RState.Failed; _current_item = _returnTaskQueue.Dequeue(); _manualTransfer.Start(_current_item.SourceModule, _current_item.SourceSlot, _current_item.DestinationModule, _current_item.DestinationSlot); return RState.Running; } public RState Monitor() { var ret = _manualTransfer.Monitor(); if (ret == RState.End) { if (_returnTaskQueue.Count > 0) { _current_item = _returnTaskQueue.Dequeue(); _manualTransfer.Start(_current_item.SourceModule, _current_item.SourceSlot, _current_item.DestinationModule, _current_item.DestinationSlot); } else return RState.End; } else if (ret == RState.Failed || ret == RState.Timeout) { LOG.Write(eEvent.ERR_ROUTINE_FAILED, ModuleName.System,"Manual Transfer", $"Return Wafer {_current_item.SourceModule}{_current_item.SourceSlot} failed"); return RState.Failed; } return RState.Running; } public void Abort() { } public void Clear() { _returnTaskQueue.Clear(); SchedulerManager.Instance.GetScheduler(ModuleName.EfemRobot).ResetTask(); } private void PushWaferToReturnQueqe(ModuleName mod, int nSlot) { var wafer = WaferManager.Instance.GetWafer(mod, nSlot); if (!wafer.IsEmpty) { _returnTaskQueue.Enqueue(new MoveItem(mod, nSlot, (ModuleName)wafer.OriginStation, wafer.OriginSlot, Hand.Blade1)); } } } }