COMPILE FUNCTION Clean_Insp(EntID,Event,Parm1,Parm2,Parm3,Parm4,Parm5) #pragma precomp SRP_PreCompiler /* Commuter module for CLEAN_INSP (Clean & Inspection) window 08/05/2009 - John C. Henry, J.C. Henry & Co., Inc. 03/07/2017 - djs - Changed the SCAN_RESULTS.GOT_FOCUS event to a CHAR event instead to allow users to select the scan results row of their choice (to view those individual wafer results) without being prompted for a manual entry data override. 10/29/2019 - djs - Fixed "SigRow EQ 1" to 'SelectedRow EQ 1' logic check within SignClean, SignInsp, and SignScan subroutines 04/23/2021 - djs - Updated SIGN_ROTR_ACCEPTANCE.CLICK event to not block acceptance signatures when a 100% failure scan is required. 05/13/2024 - djs - Replaced Ole Tab control (OLE_TAB_ROTR) with a groupbox control (ROTR_GROUP) to mitigate form behavior bugs in OI 10 post migration. 06/13/2024 djm Add new stage-specific supplement system. */ DECLARE SUBROUTINE Set_Property, End_Dialog, Send_Event, Set_Status, Center_Window, Post_Event, Comm_RDS DECLARE SUBROUTINE ErrMsg, Send_Message, Set_Property, Send_Event, Btree.Extract, obj_AppWindow, Signature_Services DECLARE SUBROUTINE obj_Notes, Security_Err_Msg, End_Window, Forward_Event, Start_Window, Create_Note DECLARE SUBROUTINE obj_WO_Mat_Log, obj_WO_Mat, obj_Clean_Insp, Unlock, Lock, Database_Services, Yield DECLARE SUBROUTINE Override_Log_Services, Dialog_Box, obj_WO_Wfr, Error_Services, Hold_Services DECLARE FUNCTION Get_Property, Get_Status, Dialog_Box, Utility, Popup, Collect.Ixvals, Environment_Services DECLARE FUNCTION Send_Message, Msg, Security_Check, obj_React_Run_CI, Select_Into, MemberOf, Database_Services DECLARE FUNCTION Start_Window, Create_Dialog, Database_Services, Set_Property, Error_Services, SRP_DateTime DECLARE FUNCTION obj_NCR, SRP_Array, Supplement_Services $INSERT LOGICAL $INSERT MSG_EQUATES $INSERT APPCOLORS $INSERT LSL_USERS_EQU $INSERT SECURITY_RIGHTS_EQU $INSERT REACT_EVENT_EQUATES $INSERT POPUP_EQUATES $INSERT RTI_STYLE_EQUATES $INSERT CLEAN_INSP_EQUATES $INSERT TOOL_CLASS_EQUATES $INSERT TOOL_EQUATES $INSERT WO_MAT_EQUATES $INSERT WO_LOG_EQUATES $INSERT SPC_QUEUE_EQUATES $INSERT WM_OUT_EQUATES $INSERT REACTOR_EQUATES $INSERT NOTIFICATION_EQUATES EQU PROTECTED$ TO 8 EQU CRLF$ TO \0D0A\ EQU TAB$ TO \09\ Equ ESC$ TO Char(27) EQU COL$CLEAN_TOOL TO 1 EQU COL$CLEAN_BOAT_ID TO 2 EQU COL$CLEAN_SRD_NO TO 3 EQU COL$CLEAN_SIG TO 4 EQU COL$CLEAN_SIG_DTM TO 5 EQU COL$DUMMY_1_PIXEL_WIDE TO 1 ;* Used for both INSP_SPEC and INSP controls EQU COL$INSP_SPEC_LPD TO 2 EQU COL$INSP_SPEC_SCRATCHES TO 3 EQU COL$INSP_SPEC_SCRATCH_LEN TO 4 EQU COL$INSP_SPEC_PITS TO 5 EQU COL$INSP_SPEC_MOUNDS TO 6 EQU COL$INSP_SPEC_STACK_FAULTS TO 7 EQU COL$INSP_SPEC_SPIKES TO 8 EQU COL$INSP_SPEC_SPOTS TO 9 EQU COL$INSP_SPEC_FOV TO 10 EQU COL$INSP_SPEC_BL_DEFECTS TO 11 EQU COL$INSP_TOOL TO 2 ;* Added INSP_TOOL column 10/29/2012 JCH EQU COL$INSP_LPD TO 3 EQU COL$INSP_SCRATCHES TO 4 EQU COL$INSP_SCRATCH_LEN TO 5 EQU COL$INSP_PITS TO 6 EQU COL$INSP_MOUNDS TO 7 EQU COL$INSP_STACK_FAULTS TO 8 EQU COL$INSP_SPIKES TO 9 EQU COL$INSP_SPOTS TO 10 EQU COL$INSP_FOV TO 11 EQU COL$INSP_BL_DEFECTS TO 12 EQU COL$INSP_SIG TO 13 EQU COL$INSP_SIG_DTM TO 14 EQU COL$INSP_SPEC_BSIDE_SCRATCHES TO 1 EQU COL$INSP_SPEC_BSIDE_SCRATCH_LEN TO 2 EQU COL$INSP_SPEC_BSIDE_NODULES TO 3 EQU COL$INSP_SPEC_BSIDE_SPIKES TO 4 EQU COL$INSP_BSIDE_SCRATCHES TO 1 EQU COL$INSP_BSIDE_SCRATCH_LEN TO 2 EQU COL$INSP_BSIDE_NODULES TO 3 EQU COL$INSP_BSIDE_SPIKES TO 4 EQU COL$SCAN_SPEC_SURF_RECIPE$ TO 1 EQU COL$SCAN_SPEC_SURF_DEFECTS$ TO 2 EQU COL$SCAN_SPEC_SURF_HAZE$ TO 3 EQU COL$SCAN_SPEC_SCRATCHES$ TO 4 EQU COL$SCAN_RECIPE TO 1 EQU COL$SCAN_TOOL TO 2 EQU COL$SCAN_SUM_OF_DEF_MIN TO 3 EQU COL$SCAN_SUM_OF_DEF_MAX TO 4 EQU COL$SCAN_SUM_OF_DEF_AVG TO 5 EQU COL$SCAN_HAZE_AVG_AVG TO 6 EQU COL$SCAN_DCNMM2 TO 7 EQU COL$SCAN_REASON TO 8 EQU COL$SCAN_SIG TO 9 EQU COL$SCAN_SIG_DTM TO 10 EQU COL$SCAN_TEST_RUN_DTM TO 11 EQU COL$SLOT TO 1 EQU COL$WAFER_ID TO 2 EQU COL$SLOT_NCR TO 3 EQU COL$MET_NO$ TO 4 EQU COL$MOVED_TO_SLOT TO 5 EQU COL$MU_WAFER_ID TO 6 EQU COL$MOVED_FROM_SLOT TO 7 EQU COL$REPLACED_BY TO 8 EQU COL$MU_ADD_DATE TO 9 EQU COL$MU_REM_DATE TO 10 EQU COL$EPP_SLOT TO 1 EQU COL$EPP_RDS_NO TO 2 EQU COL$EPP_REACT_NO TO 3 EQU COL$EPP_RDS_STATUS TO 4 EQU COL$EPP_POCKET TO 5 EQU COL$EPP_ZONE TO 6 EQU COL$EPP_IN_CASS TO 7 EQU COL$EPP_IN_SLOT TO 8 EQU COL$EPP_SLOT_NCR TO 9 EQU COL$EPP_MU_WO_NO TO 10 EQU COL$EPP_MU_WO_STEP TO 11 EQU COL$EPP_MU_CASS_NO TO 12 EQU COL$EPP_MU_SLOT_NO TO 13 EQU COL$EPP_UMW_CASS_ID TO 14 EQU COL$EPP_UMW_SLOT_NO TO 15 EQU COL$EPP_MU_BY TO 16 EQU COL$EPP_MU_ADD_DATE TO 17 EQU COL$EPP_MU_REM_DATE TO 18 EQU HIDDEN$ TO 32 EQU SKIPPED$ TO 4100 ErrTitle = 'Error in CleanInsp' ErrorMsg = '' Result = '' BEGIN CASE CASE EntID = @WINDOW BEGIN CASE CASE Event = 'CLEAR' ; GOSUB Clear CASE Event = 'CREATE' ; GOSUB Create CASE Event = 'CLOSE' ; GOSUB Close CASE Event = 'WRITE' ; GOSUB Write CASE Event = 'READ' ; GOSUB Read CASE Event = 'VSCROLL' ; GOSUB VScroll CASE Event[1,3] = 'QBF' ; GOSUB Refresh END CASE CASE EntID = @WINDOW:'.SIGN_CLEAN' AND Event = 'CLICK' ; GOSUB SignClean CASE EntID = @WINDOW:'.SIGN_INSP' AND Event = 'CLICK' ; GOSUB SignInsp CASE EntID = @WINDOW:'.SIGN_SCAN' AND Event = 'CLICK' ; GOSUB SignScan CASE EntID = @WINDOW:'.SIGN_ROTR_ACCEPTANCE' AND Event = 'CLICK' ; GOSUB SIGN_ROTR_ACCEPTANCE.CLICK CASE EntID = @WINDOW:'.BTN_WAFER_DETAILS' AND Event = 'CLICK' ; GOSUB BTN_WAFER_DETAILS.CLICK CASE EntID = @WINDOW:'.SCAN_RESULTS' AND Event = 'CHAR' ; GOSUB SCAN_RESULTS.CHAR CASE EntID = @WINDOW:'.SCAN_RESULTS' AND Event = 'POSCHANGED' ; GOSUB SCAN_RESULTS.POSCHANGED CASE EntID = @WINDOW:'.SPEC_BRIGHTLIGHT' AND Event = 'CLICK' ; GOSUB Refresh CASE EntID = @WINDOW:'.SPEC_MICROSCOPE' AND Event = 'CLICK' ; GOSUB Refresh CASE EntID = @WINDOW:'.CHK_EDGE' AND Event = 'CLICK' ; GOSUB Refresh CASE EntID = @WINDOW:'.REFRESH_SPEC' AND Event = 'CLICK' ; GOSUB RefreshSpec CASE EntID = @WINDOW:'.CI_TAB' AND Event = 'CLICK' ; GOSUB Page CASE EntID = @WINDOW:'.INSP_RESULTS' AND Event = 'POSCHANGED' ; GOSUB InspPC CASE EntID = @WINDOW:'.INSP_RESULTS_BSIDE' AND Event = 'POSCHANGED' ; GOSUB BSideInspPC CASE EntID = @WINDOW:'.SEND_SPC' AND Event = 'CLICK' ; GOSUB SendSPC CASE 1 ErrorMsg = 'Unknown Parameters ':EntID:' - ':Event:' passed to commuter' ErrMsg(ErrorMsg) END CASE IF ErrorMsg NE '' THEN ErrMsg(ErrTitle:@SVM:ErrorMsg) END RETURN Result * * * * * * * Create: * * * * * * * obj_Appwindow('Create',@WINDOW) IF MemberOf(@USER4, 'OI_SUPERUSER') THEN Set_Property(@WINDOW:'.SEND_SPC','VISIBLE',1) Set_Property(@WINDOW:'.SPC_DTM','VISIBLE',1) END ELSE Set_Property(@WINDOW:'.SEND_SPC','VISIBLE',0) Set_Property(@WINDOW:'.SPC_DTM','VISIBLE',0) END CIKey = Get_Property(@Window : '.CI_NO', 'TEXT') * Setup Cleans Section CleanStyles = Send_Message(@WINDOW:'.CLEAN_RESULTS','COLSTYLE',0,'') CleanStyles = BitOr(CleanStyles,DTCS_DROPDOWN$) CleanStyles = BitOr(CleanStyles,DTCS_DROPDOWN$) CleanStyles = BitOr(CleanStyles,DTCS_DROPDOWN$) Send_Message(@WINDOW:'.CLEAN_RESULTS','COLSTYLE',0,CleanStyles) ;* Set Styles * Setup Inspection Section InspStyles = Send_Message(@WINDOW:'.INSP_RESULTS','COLSTYLE',0,'') InspStyles = BitOr(InspStyles,DTCS_DROPDOWN$) Send_Message(@WINDOW:'.INSP_RESULTS','COLSTYLE',0,InspStyles) InspTools = 'SCOPE':@VM:'FF EDGE INSP':@VM:'SCOPE/FF EDGE INSP' Send_Message(@WINDOW:'.INSP_RESULTS','COLFORMAT',COL$INSP_TOOL,InspTools) * Setup Scan Section ScanStyles = Send_Message(@WINDOW:'.SCAN_RESULTS','COLSTYLE',0,'') ScanStyles = BitOr(ScanStyles,DTCS_DROPDOWN$) ScanStyles = BitOr(ScanStyles,DTCS_DROPDOWN$) Send_Message(@WINDOW:'.SCAN_RESULTS','COLSTYLE',0,ScanStyles) ScanTools = XLATE('TOOL_CLASS','TENCOR',TOOL_CLASS_TOOL$,'X') ;* Tencor class tools Send_Message(@WINDOW:'.SCAN_RESULTS','COLFORMAT',COL$SCAN_TOOL,ScanTools) IF MemberOf(@USER4, 'OI_SUPERUSER') THEN Set_Property(@WINDOW:'.REFRESH_SPEC','VISIBLE',1) END ELSE Set_Property(@WINDOW:'.REFRESH_SPEC','VISIBLE',0) END CIKey = Get_Property(@Window : '.CI_NO', 'TEXT') ReactorNo = Xlate('CLEAN_INSP', CIKey, 'REACT_NO', 'X') Stage = Get_Property(@Window : '.STAGE', 'TEXT') If Stage EQ 'LWI' then CanEdit = Memberof(@USER4, 'ENGINEERING') or Memberof(@USER4, 'LEAD') or Memberof(@USER4, 'SUPERVISOR') | or Memberof(@USER4, 'FINAL_QA') or Memberof(@USER4, 'ROTR_OVERRIDE') // Check if manual entry lock is temporarily disabled for all users due to ROTR queue overflow. ManualEntryLock = Xlate('APP_INFO', 'ROTR_DATA_ENTRY_LOCK', 1, 'X') If (ManualEntryLock EQ False$) then CanEdit = True$ Set_Property(@Window, '@CAN_EDIT', CanEdit) If Not(CanEdit) then // Disable manual entry of data. ScanStyles = Send_Message(@Window : '.SCAN_RESULTS', 'COLSTYLE', 0, '') For column = 1 to 7 ScanStyles = BitOr( ScanStyles, PROTECTED$ ) Next column // Disable dropdown menus for recipe and tool columns. ScanStyles = BitAnd(ScanStyles, BitNot(DTCS_DROPDOWN$) ) ScanStyles = BitAnd(ScanStyles, BitNot(DTCS_DROPDOWN$) ) ScanStyles = Send_Message(@Window : '.SCAN_RESULTS', 'COLSTYLE', 0, ScanStyles) end end RETURN * * * * * * * Page: * * * * * * * Page = Get_Property(@WINDOW:'.CI_TAB', 'VALUE') Set_Property(@WINDOW,'VPOSITION', Page) RETURN * * * * * * * VScroll: * * * * * * * Page = Parm1 Set_Property(@WINDOW:'.CI_TAB','VALUE', Page) RETURN * * * * * * * Clear: * * * * * * * Send_Event(@WINDOW,'PAGE',1) * * * * * * * Refresh: * * * * * * * CIKey = Get_Property(@WINDOW:'.CI_NO', 'TEXT') // Hide or show the Cass No label and edit line based on the whether the reactor is EpiPro or not. - 04/10/2018 - dmb WONo = Get_Property(@Window : '.WO_NO', 'TEXT') WOLogRow = Database_Services('ReadDataRow', 'WO_LOG', WONo) ReactType = WOLogRow If ReactType NE 'EPP' then Visible = True$ end else Visible = False$ end Set_Property(@Window : '.CASS_NO_LABEL', 'VISIBLE', Visible) Set_Property(@Window : '.CASS_NO', 'VISIBLE', Visible) Stage = Get_Property(@WINDOW:'.STAGE','TEXT') * * * * * Ctrls = @WINDOW:'.STAGE':@RM ; Props = 'TEXT':@RM Ctrls := @WINDOW:'.SPEC_FWI_LWI':@RM ; Props := 'TEXT':@RM Ctrls := @WINDOW:'.SPEC_CLEAN_TOOL_REP':@RM ; Props := 'DEFPROP':@RM Ctrls := @WINDOW:'.SPEC_BRIGHTLIGHT':@RM ; Props := 'CHECK':@RM Ctrls := @WINDOW:'.SPEC_MICROSCOPE':@RM ; Props := 'CHECK':@RM Ctrls := @WINDOW:'.CHK_EDGE':@RM ; Props := 'CHECK':@RM Ctrls := @WINDOW:'.SPEC_CLEAN_TOOL' ; Props := 'DEFPROP' Vals = Get_Property(Ctrls,Props) Stage = Vals[1,@RM] SpecFwiLwi = Vals[COL2()+1,@RM] SpecCleanToolRep = Vals[COL2()+1,@RM] SpecBrightlight = Vals[COL2()+1,@RM] SpecMicroscope = Vals[COL2()+1,@RM] SpecEdge = Vals[COL2()+1,@RM] SpecCleanTool = Vals[COL2()+1,@RM] SpecCleanTools = Get_Property(@WINDOW:'.SPEC_CLEAN_TOOL$','ARRAY') IF SpecCleanTools = '' THEN AkrionCleanTools = XLATE('TOOL_CLASS','AKRION',TOOL_CLASS_TOOL$,'X') WetBenchTools = XLATE('TOOL_CLASS','WET BENCH',TOOL_CLASS_TOOL$,'X') BEGIN CASE CASE AkrionCleanTools NE '' AND WetBenchTools NE '' ; SpecCleanTools = AkrionCleanTools:@VM:WetBenchTools CASE AkrionCleanTools NE '' AND WetBenchTools = '' ; SpecCleanTools = AkrionCleanTools CASE AkrionCleanTools = '' AND WetBenchTools NE '' ; SpecCleanTools = WetBenchTools CASE 1 ; NULL END CASE END LOOP UNTIL SpecCleanTools[-1,1] NE @VM OR SpecCleanTools = '' SpecCleanTools[-1,1] = '' REPEAT ScanRecipes = Get_Property(@WINDOW:'.SPEC_SURFSCAN','ARRAY') ;* 1/22/2013 JCH *********** Send_Message(@WINDOW:'.SCAN_RESULTS','COLFORMAT',COL$SCAN_RECIPE,ScanRecipes) BEGIN CASE CASE Stage = 'PRE' LabelText = 'Pre Epi Cleaning && Inspection' Send_Message(@WINDOW:'.CLEAN_RESULTS','COLFORMAT',COL$CLEAN_TOOL,SpecCleanTools) Send_Message(@WINDOW:'.CLEAN_RESULTS','COLFORMAT',COL$CLEAN_BOAT_ID,XLATE('LISTBOX_CONFIG','PRECLEANCASSID',1,'X')) Send_Message(@WINDOW:'.CLEAN_RESULTS','COLFORMAT',COL$CLEAN_SRD_NO,XLATE('LISTBOX_CONFIG','PRECLEANSRD',1,'X')) CASE Stage = 'POST' LabelText = 'Post Epi Cleaning && Inspection' Send_Message(@WINDOW:'.CLEAN_RESULTS','COLFORMAT',COL$CLEAN_TOOL,SpecCleanTools) Send_Message(@WINDOW:'.CLEAN_RESULTS','COLFORMAT',COL$CLEAN_BOAT_ID,XLATE('LISTBOX_CONFIG','POSTCLEANCASSID',1,'X')) Send_Message(@WINDOW:'.CLEAN_RESULTS','COLFORMAT',COL$CLEAN_SRD_NO,XLATE('LISTBOX_CONFIG','POSTCLEANSRD',1,'X')) CASE Stage = 'FWI' ; LabelText = 'First Wafer Inspection' CASE Stage = 'LWI' ; LabelText = 'Last Wafer Inspection' CASE Stage = 'WFR' AND SpecFwiLwi = 'FWI' ; LabelText = 'First Wafer Inspection' CASE Stage = 'WFR' AND SpecFwiLwi = 'LWI' ; LabelText = 'Last Wafer Inspection' CASE Stage[1,3] = 'WFR' ; LabelText = 'Wafer ':Stage[4,99]:' Extra Inspection' CASE 1 ; LabelText = 'Cleaning && Inspection' END CASE Set_Property(@WINDOW:'.WINDOW_LABEL_FIX','TEXT',LabelText) Ctrls = @WINDOW:'.SPEC_CLEAN_SUBOXIDE':@RM ; Props = 'CHECK':@RM Ctrls := @WINDOW:'.SPEC_CLEAN_TOOL':@RM ; Props := 'TEXT':@RM Ctrls := @WINDOW:'.SPEC_CLEAN_AKRION_RECIPE':@RM ; Props := 'TEXT':@RM Ctrls := @WINDOW:'.SPEC_BRIGHTLIGHT':@RM ; Props := 'CHECK':@RM Ctrls := @WINDOW:'.SPEC_MICROSCOPE':@RM ; Props := 'CHECK':@RM Ctrls := @WINDOW:'.CHK_EDGE':@RM ; Props := 'CHECK':@RM Ctrls := @WINDOW:'.SPEC_SURFSCAN' ; Props := 'ARRAY' Vals = Get_Property(Ctrls,Props) SCSubOxide = Vals[1,@RM] SCTool = Vals[COL2()+1,@RM] SCAkrionRecipe = Vals[COL2()+1,@RM] SBrightLight = Vals[COL2()+1,@RM] SMicroscope = Vals[COL2()+1,@RM] SEdge = Vals[COL2()+1,@RM] SSurfScanArray = Vals[COL2()+1,@RM] ScanRecipes = SSurfScanArray CONVERT @VM TO '' IN ScanRecipes SSurfScanRecipe = ScanRecipes Ctrls = @WINDOW:'.SPEC_CLEAN_REQ':@RM ; Props = 'CHECK':@RM Ctrls := @WINDOW:'.SPEC_INSP_REQ':@RM ; Props := 'CHECK':@RM Ctrls := @WINDOW:'.SPEC_SURFSCAN_REQ' ; Props := 'CHECK' Vals = Get_Property(Ctrls,Props) CleanSigReq = Vals[1,@RM] InspSigReq = Vals[COL2()+1,@RM] SurfScanSigReq = Vals[COL2()+1,@RM] IF SCTool NE '' OR CleanSigReq = 1 then CleanSigReq = 1 end else CleanSigReq = 0 end InspReq = Xlate('CLEAN_INSP', CIKey, 'SPEC_INSP_REQ', 'X') If InspReq EQ '' then InspReq = Xlate('CLEAN_INSP', CIKey, 'INSP_REQ', 'X') // Old records may have more than one RDS/CLEAN_INSP key. InspInterval = Xlate('CLEAN_INSP', CIKey, 'INSP_INTERVAL', 'X')<0, 1> If InspInterval NE '' then // Use the stored interval RDSNo = Xlate('CLEAN_INSP', CIKey, 'RDS_NO', 'X')<0, 1> PSNo = Xlate('CLEAN_INSP', CIKey, 'PS_NO', 'X')<0, 1> WONo = Xlate('CLEAN_INSP', CIKey, 'WO_NO', 'X')<0, 1> WOQty = Xlate('WO_LOG', WONo, 'QTY', 'X')<0, 1> RunNo = Xlate('RDS', RDSNo, 'RUN_ORDER_NUM', 'X')<0, 1> StageKey = PSNo:'*LWI' LastRun = ( (RunNo * 25) EQ WOQty ) InspReq = ( (Mod((RunNo - 1), InspInterval) EQ 0) or LastRun ) end else // Use the current PRS_STAGE interval InspReq = Xlate('CLEAN_INSP', CIKey, 'INSP_REQ', 'X') end If InspReq EQ False$ then Set_Property(@WINDOW:'.INSP_RESULT_GROUP', 'TEXT', 'Visual Inspection Not Required') end IF SBrightLight = 1 OR SMicroscope = 1 OR SEdge OR InspSigReq = 1 THEN InspSigReq = 1 end ELSE InspSigReq = 0 end IF SSurfScanRecipe NE '' OR SurfScanSigReq = 1 THEN SurfScanSigReq = 1 end ELSE SurfScanSigReq = 0 end DefBack = Get_Property(@WINDOW,'BACKCOLOR') ReqBackColor = CI_GROUP_BLUE$ * ROTR 2/1/2012 RotrAction = Get_Property(@WINDOW:'.ROTR_ACTION','TEXT') BEGIN CASE CASE RotrAction = 'Passed' RBackColor = GREEN$ ;*LS1_GREEN$ BypassEnabled = False$ CASE RotrAction = 'Failed' RBackColor = RED$ BypassEnabled = MemberOf(@USER4, 'ENGINEERING') OR MemberOf(@USER4, 'LEAD') OR MemberOf(@USER4, 'SUPERVISOR') OR MemberOf(@USER4, 'OI_ADMIN') OR MemberOf(@USER4, 'ROTR_OVERRIDE') CASE RotrAction = 'Waived' RBackColor = YELLOW$ ;*CMB_YELLOW$ BypassEnabled = False$ CASE RotrAction = 'Accepted' RBackColor = ORANGE$ BypassEnabled = False$ CASE 1 IF SurfScanSigReq THEN RBackColor = ReqBackColor END ELSE RBackColor = DefBack END BypassEnabled = False$ END CASE Ctrls = @WINDOW:'.ROTR_STATUS_LABEL':@FM ; Props = 'BACKCOLOR':@FM ; Vals = RBackColor:@FM Ctrls := @WINDOW:'.ROTR_REASON_LABEL':@FM ; Props := 'BACKCOLOR':@FM ; Vals := RBackColor:@FM Ctrls := @WINDOW:'.SIGN_ROTR_SIGNATURE_LABEL':@FM ; Props := 'BACKCOLOR':@FM ; Vals := RBackColor:@FM Ctrls := @WINDOW:'.SIGN_ROTR_REASON_LABEL':@FM ; Props := 'BACKCOLOR':@FM ; Vals := RBackColor:@FM Ctrls := @WINDOW:'.ROTR_GROUP':@FM ; Props := 'BACKCOLOR':@FM ; Vals := RBackColor:@FM Ctrls := @WINDOW:'.ROTR_ACTION':@FM ; Props := 'ENABLED':@FM ; Vals := 0:@FM Ctrls := @WINDOW:'.EDL_ROTR_REASON':@FM ; Props := 'ENABLED':@FM ; Vals := 0:@FM Ctrls := @WINDOW:'.SIGN_ROTR_ACCEPTANCE':@FM ; Props := 'ENABLED':@FM ; Vals := BypassEnabled:@FM Ctrls := @WINDOW ; Props := 'REDRAW' ; Vals := 1 Convert @FM to @RM in Ctrls Convert @FM to @RM in Props Convert @FM to @RM in Vals Set_Property(Ctrls,Props,Vals) Set_Property(@Window:'.OLE_PIC_ROTR', 'OLE.BackgroundColor', RBackColor) IF Get_Property(@WINDOW:'.SPC_DTM','DEFPROP') = '' THEN Set_Property(@WINDOW:'.SEND_SPC','TEXT','Send to SPC') END ELSE Set_Property(@WINDOW:'.SEND_SPC','TEXT','Resend to SPC') END * Check for out of spec on the Inspection InspSpecs = Get_Property(@WINDOW:'.SPEC_INSP','LIST') InspResults = Get_Property(@WINDOW:'.INSP_RESULTS','LIST') BSInspSpecs = Get_Property(@WINDOW:'.SPEC_INSP_BSIDE','LIST') BSInspResults = Get_Property(@WINDOW:'.INSP_RESULTS_BSIDE','LIST') InspComplete = 1 InspOutOfSpec = 0 ResultLineNo = 1 OutOfSpecLine = 0 LOOP InspResult = InspResults[1,@FM] InspResults = DELETE(InspResults,1,0,0) BSInspResult = BSInspResults[1,@FM] BSInspReults = DELETE(BSInspResults,1,0,0) UNTIL InspOutOfSpec OR InspResult = '' OR InspResult[1,9] = @VM:@VM:@VM:@VM:@VM:@VM:@VM:@VM:@VM * Check Frontside columns FOR Col = COL$INSP_SPEC_LPD TO COL$INSP_SPEC_BL_DEFECTS ColSpec = InspSpecs<1,Col> colResult = InspResult<1,Col + 1> ;* Results has the tool column in front of the actual data IF ColSpec NE '' AND colResult = '' THEN InspComplete = 0 IF colResult > 0 AND ColSpec NE '' THEN BEGIN CASE CASE Col = COL$INSP_SPEC_SCRATCH_LEN IF ColResult GT ColSpec THEN InspOutOfSpec = 1 CASE Col = COL$INSP_SPEC_FOV IF ColResult GT ColSpec THEN InspOutOfSpec = 1 CASE 1 IF ColResult GE ColSpec THEN InspOutOfSpec = 1 END CASE END NEXT Col * Check Backside columns FOR Col = COL$INSP_SPEC_BSIDE_SCRATCHES TO COL$INSP_SPEC_BSIDE_SPIKES ColSpec = BSInspSpecs<1,Col> colResult = BSInspResult<1,Col> IF ColSpec NE '' AND colResult = '' THEN InspComplete = 0 IF colResult > 0 AND ColSpec NE '' THEN BEGIN CASE CASE Col = COL$INSP_SPEC_BSIDE_SCRATCH_LEN IF ColResult GT ColSpec THEN InspOutOfSpec = 1 CASE 1 IF ColResult GE ColSpec THEN InspOutOfSpec = 1 END CASE END NEXT Col IF NOT(InspOutOfSpec) THEN ResultLineNo += 1 END REPEAT IF InspOutOfSpec THEN Set_Property(@WINDOW:'.INSP_RESULTS','BACKCOLOR',RED$) Set_Property(@WINDOW:'.INSP_RESULTS_BSIDE','BACKCOLOR',RED$) Set_Property(@WINDOW:'.SIGN_INSP','ENABLED',0) END ELSE Set_Property(@WINDOW:'.INSP_RESULTS','BACKCOLOR',WHITE$) Set_Property(@WINDOW:'.INSP_RESULTS_BSIDE','BACKCOLOR',WHITE$) Set_Property(@WINDOW:'.SIGN_INSP','ENABLED',1) END IF NOT(InspComplete) THEN Set_Property(@WINDOW:'.SIGN_INSP','ENABLED',0) END * Check for out of spec on the Surface Scan results ******************************* SSurfRecipes = SSurfScanArray SSurfDefects = SSurfScanArray SSurfHazes = SSurfScanArray LOOP SSurfRecipe = SSurfRecipes[-1,'B':@VM] UNTIL SSurfRecipe NE '' OR SSurfRecipes = '' SSurfRecipes[COL1(),1] = '' REPEAT SurfResults = Get_Property(@WINDOW:'.SCAN_RESULTS','LIST') * Remove empty lines from control LOOP SurfResLine = SurfResults[-1,'B':@FM] CONVERT @VM TO '' IN SurfResLine UNTIL SurfResLine NE '' OR SurfResults = '' SurfResults[COL1(),99] = '' REPEAT CurrRec = Get_Property(@Window, 'RECORD') ScanResults = CurrRec CtrlName = @WINDOW:'.SCAN_RESULTS' For each ScanResult in ScanResults using @VM setting Line Begin Case Case ScanResult EQ 'P' Color = GREEN$:@FM:BLACK$:@FM:BGREEN$:@FM:BLACK$ Case ScanResult EQ 'F' Color = RED$:@FM:BLACK$:@FM:BRED$:@FM:BLACK$ Case Otherwise$ Null End Case // Color the row stat = Send_Message(CtrlName, 'COLOR_BY_POS', 0, Line, Color) Next ScanResult Set_Property(@Window:'.SPEC_MICROSCOPE', 'ENABLED', False$) Set_Property(@Window:'.CHK_EDGE', 'ENABLED', False$) * QBF buttons Ctrls = @WINDOW:'.QBF_FIRST_FIX':@RM ; Props = 'ENABLED':@RM Ctrls := @WINDOW:'.QBF_PREV_FIX':@RM ; Props := 'ENABLED':@RM Ctrls := @WINDOW:'.QBF_ABS_FIX':@RM ; Props := 'ENABLED':@RM Ctrls := @WINDOW:'.QBF_NEXT_FIX':@RM ; Props := 'ENABLED':@RM Ctrls := @WINDOW:'.QBF_LAST_FIX':@RM ; Props := 'ENABLED':@RM Ctrls := @WINDOW:'.QBF_STOP_FIX' ; Props := 'ENABLED' IF Get_Property(@WINDOW,'QBFLIST') = '' THEN Vals = 0:@RM:0:@RM:0:@RM:0:@RM:0:@RM:0 END ELSE Vals = 1:@RM:1:@RM:1:@RM:1:@RM:1:@RM:1 END Set_Property(Ctrls,Props,Vals) * Turn edit table symbolic column backgrounds to green ************************************************** ETSymbolics = Get_Property(@WINDOW,'@ET_SYMBOLICS') ;* Loaded during 'Create' in obj_Appwindow ETCtrls = ETSymbolics<1> ETCols = ETSymbolics<2> FOR I = 1 TO COUNT(ETCtrls,@VM) + (ETCtrls NE '') ETCtrl = ETCtrls<1,I> ETList = Get_Property(ETCtrl,'LIST') FOR Line = 1 TO COUNT(ETList,@FM) + (ETList NE '') IF ETList NE '' THEN FOR N = 1 TO COUNT(ETCols<1,I>,@SVM) + (ETCols<1,I> NE '') stat = Send_Message(ETCtrl,'COLOR_BY_POS',ETCols<1,I,N>,Line,GREEN$) NEXT N END NEXT I NEXT I ScanResultsArray = Get_Property(@Window : '.SCAN_RESULTS', 'ARRAY') TestDTMs = ScanResultsArray Done = False$ For each DTM in TestDTMs using @VM setting vPos If DTM NE '' then Done = True$ Until Done EQ True$ Next DTM Convert @VM to '' in TestDTMs TestDTMs = Trim(TestDTMs) If TestDTMs EQ '' then Set_Property(@Window : '.BTN_WAFER_DETAILS', 'ENABLED', False$) end else Set_Property(@Window : '.SCAN_RESULTS', 'SELPOS', 1:@FM:vPos) end RETURN * * * * * * * Read: * * * * * * * GOSUB Refresh RETURN * * * * * * * Write: * * * * * * * DontClose = Get_Property(@WINDOW,'@DONT_CLOSE') IF NOT(DontClose) THEN Forward_Event() Post_Event(@WINDOW,'CLOSE') END ELSE Set_Property(@WINDOW,'@DONT_CLOSE',0) Result = 1 END RETURN * * * * * * * Close: * * * * * * * obj_Appwindow('DetailReturn',@WINDOW) RETURN * * * * * * * Delete: * * * * * * * RETURN * * * * * * * SignClean: * * * * * * * CtrlID = @WINDOW:'.CLEAN_RESULTS' CtrlList = Get_Property(CtrlID,'LIST') SlotSelection = Get_Property(CtrlID,'SELPOS') SelectedRow = SlotSelection<2> SigRow = CtrlList IF SigRow<1,COL$CLEAN_TOOL> = '' THEN ErrMsg('Process Error':@SVM:'Clean Tool column is required.') Set_Property(CtrlID,'SELPOS',COL$CLEAN_TOOL:@FM:SelectedRow) RETURN END CONVERT @VM TO '' IN SigRow **** Ctrls = @WINDOW:'.WO_NO':@RM ; Props = 'DEFPROP':@RM Ctrls := @WINDOW:'.WO_STEP':@RM ; Props := 'DEFPROP':@RM Ctrls := @WINDOW:'.CASS_NO':@RM ; Props := 'DEFPROP':@RM Ctrls := @WINDOW:'.STAGE':@RM ; Props := 'DEFPROP':@RM Ctrls := @WINDOW:'.RDS_NO' ; Props := 'DEFPROP' Vals = Get_Property(Ctrls,Props) WONo = Vals[1,@RM] WOStep = Vals[COL2()+1,@RM] CassNo = Vals[COL2()+1,@RM] Stage = Vals[COL2()+1,@RM] RDSNo = Vals[COL2()+1,@RM] WOLogRow = Database_Services('ReadDataRow', 'WO_LOG', WONo) ReactType = WOLogRow IF Stage = 'POST' THEN IF RDSNo = '' THEN * Epi Pro wafers SigAction = WOStep:'MO_PSTC' SigStage = 'MO_PSTC' END ELSE SigAction = WOStep:'PSTC' SigStage = 'PSTC' END END ELSE SigAction = WOStep:Stage:'C' SigStage = Stage:'C' END IF SigRow NE '' AND CtrlList = '' THEN If SelectedRow EQ 1 then WOMatKey = WONo:'*':CassNo Signature_Services('CheckSigOrder', WOMatKey, SigStage, RDSNo) If Error_Services('HasError') then ErrMsg(Error_Services('GetMessage')) return end end // Add check for supplement signatures ValidStages = Supplement_Services('GetStagesForLot', 'RDS', RDSNo) If Count(ValidStages, SigStage) NE 0 then UnacknowledgedSupp = Supplement_Services('UnacknowledgedSupplementCheck', 'RDS', RDSNo, SigStage) If UnacknowledgedSupp NE FALSE$ then Response = Dialog_Box('NDW_RDS_SUPP_SIG', @Window, RDSNo :@FM: SigStage :@FM: FALSE$) If Response EQ False$ then return end End IF MemberOf(@USER4, 'OI_SUPERUSER') THEN Valid = 1 END ELSE Valid = Dialog_Box( 'QUOTE_SIG_PWD_ENTRY', @WINDOW, @USER4:@VM:XLATE( 'LSL_USERS', @USER4, LSL_USERS_PASSWORD$, 'X' ) ) END IF Valid = 1 THEN CurrDate = OCONV(Date(),'D4/') CurrTime = OCONV(Time(),'MTHS') CurrDTM = CurrDate:' ':CurrTime Signer = @USER4 ToolID = CtrlList ToolRec = XLATE('TOOL',ToolID,'','X') ToolWHCd = ToolRec ToolLoc = ToolRec Tag = '' owmParms = WONo:@RM:CassNo:@RM:WOStep:@RM:SigStage:@RM:Signer:@RM:CurrDTM:@RM:ToolID:@RM:ToolWHCd:@RM:ToolLoc:@RM:Tag ;* Sets PSTC signature IF Get_Status(errCode) THEN CALL ErrMsg(ErrCode) RETURN END ToolID = CtrlList ToolRec = XLATE('TOOL',ToolID,'','X') ToolWHCd = ToolRec ToolLoc = ToolRec LogFile = 'WO_MAT' ; WOMLParms = LogFile:@RM LogDTM = CurrDTM ; WOMLParms := LogDTM:@RM Action = SigAction ; WOMLParms := Action:@RM WhCd = ToolWHCd ; WOMLParms := WhCd:@RM LocCd = ToolLoc ; WOMLParms := LocCd:@RM WONos = WONo ; WOMLParms := WONos:@RM CassNos = CassNo ; WOMLParms := CassNos:@RM UserID = Signer ; WOMLParms := UserID:@RM Tags = Tag ; WOMLParms := Tags:@RM ToolID = ToolID ; WOMLParms := ToolID obj_WO_Mat_Log('Create',WOMLParms) ;* Stage PSTC log entry IF Get_Status(errCode) THEN ErrMsg(errCode) RETURN END Set_Property(CtrlID,'CELLPOS',Signer,COL$CLEAN_SIG:@FM:SelectedRow) Set_Property(CtrlID,'CELLPOS',CurrDTM,COL$CLEAN_SIG_DTM:@FM:SelectedRow) CINo = Get_Property(@WINDOW:'.CI_NO','DEFPROP') Set_Property(@WINDOW,'@DONT_CLOSE',1) Send_Event(@WINDOW,'WRITE') obj_AppWindow('LUValReturn',CINo:@RM:@WINDOW:'.CI_NO') END END ELSE IF SigRow = '' THEN ErrMsg('Process Error':@SVM:'Must have some information in selected row to sign.') RETURN END IF CtrlList NE '' THEN ErrMsg('Process Error':@SVM:'Row is already signed.') RETURN END END RETURN * * * * * * * SignInsp: * * * * * * * CtrlID = @WINDOW:'.INSP_RESULTS' CtrlList = Get_Property(CtrlID,'LIST') SlotSelection = Get_Property(CtrlID,'SELPOS') SelectedRows = SlotSelection<2> SlotSelection = Get_Property(CtrlID,'SELPOS') SelectedRow = SlotSelection<2> SigRow = CtrlList BackSigRow = Get_Property(@Window:'.INSP_RESULTS_BSIDE', 'LIST') FrontSpecRow = Get_Property(@Window:'.SPEC_INSP', 'LIST') BackSpecRow = Get_Property(@Window:'.SPEC_INSP_BSIDE', 'LIST') InspTools = 'SCOPE':@VM:'FF EDGE INSP':@VM:'SCOPE/FF EDGE INSP' SelTool = SigRow<1,COL$INSP_TOOL> IF SelTool = '' THEN ErrMsg('Process Error':@SVM:'Insp Tool column is required.') Set_Property(CtrlID,'SELPOS',COL$INSP_TOOL:@FM:SelectedRow) RETURN END // Ensure tool selected matches that of the prescribed inspection type EdgeInspReq = Get_Property(@Window:'.CHK_EDGE', 'CHECK') ScopeInspReq = Get_Property(@Window:'.SPEC_MICROSCOPE', 'CHECK') Begin Case Case EdgeInspReq and ScopeInspReq If SelTool NE 'SCOPE/FF EDGE INSP' then ErrMsg('Process Error':@SVM:'Edge inspection and scope inspection are required. Selected tool must be "SCOPE/FF EDGE INSP"') Set_Property(CtrlID,'SELPOS',COL$INSP_TOOL:@FM:SelectedRow) return end Case ScopeInspReq If SelTool NE 'SCOPE' then ErrMsg('Process Error':@SVM:'Microscope inspection is required. Selected tool must be "SCOPE"') Set_Property(CtrlID,'SELPOS',COL$INSP_TOOL:@FM:SelectedRow) return end Case EdgeInspReq If SelTool NE 'FF EDGE INSP' then ErrMsg('Process Error':@SVM:'Edge inspection is required. Selected tool must be "FF EDGE INSP"') Set_Property(CtrlID,'SELPOS',COL$INSP_TOOL:@FM:SelectedRow) return end End Case // Verify frontside inspection data For Col = COL$INSP_SPEC_LPD to COL$INSP_SPEC_BL_DEFECTS ColSpec = FrontSpecRow<1, Col> ColVal = SigRow<1, Col + 1> ;* Results has the tool column in front of the actual data If ( (ColSpec NE '') and (ColVal EQ '') ) then ErrMsg('Process Error':@SVM:'Data is missing in column number ':Col-1:'.') Set_Property(CtrlID,'SELPOS',Col:@FM:SelectedRow) RETURN end Next Col // Verify backside inspection data For Col = COL$INSP_SPEC_BSIDE_SCRATCHES to COL$INSP_SPEC_BSIDE_SPIKES ColSpec = BackSpecRow<1, Col> ColVal = BackSigRow<1, Col> If ( (ColSpec NE '') and (ColVal EQ '') ) then ErrMsg('Process Error':@SVM:'Data is missing in column number ':Col-1:'.') Set_Property(CtrlID,'SELPOS',Col:@FM:SelectedRow) RETURN end Next Col CONVERT @VM TO '' IN SigRow Ctrls = @WINDOW:'.WO_NO':@RM ; Props = 'DEFPROP':@RM Ctrls := @WINDOW:'.WO_STEP':@RM ; Props := 'DEFPROP':@RM Ctrls := @WINDOW:'.CASS_NO':@RM ; Props := 'DEFPROP':@RM Ctrls := @WINDOW:'.STAGE':@RM ; Props := 'DEFPROP':@RM Ctrls := @WINDOW:'.RDS_NO' ; Props := 'DEFPROP' Vals = Get_Property(Ctrls,Props) WONo = Vals[1,@RM] WOStep = Vals[COL2()+1,@RM] CassNo = Vals[COL2()+1,@RM] Stage = Vals[COL2()+1,@RM] RDSNo = Vals[COL2()+1,@RM] WOLogRow = Database_Services('ReadDataRow', 'WO_LOG', WONo) ReactType = WOLogRow IF Stage = 'POST' THEN IF RDSNo = '' THEN * Epi Pro wafers SigAction = WOStep:'MO_PSTI' SigStage = 'MO_PSTI' END ELSE SigAction = WOStep:'PSTI' SigStage = 'PSTI' END END ELSE SigAction = WOStep:Stage:'I' SigStage = Stage:'I' END IF SigRow NE '' AND CtrlList = '' THEN If SelectedRow EQ 1 then WOMatKey = WONo:'*':CassNo Signature_Services('CheckSigOrder', WOMatKey, SigStage, False$, RDSNo) If Error_Services('HasError') then ErrMsg(Error_Services('GetMessage')) return end END ;* End of check for 1st Signature row // Add check for supplement signatures ValidStages = Supplement_Services('GetStagesForLot', 'RDS', RDSNo) If Count(ValidStages, SigStage) NE 0 then UnacknowledgedSupp = Supplement_Services('UnacknowledgedSupplementCheck', 'RDS', RDSNo, SigStage) If UnacknowledgedSupp NE FALSE$ then Response = Dialog_Box('NDW_RDS_SUPP_SIG', @Window, RDSNo :@FM: SigStage :@FM: FALSE$) If Response EQ False$ then return end End // Check if edge inspection is prescribed. If so, prompt user whether or not edge defects are present. If EdgeInspReq then // If edge defects are present, present user with a wafer selection dialog and create an NCR for those wafers. Response = Msg(@Window, '', 'YESNO', '', 'Edge Defects':@FM:'Are any edge defects present?') If Response EQ True$ then // Display a popup of wafers in the RDS or WM_OUT cassette WONo = Get_Property(@Window : '.WO_NO', 'TEXT') WOStepNo = Get_Property(@Window:'.WO_STEP', 'TEXT') ReactType = Xlate('WO_LOG', WONo, 'REACT_TYPE', 'X') CassNo = Get_Property(@Window:'.CASS_NO', 'TEXT') WOMatKey = WONo:'*':CassNo If ReactType NE 'EPP' then // Non-EpiPro // Loop until user successfully creates an NCR Loop ErrFlag = False$ // Prompt user to select affected wafers Response = Dialog_Box('DBW_WO_MAT_WAFER_SELECT', @Window, WOMatKey) If Response EQ 'Cancel' then ErrMsg('Signature operation aborted.') return end SelRowData = SRP_Array('Rotate', Response, @FM, @VM) SlotNos = SelRowData WfrIDs = SelRowData PrevNCRs = SelRowData MetNos = SelRowData MUWfrIDs = SelRowData IneligibleSlots = '' For each SlotNo in SlotNos using @VM setting vPos MetNo = MetNos<0, vPos> WfrID = WfrIDs<0, vPos> PrevNCR = PrevNCRs<0, vPos> MUWfrID = MUWfrIDs<0, vPos> If ( (MetNo NE '') or (WfrID EQ '') or (PrevNCR NE '' and MUWfrID EQ '') ) then ErrFlag = True$ IneligibleSlots<0, -1> = SlotNo end Next SlotNo If ErrFlag EQ False$ then // Place the lot on hold if it isn't already. HoldEntity = 'WO_MAT' HoldEntityID = WOMatKey Set_Status(0) OnHold = Xlate('WO_MAT', WOMatKey, 'HOLD', 'X') * If Not(OnHold) then obj_WO_Mat('ToggleHold',WOMatKey:@RM:HoldEntity:@RM:HoldEntityID:@RM:'') If Not(OnHold) then Hold_Services('ToggleHold', WOMatKey, HoldEntity, HoldEntityID, '', '', '', '') ErrCode = '' If Not(Get_Status(ErrCode)) then // Ensure the user didn't cancel the hold operation. OnHold = Xlate('WO_MAT', WOMatKey, 'HOLD', 'X') If OnHold then // Set ROTR block on reactor Reactor = Xlate('RDS', RDSNo, 'REACTOR', 'X') ReactorRec = Database_Services('ReadDataRow', 'REACTOR', Reactor) ReactorRec = 'F' ReactorRec = 'Edge defects reported for RDS ':RDSNo:'.' Database_Services('WriteDataRow', 'REACTOR', RDSNo, ReactorRec) Def = "" Def = "Creating NCR...Please wait" Def = "U" MsgUp = Msg(@window, Def) ;* display the processing message WOMatKey = WONo:'*':CassNo ncrParms = WONo:@RM ncrParms := WOStepNo:@RM ncrParms := CassNo:@RM ncrParms := RDSNo:@RM ncrParms := Reactor:@RM ncrParms := '':@RM ;* Stage ncrParms := '':@RM ;* InCassNos ncrParms := SlotNos:@RM ;* InSlotNos ncrParms := '':@RM ;* EPP only - PockeNots ncrParms := '':@RM ;* EPP only - Zones ncrParms := '':@RM ;* EPP only - OutCassNos ncrParms := '':@RM ;* EPP only - OutSlotNos ncrParms := '':@RM ;* EPP only - Multiple RDSNos ncrParms := WfrIDs:@RM ;* Rejected Wafer ID's ncrParms := PrevNCRs:@RM ;* Previous NCR Nos ncrParms := '':@RM ;* EPP only - MU WONos ncrParms := '':@RM ;* EPP only - MU WO Step Nos ncrParms := '':@RM ;* EPP only - MU Cass Nos ncrParms := '':@RM ;* EPP only - MU Slot Nos ncrParms := 'C':@RM ;* Loss By ncrParms := 'Wafers removed due to edge defects':@RM ;* Containment Actions ncrParms := 'Edge defects discovered during post-epi inspection':@RM ;* Loss Comments ncrParms := '':@RM ;* AC Comments ncrParms := '':@RM ;* Department Responsible ncrParms := '':@RM ;* AC Code ncrParms := 'D63':@RM ;* Loss Code ncrParms := 'O':@RM ;* NCR Status - Open ncrParms := '':@RM ;* Shift ncrParms := '':@RM ;* Shipment Signature ncrParms := '':@RM ;* Reject Signature ncrParms := '':@RM ;* Sent to SPC Datetime ncrParms := '':@RM ;* Shipment Signature Datetime ncrParms := 'Production' ;* Department Handled Set_Status(0) NCRNo = obj_NCR('Create',ncrParms) ;* Create new NCR for this wafer/group of wafers Msg(@window, MsgUp) ;* take down the processing message SAPBatchNo = Xlate('WO_MAT', WOMatKey, 'SAP_BATCH_NO', 'X') IF Not(Get_Status(errCode)) THEN IF SAPBatchNo NE '' THEN IF SAPBatchNo[-1,1] NE 'R' THEN MUFlag = Xlate('NCR', NCRNo, 'MAKEUP_BOX', 'X') MUFlag = OCONV(MUFlag ,'BYes,') PartNoID = Xlate('NCR', NCRNo, 'WO_MAT_PART_NO', 'X') RejCnt = Xlate('NCR', NCRNo, 'REJ_CNT', 'X') Recipients = XLATE('NOTIFICATION', 'NCR_AFTER_GR', NOTIFICATION_USER_ID$, 'X') SentFrom = @USER4 Subject = 'SAP Post - GR Scrap Qty - NCR Reported' ;* Modified subject line - dkk 7/17/14 Message = "NCR: ":NCRNo:CRLF$:"Batch_No: ":SAPBatchNo:CRLF$:"MU Box: ":MUFlag:CRLF$:"Epi PN: ":PartNoID:CRLF$:"Qty: ":RejCnt ;* Added Epi PN on the end - dkk 7/17/14 AttachWindow = 'NCR' AttachKey = NCRNo SendToGroup = '' Parms = Recipients:@RM:SentFrom:@RM:Subject:@RM:Message:@RM:AttachWindow:@RM:AttachKey:@RM:SendToGroup obj_Notes('Create',Parms) END END RejDTM = OCONV(Date(),'D4/'):' ':OCONV(Time(),'MTS') sCnt = COUNT(SlotNos,@VM) + (SlotNos NE '') FOR N = 1 TO sCnt * * * * Added 3/23/2016 JCH - wafer history * * * * RejWfrID = WfrIDs<1,N> CurrSlotID = WONo:'*':CassNo:'*':SlotNos<1,N> Convert '.' To '*' In RejWfrID Parms = RejWfrID:@RM ;* WfrID Parms := RejDTM:@RM ;* EventDtm Parms := @USER4:@RM ;* EventBy Parms := 'NCR':@RM ;* Event Parms := '':@RM ;* NewSlotID Parms := '':@RM ;* RunLoc Parms := NCRNo:@RM ;* NCRNo Parms := '':@RM ;* TWUse Parms := CurrSlotID:@RM ;* CurrSlotID Parms := '':@RM ;* NewToolID Parms := '':@RM ;* CurrToolID Parms := '':@RM ;* NewInvLoc Parms := '':@RM ;* CurrInvLoc Parms := 'O' ;* Wfr Side obj_WO_Wfr('AddEvent',Parms) * * * * * * * * * LineNo = SlotNos<1,N> NEXT N // Display the new NCR so the user can fill in the details and sign it off. Dialog_Box('NCR', @Window, NCRNo) end else // Bail to force user to contact FI to correct issue. ErrMsg('Error creating NCR. Error message: ':ErrCode:'. Please contact FI for assistance.') return end end else // User cancelled the hold operation. ErrMsg('The lot must be placed on hold. Signature operation cancelled.') return end end else // Bail to force user to contact FI to correct issue. ErrMsg('Error placing lot on hold. Error message: ':ErrCode:'. Please contact FI for assistance.') return end end else // Inform user ineligible wafer(s) were selected and loop to try again. Swap @VM with ',' in IneligibleSlots ErrMsg('Selected slot(s) ' : IneligibleSlots : ' are not eligible for NCR.') end Until Not(ErrFlag) Repeat end else // EpiPro WMOKey = WONo:'*':WOStepNo:'*':CassNo // Loop until user selects at least one eligible wafer to NCR. Loop ErrFlag = False$ // Prompt user to select affected wafers. SelRows = '' Response = Dialog_Box('DBW_WM_OUT_WAFER_SELECT', @Window, WMOKey) If Response EQ 'Cancel' then ErrMsg('Signature operation aborted.') return end SelRowData = SRP_Array('Rotate', Response, @FM, @VM) NCROutSlotNos = SelRowData NCROutCassNos = Str(CassNo:@VM, DCount(NCROutSlotNos, @VM)) NCROutCassNos[-1 ,1] = '' NCRRDSNos = SelRowData NCRPocketNos = SelRowData NCRZones = SelRowData NCRInCassNos = SelRowData NCRInSlotNos = SelRowData NCRSlotNCRs = SelRowData NCRMUWONos = SelRowData NCRMUWOSteps = SelRowData NCRMUCassIDs = SelRowData NCRMUSlotNos = SelRowData UsedMUCassIDs = SelRowData ErrFlag = False$ For each SelSlot in NCROutSlotNos using @VM setting vPos IF UsedMUCassIDs<0, vPos> = '' THEN IF NCRRDSNos<0, vPos> NE '' THEN IF NCRSlotNCRs<0, vPos> = '' OR NCRMUWONos<0, vPos> NE '' THEN Null END ELSE ErrMsg('Slot ':SelSlot:' is empty.') ErrFlag = True$ END ;* End of check for no Slot NCR (original wafer being rejected) or MU wafer data (makeup wafer being rejected) END ELSE ErrMsg('Slot ':SelSlot:' is not used.') ErrFlag = True$ END ;* End of check for RDS (wafer) present and not used for makeup END ELSE ErrMsg('Slot ':SelSlot:' has been used for makeup.') ErrFlag = True$ END ;* End of check for slot Used for Makeup Wafer Until ErrFlag Next SelSlot // Create an NCR with edge defects loss code If Not(ErrFlag) then // Place the lot on hold if it isn't already on hold. HoldEntity = 'WM_OUT' HoldEntityID = WMOKey Set_Status(0) OnHold = Xlate('WO_MAT', WOMatKey, 'HOLD', 'X') * If Not(OnHold) then obj_WO_Mat('ToggleHold',WOMatKey:@RM:HoldEntity:@RM:HoldEntityID:@RM:'') If Not(OnHold) then Hold_Services('ToggleHold', WOMatKey, HoldEntity, HoldEntityID, '', '', '', '') ErrCode = '' If Not(Get_Status(ErrCode)) then // Ensure the user didn't cancel the hold operation. OnHold = Xlate('WM_OUT', WMOKey, 'HOLD', 'X') If OnHold then // Set ROTR block on reactor ROTRReactNos = SRP_Array('Clean', NCRRDSNos, 'TrimAndMakeUnique', @VM) If ROTRReactNos NE '' then For each ROTRReactNo in ROTRReactNos using @VM Reactor = Xlate('RDS', ROTRReactNo, 'REACTOR', 'X') ReactorRec = Database_Services('ReadDataRow', 'REACTOR', Reactor) ReactorRec = 'F' ReactorRec = 'Edge defects reported for outbound cassette ':WMOKey:'.' Database_Services('WriteDataRow', 'REACTOR', Reactor, ReactorRec) Next ROTRReactNo end Def = "" Def = "Creating NCR...Please wait" Def = "U" MsgUp = Msg(@window, Def) ;* display the processing message ncrParms = WONo:@RM ncrParms := WOStep:@RM ncrParms := CassNo:@RM ncrParms := '':@RM ;* Single RDS field - N/A for EpiPro ncrParms := '':@RM ;* Reactor No - N/A for EpiPro ncrParms := 'POST':@RM ncrParms := NCRInCassNos:@RM ncrParms := NCRInSlotNos:@RM ncrParms := NCRPocketNos:@RM ncrParms := NCRZones:@RM ncrParms := NCROutCassNos:@RM ncrParms := NCROutSlotNos:@RM ncrParms := NCRRDSNos:@RM ncrParms := '':@RM ;* Placeholder for RejWaferIDS - N/A for EpiPro ncrParms := NCRSlotNCRs:@RM ncrParms := NCRMUWONos:@RM ncrParms := NCRMUWOSteps:@RM ncrParms := NCRMUCassIDs:@RM ncrParms := NCRMUSlotNos:@RM ncrParms := 'C':@RM ;* Loss By ncrParms := 'Wafers removed due to edge defects':@RM ;* Containment Actions ncrParms := 'Edge defects discovered during post-epi inspection':@RM ;* Loss Comments ncrParms := '':@RM ;* AC Comments ncrParms := '':@RM ;* Department Responsible ncrParms := '':@RM ;* AC Code ncrParms := 'D63':@RM ;* Loss Code ncrParms := 'O':@RM ;* NCR Status - Open ncrParms := '':@RM ;* Shift ncrParms := '':@RM ;* Shipment Signature ncrParms := '':@RM ;* Reject Signature ncrParms := '':@RM ;* Sent to SPC Datetime ncrParms := '':@RM ;* Shipment Signature Datetime ncrParms := 'Production' ;* Department Handled Set_Status(0) NCRNo = obj_NCR('Create',ncrParms) ;* Create new NCR for this wafer/group of wafers Msg(@window, MsgUp) ;* take down the processing message ErrCode = '' If Not(Get_Status(ErrCode)) then WMORec = Database_Services('ReadDataRow', 'WM_OUT', WMOKey) RejDTM = OCONV(Date(),'D4/'):' ':OCONV(Time(),'MTS') RejWfrIDs = '' FOR N = 1 TO COUNT(NCROutSlotNos,@VM) + (NCROutSlotNos NE '') * * * * Added 4/23/2016 JCH - wafer history * * * * CurrSlotID = WONo:'*':NCROutCassNos<1,N>:'*':NCROutSlotNos<1,N> IF NCRMUWONos<1,N> = '' THEN RejWfrID = WONo:'*':NCRInCassNos<1,N>:'*':NCRInSlotNos<1,N> END ELSE RejWfrID = NCRMUWONos<1,N>:'*':NCRMUCassIDs<1,N>:'*':NCRMUSlotNos<1,N> END RejWfrIDs<1,-1> = RejWfrID Parms = RejWfrID:@RM ;* WfrID Parms := RejDTM:@RM ;* EventDtm Parms := @USER4:@RM ;* EventBy Parms := 'NCR':@RM ;* Event Parms := '':@RM ;* NewSlotID Parms := '':@RM ;* RunLoc Parms := NCRNo:@RM ;* NCRNo Parms := '':@RM ;* TWUse Parms := CurrSlotID:@RM ;* CurrSlotID Parms := '':@RM ;* NewToolID Parms := '':@RM ;* CurrToolID Parms := '':@RM ;* NewInvLoc Parms := '':@RM ;* CurrInvLoc Parms := 'O' ;* Wfr Side obj_WO_Wfr('AddEvent',Parms) // Add NCR details to WM_OUT record SlotNo = NCROutSlotNos<1,N> WMORec = '' WMORec = '' WMORec = '' WMORec = '' WMORec = '' WMORec = NCRNo WMORec = '' WMORec = '' WMORec = '' WMORec = '' NEXT N Database_Services('WriteDataRow', 'WM_OUT', WMOKey, WMORec) Dialog_Box('NCR', @Window, NCRNo) end else // Bail to force user to contact FI to correct issue. ErrMsg('Error creating NCR. Error message: ':ErrCode:'. Please contact FI for assistance.') return end end else // User cancelled the hold operation. ErrMsg('The lot must be placed on hold. Signature operation cancelled.') return end end else // Bail to force user to contact FI to correct issue. ErrMsg('Error placing lot on hold. Error message: ':ErrCode:'. Please contact FI for assistance.') return end end Until Not(ErrFlag) Repeat end end end IF MemberOf(@USER4, 'OI_SUPERUSER') THEN Valid = 1 END ELSE Valid = Dialog_Box( 'QUOTE_SIG_PWD_ENTRY', @WINDOW, @USER4:@VM:XLATE( 'LSL_USERS', @USER4, LSL_USERS_PASSWORD$, 'X' ) ) END IF Valid = 1 THEN Def = "" Def = "Updating material log and saving clean && inspection record..." Def = "U" MsgUp = Msg(@window, Def) ;* display the processing message CurrDate = OCONV(Date(),'D4/') CurrTime = OCONV(Time(),'MTHS') CurrDTM = CurrDate:' ':CurrTime Signer = @USER4 ToolID = CtrlList If ToolID EQ 'SCOPE' or ToolID EQ 'SCOPE/FF EDGE INSP' then ToolWHCd = 'CR' ToolLoc = 'QA' end else ToolRec = XLATE('TOOL',ToolID,'','X') ToolWHCd = ToolRec ToolLoc = ToolRec end Tag = '' IF CassNo NE '' THEN owmParms = WONo:@RM:CassNo:@RM:WOStep:@RM:SigStage:@RM:Signer:@RM:CurrDTM:@RM:ToolID:@RM:ToolWHCd:@RM:ToolLoc:@RM:Tag ;* Sets PSTI signature IF Get_Status(errCode) THEN CALL ErrMsg(ErrCode) RETURN 0 END LogFile = 'WO_MAT' ; WOMLParms = LogFile:@RM LogDTM = CurrDTM ; WOMLParms := LogDTM:@RM Action = SigAction ; WOMLParms := Action:@RM WhCd = ToolWHCd ; WOMLParms := WhCd:@RM LocCd = ToolLoc ; WOMLParms := LocCd:@RM WONos = WONo ; WOMLParms := WONos:@RM CassNos = CassNo ; WOMLParms := CassNos:@RM UserID = @USER4 ; WOMLParms := UserID:@RM Tags = '' ; WOMLParms := Tags:@RM ToolID = ToolID ; WOMLParms := ToolID obj_WO_Mat_Log('Create',WOMLParms) ;* Add WOStep:'PSTI' to WO_MAT Event Log IF Get_Status(errCode) THEN ErrMsg(errCode) END END ;* End of check for null Cass No (EpiPro Reactor runs) Set_Property(CtrlID,'CELLPOS',Signer,COL$INSP_SIG:@FM:SelectedRow) Set_Property(CtrlID,'CELLPOS',CurrDTM,COL$INSP_SIG_DTM:@FM:SelectedRow) CINo = Get_Property(@WINDOW:'.CI_NO','DEFPROP') Set_Property(@WINDOW,'@DONT_CLOSE',1) Send_Event(@WINDOW,'WRITE') Msg(@window, MsgUp) ;* take down the processing message obj_AppWindow('LUValReturn',CINo:@RM:@WINDOW:'.CI_NO') END END ELSE IF SigRow = '' THEN ErrMsg('Process Error':@SVM:'Must have some information in selected row to sign.') RETURN END IF CtrlList NE '' THEN ErrMsg('Process Error':@SVM:'Row is already signed.') RETURN END END RETURN * * * * * * * SignScan: * * * * * * * CtrlID = @WINDOW:'.SCAN_RESULTS' CtrlList = Get_Property(CtrlID,'LIST') SlotSelection = Get_Property(CtrlID,'SELPOS') SelectedRows = SlotSelection<2> SlotSelection = Get_Property(CtrlID,'SELPOS') SelectedRow = SlotSelection<2> SigRow = CtrlList IF SigRow<1,COL$SCAN_TOOL> = '' THEN ErrMsg('Process Error':@SVM:'Scan Tool column is required.') Set_Property(CtrlID,'SELPOS',COL$SCAN_TOOL:@FM:SelectedRow) RETURN END CONVERT @VM TO '' IN SigRow *** Ctrls = @WINDOW:'.WO_NO':@RM ; Props = 'DEFPROP':@RM Ctrls := @WINDOW:'.WO_STEP':@RM ; Props := 'DEFPROP':@RM Ctrls := @WINDOW:'.CASS_NO':@RM ; Props := 'DEFPROP':@RM Ctrls := @WINDOW:'.STAGE':@RM ; Props := 'DEFPROP':@RM Ctrls := @WINDOW:'.RDS_NO' ; Props := 'DEFPROP' Vals = Get_Property(Ctrls,Props) WONo = Vals[1,@RM] WOStep = Vals[COL2()+1,@RM] CassNo = Vals[COL2()+1,@RM] Stage = Vals[COL2()+1,@RM] RDSNo = Vals[COL2()+1,@RM] WOLogRow = Database_Services('ReadDataRow', 'WO_LOG', WONo) ReactType = WOLogRow IF Stage = 'POST' THEN IF RDSNo = '' THEN * Epi Pro wafers SigAction = WOStep:'MO_PSTS' SigStage = 'MO_PSTS' END ELSE SigAction = WOStep:'PSTS' SigStage = 'PSTS' END END ELSE SigAction = WOStep:Stage:'S' SigStage = Stage:'S' END IF SigRow NE '' AND CtrlList = '' AND CtrlList = '' THEN If SelectedRow EQ 1 then WOMatKey = WONo:'*':CassNo Signature_Services('CheckSigOrder', WOMatKey, SigStage, False$, RDSNo) If Error_Services('HasError') then ErrMsg(Error_Services('GetMessage')) return end end // Add check for supplement signatures ValidStages = Supplement_Services('GetStagesForLot', 'RDS', RDSNo) If Count(ValidStages, SigStage) NE 0 then UnacknowledgedSupp = Supplement_Services('UnacknowledgedSupplementCheck', 'RDS', RDSNo, SigStage) If UnacknowledgedSupp NE FALSE$ then Response = Dialog_Box('NDW_RDS_SUPP_SIG', @Window, RDSNo :@FM: SigStage :@FM: FALSE$) If Response EQ False$ then return end End // This checks to see if manually entered data is authorized to be signed. IF (SigRow NE '') AND (CtrlList = '') AND (Stage NE 'POST') THEN Authorized = MemberOf(@USER4, 'ENGINEERING') OR MemberOf(@USER4, 'LEAD') OR MemberOf(@USER4, 'SUPERVISOR') OR MemberOf(@USER4, 'ROTR_OVERRIDE') If Not(Authorized) then ErrorText = 'Only Leads, Supervisors or Engineers can sign ROTR Tencor data manually entered.' ErrMsg('Process Error':@SVM:ErrorText) Return end end IF MemberOf(@USER4, 'OI_SUPERUSER') THEN Valid = 1 END ELSE Valid = Dialog_Box( 'QUOTE_SIG_PWD_ENTRY', @WINDOW, @USER4:@VM:XLATE( 'LSL_USERS', @USER4, LSL_USERS_PASSWORD$, 'X' ) ) END IF Valid = 1 THEN CurrDate = OCONV(Date(),'D4/') CurrTime = OCONV(Time(),'MTHS') CurrDTM = CurrDate:' ':CurrTime Signer = @USER4 ToolID = CtrlList ToolRec = XLATE('TOOL',ToolID,'','X') ToolWHCd = ToolRec ToolLoc = ToolRec Tag = '' // Only call if this is non-EpiPro. - 04/09/2018 - dmb If ReactType NE 'EPP' then owmParms = WONo:@RM:CassNo:@RM:WOStep:@RM:SigStage:@RM:Signer:@RM:CurrDTM:@RM:ToolID:@RM:ToolWHCd:@RM:ToolLoc:@RM:Tag ;* Sets PSTI signature IF Get_Status(errCode) THEN CALL ErrMsg(ErrCode) RETURN 0 END LogFile = 'WO_MAT' ; WOMLParms = LogFile:@RM LogDTM = CurrDTM ; WOMLParms := LogDTM:@RM Action = SigAction ; WOMLParms := Action:@RM WhCd = ToolWHCd ; WOMLParms := WhCd:@RM LocCd = ToolLoc ; WOMLParms := LocCd:@RM WONos = WONo ; WOMLParms := WONos:@RM CassNos = CassNo ; WOMLParms := CassNos:@RM UserID = @USER4 ; WOMLParms := UserID:@RM Tags = '' ; WOMLParms := Tags:@RM ToolID = ToolID ; WOMLParms := ToolID obj_WO_Mat_Log('Create',WOMLParms) ;* Sets PSTI in WO_MAT Event Log IF Get_Status(errCode) THEN ErrMsg(errCode) END end Set_Property(CtrlID,'CELLPOS',Signer,COL$SCAN_SIG:@FM:SelectedRow) Set_Property(CtrlID,'CELLPOS',CurrDTM,COL$SCAN_SIG_DTM:@FM:SelectedRow) CINo = Get_Property(@WINDOW:'.CI_NO','DEFPROP') Set_Property(@WINDOW,'@DONT_CLOSE',1) Send_Event(@WINDOW,'WRITE') obj_AppWindow('LUValReturn',CINo:@RM:@WINDOW:'.CI_NO') END END ELSE IF SigRow = '' THEN ErrMsg('Process Error':@SVM:'Must have some information in selected row to sign.') RETURN END IF CtrlList NE '' OR CtrlList NE '' THEN ErrMsg('Process Error':@SVM:'Row is already signed.') RETURN END END RETURN SIGN_ROTR_ACCEPTANCE.CLICK: Valid = Dialog_Box( 'QUOTE_SIG_PWD_ENTRY', @WINDOW, @USER4:@VM:XLATE( 'LSL_USERS', @USER4, LSL_USERS_PASSWORD$, 'X' ) ) If Valid EQ True$ then OrigReason = Get_Property(@Window : '.SIGN_ROTR_REASON', 'DEFPROP') Reason = Msg(@Window, '', 'MESSAGE_INPUT', '', 'ROTR Acceptance' : @FM : 'ROTR Acceptance Reason' : @FM : OrigReason) If Reason NE '' then Set_Property(@Window : '.SIGN_ROTR_SIGNATURE', 'INVALUE', @USER4) Set_Property(@Window : '.SIGN_ROTR_DATE_TIME', 'DEFPROP', Oconv(Date(), 'D4/') : ' ' : Oconv(Time(), 'MTHS')) Set_Property(@Window : '.SIGN_ROTR_REASON', 'DEFPROP', Reason) Send_Event(@Window : '.SIGN_ROTR_SIGNATURE_NAME', 'CALCULATE') end end return SCAN_RESULTS.CHAR: Stage = Get_Property(@Window : '.STAGE', 'TEXT') If Stage EQ 'LWI' then CtrlEntID = 'SCAN_RESULTS' CIKey = Get_Property(@Window : '.CI_NO', 'TEXT') ReactorNo = Xlate('CLEAN_INSP', CIKey, 'REACT_NO', 'X') CanEdit = Get_Property(@Window, '@CAN_EDIT') If Not(CanEdit) then PrevFocusID = Get_Property (@Window, "PREVFOCUS") Message = 'Only a member of lead, supervisor, final_qa,':@SVM:'engineering, or rotr_override can manually enter data.' Response = Msg(@Window, '', 'OVERRIDE', '', Message) Begin Case Case Response EQ 1 Response = True$ ; // User Clicked Override Case Response EQ 2 Response = False$ ; // User Clicked Cancel Case Response EQ char(27) Response = False$ ; // User Pressed Escape Key End Case If Response EQ True$ then OverrideGroups = 'LEAD' : @VM : 'SUPERVISOR' : @VM : 'ENGINEERING' :@VM: 'FINAL_QA' :@VM: 'ROTR_OVERRIDE' Response = Dialog_Box('NDW_VERIFY_USER', @WINDOW, @USER4 : @FM : OverrideGroups) Valid = Response<1> Username = Response<2> If NOT(Valid) then Set_Property(@Window, 'FOCUS', PrevFocusID) Set_Property(CtrlEntID, 'SELPOS', -1:@FM:-1) end else Set_Property(@Window, '@CAN_EDIT', True$) CanEdit = True$ end end else Set_Property(@Window, 'FOCUS', PrevFocusID) Set_Property(CtrlEntID, 'SELPOS', -1:@FM:-1) end end If (CanEdit EQ True$) then // Enable manual entry of data. ScanStyles = Send_Message(@Window : '.SCAN_RESULTS', 'COLSTYLE', 0, '') For column = 1 to 7 ScanStyles = BitAnd( ScanStyles, BitNot(PROTECTED$) ) Next column // Enable dropdown menus for recipe and tool columns. ScanStyles = BitOr(ScanStyles, DTCS_DROPDOWN$ ) ScanStyles = BitOr(ScanStyles, DTCS_DROPDOWN$ ) ScanStyles = Send_Message(@Window : '.SCAN_RESULTS', 'COLSTYLE', 0, ScanStyles) end end ****************Logging Manual Data Entry******************** TableContents = Get_Property(@Window:'.SCAN_RESULTS', 'ARRAY') ToolID = TableContents IF ToolID NE '' then Date = SRP_DateTime('Now') EpochStart = 00732 EpochTime = SRP_DateTime('SecondSpan',EpochStart, Date) RDSNo = Get_Property(@Window:'.RDS_NO', 'DEFPROP') PSNo = Get_Property(@Window:'.PS_NO', 'DEFPROP') User = @User4 Description = 'Manual SurfScan Data Entry detected for RDS #: ':RDSNo Reactor = XLATE('RDS', RDSNo, 2, 'X') FileName = Environment_Services('GetApplicationRootPath'): '\LogFiles\ManualDataEntry\PollPath\' : EpochTime :'.json' OSWrite '' to FileName JSON = '{"Equipment":"':ToolID:'", "Reactor":"':Reactor:'", "PSN":"':PSNo:'", "RDS":"':RDSNo:'", "User": "':User:'", "Description":"':Description:'"}' OSWrite JSON to FileName end return SCAN_RESULTS.POSCHANGED: ScanCtrl = @Window : '.SCAN_RESULTS' ScanCtrlList = Get_Property(ScanCtrl, 'LIST') SelPos = Get_Property(ScanCtrl, 'SELPOS') RowPos = SelPos<2> TestDTM = ScanCtrlList If TestDTM EQ '' then Set_Property(@Window:'.BTN_WAFER_DETAILS', 'ENABLED', False$) end else Set_Property(@Window:'.BTN_WAFER_DETAILS', 'ENABLED', True$) end return BTN_WAFER_DETAILS.CLICK: PrevCursor = Set_Property('SYSTEM', 'CURSOR', 'H') Yield() CleanInspKey = Get_Property(@Window : '.CI_NO', 'TEXT') SelPos = Get_Property(@Window : '.SCAN_RESULTS', 'SELPOS') RowPos = SelPos<2> If RowPos EQ '' then RowPos = 1 CreateParam = CleanInspKey : @FM : RowPos WindowName = Create_Dialog('NDW_ROTR_WAFER_DETAILS', @Window, True$, CreateParam) PrevCursor = Set_Property('SYSTEM', 'CURSOR', PrevCursor) return * * * * * * * RefreshSpec: * * * * * * * CINo = Get_Property(@WINDOW:'.CI_NO','TEXT') PSStageKey = Get_Property(@WINDOW:'.PS_STAGE_KEY','TEXT') IF CINo NE '' AND PSStageKey NE '' THEN Send_Event(@WINDOW,'WRITE') obj_Clean_Insp('SpecDelta',CINo:@RM:PSStageKey) IF Get_Status(errCode) THEN ErrMsg(errCode) END obj_Appwindow('LUValReturn',CINo:@RM:@WINDOW:'.CI_NO') END RETURN * * * * * * * InspPC: * * * * * * * CurrInspPos = Get_Property(@WINDOW:'.INSP_RESULTS','SELPOS') CurrBSInspPos = Get_Property(@WINDOW:'.INSP_RESULTS_BSIDE','SELPOS') CurrInspCol = CurrInspPos<1> CurrInspRow = CurrInspPos<2> CurrBSInspCol = CurrBSInspPos<1> CurrBSInspRow = CurrBSInspPos<2> Set_Property(@WINDOW:'.INSP_RESULTS_BSIDE','SELPOS',CurrBSInspCol:@FM:CurrInspRow) GOSUB Refresh RETURN * * * * * * * BSideInspPC: * * * * * * * CurrInspPos = Get_Property(@WINDOW:'.INSP_RESULTS','SELPOS') CurrBSInspPos = Get_Property(@WINDOW:'.INSP_RESULTS_BSIDE','SELPOS') CurrInspCol = CurrInspPos<1> CurrInspRow = CurrInspPos<2> CurrBSInspCol = CurrBSInspPos<1> CurrBSInspRow = CurrBSInspPos<2> Set_Property(@WINDOW:'.INSP_RESULTS','SELPOS',CurrInspCol:@FM:CurrBSInspRow) GOSUB Refresh RETURN * * * * * * * SendSPC: * * * * * * * Ctrls = @WINDOW:'.RDS_NO':@RM ; Props = 'DEFPROP':@RM Ctrls := @WINDOW:'.STAGE':@RM ; Props := 'DEFPROP':@RM Ctrls := @WINDOW:'.SS_SCAN_TOOL':@RM ; Props := 'DEFPROP':@RM Ctrls := @WINDOW:'.SUM_OF_DEF_MIN':@RM ; Props := 'DEFPROP':@RM Ctrls := @WINDOW:'.SUM_OF_DEF_MAX':@RM ; Props := 'DEFPROP':@RM Ctrls := @WINDOW:'.SUM_OF_DEF_AVG':@RM ; Props := 'DEFPROP':@RM Ctrls := @WINDOW:'.HAZE_AVG_AVG':@RM ; Props := 'DEFPROP':@RM Ctrls := @WINDOW:'.SPOTS':@RM ; Props := 'DEFPROP':@RM Ctrls := @WINDOW:'.FOV':@RM ; Props := 'DEFPROP':@RM Ctrls := @WINDOW:'.SCRATCHES':@RM ; Props := 'DEFPROP':@RM Ctrls := @WINDOW:'.SCRATCH_LEN':@RM ; Props := 'DEFPROP':@RM Ctrls := @WINDOW:'.REACT_NO':@RM ; Props := 'DEFPROP':@RM Ctrls := @WINDOW:'.WAFER_SIZE':@RM ; Props := 'DEFPROP':@RM Ctrls := @WINDOW:'.SS_SCRATCH_MAX':@RM ; Props := 'DEFPROP':@RM Ctrls := @WINDOW:'.SS_SCRATCH_AVG' ; Props := 'DEFPROP' Vals = Get_Property(Ctrls,Props) RDSNo = Vals[1,@RM] Stage = Vals[COL2()+1,@RM] ScanTool = Vals[COL2()+1,@RM] SumOfDefMin = Vals[COL2()+1,@RM] SumOfDefMax = Vals[COL2()+1,@RM] SumOfDefAvg = Vals[COL2()+1,@RM] HazeAvgAvg = Vals[COL2()+1,@RM] Spots = Vals[COL2()+1,@RM] FOV = Vals[COL2()+1,@RM] Scratches = Vals[COL2()+1,@RM] ScratchLen = Vals[COL2()+1,@RM] ReactNo = Vals[COL2()+1,@RM] WaferSize = Vals[COL2()+1,@RM] SSScratchMax = Vals[COL2()+1,@RM] SSScratchAvg = Vals[COL2()+1,@RM] WaferSize = WaferSize[1,' '] ;* Data looks like "125 mm 6 in" UserName = OCONV(@USER4,'[XLATE_CONV,LSL_USERS*FIRST_LAST]') DataLine = QUOTE(ReactNo):TAB$ DataLine := QUOTE(RDSNo):TAB$ DataLine := QUOTE(Stage):TAB$ DataLine := QUOTE(ScanTool):TAB$ DataLine := QUOTE(SumOfDefMin):TAB$ DataLine := QUOTE(SumOfDefMax):TAB$ DataLine := QUOTE(SumOfDefAvg):TAB$ DataLine := QUOTE(HazeAvgAvg):TAB$ DataLine := QUOTE(Spots):TAB$ DataLine := QUOTE(FOV):TAB$ DataLine := QUOTE(Scratches):TAB$ DataLine := QUOTE(ScratchLen):TAB$ DataLine := QUOTE(UserName):TAB$ DataLine := QUOTE(SSScratchAvg):TAB$ DataLine := QUOTE(SSScratchMax):TAB$ DataLine := QUOTE(WaferSize) DOSFile = Environment_Services('GetSPCDataPath') : '\SPC_Surf.txt' * * * * * * * DosRead: * * * * * * * // SPC Server has been migrated to the EC domain. SPC Queue must be utilized to transfer SPC files. Filename = 'SPC_Surf.txt' SPCQueueKey = Date():'*':Time():'*':@USER4 SPCQueueRec = '' SPCQueueRec = Filename SPCQueueRec = DataLine:CRLF$ Database_Services('WriteDataRow', 'SPC_QUEUE', SPCQueueKey, SPCQueueRec, True$, False$, False$) CurrDTM = OCONV(Date(),'D4/'):' ':OCONV(Time(),'MTS') Set_Property(@WINDOW:'.SPC_DTM','DEFPROP',CurrDTM) RETURN * * * * * * * SetGroupBackground: * * * * * * *