public WaferData(EFEM_TYPE efType, WaferType wType, int nSlot) { this.efemType = efType; this.waferType = wType; this.nSlot = nSlot; Init(); }
/// <summary> /// EFEM의 슬롯에 Wafer가 있는지 /// </summary> /// <param name="efType"></param> /// <param name="nSlot"></param> /// <returns></returns> public bool IsInSlotEFEM(EFEM_TYPE efType, int nSlot) { WaferData[] wData = GetEfemData(efType); if (wData[nSlot] == null) { return(false); } return(true); }
private int TimeCoolingEnd; // 쿨링 끝 public WaferData() { efemType = EFEM_TYPE.A_CARRIER; waferType = WaferType.CARRIER; nSlot = 0; bIsPreAlign = false; bIsPostAlign = false; bIsLami = false; bIsBond = false; bIsHP = false; }
/// <summary> /// EFEM에서 FM Robot으로 이동 /// </summary> /// <param name="nSlot"></param> public bool LoadingEfemToFm(EFEM_TYPE efType, int nSlot, HAND arm) { WaferData[] wData = GetEfemData(efType); if (wData[nSlot] == null || robotFM[(int)arm] != null) { return(false); } robotFM[(int)arm] = wData[nSlot]; wData[nSlot] = null; Save(); return(true); }
/// <summary> /// FM에서 EFEM으로 이동 /// </summary> /// <param name="efType"></param> /// <param name="nSlot"></param> /// <returns></returns> public bool LoadingFmToEfem(EFEM_TYPE efType, int nSlot, HAND arm) { WaferData[] wData = GetEfemData(efType); if (robotFM[(int)arm] == null || wData[nSlot] != null) { return(false); } wData[nSlot] = robotFM[(int)arm]; robotFM[(int)arm] = null; Save(); return(true); }
WaferData[] GetEfemData(EFEM_TYPE efType) { switch (efType) { case EFEM_TYPE.A_CARRIER: return(carrierArray1); case EFEM_TYPE.B_CARRIER: return(carrierArray2); case EFEM_TYPE.C_DEVICE: return(deviceArray1); case EFEM_TYPE.D_DEVICE: return(deviceArray2); default: System.Diagnostics.Debug.Fail("EFEM_TYPE이 이상함"); break; } return(null); }
public void Run() { if (!isAcceptRun()) { return; } if (nSeqNo != nPreSeqNo) { resetCmd(); } nPreSeqNo = nSeqNo; CaseFM seqCase = (CaseFM)nSeqNo; //test int nRetV = 0; alwaysCheck(); switch (seqCase) { case CaseFM.Initialze: break; case CaseFM.Check_Interlock: //임시 테스트, 웨이퍼 2장만 진행하기 위함 //if (nWaferCount >= 2) return; //strLog = seqCase.ToString(); //AddMessage(strLog); break; case CaseFM.Start_LPM_Load: if (bLPM_Load[(int)EFEM.LPMA] && bLPM_Load[(int)EFEM.LPMC]) { //이미 LPM 로드 상태면 진행하지 않는다 nextSeq((int)CaseFM.Check_Status); return; } break; case CaseFM.Move_LPM_Load: if (bLPM_Load[(int)EFEM.LPMA] == false) { //로드 전 Flag 초기화 LpmRoot.InitMappingFlag(EFEM.LPMA); LoadLPM(EFEM.LPMA); } if (bLPM_Load[(int)EFEM.LPMC] == false) { LpmRoot.InitMappingFlag(EFEM.LPMC); LoadLPM(EFEM.LPMC); } Thread.Sleep(500); //Load Delay break; case CaseFM.Compl_LPM_Load: if (CheckLoad_LPM(EFEM.LPMA) != fn.success) { return; } break; case CaseFM.End_LPM_Load: if (CheckLoad_LPM(EFEM.LPMC) != fn.success) { return; } break; case CaseFM.LPM_Mapping_Data: //로드 시 Scan한 Map Data 연결 break; case CaseFM.Check_Status_Load_A: //Status를 체크 할 경우 LPM Alarm이 발생함, //테스트 시 제거 후 진행 함 //LpmRoot.GetStatus(EFEM.LPMA); break; case CaseFM.Compl_Status_Load_A: //if (CheckLoad_LPM(EFEM.LPMA) != fn.success) return; break; case CaseFM.End_Status_Load_A: #if _REAL_MC //LPM Load 후 Mapping Flag가 변경되면 완료 if (LpmRoot.GetMappingComplete(EFEM.LPMA) == false) { return; } if (LpmRoot.GetMappingComplete(EFEM.LPMC) == false) { return; } #endif bLPM_Load[(int)EFEM.LPMA] = true; bLPM_Load[(int)EFEM.LPMC] = true; break; case CaseFM.Check_Status: RUN_MODE RunMode = RecipeMgr.Inst.TempRcp.eRunMode; //현재 레시피 if (RunMode == RUN_MODE.FULL || RunMode == RUN_MODE.ONLY_BOND) { //FULL Mode if (nWaferCount % 2 == 0) { Working_LPM = EFEM.LPMA; efemType = EFEM_TYPE.A_CARRIER; } else { Working_LPM = EFEM.LPMC; efemType = EFEM_TYPE.C_DEVICE; } } else if (RunMode == RUN_MODE.ONLY_LAMI) { //Only Lami 일경우 Carrier 고정 사용 Working_LPM = EFEM.LPMA; efemType = EFEM_TYPE.A_CARRIER; } else { return; } //Next Wafer Slot 유/무 확인 GlobalVariable.WaferInfo.nWaferLoadSlot[(int)Working_LPM] = LpmRoot.GetNextWaferSlot(Working_LPM, LPMStatus.Load, COUNT.MAX_PORT_SLOT); if (GlobalVariable.WaferInfo.nWaferLoadSlot[(int)Working_LPM] < 0) { //Wafer Empty //더이상 투입할 웨이퍼가 없을경우 언로딩 시퀀스로 보낸다 nextSeq((int)CaseFM.Check_Unload_Wafer); return; } break; case CaseFM.Start_FM_Pickup_LPM: //FM 로봇 상태 확인 //FM 로봇 웨이퍼 상태 확인 //웨이퍼 택타임 측정 시작 시간 if (Working_LPM == EFEM.LPMA) { GlobalVariable.seqShared.carrierArray1[GlobalVariable.WaferInfo.nWaferLoadSlot[(int)Working_LPM]].strTotalSt = DateTime.Now.ToString("hh:mm:ss.fff"); } else if (Working_LPM == EFEM.LPMB) { GlobalVariable.seqShared.carrierArray2[GlobalVariable.WaferInfo.nWaferLoadSlot[(int)Working_LPM]].strTotalSt = DateTime.Now.ToString("hh:mm:ss.fff"); } else if (Working_LPM == EFEM.LPMC) { GlobalVariable.seqShared.deviceArray1[GlobalVariable.WaferInfo.nWaferLoadSlot[(int)Working_LPM]].strTotalSt = DateTime.Now.ToString("hh:mm:ss.fff"); } else if (Working_LPM == EFEM.LPMD) { GlobalVariable.seqShared.deviceArray2[GlobalVariable.WaferInfo.nWaferLoadSlot[(int)Working_LPM]].strTotalSt = DateTime.Now.ToString("hh:mm:ss.fff"); } break; case CaseFM.Move_FM_Pickup_LPM: fmStatus = FMStatus.LPM_LOAD; Working_Stage = (FMStage)Working_LPM + 1; //현재 LPM을 작업 할 Stage로 변경 nWorking_Slot = GlobalVariable.WaferInfo.nWaferLoadSlot[(int)Working_LPM] + 1; //현재 작업할 Wafer Slot Working_Arm = ARM.UPPER; MoveFmRobot(Working_Stage, nWorking_Slot, Working_Arm, fmStatus); strLog = string.Format("FmRobot Pickup Move Start -> {0}, {1}, {2}", Working_Stage.ToString(), nWorking_Slot, Working_Arm.ToString()); AddMessage(strLog); break; case CaseFM.Compl_FM_Pickup_LPM: if (CheckCompl_FM() != fn.success) { return; } //nRetV = CheckCompl_FM(); //f(nRetV == err ) strLog = string.Format("FmRobot Pickup Move End -> {0}, {1}, {2}", Working_Stage.ToString(), nWorking_Slot, Working_Arm.ToString()); AddMessage(strLog); break; case CaseFM.End_FM_Pickup_LPM: GlobalSeq.autoRun.prcFM.LpmRoot.SetWaferInfo(Working_LPM, nWorking_Slot - 1, false); //웨이퍼 맵핑 데이터 갱신 GlobalVariable.seqShared.LoadingEfemToFm(efemType, nWorking_Slot - 1, (HAND)Working_Arm); nWaferCount++; break; case CaseFM.Waiting_AL: if (GlobalVariable.seqShared.IsInAligner() || GlobalVariable.interlock.bAlignMoving == true) { //Alinger에 Wafer가 아직 있으면 대기 하도록 하자 return; } break; case CaseFM.Start_FM_Place_AL: break; case CaseFM.Move_FM_Place_AL: fmStatus = FMStatus.BUFFER_LOAD; Working_Stage = FMStage.AL; nWorking_Slot = 1; Working_Arm = ARM.UPPER; MoveFmRobot(Working_Stage, nWorking_Slot, Working_Arm, fmStatus); strLog = string.Format("FmRobot Place Move Start -> {0}, {1}, {2}", Working_Stage.ToString(), nWorking_Slot, Working_Arm.ToString()); AddMessage(strLog); break; case CaseFM.Compl_FM_Place_AL: if (CheckCompl_FM() != fn.success) { return; } strLog = string.Format("FmRobot Place Move End -> {0}, {1}, {2}", Working_Stage.ToString(), nWorking_Slot, Working_Arm.ToString()); AddMessage(strLog); break; case CaseFM.End_FM_Place_AL: GlobalVariable.seqShared.LoadingFmToAligner((HAND)Working_Arm); GlobalVariable.interlock.bAlignMoving = true; //얼라인 동작 break; case CaseFM.Check_Unload_Wafer: //CP에 언로드 할 웨이퍼가 있는지 확인 if (GlobalVariable.seqShared.IsInCP(0) == false) { nextSeq((int)CaseFM.Initialze); return; } break; ////////////////////////////////////// //Wafer Unload ///////////////////////////////////// case CaseFM.Start_FM_Pickup_CP: //CP 웨이퍼 감지 센서 확인 필요! break; case CaseFM.Move_FM_Pickup_CP: fmStatus = FMStatus.BUFFER_UNLOAD; Working_Stage = FMStage.CP1; nWorking_Slot = 1; Working_Arm = ARM.LOWER; //CP에서 언로딩 시에는 LOW ARM 사용하자 MoveFmRobot(Working_Stage, nWorking_Slot, Working_Arm, fmStatus); strLog = string.Format("FmRobot Pickup Move Start -> {0}, {1}, {2}", Working_Stage.ToString(), nWorking_Slot, Working_Arm.ToString()); AddMessage(strLog); break; case CaseFM.Compl_FM_Pickup_CP: if (CheckCompl_FM() != fn.success) { return; } strLog = string.Format("FmRobot Pickup Move End -> {0}, {1}, {2}", Working_Stage.ToString(), nWorking_Slot, Working_Arm.ToString()); AddMessage(strLog); break; case CaseFM.End_FM_Pickup_cp: GlobalVariable.seqShared.LoadingCpToFm(0, (HAND)Working_Arm); break; case CaseFM.Start_FM_Place_LPM: //완료 웨이퍼 언로딩 시 LPM A부터 채워넣자 Working_LPM = EFEM.LPMA; //LPM 상태를 확인하자 if (CheckLoad_LPM(Working_LPM) != fn.success) { //로드 상태가 아니면 에러 return; } //Unload Slot Check //Next Wafer Slot 유/무 확인 GlobalVariable.WaferInfo.nWaferUnloadSlot[(int)Working_LPM] = LpmRoot.GetNextWaferSlot(Working_LPM, LPMStatus.Unload, COUNT.MAX_PORT_SLOT); if (GlobalVariable.WaferInfo.nWaferUnloadSlot[(int)Working_LPM] < 0) { //Wafer Empty return; } break; case CaseFM.Move_FM_Place_LPM: fmStatus = FMStatus.LPM_UNLOAD; Working_Stage = (FMStage)Working_LPM + 1; nWorking_Slot = GlobalVariable.WaferInfo.nWaferUnloadSlot[(int)Working_LPM] + 1; //현재 작업할 Wafer Slot Working_Arm = ARM.LOWER; //CP에서 언로딩 시에는 LOW ARM 사용하자 MoveFmRobot(Working_Stage, nWorking_Slot, Working_Arm, fmStatus); strLog = string.Format("FmRobot Place Move Start -> {0}, {1}, {2}", Working_Stage.ToString(), nWorking_Slot, Working_Arm.ToString()); AddMessage(strLog); break; case CaseFM.Compl_FM_Place_LPM: if (CheckCompl_FM() != fn.success) { return; } strLog = string.Format("FmRobot Place Move End -> {0}, {1}, {2}", Working_Stage.ToString(), nWorking_Slot, Working_Arm.ToString()); AddMessage(strLog); break; case CaseFM.End_FM_Place_LPM: GlobalVariable.seqShared.LoadingFmToEfem(EFEM_TYPE.A_CARRIER, nWorking_Slot - 1, (HAND)Working_Arm); //Wafer Unload 후 Data 변경 GlobalSeq.autoRun.prcFM.LpmRoot.SetUnloadSlot(Working_LPM, nWorking_Slot - 1, true); if (Working_LPM == EFEM.LPMA) { GlobalVariable.seqShared.carrierArray1[GlobalVariable.WaferInfo.nWaferUnloadSlot[(int)Working_LPM]].strTotalEnd = DateTime.Now.ToString("hh:mm:ss.fff"); } else if (Working_LPM == EFEM.LPMB) { GlobalVariable.seqShared.carrierArray2[GlobalVariable.WaferInfo.nWaferUnloadSlot[(int)Working_LPM]].strTotalEnd = DateTime.Now.ToString("hh:mm:ss.fff"); } else if (Working_LPM == EFEM.LPMC) { GlobalVariable.seqShared.deviceArray1[GlobalVariable.WaferInfo.nWaferUnloadSlot[(int)Working_LPM]].strTotalEnd = DateTime.Now.ToString("hh:mm:ss.fff"); } else if (Working_LPM == EFEM.LPMD) { GlobalVariable.seqShared.deviceArray2[GlobalVariable.WaferInfo.nWaferUnloadSlot[(int)Working_LPM]].strTotalEnd = DateTime.Now.ToString("hh:mm:ss.fff"); } nextSeq((int)CaseFM.Initialze); return; /////////////////////////////////// //LPM Unload ////////////////////////////////// case CaseFM.Start_LPM_Unload: break; case CaseFM.Move_LPM_Unload: UnloadLPM(Working_LPM); break; case CaseFM.Check_Status_Unload: LpmRoot.GetStatus(Working_LPM); break; case CaseFM.Compl_LPM_Unload: if (CheckUnload_LPM(Working_LPM) != fn.success) { return; } break; case CaseFM.End_LPM_Unload: //처음 case로 nextSeq((int)CaseFM.Initialze); return; } nSeqNo++; }