using System; using System.Collections.Generic; using Aitex.Core.RT.Device; using Aitex.Core.RT.Event; using Aitex.Core.RT.Routine; using Aitex.Core.Util; using EFEM.RT.Devices; using EFEM.RT.Routines; using Aitex.Sorter.Common; using MECF.Framework.Common.Equipment; using MECF.Framework.Common.SubstrateTrackings; using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.LoadPorts; using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.LoadPorts.LoadPortBase; namespace EFEM.RT.Modules { public class StaticTransfer { public int Notch1 { get; set; } public int Notch2 { get; set; } public ModuleName SourceStation => _sourceStation; public ModuleName TargetStation => _targetStation; private Queue steps = null; private IRoutine curStep = null; private PickRoutine[] pickRoutine = null; private PlaceRoutine[] placeRoutine = null; private AlignRoutine[] alignRoutine = null; private ModuleName _sourceStation; private ModuleName _targetStation; public bool Initialize() { steps = new Queue(); pickRoutine = new PickRoutine[5]; for (int i = 0; i < 5; i++) { pickRoutine[i] = new PickRoutine("System", "PickWafer"); pickRoutine[i].Initalize(); } placeRoutine = new PlaceRoutine[5]; for (int i = 0; i < 5; i++) { placeRoutine[i] = new PlaceRoutine("System", "PlaceWafer"); placeRoutine[i].Initalize(); } alignRoutine = new AlignRoutine[2]; for (int i = 0; i < 2; i++) { alignRoutine[i] = new AlignRoutine("System", "Alignment"); alignRoutine[i].Initalize(); } return true; } public bool Start(object[] objs) { MoveType type = (MoveType)objs[0]; MoveOption option = (MoveOption)objs[1]; bool bAlign = ((option & MoveOption.Align) == MoveOption.Align) || ((option & MoveOption.ReadID) == MoveOption.ReadID) || ((option & MoveOption.ReadID2) == MoveOption.ReadID2); Hand hand = (Hand)objs[2]; ModuleName st1 = (ModuleName)objs[3]; _sourceStation = st1; int ss1 = (int)objs[4]; ModuleName dt1 = (ModuleName)objs[5]; _targetStation = dt1; int ds1 = (int)objs[6]; steps.Clear(); // if (st1 == ModuleName.Robot) // hand = (Hand)ss1; if (type == MoveType.Move) //单片传输 { if (st1 != ModuleName.Robot) { pickRoutine[0].Source = st1; pickRoutine[0].Slot = ss1; pickRoutine[0].Blade = hand; steps.Enqueue(pickRoutine[0]); } if (bAlign) { placeRoutine[0].Station = ModuleName.Aligner; placeRoutine[0].Slot = 0; placeRoutine[0].Blade = hand; steps.Enqueue(placeRoutine[0]); alignRoutine[0].Option = option; alignRoutine[0].Notch = Notch1; steps.Enqueue(alignRoutine[0]); if (dt1 != ModuleName.Aligner) { if (dt1 == ModuleName.Robot) { pickRoutine[1].Source = ModuleName.Aligner; pickRoutine[1].Slot = 0; pickRoutine[1].Blade = (Hand)ds1; steps.Enqueue(pickRoutine[1]); } else { pickRoutine[1].Source = ModuleName.Aligner; pickRoutine[1].Slot = 0; pickRoutine[1].Blade = hand; steps.Enqueue(pickRoutine[1]); placeRoutine[1].Station = dt1; placeRoutine[1].Slot = ds1; placeRoutine[1].Blade = hand; steps.Enqueue(placeRoutine[1]); } } } else { if (dt1 != ModuleName.Robot) { placeRoutine[1].Station = dt1; placeRoutine[1].Slot = ds1; placeRoutine[1].Blade = hand; steps.Enqueue(placeRoutine[1]); } } } else if (type == MoveType.Swap) //交换 { //do nothing } else //双片传盘 { ModuleName st2 = (ModuleName)objs[7]; int ss2 = (int)objs[8]; ModuleName dt2 = (ModuleName)objs[9]; int ds2 = (int)objs[10]; if (type == MoveType.SPSP || type == MoveType.SPDP) //seperate pick { if (st1 != ModuleName.Robot && st2 != ModuleName.Robot) { pickRoutine[0].Source = st1; pickRoutine[0].Slot = ss1; pickRoutine[0].Blade = Hand.Blade1; steps.Enqueue(pickRoutine[0]); pickRoutine[1].Source = st2; pickRoutine[1].Slot = ss2; pickRoutine[1].Blade = Hand.Blade2; steps.Enqueue(pickRoutine[1]); } else { if (st1 == ModuleName.Robot) { pickRoutine[1].Source = st2; pickRoutine[1].Slot = ss2; if (ss1 == (int)Hand.Blade1) pickRoutine[1].Blade = Hand.Blade2; else pickRoutine[1].Blade = Hand.Blade1; steps.Enqueue(pickRoutine[1]); } else { pickRoutine[0].Source = st1; pickRoutine[0].Slot = ss1; if (ss2 == (int)Hand.Blade1) pickRoutine[0].Blade = Hand.Blade2; else pickRoutine[0].Blade = Hand.Blade1; steps.Enqueue(pickRoutine[0]); } } } else { if (st1 != ModuleName.Robot) { pickRoutine[0].Source = st1; pickRoutine[0].Slot = ss1; pickRoutine[0].Blade = Hand.Both; steps.Enqueue(pickRoutine[0]); } } if (type == MoveType.SPSP || type == MoveType.DPSP) //serpate place { if (dt1 != ModuleName.Robot && dt1 != ModuleName.Robot) { placeRoutine[1].Station = dt1; placeRoutine[1].Slot = ds1; placeRoutine[1].Blade = Hand.Blade1; steps.Enqueue(placeRoutine[1]); placeRoutine[2].Station = dt2; placeRoutine[2].Slot = ds2; placeRoutine[2].Blade = Hand.Blade2; steps.Enqueue(placeRoutine[2]); } else { if (dt1 == ModuleName.Robot) { placeRoutine[2].Station = dt2; placeRoutine[2].Slot = ds2; if (ss2 == (int)Hand.Blade1) placeRoutine[2].Blade = Hand.Blade2; else placeRoutine[2].Blade = Hand.Blade1; steps.Enqueue(placeRoutine[2]); } else { placeRoutine[1].Station = dt1; placeRoutine[1].Slot = ds1; if (ss1 == (int)Hand.Blade1) placeRoutine[1].Blade = Hand.Blade2; else placeRoutine[1].Blade = Hand.Blade1; steps.Enqueue(placeRoutine[1]); } } } else { if (dt1 != ModuleName.Robot) { placeRoutine[1].Station = dt1; placeRoutine[1].Slot = ds1; placeRoutine[1].Blade = Hand.Both; steps.Enqueue(placeRoutine[1]); } } } if (steps.Count == 0) { string reason = string.Format("Unsupport transfer path {0} {1:D2} to {2} {3:D2}", st1.ToString(), ss1, dt1.ToString(), ds1); EV.PostMessage(ModuleName.System.ToString(), EventEnum.DefaultWarning, reason); return false; } curStep = steps.Dequeue(); if (curStep.Start(objs) == Result.FAIL) { EV.PostWarningLog(ModuleName.System.ToString(), "Failed start transfer"); return false; } return true; } public bool Return(object[] objs) { steps.Clear(); ModuleName chamber = ModuleName.LP1; int slot = 0; if (WaferManager.Instance.CheckHasWafer(ModuleName.Robot, (int)Hand.Blade1)) { if(!FindEmptySlot(ref chamber, ref slot)) { EV.PostMessage(ModuleName.System.ToString(),EventEnum.DefaultWarning,"No empty slot for return wafers"); steps.Clear(); return false; } placeRoutine[0].Station = chamber; placeRoutine[0].Slot = slot; placeRoutine[0].Blade = Hand.Blade1; steps.Enqueue(placeRoutine[0]); } if ( WaferManager.Instance.CheckHasWafer(ModuleName.Robot, (int)Hand.Blade2) || WaferManager.Instance.CheckHasWafer(ModuleName.Robot, (int)Hand.Blade2 + 1) || WaferManager.Instance.CheckHasWafer(ModuleName.Robot, (int)Hand.Blade2 + 2) ) { slot++; if(!FindEmptySlotForMultiBlade(ref chamber, ref slot)) { EV.PostMessage(ModuleName.System.ToString(), EventEnum.DefaultWarning, "No empty slot for return wafers"); steps.Clear(); return false; } placeRoutine[1].Station = chamber; placeRoutine[1].Slot = slot; placeRoutine[1].Blade = Hand.Blade2; steps.Enqueue(placeRoutine[1]); } if (WaferManager.Instance.CheckHasWafer(ModuleName.Aligner, 0)) { slot++; if(!FindEmptySlot(ref chamber, ref slot)) { EV.PostMessage(ModuleName.System.ToString(), EventEnum.DefaultWarning, "No empty slot for return wafers"); steps.Clear(); return false; } pickRoutine[0].Source = ModuleName.Aligner; pickRoutine[0].Slot = 0; pickRoutine[0].Blade = Hand.Blade1; steps.Enqueue(pickRoutine[0]); placeRoutine[2].Station = chamber; placeRoutine[2].Slot = slot; placeRoutine[2].Blade = Hand.Blade1; steps.Enqueue(placeRoutine[2]); } if (steps.Count == 0) { return false; } curStep = steps.Dequeue(); if (curStep.Start(objs) == Result.FAIL) { EV.PostWarningLog(ModuleName.System.ToString(), "Failed start return"); return false; } return true; } private bool FindEmptySlot(ref ModuleName lpModule, ref int slot) { LoadPortBaseDevice lp = DEVICE.GetDevice(lpModule.ToString()); if (lp.IsEnableTransferWafer(out _)) { for (int index = slot; index < 25; index++) { if (WaferManager.Instance.CheckNoWafer(lp.Name, index)) { slot = index; return true; } } } LoadPortBaseDevice[] lps = Singleton.Instance.GetAllLoadPorts(); foreach (var loadPort in lps) { if (loadPort.Name == lpModule.ToString()) continue; if (loadPort.IsEnableTransferWafer(out _)) { for (int index = 0; index < 25; index++) { if (WaferManager.Instance.CheckNoWafer(loadPort.Name, index)) { lpModule = (ModuleName) Enum.Parse(typeof(ModuleName), loadPort.Name); slot = index; return true; } } } } return false; } private bool FindEmptySlotForMultiBlade( ref ModuleName lpModule, ref int slot) { LoadPortBaseDevice lp = DEVICE.GetDevice(lpModule.ToString()); if (lp.IsEnableTransferWafer(out _)) { for (int index = slot; index < 23; index++) { if ( WaferManager.Instance.CheckNoWafer(lp.Name, index) && WaferManager.Instance.CheckNoWafer(lp.Name, index + 1) && WaferManager.Instance.CheckNoWafer(lp.Name, index + 2) ) { slot = index; return true; } } } LoadPortBaseDevice[] lps = Singleton.Instance.GetAllLoadPorts(); foreach (var loadPort in lps) { if (loadPort.Name == lpModule.ToString()) continue; if (loadPort.IsEnableTransferWafer(out _)) { for (int index = 0; index < 23; index++) { if(WaferManager.Instance.CheckNoWafer(loadPort.Name, index) && WaferManager.Instance.CheckNoWafer(loadPort.Name, index + 1) && WaferManager.Instance.CheckNoWafer(loadPort.Name, index + 2) ) { lpModule = (ModuleName)Enum.Parse(typeof(ModuleName), loadPort.Name); slot = index; return true; } } } } return false; } public bool Monitor(object[] objs) { Result ret = Result.FAIL; if (curStep != null) { ret = curStep.Monitor(); } if (ret == Result.DONE) { if (steps.Count > 0) { curStep = steps.Dequeue(); } else { curStep = null; } if (curStep != null) { ret = curStep.Start(); if (ret == Result.FAIL) { PostMsg(RouteManager.MSG.ERROR); return true; //transition } } else { return true; //transition } return false; } else if (ret == Result.FAIL) { PostMsg(RouteManager.MSG.ERROR); return true; //transition } return false; } public void Clear() { steps.Clear(); curStep = null; } private void PostMsg(RouteManager.MSG msg, params object[] objs) { Singleton.Instance.PostMsg(msg, objs); } } }