using Aitex.Core.Common; using Aitex.Core.RT.Device.Unit; using Aitex.Core.RT.Log; using Aitex.Core.RT.Routine; using Aitex.Core.RT.SCCore; using Aitex.Core.Util; using Aitex.Sorter.Common; using MECF.Framework.Common.Equipment; using MECF.Framework.Common.Schedulers; using MECF.Framework.Common.SubstrateTrackings; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Venus_Core; using Venus_RT.Modules.Schedulers; namespace Venus_RT.Modules { public class SEManualTransfer : IRoutine { SchedulerSETMRobot _tmrobot = (SchedulerSETMRobot)Singleton.Instance.GetScheduler(ModuleName.SETM); private List _moveQueue = new List(); private MovingStatus _moving_status = MovingStatus.Idle; private RState _transferstate = RState.Init; private ModuleName source_station; private int source_slot; private ModuleName destination_station; private int destination_slot; private ModuleName original_station; private int original_slot; private float align_angle; public SEManualTransfer() { } public RState Start(params object[] objs) { _moveQueue.Clear(); // obj is enable && robot is usable if (objs.Length > 6) { _transferstate = RState.Running; //get where we from and where we go source_station = (ModuleName)Enum.Parse(typeof(ModuleName),objs[0].ToString()); source_slot = Convert.ToInt32(objs[1]); destination_station = (ModuleName)Enum.Parse(typeof(ModuleName), objs[2].ToString()); destination_slot = Convert.ToInt32(objs[3]); WaferInfo waferInfo = WaferManager.Instance.GetWafer(source_station,source_slot); original_station = (ModuleName)waferInfo.OriginStation; original_slot = waferInfo.OriginSlot; if ((bool)objs[4]) { align_angle = float.Parse(objs[5].ToString()); _moving_status = MovingStatus.WaitAlign; } else _moving_status = MovingStatus.Waiting; if (ModuleHelper.IsVCE(source_station) && _tmrobot.IsVCESlitDoorClosed) { LOG.Write(eEvent.ERR_TM, ModuleName.TMRobot, $"cannot transfer from {source_station} as VCE InnerDoor is close."); _transferstate = RState.Failed; } if (ModuleHelper.IsVCE(destination_station) && _tmrobot.IsVCESlitDoorClosed) { LOG.Write(eEvent.ERR_TM, ModuleName.TMRobot, $"cannot transfer to {destination_station} as VCE InnerDoor is close."); _transferstate = RState.Failed; } //from tm to tm if (source_station == destination_station && ModuleHelper.IsTMRobot(source_station)) { LOG.Write(eEvent.ERR_TM,ModuleName.TMRobot,"cannot transfer from TMRobot to TMRobot."); _transferstate = RState.Failed; } if(WaferManager.Instance.CheckNoWafer(source_station,source_slot)) { LOG.Write(eEvent.ERR_TM, ModuleName.TMRobot, "cannot transfer cause wafer has no wafer."); _transferstate = RState.Failed; } if (WaferManager.Instance.CheckHasWafer(destination_station, destination_slot)) { LOG.Write(eEvent.ERR_TM, ModuleName.TMRobot, "cannot transfer cause wafer has wafer."); _transferstate = RState.Failed; } } else { _transferstate = RState.Failed; } return _transferstate; } public RState Monitor() { //if tm is free if (_tmrobot.IsAvailable) { CheckTransferOver(); WaferNextGoto(); TMRobotTask(); } return _transferstate; } private void CheckTransferOver() { //when the transfer is over? //the wafer has arrived the targetModule and targetSlot if (WaferManager.Instance.CheckHasWafer(destination_station,destination_slot) && (ModuleName)WaferManager.Instance.GetWafer(destination_station, destination_slot).OriginStation == original_station && WaferManager.Instance.GetWafer(destination_station, destination_slot).OriginSlot == original_slot) { _moving_status = MovingStatus.Idle; _transferstate = RState.End; } } private void WaferNextGoto() { switch(_moving_status) { case MovingStatus.WaitAlign: _moveQueue.Add(new MoveItem(source_station, source_slot, ModuleName.VPA, 0, 0)); _moving_status = MovingStatus.StartAlign; break; case MovingStatus.StartAlign: _tmrobot.Align(align_angle); _moving_status = MovingStatus.Aligning; break; case MovingStatus.Aligning: _moveQueue.Add(new MoveItem(ModuleName.VPA, 0, destination_station, destination_slot, 0)); break; //goto slot need to go case MovingStatus.Waiting: _moveQueue.Add(new MoveItem(source_station, source_slot, destination_station, destination_slot, 0)); break; } } private void TMRobotTask() { if (_tmrobot.IsAvailable) { if (_moveQueue.Count > 0 && _tmrobot.PostMoveItems(_moveQueue.ToArray())) { foreach (var item in _moveQueue) { var wafer = WaferManager.Instance.GetWafer(item.SourceModule, item.SourceSlot); if (wafer.IsEmpty && _tmrobot.IsAvailable) { // post alarm _transferstate = RState.Failed; LOG.Write(eEvent.ERR_ROUTER, ModuleName.System, $"Cannot run TM moving task as Get {item.SourceModule}{item.SourceSlot} Wafer Info failed"); return; } } _moveQueue.Clear(); } } } public void Abort() { } } public class SEReturnWafer : IRoutine { //target: //1. 1 wafer return as a Queue //2. all wafers return as a Queue private SEManualTransfer _transfer = null; private Queue _ReturnQueue = new Queue ();//all wafer enqueue private List modulelist = new List(); private bool _alignflag; private float _alignangle; public SEReturnWafer(SEManualTransfer transfer) { _transfer = transfer; string[] InstalledModules = SC.GetStringValue("System.InstalledModules").ToString().Split(','); foreach (string module in InstalledModules) { //module without vce if(Enum.TryParse(module,out ModuleName mod) && !ModuleHelper.IsVCE(mod) && mod!=ModuleName.SETM) modulelist.Add(mod); } } public RState Start(params object[] objs) { _ReturnQueue.Clear(); //单个wafer if (objs.Length >= 4) { if (bool.TryParse(objs[2].ToString(), out bool alignflag) && float.TryParse(objs[3].ToString(), out float alignangle)) { _alignflag = alignflag; _alignangle = alignangle; } } //all wafer return AllWaferBack(); return RState.Running; } public RState Monitor() { while (_ReturnQueue.Count > 0 || _transfer.Monitor() == RState.Running) { switch (_transfer.Monitor()) { case RState.Init: case RState.End: MoveItem moveItem = _ReturnQueue.Dequeue(); return _transfer.Start(moveItem.SourceModule,moveItem.SourceSlot,moveItem.DestinationModule,moveItem.DestinationSlot, _alignflag, _alignangle, false,1,""); case RState.Running: return RState.Running; case RState.Timeout: case RState.Failed: return RState.Failed; } } return RState.End; } private void AllWaferBack() { //Firstly,robot wafer back //Then,chamber wafer back CheckWaferEnqueue(ModuleName.TMRobot, 0); CheckWaferEnqueue(ModuleName.TMRobot, 1); foreach (ModuleName mod in modulelist) { if (mod == ModuleName.TMRobot) continue; else CheckWaferEnqueue(mod,0); } } //wafer back vce //1. has wafer //2. vce isinstalled and slot no wafer //3. robot check hand && chamber check 0 private void CheckWaferEnqueue(ModuleName source_module,int source_slot) { if (WaferManager.Instance.CheckHasWafer(source_module, source_slot)) { WaferInfo waferInfo = WaferManager.Instance.GetWafer(source_module, source_slot); if (ModuleHelper.IsVCE((ModuleName)waferInfo.OriginStation) && ModuleHelper.IsInstalled((ModuleName)waferInfo.OriginStation) && WaferManager.Instance.CheckNoWafer((ModuleName)waferInfo.OriginStation, waferInfo.OriginSlot)) { if(source_module == ModuleName.TMRobot) _ReturnQueue.Enqueue(new MoveItem(source_module, source_slot, (ModuleName)waferInfo.OriginStation, waferInfo.OriginSlot, (Hand)source_slot)); else _ReturnQueue.Enqueue(new MoveItem(source_module, source_slot, (ModuleName)waferInfo.OriginStation, waferInfo.OriginSlot, 0)); } } } public void Abort() { } } }