Compile function REACT_RUN_EVENTS(CtrlEntId, Event, @PARAMS) /*********************************************************************************************************************** Name : React_Run_Events Description : Commuter module for the REACT_RUN form. Notes : Application errors should be logged using the Error Services module. There are a few methodological assumptions built into way errors are managed which are important to understand in order to properly work with Error Services: - The term 'top' refers to the originating procedure of a call stack and the term 'bottom' refers to the last routine (or the current routine) within a call stack. Within the OpenInsight Debugger this will appear backwards since the originating procedure always appears at the bottom of the list and the current routine appears at the top of the list. We are using this orientation because it is common to refer to the process of calling other procedures as 'drilling down'. - The reason for defining the orientation of the call stack is because Error_Services allows for multiple error conditions to be appended to an original error. In most cases this will happen when a procedure at the bottom of the stack generates an error condition and then returns to its calling procedure. This higher level procedure can optionally add more information relevant to itself. This continues as the call stack 'bubbles' its way back to the top to where the originating procedure is waiting. - Native OpenInsight commands that handle errors (e.g., Set_Status, Set_FSError, Set_EventStatus) preserve their error state until explicitly cleared. This can hinder the normal execution of code since subsequent procedures (usually SSPs) will fail if a pre-existing error condition exists. Our philosophy is that error conditions should automatically be cleared before a new procedure is executed to avoid this problem. However, the nature of Basic+ does not make this easy to automate for any given stored procedure. Therefore, if a stored procedure wants to conform to our philosophy then it should include a call into the 'Clear' service request at the top of the program. Alternatively this can be done through a common insert (see SERVICE_SETUP for example.) - Service modules will use the SERVICE_SETUP insert and therefore automatically clear out any error conditions that were set before. Parameters : Service [in] -- Name of the service being requested Param1-10 [in/out] -- Additional request parameter holders Response [out] -- Response to be sent back to the Controller (MCP) or requesting procedure Metadata : History : (Date, Initials, Notes) 01/11/19 djs Original programmer. 07/12/19 fr Updated FillDispEditTable subroutine to not allow "Internal" wafers to be NCR'd. 07/23/19 djs Updated the UpdateDispData routine to only look for 06/06/20 djs Cutover to CR-004 and CR-005 ***********************************************************************************************************************/ #pragma precomp SRP_PreCompiler #window REACT_RUN DECLARE SUBROUTINE Set_Property, End_Dialog, Send_Event, Set_Status, Center_Window, Post_Event, SRP_EditTable_Manager DECLARE SUBROUTINE ErrMsg, Send_Message, Set_Property, Send_Event, Btree.Extract, obj_AppWindow, SRP_Show_Window DECLARE SUBROUTINE obj_Notes, Security_Err_Msg, End_Window, Forward_Event, Start_Window, Create_Note, Excel_Services DECLARE SUBROUTINE obj_RDS_Test, Print_Control_Plan, Print_RDS_Instruction, Send_Info, Post_Event, Database_Services DECLARE SUBROUTINE obj_Run_Stage_Wfr, obj_WO_Wfr, obj_Run_Stage, GaN_Services, Utility, SRP_Stopwatch, COMM_NCR DECLARE SUBROUTINE Dialog_Box, Get_Status, Logging_Services, Messaging_Services, SRP_Array, Error_Services DECLARE SUBROUTINE Disposition_Services, Engineering_Services, Reactor_Services DECLARE FUNCTION Get_Property, Get_Status, Dialog_Box, Utility, Center_Window, Popup, Collect.Ixvals, Security_Services DECLARE FUNCTION Send_Message, Msg, Security_Check, RowExists, NextKey, obj_React_Esc, obj_React_Run, Form_Services DECLARE FUNCTION obj_RDS_Test, MemberOf, Create_Dialog, obj_Popup, obj_WO_Wfr, SRP_EditTable_Manager, Database_Services DECLARE FUNCTION Obj_Run_Stage, Obj_Run_Stage_Wfr, Gan_Services, SRP_Array, DateTime, Error_Services, Obj_NCR DECLARE FUNCTION Memory_Services, SRP_Get_Window_Rect, Excel_Services, Environment_Services, Logging_Services DECLARE FUNCTION SRP_Array $INSERT APPCOLORS $INSERT RTI_STYLE_EQUATES $INSERT EVENT_SETUP $INSERT MSG_EQUATES $INSERT LSL_USERS_EQU $INSERT SECURITY_RIGHTS_EQU $INSERT REACT_EVENT_EQUATES $INSERT REACT_RUN_EQUATES $INSERT WO_STEP_EQU $INSERT WO_MAT_EQUATES $INSERT WO_WFR_WIP_EQUATES $INSERT EPI_SUSCEPTOR_EQUATES $INSERT REACTOR_EQUATES $INSERT POPUP_EQUATES $INSERT TOOL_CLASS_EQUATES $INSERT RUN_STAGE_EQUATES $INSERT LOCATION_EQUATES $INSERT RUN_STAGE_WFR_EQUATES $INSERT WO_WFR_EQUATES $INSERT SRP_POPUP_EQUATES $INSERT LOGICAL $INSERT WO_LOG_EQUATES // Cassette / Wafer Action Combo Box Selections EQU COMBO_X$ TO 1 EQU COMBO_START$ TO 2 EQU COMBO_STOP$ TO 3 EQU COMBO_COMP$ TO 4 EQU COMBO_PART$ TO 5 EQU COL$LSID TO 1 EQU COL$RECIPE TO 2 EQU COL$RECIPE_NAME TO 3 EQU COL$PARAMS TO 4 EQU COL$PARMS_OUT TO 5 EQU COL$BLANK_COL TO 6 EQU COL$MET_NO TO 7 EQU COL$THICK_AVG TO 8 EQU COL$RRHO_AVG TO 9 EQU COL$MET_NO_Z1 TO 10 EQU COL$THICK_AVG_Z1 TO 11 EQU COL$RRHO_AVG_Z1 TO 12 EQU COL$MET_NO_Z2 TO 13 EQU COL$THICK_AVG_Z2 TO 14 EQU COL$RRHO_AVG_Z2 TO 15 EQU COL$MET_OUT TO 16 EQU COL$MET_OUT_Z1 TO 17 EQU COL$MET_OUT_Z2 TO 18 EQU COL$MET_TWSIG TO 19 EQU COL$MET_TWSIG_Z1 TO 20 EQU COL$MET_TWSIG_Z2 TO 21 EQU COL$CHAR_WFR_ID TO 1 EQU COL$SCRIBE TO 2 EQU COL$SPLIT_BY TO 3 EQU COL$SPLIT_DTM TO 4 EQU COL$CURR_STAGE TO 5 EQU COL$CHAR_DEST TO 6 EQU COL$CHAR_TW_NO TO 7 EQU COL$CHAR_WFR_STATUS TO 8 EQU COL$CARR_SLOG_NO TO 1 EQU COL$CARR_WFR_ID TO 2 EQU COL$CARR_SCRIBE TO 3 EQU COL$CARR_CHAR_FLAG TO 4 EQU COL$CARR_NCR TO 5 EQU COL$CARR_GRADE TO 6 EQU COL$SIG_PROF TO 1 EQU COL$SIGNATURE TO 2 EQU COL$SIG_DTM TO 3 EQU COL$STAGE_COMMENT TO 4 EQU COL$STAGE_STATUS TO 5 EQU COL$MET_STAGE TO 1 EQU COL$MET_TOOL_ID TO 2 // Disposition OLE Edit Table EQU COL$DISP_SLOT TO 1 EQU COL$DISP_WFR_ID TO 2 EQU COL$DISP_SCRIBE TO 3 EQU COL$DISP_GRADE TO 4 EQU COL$DISP_REASON TO 5 EQU COL$DISP_RDS_NCR TO 6 EQU COL$DISP_WMO_NCR TO 7 EQU COL$DISP_SHIP TO 8 EQU COL$DISP_SHIP_ID TO 9 EQU COL$DISP_INTERNAL TO 10 EQU COL$DISP_EXTERNAL TO 11 EQU COL$DISP_RETAIN TO 12 EQU COL$DISP_RETAIN_BOX TO 13 EQU COL$DISP_RETAIN_SLOT TO 14 // NCR OLE Edit Table EQU COL$NCR_NO TO 1 EQU COL$NCR_STATUS TO 2 EQU COL$NCR_REJ_QTY TO 3 EQU COL$NCR_RESP TO 4 EQU COL$NCR_STAGE TO 5 EQU COL$NCR_LOSS_DESC TO 6 EQU COL$NCR_LOSS_COMM TO 7 EQU COL$NCR_FIN_SIG TO 8 EQU COL$NCR_FIN_SIG_DTM TO 9 EQU COL$SUSC_LOAD_WFR_ID TO 6 ;* SUSC_LOAD control EQU COL$SUSC_LOAD_WFR_SCRIBE TO 7 EQU EDITABLE$ TO 4 EQU PROTECTED$ TO 8 ;* Protected - Edittable COLSTYLE constants EQU MULTILINE_STYLE$ TO 512 ;* MultiLine Select EQU LOCKED$ TO 8192 EQU DROPDOWN_STYLE$ TO 131072 LogPath = Environment_Services('GetApplicationRootPath') : '\LogFiles\GaNWIP' LogDate = Oconv(Date(), 'D4/') LogTime = Oconv(Time(), 'MTS') LogFileName = LogDate[7, 4] : '-' : LogDate[1, 2] : '-' : LogDate[4, 2] : ' GaN WIP Log.csv' Headers = 'Logging DTM' : @FM : 'RDS Key ID' : @FM : 'Username' : @FM : 'Notes' objLog = Logging_Services('NewLog', LogPath, LogFileName, CRLF$, Comma$, Headers, '', False$, False$) LoggingDTM = LogDate : ' ' : LogTime ; // Logging DTM SubclassInfo = Form_Services('FindSubclassControl') Subclass = SubclassInfo<1> // Update the arguments so that the OpenInsight OLE event will treate the ActiveX event as a native event handler. If Event EQ 'OLE' then Transfer Event to OIEvent Transfer Param1 to Event Transfer Param2 to Param1 Transfer Param3 to Param2 Transfer Param4 to Param3 Transfer Param5 to Param4 Transfer Param6 to Param5 Transfer Param7 to Param6 Transfer Param8 to Param7 end GoToEvent Event for CtrlEntId else // Event not implemented end Return EventFlow or 1 //----------------------------------------------------------------------------- // EVENT HANDLERS //----------------------------------------------------------------------------- Event WINDOW.CREATE(CreateParam) IOOptions = Get_Property(@Window, 'IOOPTIONS') IOOptions<2> = 2 ;// Do not lock the record Set_Property(@Window, 'IOOPTIONS', IOOptions) FormVisible = Get_Property(@Window, 'VISIBLE') If CreateParam NE '' then RDSNo = CreateParam WONo = Xlate('REACT_RUN', RDSNo, 'WO_NO', 'X') PSNo = Xlate('REACT_RUN', RDSNo, 'PS_NO', 'X') TechType = Xlate('PROD_SPEC', PSNo, 'TECH_TYPE', 'X') If TechType EQ 'P' then ParentWindow = Get_Property(@Window, "PARENT") Start_Window('DBW_GAN_RDS_PROD', ParentWindow, RDSNo) GoTo Abort end Set_Property(@Window, '@RDSNO', RDSNo) Def = "" Def = "Loading..." Def = "G" Def = 100 ; // 100% Def = 400 Def = -2 ;* message h-pos in pixels, or -2 (center screen, the default), -1 (center parent) Def = -2 ;* message v-pos in pixels MsgUp = Msg(@Window, Def) If FormVisible then Set_Property(@Window, 'REDRAW', False$) Set_Property(@Window:'.OLE_REACTOR_EDT' , "OLE.Redraw", False$) Set_Property(@Window:'.OLE_METROLOGY_EDT' , "OLE.Redraw", False$) Set_Property(@Window:'.OLE_DISP_EDT' , "OLE.Redraw", False$) Set_Property(@Window:'.OLE_DISP_STAGE_EDT' , "OLE.Redraw", False$) Set_Property(@Window:'.OLE_NCR_EDT' , "OLE.Redraw", False$) end RDSNo = CreateParam Set_Property(@Window : '.RDS_NO', 'TEXT', RDSNo) RunPriorities = '':@FM:'P1':@FM:'P2':@FM:'P3' Set_Property(@Window:'.COMBO_PRIORITY', 'LIST', RunPriorities) If RDSNo Not(Num(RDSNo)) then * update the gauge Msg(@Window, MsgUp, 10, MSGINSTUPDATE$) // Check if run info scribes have been updated ReactRunRec = Database_Services('ReadDataRow', 'REACT_RUN', RDSNo) InWfrIDs = ReactRunRec RunPriority = ReactRunRec Set_Property(@Window:'.COMBO_PRIORITY', 'TEXT', RunPriority) GaNRunID = ReactRunRec GrowthKey = RDSNo:'*GROWTH' GrowthRec = Database_Services('ReadDataRow', 'RUN_STAGE', GrowthKey) InvActions = GrowthRec Locate 'LOAD' in InvActions using @VM setting vPos then LoadSig = GrowthRec If LoadSig NE '' then RRScribes = Xlate('REACT_RUN', RDSNo, 'WFR_SCRIBES', 'X') GaNRunInfo = Gan_Services('GetRunInfo', GaNRunID) If Error_Services('NoError') then RunScribes = GaNRunInfo<4> If ( (RRScribes NE RunScribes) and (RunScribes NE '') ) then // Scribes have been updated in wafer track database For each WfrID in InWfrIDs using @VM setting vPos WOWfrRec = Database_Services('ReadDataRow', 'WO_WFR', WfrID) WOWfrRec = RunScribes<0, vPos> Database_Services('WriteDataRow', 'WO_WFR', WfrID, WOWfrRec) Next WfrID end end end end Send_Event(@Window, 'READ') FormVisible = Get_Property(@Window, 'VISIBLE') * update the gauge Msg(@Window, MsgUp, 20, MSGINSTUPDATE$) WONo = Get_Property(@Window:'.WO_NO', 'TEXT') If WONo EQ '' then WONo = Xlate('RDS', RDSNo, 'WO', 'X') WOLogRec = Database_Services('ReadDataRow', 'WO_LOG', WONo) SPCWaferTrackPart = WOLogRec Set_Property(@Window:'.EDL_WAFER_TRACK_PART', 'TEXT', SPCWaferTrackPart) Reactor = ReactRunRec If Reactor EQ '' then Reactor = GaN_Services('GetReactor', WONo) Set_Property(@Window, '@REACTOR', Reactor) ReactRunRec = Reactor Database_Services('WriteDataRow', 'REACT_RUN', RDSNo, ReactRunRec, True$, False$, True$) * update the gauge Msg(@Window, MsgUp, 30, MSGINSTUPDATE$) If GaNRunID EQ '' then AvailGaNRunIDs = Gan_Services('GetAvailableRunIDs', Reactor, WoNo) Msg(@Window, MsgUp, 40, MSGINSTUPDATE$) EpiPartNo = Get_Property(@Window:'.EPI_PART_NO', 'TEXT') NumRunIDs = DCount(AvailGaNRunIDs, @FM) FilteredList = '' Voltage = '' Voltage = Xlate('WO_LOG', WONo, 'GAN_COST_TYPE', 'X') Begin Case Case Voltage _EQC 'High Voltage' // Filter on hvfet For RunIndex = 1 to NumRunIDs RunID = AvailGaNRunIDs If Indexc(RunID, 'HV', 1) then FilteredList<-1> = RunID end Next RunIndex Case Voltage _EQC 'Mid Voltage' // Filter on mvfet - ( e.g. U014 is Medium Voltage (MV) ) For RunIndex = 1 to NumRunIDs RunID = AvailGaNRunIDs If Indexc(RunID, 'MV', 1) then FilteredList<-1> = RunID end Next RunIndex Case Otherwise$ ErrorMsg = 'Unrecognized GaN Cost Type (Voltage): "':Voltage:'" read from work order.':CRLF$ | : 'Unabled to filter GaN Run ID list.':CRLF$:' Verify GaN Cost Type in work order ' | : 'or contact FI team for assistance.' ErrMsg(ErrorMsg) FilteredList = AvailGaNRunIDs End Case Set_Property(@Window : '.CMB_GAN_RUN_ID', 'LIST', FilteredList) end else Convert @Upper.Case to @Lower.Case in GaNRunID Set_Property(@Window : '.CMB_GAN_RUN_ID', 'LIST', GaNRunID) Set_Property(@Window : '.CMB_GAN_RUN_ID', 'SELPOS', 1) end * update the gauge Msg(@Window, MsgUp, 50, MSGINSTUPDATE$) GaNEtchIDs = Xlate('REACT_RUN', RDSNo, 'GAN_ETCH_ID', 'X') Convert @VM to @FM in GaNEtchIDs If GaNEtchIDs NE '' then NumEtchIDs = DCount(GaNEtchIDs, @FM) Set_Property(@Window : '.CMB_GAN_ETCH_ID', 'LIST', GaNEtchIDs) // Select the last external etch ID to display by default Set_Property(@Window : '.CMB_GAN_ETCH_ID', 'SELPOS', NumEtchIDs) GaNEtchRecipes = Xlate('REACT_RUN', RDSNo, 'GAN_ETCH_RECIPE', 'X') LastEtchRecipe = GaNEtchRecipes<0, NumEtchIDs> Set_Property(@Window : '.ETCH_RECIPE', 'TEXT', LastEtchRecipe) EtchKey = RDSNo:'*ETCH' EtchStatus = Xlate('RUN_STAGE', EtchKey, 'STATUS', 'X') If EtchStatus EQ 'COMP' then // Verify the etch recipe hasn't changed. ExternalEtchID = Get_Property(@Window:'.CMB_GAN_ETCH_ID', 'TEXT') GaNEtchInfo = Gan_Services('GetRunInfo', ExternalEtchID) WaferTrackEtchRecipe = GaNEtchInfo<1,1> If WaferTrackEtchRecipe NE LastEtchRecipe then ReactRunRec = WaferTrackEtchRecipe Database_Services('WriteDataRow', 'REACT_RUN', RDSNo, ReactRunRec, True$, False$, True$) Set_Property(@Window:'.ETCH_RECIPE', 'TEXT', WaferTrackEtchRecipe) end end end else Set_Property(@Window : '.CMB_GAN_RUN_ID', 'ENABLED', False$) end GoSub Setup_OLE_Controls // Need to check if any wafers have made it to disposition. If so, then check the Disposition Report // for any updates. * update the gauge Msg(@Window, MsgUp, 60, MSGINSTUPDATE$) WfrIDs = ReactRunRec If WfrIDs NE '' then For each WfrID in WfrIDs using @VM setting vPos MetDone = GaN_Services('GetMetrologyStatus', WfrID) Until MetDone EQ True$ Next WfrID RDSClosed = ReactRunRec Begin Case Case ( (MetDone EQ True$) and (RDSClosed NE True$) ) Set_Property(@Window:'.PUB_UPDATE_DISP', 'ENABLED', True$) GoSub UpdateDispData Disposition_Services('AutoDispositionRun', RDSNo) Case ( (MetDone EQ True$) and (RDSClosed EQ True$) ) Set_Property(@Window:'.PUB_UPDATE_DISP', 'ENABLED', True$) Case Otherwise$ Null End Case end GoSub VerifyRecipe * update the gauge Msg(@Window, MsgUp, 70, MSGINSTUPDATE$) GoSub FillDispEditTable * update the gauge Msg(@Window, MsgUp, 80, MSGINSTUPDATE$) GoSub FillNCREditTable * update the gauge Msg(@Window, MsgUp, 90, MSGINSTUPDATE$) GoSub FillCommentsTable end * GoSub VerifyScribes GoSub EnableRunIDComboBox GoSub EnableDispButton GoSub UpdateRDSStatus GoSub EnableLotAbortButton * update the gauge Msg(@Window, MsgUp, 100, MSGINSTUPDATE$) Msg(@Window, MsgUp) ;* take down the gauge end If Not(FormVisible) then SRP_Show_Window(@Window, '', 'C', 'C', 1, '', False$, False$, FormSize) Set_Property(@Window, 'REDRAW', True$) Set_Property(@Window:'.OLE_REACTOR_EDT' , "OLE.Redraw", True$) Set_Property(@Window:'.OLE_METROLOGY_EDT' , "OLE.Redraw", True$) Set_Property(@Window:'.OLE_DISP_EDT' , "OLE.Redraw", True$) Set_Property(@Window:'.OLE_DISP_STAGE_EDT' , "OLE.Redraw", True$) Set_Property(@wINDOW:'.OLE_NCR_EDT' , "OLE.Redraw", True$) End Event Event WINDOW.CLEAR(bSaveKey, bSuppressWarning, bMaintainFocus, CtrlIDFocus) IF Get_Property(@WINDOW,'@READONLY') THEN obj_AppWindow('ReadOnly',@RM:1) ;* Reenables data bound controls Set_Property(@WINDOW,'@READONLY',0) ;* Clear flag on window END end event Event WINDOW.CLOSE(CancelFlag) obj_Notes('Inbox',@USER4) ;* Checks for any new messages Parent = Get_Property(@WINDOW,'PARENT') IF Parent[1,7] = 'WO_PROD' THEN Post_Event(Parent, 'READ') END end event Event WINDOW.WRITE() prevControl = Get_Property("SYSTEM" , "PREVFOCUS") EventFlow = 1 end event Event WINDOW.PAGE(PageAction) Page = Get_Property(@WINDOW:'.TABCONTROL', 'VALUE') Set_Property(@WINDOW,'VPOSITION', Page) end event Event WINDOW.VSCROLL(Value) Set_Property(@WINDOW:'.TABCONTROL','VALUE', Value) end event Event WINDOW.OMNIEVENT(Message, Param1, Param2, Param3, Param4) Begin Case Case Message _EQC 'FillDispEditTable' GoSub FillDispEditTable Case Message _EQC 'FillNCREditTable' GoSub FillNCREditTable End Case end event Event CMB_GAN_RUN_ID.CHANGED(NewData) If NewData NE '' then GaNRunID = NewData ReactorNo = Get_Property(@Window, '@REACTOR') GaNRunInfo = Gan_Services('GetRunInfo', GaNRunID) Recipe = GaNRunInfo<1,1> SuscSerialNo = GaNRunInfo<2,1> SPCWaferTrackPart = GaNRunInfo<6,1> Set_Property(@Window:'.EDL_WAFER_TRACK_PART', 'TEXT', SPCWaferTrackPart) Set_Property(@Window:'.OLE_REACTOR_EDT', "OLE.HeaderText[1; 2]", 'Reactor ':ReactorNo) WOLogOpenInsightPart = Get_Property(@Window:'.EPI_PART_NO', 'TEXT') Convert @Lower.Case to @Upper.Case in GaNRunID SchedWaferTrackPart = Xlate('GAN_SCHEDULE', GaNRunID, 'WAFER_TRACK_PART', 'X') SchedOpenInsightPart = Xlate('GAN_SCHEDULE', GaNRunID, 'OPENINSIGHT_PART', 'X') // OpenInsightPart Verification If SchedOpenInsightPart NE WOLogOpenInsightPart then Set_Property(@Window:'.EPI_PART_NO', 'BACKCOLOR', RED$) end else Set_Property(@Window:'.EPI_PART_NO', 'BACKCOLOR', GREEN$) end // WaferTrackPart Verification If SchedWaferTrackPart NE SPCWaferTrackPart then Set_Property(@Window:'.EDL_WAFER_TRACK_PART', 'BACKCOLOR', RED$) end else Set_Property(@Window:'.EDL_WAFER_TRACK_PART', 'BACKCOLOR', GREEN$) end Set_Property(@Window, '@GANRUNINFO', GaNRunInfo) Set_Property(@Window : '.GAN_RECIPE', 'TEXT', Recipe) Set_Property(@Window : '.GAN_SUSC_SERIAL', 'TEXT', SuscSerialNo) GoSub VerifyRecipe end end event Event CMB_GAN_ETCH_ID.CHANGED(NewData) ExternalEtchID = NewData Begin Case Case (ExternalEtchID _EQC 'No Etch Required') Set_Property(@Window : '.ETCH_RECIPE', 'TEXT', 'Not Applicable') Case (ExternalEtchID NE '') and (ExternalEtchID _NEC 'No Etch Required') GaNEtchInfo = Gan_Services('GetRunInfo', ExternalEtchID) Recipe = GaNEtchInfo<1,1> Set_Property(@Window : '.ETCH_RECIPE', 'TEXT', Recipe) End Case end event Event CTRL_PLAN.CLICK() PSNo = Get_Property(@WINDOW:'.PS_NO','DEFPROP') IF PSNo NE '' THEN Print_Control_Plan(PSNo) END end event Event WONO_BUTTON.CLICK() WONo = Get_Property(@WINDOW:'.WO_NO','DEFPROP') IF WONo NE '' THEN NewForm = Xlate('APP_INFO', 'NEW_WO_FORM', '', 'X') If NewForm then Start_Window('NDW_WO_LOG', @Window, WONo) end else Start_Window('WO_LOG2',@WINDOW, WONo:'*CENTER', '', '' ) ;* Added (copied from ViewPSN) -dkk 10/23/14 end END end event Event RDS_NO.LOSTFOCUS(Flag, FocusID) ReactRunKey = Get_Property(@Window:'.RDS_NO', 'TEXT') If ReactRunKey NE '' then RDSNo = Get_Property(@Window, '@RDSNO') If ReactRunKey NE RDSNo then Reactor = Xlate('REACT_RUN', ReactRunKey, 'REACTOR', 'X') If Reactor EQ '' then WONo = Get_Property(@Window:'.WO_NO', 'DEFPROP') Reactor = GaN_Services('GetReactor', WONo) If ( (Reactor EQ 69) or (Reactor EQ 71) ) then ReactRunRec = Database_Services('ReadDataRow', 'REACT_RUN', ReactRunKey) ReactRunRec = Reactor Database_Services('WriteDataRow', 'REACT_RUN', ReactRunKey, ReactRunRec, True$, False$, True$) end end ReactorType = Xlate('REACT_RUN', ReactRunKey, 'REACTOR_TYPE', 'X') If ReactorType _EQC 'GAN' then If RowExists('REACT_RUN', ReactRunKey) then Send_Event(@Window, 'CREATE', ReactRunKey) end else ErrMsg('REACT_RUN record ':ReactRunKey:' does not exist! Contact FI admin for assistance.') end end else ErrMsg('Incompatible reactor type ':ReactorType:'. Reactor type must be GAN.') end end end end event Event SEND_MSG.CLICK() CurrWindow = @WINDOW CurrKey = Get_Property(CurrWindow,'ID') IF CurrKey = '' THEN MsgInfo = '' MsgInfo = 'You must have a record present...' MsgInfo = 'H' Msg( '', MsgInfo ) RETURN END IF RowExists('REACT_RUN',CurrKey) THEN NoteID = NextKey('NOTES') obj_AppWindow('ViewRelated','NOTE_MESSAGE':@RM:NoteID:@RM:@WINDOW:@FM:CurrKey) END ELSE MsgInfo = '' MsgInfo = 'You must save this run data sheet first...' MsgInfo = 'H' Msg( '', MsgInfo ) END end event Event PSNO_BUTTON.CLICK() PSNo = Get_Property(@WINDOW:'.PS_NO','DEFPROP') IF PSNo NE '' THEN Start_Window('PROD_SPEC',@WINDOW, PSNo:'*CENTER', '', '' ) ;* Old style call to old style window END end event Event EDB_CASS_COMMENTS.CHANGED(NewData) NewComments = NewData OrigComments = Get_Property(@Window, '@COMMENTS') If NewComments NE OrigComments then Set_Property(@Window:'.PUB_SAVE_COMMENTS', 'ENABLED', True$) end else Set_Property(@Window:'.PUB_SAVE_COMMENTS', 'ENABLED', True$) end end event Event PUB_SAVE_COMMENTS.CLICK() RDSNo = Get_Property(@Window:'.RDS_NO', 'TEXT') CassComments = Get_Property(@Window:'.EDB_CASS_COMMENTS', 'TEXT') ReactRunRec = Database_Services('ReadDataRow', 'REACT_RUN', RDSNo) ReactRunRec = CassComments Database_Services('WriteDataRow', 'REACT_RUN', RDSNo, ReactRunRec, True$, False$, True$) Set_Property(CtrlEntID, 'ENABLED', False$) Set_Property(@Window, '@COMMENTS', CassComments) end event Event PUB_UPDATE_DISP.CLICK() PrevCursor = Set_Property('SYSTEM', 'CURSOR', 'H') RDSNo = Get_Property(@Window:'.RDS_NO', 'TEXT') GoSub UpdateDispData Disposition_Services('AutoDispositionRun', RDSNo) GoSub FillDispEditTable GoSub FillMetEditTable PrevCursor = Set_Property('SYSTEM', 'CURSOR', 'A') end event Event PUB_UPDATE_EA_DATA.CLICK() RDSNo = Get_Property(@Window:'.RDS_NO', 'TEXT') Engineering_Services('UpdateAll', RDSNo) end event Event PUB_DISP.CLICK() RDSNo = Get_Property(@Window:'.RDS_NO', 'TEXT') ReactRunRec = Database_Services('ReadDataRow', 'REACT_RUN', RDSNo) DispComp = ReactRunRec WfrIDs = ReactRunRec If DispComp EQ True$ then // User is attempting to open this RDS. Check for GAN_WIP_SUPERVISOR group membership. Response = Dialog_Box('NDW_VERIFY_USER', @Window, @USER4 : @FM : 'GAN_WIP_SUPERVISOR') Valid = Response<1> If Valid EQ True$ then CurrDTM = Datetime() DispComp = False$ // Move wafers back into the DISP location queue. For each WfrID in WfrIDs using @VM setting vPos // Mark DISP, G_PACK, and RETAIN as INIT Stages = 'DISP,G_PACK,RETAIN' For each Stage in Stages using ',' FormattedWfrID = WfrID Convert '*' to '.' in FormattedWfrID RunStageWfrKey = RDSNo:'*':Stage:'*':FormattedWfrID RunStageWfrRec = Database_Services('ReadDataRow', 'RUN_STAGE_WFR', RunStageWfrKey) RunStageWfrRec = '' RunStageWfrRec = '' RunStageWfrRec = 'INIT' Database_Services('WriteDataRow','RUN_STAGE_WFR',RunStageWfrKey,RunStageWfrRec,True$,False$,True$) Next Stage DispQ = 'GGR*Q_DISP' CurrQ = Gan_Services('GetWfrQueue', WfrID) Gan_Services('RemoveWfrFromWIP', WfrID) Gan_Services('MoveWfrToQueue', WfrID, DispQ) WOWfrRec = Database_Services('ReadDataRow', 'WO_WFR', WfrID) LocDTM = WOWfrRec NextPos = DCount(LocDTM, @VM) + 1 WOWfrRec = CurrDTM WOWfrRec = @USER4 WOWfrRec = 'OPEN' WOWfrRec = '' WOWfrRec = DispQ Database_Services('WriteDataRow', 'WO_WFR', WfrID, WOWfrRec, True$, False$, True$) Next WfrID ReactRunRec = DispComp Database_Services('WriteDataRow', 'REACT_RUN', RDSNo, ReactRunRec, True$, False$, True$) GoSub UpdateDispData end end else AllWfrsComp = GaN_Services('ReadyToClose', RDSNo) If AllWfrsComp EQ True$ then // User is marking disposition complete for the cassette DispComp = True$ ReactRunRec = DispComp Database_Services('WriteDataRow', 'REACT_RUN', RDSNo, ReactRunRec, True$, False$, True$) Engineering_Services('ClearEARequests', RDSNo) // Refresh the WO_PROD_GAN form if it is open to reflect possible updates to outbound cassettes. GaNProdVis = Get_Property('WO_PROD_GAN', 'VISIBLE') If GaNProdVis EQ True$ then Send_Event('WO_PROD_GAN', 'READ') end else Dialog_Box('NDW_WAFER_STATUS', @Window, RDSNo) end end Disposition_Services('AutoDispositionRun', RDSNo) GoSub EnableDispButton GoSub UpdateRDSStatus end event Event PUB_CREATE_NCR.CLICK() DispEDTCtrl = @Window:".OLE_DISP_EDT" CarrSlotList = Get_Property(DispEDTCtrl, 'OLE.List') SelectedRows = Get_Property(DispEDTCtrl, "OLE.ColumnData[":COL$DISP_RDS_NCR:"]") CONVERT @VM TO @FM in SelectedRows NumWfrs = DCount(SelectedRows, @FM) WONo = Get_Property(@Window:'.WO_NO', 'TEXT') RDSNo = Get_Property(@Window:'.RDS_NO', 'TEXT') Reactor = Get_Property(@Window, '@REACTOR') RejWfrIDs = '' RejSlotIDs = '' GoodLines = 0 FOR WfrIndex = 1 TO NumWfrs RowSelected = SelectedRows If RowSelected EQ True$ then SlotNo = CarrSlotList IF CarrSlotList NE '' Then GoodLines += 1 RejWfrIDs<1,GoodLines> = CarrSlotList RejSlotIDs<1,GoodLines> = RDSNo:'*':SlotNo END end NEXT I ncrParms = WONo:@RM ncrParms := '1':@RM ncrParms := '':@RM ;* Place holder for WO_MAT_CASS_NO ncrParms := RDSNo:@RM ;* Single RDS field ncrParms := Reactor:@RM ;* Reactor No ncrParms := '':@RM ;* Loss Stage ncrParms := RejWfrIDs:@RM ;* WfrIDs ;* CarrWafer IDs ncrParms := RejSlotIDs:@RM ;* CarrSlotIDs ;* GaN PostEpi Carrier Slot ID -> GaN non-characterization wafers ncrParms := '':@RM ;* CassSlotIDs ;* WOMat Cassette Slot ID -> Rej from cassette ncrParms := '' ;* RunPocketZone ;* RPZ -> Rej from susceptor Set_Status(0) NCRNo = obj_NCR('CreateWfr',ncrParms) ;* Create new NCR for this wafer/group of wafers errCode = '' IF Get_Status(errCode) THEN ErrMsg(errCode) end else ReactRunRec = Database_Services('ReadDataRow', 'REACT_RUN', RDSNo) Grades = ReactRunRec WfrIDs = ReactRunRec For each RejWfrID in RejWfrIDs using @VM setting vPos Locate RejWfrID in WfrIDs using @VM setting wPos then Grades<0, wPos> = 'Scrap' end Next RejWfrID ReactRunRec = Grades Database_Services('WriteDataRow', 'REACT_RUN', RDSNo, ReactRunRec, True$, False$, True$) // Check if these wafers are in an outbound cassette. If so, // then remove them. Wafers cannot be shipped and scrapped at the same time. OutSlotIDs = ReactRunRec WfrIDs = ReactRunRec For each RejWfrID in RejWfrIDs using @VM setting vPos Locate RejWfrID in WfrIDs using @VM setting wPos then Database_Services('ActivateRecord', 'WO_WFR', RejWfrID) {RDS_NCR_NO} = NCRNo Database_Services('WriteDataRow', 'WO_WFR', RejWfrID, @Record, True$, False$, True$) OutSlotID = OutSlotIDs<0, wPos> If OutSlotID NE '' then // Remove wafer from outbound cassette OutCass = Field(OutSlotID, '*', 1, 2) GaN_Services('RemoveWfrsFromOutCass', OutCass, RejWfrID) end end Next RejWfrID Dialog_Box('NCR', @Window, NCRNo) PrevCursor = Set_Property('SYSTEM', 'CURSOR', 'H') Gan_Services('UpdateDisposition') GoSub FillMetEditTable GoSub FillDispEditTable GoSub FillNCREditTable PrevCursor = Set_Property('SYSTEM', 'CURSOR', 'A') end end event Event PUB_LOT_ABORT.CLICK() RDSNo = Get_Property(@Window : '.RDS_NO', 'TEXT') WfrIDs = Xlate('REACT_RUN', RDSNo, 'IN_WFR_ID', 'X') For each WfrID in WfrIDs using @VM setting vPos FormattedWfrID = WfrID Convert '*' to '.' in FormattedWfrID CurrStage = Gan_Services('GetCurrStage', WfrID) Begin Case Case ( (CurrStage _EQC 'UV') or (CurrStage _EQC 'UV_PRE') or (CurrStage _EQC 'UV_PST') or (CurrStage _EQC 'WARP') or (CurrStage _EQC 'CAN') or (CurrStage _EQC 'CAN_PRE') or (CurrStage _EQC 'CAN_PST') ) // Pre-SPLIT wafer // a) Skip any pre-SPLIT stages // b) Mark all wafers as "Disposition" at SPLIT stage Loop StageKey = RDSNo:'*':CurrStage:'*':FormattedWfrID StageStatus = Xlate('RUN_STAGE_WFR', StageKey, 'STATUS', 'X') Begin Case Case StageStatus _EQC 'INIT' // Skip stage - Moves wafer to next stage Gan_Services('SkipWaferStage', RDSNo, WfrID, CurrStage) Case StageStatus _EQC 'START' // Stop wafer - Moves wafer to next stage Gan_Services('StopWaferStage', RDSNo, WfrID, CurrStage) Case StageStatus _EQC 'COMP' Null Case Otherwise$ Null End Case CurrStage = Gan_Services('GetCurrStage', WfrID) Until CurrStage _EQC 'SPLIT' Repeat If CurrStage _EQC 'SPLIT' then Gan_Services('DispositionWfr', RDSNo, WfrID) Case CurrStage _EQC 'SPLIT' // SPLIT wafer - Simply disposition the wafer Gan_Services('DispositionWfr', RDSNo, WfrID) Case (CurrStage _EQC 'XRD') or (CurrStage _EQC 'AFM') | or (CurrStage _EQC 'RPM') or (CurrStage _EQC 'PR') or (CurrStage _EQC 'SCOPE') | or (CurrStage _EQC 'HALL') or (CurrStage _EQC 'EBEAM') or (CurrStage _EQC 'RTA_HALL') | or (CurrStage _EQC 'RTA') or (CurrStage _EQC 'HALL_PGAN') | or (CurrStage _EQC 'BV') or (CurrStage _EQC 'JV_XRD') or (CurrStage _EQC 'BV100%') // Post-SPLIT wafer // a) Currently running wafers will need to be stopped // b) All subsequent stages will need to be auto-skipped including unprescribed stages Loop CurrQ = Gan_Services('GetWfrQueue', WfrID) QType = Gan_Services('GetQueueType', CurrQ) Begin Case Case QType _EQC 'Location' // Wafer not running on a tool. Skip the stage. Gan_Services('SkipWaferStage', RDSNo, WfrID, CurrStage) Case QType _EQC 'Tool' // Wafer running on tool. Stop the stage. Gan_Services('StopWaferStage', RDSNo, WfrID, CurrStage) End Case CurrStage = Gan_Services('GetCurrStage', WfrID) Until CurrStage _EQC 'DISP' Repeat Case CurrStage _EQC 'DISP' // Wafer is where it needs to be. Nothing needed to do. Null Case Otherwise$ ErrorMsg = 'Error aborting wafer ':WfrID:'. Contact FI team for assistance.' ErrMsg(ErrorMsg) End Case Next WfrID GoSub UpdateDispData Disposition_Services('AutoDispositionRun', RDSNo) GoSub FillMetEditTable GoSub FillDispEditTable end event Event PUB_SEND_MSG.CLICK() RDSNo = Get_Property(@Window:'.RDS_NO', 'TEXT') IF RDSNo = '' THEN MsgInfo = '' MsgInfo = 'You must have a record present...' MsgInfo = 'H' Msg( '', MsgInfo ) RETURN END IF RowExists('REACT_RUN',RDSNo) THEN NoteID = NextKey('NOTES') obj_AppWindow('ViewRelated','NOTE_MESSAGE':@RM:NoteID:@RM:@WINDOW:@FM:RDSNo) END ELSE MsgInfo = '' MsgInfo = 'You must save this run data sheet first...' MsgInfo = 'H' Msg( '', MsgInfo ) END end event Event TABCONTROL.CLICK() Page = Get_Property(@WINDOW:'.TABCONTROL', 'VALUE') Set_Property(@WINDOW,'VPOSITION', Page) end event Event OLE_METROLOGY_EDT.OnButtonClick(Cell, Point, Button, Shift, Ctrl) Row = Field(Cell, ';', 2) Col = Field(Cell, ';', 1) SelStage = Get_Property(CtrlEntID, "OLE.CellText[":Col:";":Row:"]") SelStageID = GaN_Services('GetStageID', SelStage) If ( (SelStageID EQ 'UV') or (SelStageID EQ 'UV_PRE') or (SelStageID EQ 'UV_PST') or (SelStageID EQ 'WARP') or (SelStageID EQ 'WET_CLEAN') or (SelStageID EQ 'CAN_PRE') or (SelStageID EQ 'CAN_PST') ) then RDSNo = Get_Property(@Window : '.RDS_NO', 'TEXT') ToolID = Get_Property(@Window : '.OLE_METROLOGY_EDT', 'OLE.CellText[2; ':Row:']') IsSplit = Gan_Services('IsCassSplit', RDSNo) Menu = "" // Initialize menu options StartStatus = False$ StopStatus = False$ CompStatus = False$ SkipStatus = False$ UnskipStatus = False$ WfrIDs = Xlate('REACT_RUN', RDSNo, 'IN_WFR_ID', 'X') WfrStages = Xlate('REACT_RUN', RDSNo, 'WFR_STAGE', 'X') CanPreStartCnt = 0 CanPstStartCnt = 0 WetCleanStartCnt = 0 NumWfrs = Get_Property(@Window, '@NUMWFRS') // Check each wafer in the selected stage to determine which menu options should be enabled. For each WfrID in WfrIDs using @VM setting wPos Convert '*' to '.' in WfrID Begin Case Case SelStageID EQ 'UV_PRE' // Check if UV stage exists UVStageWfrKey = RDSNo:'*UV*':WfrID If RowExists('RUN_STAGE_WFR', UVStageWfrKey) then // Display this on the UV_PRE line RunStageWfrKey = UVStageWfrKey end else RunStageWfrKey = RDSNo:'*':SelStageID:'*':WfrID end Case SelStageID EQ 'CAN_PRE' // Check if CAN stage exists CanStageWfrKey = RDSNo:'*CAN*':WfrID If RowExists('RUN_STAGE_WFR', CanStageWfrKey) then // Display this on the CAN_PRE line RunStageWfrKey = CanStageWfrKey end else RunStageWfrKey = RDSNo:'*':SelStageID:'*':WfrID end Case Otherwise$ RunStageWfrKey = RDSNo:'*':SelStageID:'*':WfrID End Case WfrStatus = Xlate('RUN_STAGE_WFR', RunStageWfrKey, 'STATUS', 'X') Begin Case Case WfrStatus EQ 'INIT' and ToolID NE 'Select' StartStatus = True$ SkipStatus = True$ Case WfrStatus EQ 'INIT' SkipStatus = True$ Case WfrStatus EQ 'START' StopStatus = True$ Case WfrStatus EQ 'STOP' CompStatus = True$ Case WfrStatus EQ 'SKIP' If IsSplit EQ False$ then UnskipStatus = True$ End Case Next WfrID Menu<-1> = "START" :@VM:"Start" :@VM:StartStatus Menu<-1> = "STOP" :@VM:"Stop" :@VM:StopStatus Menu<-1> = "COMP" :@VM:"Complete" :@VM:CompStatus Menu<-1> = "SKIP" :@VM:"Skip" :@VM:SkipStatus Menu<-1> = "UNSKIP" :@VM:"Unskip" :@VM:UnskipStatus Send_Message(CtrlEntID, "OLE.ShowContextMenu", Point, Menu, Cell) end end event Event OLE_REACTOR_EDT.OnButtonClick(Cell, Point, Button, Shift, Ctrl) RecipeMismatch = Get_Property(@Window, '@RECIPEMISMATCH') RDSNo = Get_Property(@Window:'.RDS_NO', 'TEXT') Row = Field(Cell, ';', 2) Col = Field(Cell, ';', 1) Stage = Get_Property(CtrlEntID, "OLE.CellText[":Col:";":Row:"]") StageID = Gan_Services('GetStageID', Stage) If StageID NE 'ETCH' then Menu = "" // Initialize all menu options to false until we deem they need to be turned on StartStatus = False$ StopStatus = False$ LoadStatus = False$ UnloadStatus = False$ CompStatus = False$ // Get inventory actions associated with this particular stage RDSNo = Get_Property(@Window : '.RDS_NO', 'TEXT') RunStageKey = RDSNo:'*':StageID InvActions = Xlate('RUN_STAGE', RunStageKey, 'SPEC_INV_ACTION', 'X') CurrStatus = Xlate('RUN_STAGE', RunStageKey, 'STATUS', 'X') Begin Case Case StageID EQ 'G_RDS' // Need to check if GaN Run ID has been selected and if the GaN Recipe is populated. GaNRunID = Get_Property(@Window:'.CMB_GAN_RUN_ID', 'TEXT') GaNRecipe = Get_Property(@Window:'.GAN_RECIPE', 'TEXT') EtchKey = RDSNo:'*ETCH' EtchStageComp = Xlate('RUN_STAGE', EtchKey, 'STATUS', 'X') If (GaNRunID NE '') and (GaNRecipe NE '') and (EtchStageComp _EQC 'COMP') and (CurrStatus NE 'COMP') then CompStatus = True$ end Case StageID EQ 'GROWTH' PrevStageKey = RDSNo:'*':'ETCH' PrevStageStatus = Xlate('RUN_STAGE', PrevStageKey, 'STATUS', 'X') If PrevStageStatus EQ 'COMP' then Begin Case Case CurrStatus EQ 'START' UnloadStatus = True$ Case CurrStatus EQ 'COMP' Null Case Otherwise$ LoadStatus = True$ End Case end Case StageID EQ 'G_RATE' PrevStageKey = RDSNo:'*':'GROWTH' PrevStageStatus = Xlate('RUN_STAGE', PrevStageKey, 'STATUS', 'X') If PrevStageStatus EQ 'COMP' and CurrStatus NE 'COMP' then CompStatus = True$ End Case For each Action in InvActions using @VM Begin Case Case Action EQ "START" Menu<-1> = "START" :@VM:"Start" :@VM:StartStatus Case Action EQ "STOP" Menu<-1> = "STOP" :@VM:"Stop" :@VM:StopStatus Case Action EQ "LOAD" Menu<-1> = "LOAD" :@VM:"Load" :@VM:LoadStatus Case Action EQ "UNLOAD" Menu<-1> = "UNLOAD" :@VM:"Unload" :@VM:UnloadStatus End Case Next Action If RecipeMismatch EQ True$ then CompStatus = False$ If StageID NE 'GROWTH' then Menu<-1> = "COMP" :@VM:"Complete" :@VM:CompStatus Send_Message(CtrlEntID, "OLE.ShowContextMenu", Point, Menu, Cell) end end event Event OLE_REACTOR_EDT.OnContextMenuClick(Item, UserData) CurrDTM = DateTime() SelCell = UserData Row = Field(SelCell, ';', 2) RowData = Get_Property(CtrlEntID, "OLE.RecordData[":Row:"]") ReactorStageCtrl = @Window:'.OLE_REACTOR_EDT' RDSNo = Get_Property(@Window : '.RDS_NO', 'TEXT') PSNo = Xlate('REACT_RUN', RDSNo, 'PS_NO', 'X') NumWfrs = DCount(InWfrIDs, @VM) StartCol = 3 EndCol = StartCol + (NumWfrs - 1) WfrActions = '' WfrStage = RowData<1, 1> For Col = StartCol to EndCol WfrActions<1, -1> = RowData<1, Col> Next Col StageName = Get_Property(CtrlEntID, 'OLE.CellText[1; ':Row:']') StageID = Gan_Services('GetStageID', StageName) PRSStageKey = PSNo :'*': StageID CurrAction = Item RunStageKey = RDSNo:'*':StageID RunStageRec = Database_Services('ReadDataRow', 'RUN_STAGE', RunStageKey) WONo = Get_Property(@Window:'.WO_NO', 'TEXT') CassNo = Get_Property(@Window:'.CASS_NO', 'TEXT') WOMatKey = WONo:'*':CassNo WOMatRec = Database_Services('ReadDataRow', 'WO_MAT', WOMatKey) ReactRunRec = Database_Services('ReadDataRow', 'REACT_RUN', RDSNo) Begin Case Case CurrAction EQ 'UNLOAD' Begin Case Case StageID EQ 'GROWTH' GaN_Services('UnloadSusceptor', RDSNo) If Error_Services('NoError') then Set_Property(ReactorStageCtrl, "OLE.CellText[2; ":Row:"]", 'Complete') ReactRunRec = Database_Services('ReadDataRow', 'REACT_RUN', RDSNo) CarrSlotIDs = ReactRunRec Scribes = Xlate('REACT_RUN', RDSNo, 'WFR_SCRIBES', 'X') Set_Property(@Window, '@CARRSLOTIDS', CarrSlotIDs) Set_Property(@Window, '@SCRIBES', Scribes) Engineering_Services('PostEARequest', RDSNo, 'GROWTH') Reactor = Xlate('REACT_RUN', RDSNo, 'REACTOR', 'X') ToolID = 'R':Reactor Reactor_Services('IncrementCycleCount', ToolID) end else ErrorMessages = Error_Services('GetMessages') Convert @FM to CRLF$ in ErrorMessages ErrMsg(ErrorMessages) end End Case Case CurrAction EQ 'LOAD' Begin Case Case StageID EQ 'GROWTH' RunStageKey = RDSNo:'*':StageID Reactor = Get_Property(@Window, '@REACTOR') // Need to sign 'LOAD' inventory action LoadComplete = Dialog_Box('DIALOG_LOAD_SUSCEPTOR', @WINDOW, RDSNo:@FM:StageName:@FM:Reactor) If LoadComplete EQ True$ then // Update the UI Set_Property(ReactorStageCtrl, "OLE.CellText[2; ":Row:"]", 'Load') Scribes = Xlate('REACT_RUN', RDSNo, 'WFR_SCRIBES', 'X') WfrIDs = Xlate('REACT_RUN', RDSNo, 'IN_WFR_ID', 'X') Set_Property(@Window, '@WFRIDS', WfrIDs) HeaderTitles = "Stage":@VM:"Tool ID":@VM:Scribes Set_Property(MetStageCtrl, "OLE.TitleList", HeaderTitles) GaNProdVis = Get_Property('WO_PROD_GAN', 'VISIBLE') If GaNProdVis EQ True$ then Send_Event('WO_PROD_GAN', 'READ') GoSub FillDispEditTable GoSub FillNCREditTable end End Case Case CurrAction EQ 'COMP' // 1. Save REACT_RUN record (Bind REACT_RUN (RDS) key id to GaN Run ID and to GaN Etch ID). Remove GaN Run ID and GaN Etch ID from their respective lists. // 2. Remove all wafers from previous Location/Tool ID queue if applicable // 3. Insert all wafers into Location/Tool ID queue (e.g. LOCATION*GCH*Q_ETCH/TOOL_WFR*R69) // 4. Add COMP_BY and COMP_DTM to RUN_STAGE record // 5. Update UI // 6. Refresh GaN Work Order status form Begin Case Case StageID EQ 'G_RDS' // 1 GaNRunID = Get_Property(@Window:'.CMB_GAN_RUN_ID', 'TEXT') GanSuscSerial = Get_Property(@Window:'.GAN_SUSC_SERIAL', 'TEXT') GaNRunRecipe = Get_Property(@Window:'.GAN_RECIPE', 'TEXT') SPCWaferTrackPart = Get_Property(@Window:'.EDL_WAFER_TRACK_PART', 'TEXT') ReactRunRec = Database_Services('ReadDataRow', 'REACT_RUN', RDSNo) RunInfo = Gan_Services('GetRunInfo', GaNRunID) PocketNos = RunInfo<3> Scribes = RunInfo<4> SatSerialNos = RunInfo<5> // Save the Wafer Track Part from SPC into the WO_LOG record. WOLogRec = Database_Services('ReadDataRow', 'WO_LOG', WONo) WOLogRec = SPCWaferTrackPart Database_Services('WriteDataRow', 'WO_LOG', WONo, WOLogRec, True$, False$, True$) // Just get the first reator in the list Reactor = Get_Property(@Window, '@REACTOR') ReactRunRec = GaNRunID ReactRunRec = GaNRunRecipe ReactRunRec = GanSuscSerial * ReactRunRec = PocketNos ReactRunRec = SatSerialNos ReactRunRec = Reactor GaN_Services('RemoveRunID', GaNRunID) Database_Services('WriteDataRow', 'REACT_RUN', RDSNo, ReactRunRec, True$, False$, True$) // 2 - N/A // 3 - Move cassette to GROWTH queue. GrowthQ = 'GCH*Q_GROWTH' GaN_Services('MoveCassToQueue', WOMatKey, GrowthQ) WOMatRec = Database_Services('ReadDataRow', 'WO_MAT', WOMatKey) WOMatRec = CurrDTM WOMatRec = @User4 WOMatRec = GrowthQ Database_Services('WriteDataRow', 'WO_MAT', WOMatKey, WOMatRec, True$, False$, True$) // 4 RunStageRec = @User4 RunStageRec = CurrDTM RunStageRec = 'COMP' Database_Services('WriteDataRow', 'RUN_STAGE', RunStageKey, RunStageRec, True$, False$, True$) // 5 Set_Property(ReactorStageCtrl, "OLE.CellText[2; ":Row:"]", 'Complete') // 6 GaNProdVis = Get_Property('WO_PROD_GAN', 'VISIBLE') If GaNProdVis EQ True$ then Send_Event('WO_PROD_GAN', 'READ') Case StageID EQ 'G_RATE' // 1. Remove all wafers from current Location queue // 2. Lookup next Location queue // 3. Insert all wafers into next Location queue CurrLocQID = 'GCH*Q_RATE' NextLocQID = 'GCH*UV_PRE_Q' InWfrIDs = ReactRunRec For each WfrID in InWfrIDs using @VM setting vPos If WfrID NE '' then Gan_Services('RemoveWfrFromWIP', WfrID) WOWfrRec = Database_Services('ReadDataRow', 'WO_WFR', WfrID) LocDTMs = WOWfrRec NextIndex = DCount(LocDTMs, @VM) + 1 WOWfrRec = CurrDTM WOWfrRec = @User4 WOWfrRec = NextLocQID WOWfrRec = 'COMP' Database_Services('WriteDataRow', 'WO_WFR', WfrID, WOWfrRec, True$, False$, True$) Gan_Services('MoveWfrToQueue', WfrID, NextLocQID) end Next WfrID // 3. Add COMP_BY and COMP_DTM to RUN_STAGE record RunStageRec = @User4 RunStageRec = CurrDTM RunStageRec = 'COMP' Database_Services('WriteDataRow', 'RUN_STAGE', RunStageKey, RunStageRec, True$, False$, True$) // 4. Create prescribed RUN_STAGE_WFR records Gan_Services('CreateAllRunStageWfr', RDSNo, 'SPLIT') // 5. Update REACT_RUN form Set_Property(ReactorStageCtrl, "OLE.CellText[2; ":Row:"]", 'Complete') GoSub EnableRows GoSub FillMetEditTable GoSub FillMetHeader // 6. Refresh GaN Work Order status form if it is open GaNProdVis = Get_Property('WO_PROD_GAN', 'VISIBLE') If GaNProdVis EQ True$ then Send_Event('WO_PROD_GAN', 'READ') End Case End Case end event Event OLE_METROLOGY_EDT.OnContextMenuClick(Item, UserData) PrevCursor = Set_Property('SYSTEM', 'CURSOR', 'H') SelCell = UserData Row = Field(SelCell, ';', 2) RowData = Get_Property(CtrlEntID, "OLE.RecordData[":Row:"]") RDSNo = Get_Property(@Window : '.RDS_NO', 'TEXT') InWfrIDs = Xlate('REACT_RUN', RDSNo, 'IN_WFR_ID', 'X') PSNo = Xlate('REACT_RUN', RDSNo, 'PS_NO', 'X') NumWfrs = DCount(InWfrIDs, @VM) StartCol = 3 EndCol = StartCol + (NumWfrs - 1) WfrActions = '' WfrStage = RowData<1, 1> For Col = StartCol to EndCol WfrActions<1, -1> = RowData<1, Col> Next Col StageName = Get_Property(@Window : '.OLE_METROLOGY_EDT', 'OLE.CellText[1; ':Row:']') StageID = GaN_Services('GetStageID', StageName) ToolID = Get_Property(@Window : '.OLE_METROLOGY_EDT', 'OLE.CellText[2; ':Row:']') If ToolID EQ 'Select' then ToolID = '' PRSStageKey = PSNo :'*': StageName Action = Item SpecToolClass = Xlate('PRS_STAGE', PRSStageKey, 'PROC_TOOL_CLASS', 'X') ToolClassRec = Database_Services('ReadDataRow', 'TOOL_CLASS', SpecToolClass) CurrDTM = DateTime() Begin Case Case Action _EQC 'START' For each WfrID in InWfrIDs using @VM setting WaferIndex FormattedWfrID = WfrID Swap '*' with '.' in FormattedWfrID RunStageWfrKey = RDSNo:'*':StageID:'*':FormattedWfrID StageStatus = Xlate('RUN_STAGE_WFR', RunStageWfrKey, 'STATUS', 'X') ReadyToStart = GaN_Services('ReadyToStart', RDSNo, WfrID) If ( (StageStatus EQ 'INIT') and (ReadyToStart EQ True$) ) then GaN_Services('StartWaferStage', RDSNo, WfrID, StageID, ToolID) Next WfrID Case Action _EQC 'STOP' For each WfrID in InWfrIDs using @VM setting WaferIndex FormattedWfrID = WfrID Swap '*' with '.' in FormattedWfrID RunStageWfrKey = RDSNo:'*':StageID:'*':FormattedWfrID StageStatus = Xlate('RUN_STAGE_WFR', RunStageWfrKey, 'STATUS', 'X') If StageStatus EQ 'START' then GaN_Services('StopWaferStage', RDSNo, WfrID, StageID) StageStatus = Xlate('RUN_STAGE_WFR', RunStageWfrKey, 'STATUS', 'X') If StageStatus EQ 'STOP' then GaN_Services('CompleteWaferStage', RDSNo, WfrID, StageID) Next WfrID Engineering_Services('PostEARequest', RDSNo, StageID) If StageID EQ 'WARP' then GaN_Services('CheckForCriticalFailures', RDSNo, ToolID) * If ( (StageID EQ 'CAN_PRE') or (StageID EQ 'CAN_PST') or (StageID EQ 'JV_XRD') ) then * GaN_Services('VerifyWaferScribes', RDSNo, ToolID) * GoSub VerifyScribes * end Case Action _EQC 'SKIP' For each WfrID in InWfrIDs using @VM setting WaferIndex FormattedWfrID = WfrID Swap '*' with '.' in FormattedWfrID RunStageWfrKey = RDSNo:'*':StageID:'*':FormattedWfrID StageStatus = Xlate('RUN_STAGE_WFR', RunStageWfrKey, 'STATUS', 'X') If StageStatus EQ 'INIT' then GaN_Services('SkipWaferStage', RDSNo, WfrID, StageID) Next WfrID Case Action _EQC 'UNSKIP' For each WfrID in InWfrIDs using @VM setting WaferIndex FormattedWfrID = WfrID Swap '*' with '.' in FormattedWfrID RunStageWfrKey = RDSNo:'*':StageID:'*':FormattedWfrID StageStatus = Xlate('RUN_STAGE_WFR', RunStageWfrKey, 'STATUS', 'X') If StageStatus EQ 'SKIP' then GaN_Services('UnskipWaferStage', RDSNo, WfrID, StageID) Next WfrID End Case Disposition_Services('AutoDispositionRun', RDSNo) GoSub FillMetEditTable PrevCursor = Set_Property('SYSTEM', 'CURSOR', PrevCursor) end event Event OLE_METROLOGY_EDT.OnClick(Cell, Point, Button, Shift, Ctrl) If Button _EQC 'Right' then Column = Field(Cell, ';', 1, 1) Row = Field(Cell, ';', 2, 1) PopupCtrl = @Window : '.OLE_POPUP' AllowPopup = False$ PopupVisible = Get_Property(PopupCtrl, 'OLE.Visible') If PopupVisible EQ True$ then GoSub DismissPopup end GoSub DisplayPopup end end event Event OLE_METROLOGY_EDT.OnHeaderDblClick(Cell, Point, Button, Shift, Ctrl) Col = Field(Cell, ';', 1, 1) If Col GT 3 then RDSNo = Get_Property(@Window:'.RDS_NO', 'TEXT') WfrIDs = Xlate('REACT_RUN', RDSNo, 'IN_WFR_ID', 'X') WfrIndex = Col - 3 WfrID = WfrIDs<0, WfrIndex> WfrComments = '' WfrComments = Xlate('WO_WFR', WfrID, 'COMMENTS', 'X') // Display wafer comments and allow user to edit/erase comments. Response = Dialog_Box('NDW_WFR_COMMENTS', @WINDOW, WfrComments) Save = Response<1> NewComments = Response<2> If Save EQ True$ then // Insert comments into WO_WFR record WOWfrRec = Database_Services('ReadDataRow', 'WO_WFR', WfrID) WOWfrRec = NewComments Database_Services('WriteDataRow', 'WO_WFR', WfrID, WOWfrRec, True$, False$, True$) ColNo = WfrIndex + 3 Set_Property(CtrlEntID, "OLE.HeaderToolTip[":ColNo:";1]", NewComments) HeaderColors = Get_Property(CtrlEntID, "OLE.HeaderColors[":ColNo:";1]") If NewComments NE '' then // Set header to cyan so the user knows there's a comment HeaderColors<2> = 'LightCyan' HeaderColors<4> = 'LightCyan' end else // Comment has been removed, so reset header colors back to default colors HeaderColors<2> = 'None' HeaderColors<4> = OI_HOT_BLUE$ end Set_Property(CtrlEntID, "OLE.HeaderColors[":ColNo:";1]", HeaderColors) end end end event Event OLE_REACTOR_EDT.OnClick(Cell, Point, Button, Shift, Ctrl) If Button _EQC 'Right' then Column = Field(Cell, ';', 1, 1) Row = Field(Cell, ';', 2, 1) PopupCtrl = @Window : '.OLE_POPUP' AllowPopup = False$ PopupVisible = Get_Property(PopupCtrl, 'OLE.Visible') If PopupVisible EQ True$ then GoSub DismissPopup end GoSub DisplayPopup end end event Event OLE_METROLOGY_EDT.OnComboClicked(Cell, SelPos, Value) PrevCursor = Set_Property('SYSTEM', 'CURSOR', 'H') Column = Field(Cell, ';', 1, 1) Row = Field(Cell, ';', 2, 1) MetStageCtrl = @Window:'.OLE_METROLOGY_EDT' MetStageList = Get_Property(MetStageCtrl, "OLE.ColumnData[1]") StageDesc = MetStageList<0, Row> StageID = GaN_Services('GetStageID', StageDesc) RDSNo = Get_Property(@Window:'.RDS_NO', 'TEXT') WfrIDs = Xlate('REACT_RUN', RDSNo, 'IN_WFR_ID', 'X') MetRowsEnabled = Get_Property(@Window, '@METROWSENABLED') ColorArray = 'None':@FM:'None':@FM:'None':@FM:'None':@FM:'None' ReactRunRec = Database_Services('ReadDataRow', 'REACT_RUN', RDSNo) WfrStages = ReactRunRec UnRxStages = ReactRunRec ToolID = Get_Property(@Window : '.OLE_METROLOGY_EDT', 'OLE.CellText[2; ':Row:']') CurrDTM = DateTime() WfrIndex = Column - 2 If Column EQ COL$MET_TOOL_ID then ToolID = Value // A tool ID has been selected. Need to check all RUN_STAGE_WFR statuses. Tool IDs can only be updated if the // status is 'INIT' or 'X'. For each WfrID in WfrIDs using @VM setting vPos If WfrID NE '' then WfrIDFormatted = WfrID Swap '*' with '.' in WfrIDFormatted RunStageWfrKey = RDSNo:'*':StageID:'*':WfrIDFormatted If RowExists('RUN_STAGE_WFR', RunStageWfrKey) then WfrStatus = Xlate('RUN_STAGE_WFR', RunStageWfrKey, 'STATUS', 'X') If WfrStatus _EQC 'INIT' then Set_Property(MetStageCtrl, "OLE.CellProtection[":Column:";":Row:"]", "None") RunStageWfrRec = Database_Services('ReadDataRow', 'RUN_STAGE_WFR', RunStageWfrKey) RunStageWfrRec = ToolID Database_Services('WriteDataRow','RUN_STAGE_WFR',RunStageWfrKey,RunStageWfrRec,True$,False$,True$) end end end Next WfrID MetRowsEnabled = True$ Set_Property(@Window, '@METROWSENABLED', MetRowsEnabled) end else Action = Value WfrID = WfrIDs<0, WfrIndex> Set_Property(@Window, '@SINGLE_WFR_ID', WfrID) Begin Case Case Action _EQC 'START' Gan_Services('StartWaferStage', RDSNo, WfrID, StageID, ToolID) Case Action _EQC 'STOP' Gan_Services('StopWaferStage', RDSNo, WfrID, StageID) Gan_Services('CompleteWaferStage', RDSNo, WfrID, StageID) Engineering_Services('PostEARequest', RDSNo, StageID) Case Action _EQC 'COMPLETE' Gan_Services('CompleteWaferStage', RDSNo, WfrID, StageID) Engineering_Services('PostEARequest', RDSNo, StageID) Case Action _EQC 'SKIP' Gan_Services('SkipWaferStage', RDSNo, WfrID, StageID) Case Action _EQC 'UNSKIP' Gan_Services('UnskipWaferStage', RDSNo, WFrID, StageID) Case Action _EQC 'ADD' If ( (ToolID EQ '') or (ToolID EQ 'Select') ) then Error_Services('Add', 'A tool ID must be selected before adding a stage') Set_Property(@Window : '.OLE_METROLOGY_EDT', 'OLE.CellText[':Cell:']', '') end else Gan_Services('AddWaferStage', RDSNo, WfrID, StageID, ToolID) end Case Action _EQC 'REMOVE' Gan_Services('RemoveWaferStage', RDSNo, WfrID, StageID) Case Action _EQC 'CHARACTERIZE' Gan_Services('CharacterizeWafer', RDSNo, WfrID) Case Action _EQC 'DISPOSITION' Gan_Services('DispositionWfr', RDSNo, WfrID) Case Action _EQC 'WITHDRAW' Gan_Services('WithdrawWfr', RDSNo, WfrID) Case Otherwise$ End Case end If Error_Services('HasError') then PrevCursor = Set_Property('SYSTEM', 'CURSOR', 'A') Errmsg(Error_Services('GetMessage')) end else CurrStage = Gan_Services('GetCurrStage', WfrID) If CurrStage _EQC 'DISP' then // Update the Disposition DTM for all wafers that have been through or are at disposition ReactRunRec = Database_Services('ReadDataRow', 'REACT_RUN', RDSNo) InWfrIDs = ReactRunRec For each WOWfrID in InWfrIDs using @VM setting vPos ThisWOWfrRec = Database_Services('ReadDataRow', 'WO_WFR', WOWfrID) LocDTMs = ThisWOWfrRec LocQs = ThisWOWfrRec Locate 'GGR*Q_DISP' in LocQs using @VM setting vPos then // Wafer has been dispositioned at some point, so update the disposition DTM LocDTMs<0, vPos> = CurrDTM ThisWOWfrRec = LocDTMs Database_Services('WriteDataRow', 'WO_WFR', WOWfrID, ThisWOWfrRec, True$, False$, True$) end Next WOWfrID Set_Property(@Window:'.PUB_UPDATE_DISP', 'ENABLED', True$) end GoSub UpdateDispData Disposition_Services('AutoDispositionRun', RDSNo) GoSub FillMetEditTable Set_Property(@Window, '@SINGLE_WFR_ID', '') GoSub FillDispEditTable end PrevCursor = Set_Property('SYSTEM', 'CURSOR', 'A') end event Event OLE_DISP_EDT.OnCheckChanged(Cell, OldValue, NewValue) RDSNo = Get_Property(@Window:'.RDS_NO', 'TEXT') ReactRunRec = Database_Services('ReadDataRow', 'REACT_RUN', RDSNo) Col = Field(Cell, ';', 1, 1) Row = Field(Cell, ';', 2, 1) NCRButton = '' Begin Case Case Col EQ COL$DISP_EXTERNAL ExternalFlags = ReactRunRec ExternalFlags<0, Row> = NewValue ReactRunRec = ExternalFlags Database_Services('WriteDataRow', 'REACT_RUN', RDSNo, ReactRunRec, True$, False$, True$) If Error_Services('NoError') then Disposition_Services('AutoDispositionRun', RDSNo) Engineering_Services('PostEARequest', RDSNo, 'CHAR') GoSub FillDispEditTable end Case Col EQ COL$DISP_RDS_NCR // The checkbox is only used for creating NCRs. We don't need to save anything at this time. // Check (no pun intended) if any of the checkboxes in this column are True$. If so, then enable // the "Create NCR" button, otherwise disable it. GoSub EnableNCRButton End Case end event Event COMBO_PRIORITY.CHANGED(NewData) Priority = NewData RDSNo = Get_Property(@Window:'.RDS_NO', 'TEXT') ReactRunRec = Database_Services('ReadDataRow', 'REACT_RUN', RDSNo) ReactRunRec = Priority Database_Services('WriteDataRow', 'REACT_RUN', RDSNo, ReactRunRec, True$, False$, True$) end event Event CMB_GAN_ETCH_ID.DROPDOWN(EditLineText) /* If ETCH stage complete, then display dropdown of all external etch IDs bound to this RDS. If ETCH stage is not complete, then provide a popup of all available etch IDs and allow the user to select multiple external etch IDs to bind to the RDS */ RDSNo = Get_Property(@Window:'.RDS_NO', 'TEXT') LogData = '' LogData<1> = OConv(Datetime(), 'DT') LogData<2> = RDSNo LogData<3> = @User4 LogData<4> = 'Begin dropdown event.' Logging_Services('AppendLog', objLog, LogData, @RM, @FM, True$) EtchStageKey = RDSNo:'*ETCH' EtchStageStatus = Xlate('RUN_STAGE', EtchStageKey, 'STATUS', 'X') LogData<4> = 'Etch Stage Status: ':EtchStageStatus Logging_Services('AppendLog', objLog, LogData, @RM, @FM, True$) If EtchStageStatus _NEC 'COMP' then // Open the External Etch Manager so that users can select one or more internal and external etch ID(s) to // bind to this RDS (REACT_RUN) record. Reactor = Get_Property(@Window, '@REACTOR') LogData<4> = 'Reactor: ':Reactor Logging_Services('AppendLog', objLog, LogData, @RM, @FM, True$) If (Reactor NE '') then SelEtchIDs = '' SelEtchIDs = Dialog_Box('NDW_EXTERNAL_ETCH_MANAGER', @Window, Reactor) LogEtchIDs = SelEtchIDs Convert @FM to ',' in LogEtchIDs LogData<4> = 'Selected etch IDs: ':LogEtchIDs Logging_Services('AppendLog', objLog, LogData, @RM, @FM, True$) // If SelEtchIDs is equal to False$ (0) then the user canceled the external etch selection process. If SelEtchIDs NE False$ then SelIntEtchIDs = SelEtchIDs<1> SelExtEtchIDs = SelEtchIDs<2> // Update RUN_STAGE record RunStageKey = RDSNo:'*ETCH' RunStageRec = Database_Services('ReadDataRow', 'RUN_STAGE', RunStageKey) If Error_Services('NoError') then CurrDTM = DateTime() RunStageRec = @User4 RunStageRec = CurrDTM RunStageRec = 'COMP' RunStageRec = SelIntEtchIDs Database_Services('WriteDataRow', 'RUN_STAGE', RunStageKey, RunStageRec, True$, False$, True$) If Error_Services('NoError') then // Update REACT_RUN record NumExtEtchIDs = DCount(SelExtEtchIDs, @VM) LastExtEtchID = SelExtEtchIDs<0, NumExtEtchIDs> ExtEtchRecipes = '' Set_Property(@Window:'.CMB_GAN_ETCH_ID', 'LIST', SelExtEtchIDs) Set_Property(@Window:'.CMB_GAN_ETCH_ID', 'SELPOS', -1) Set_Property(@Window:'.CMB_GAN_RUN_ID', 'ENABLED', True$) For each ExtEtchID in SelExtEtchIDs using @VM setting vPos If ExtEtchID _NEC 'No Etch Required' then LogData<4> = 'Calling Gan_Services("GetRunInfo", ':ExtEtchID:').' Logging_Services('AppendLog', objLog, LogData, @RM, @FM, True$) GaNEtchInfo = Gan_Services('GetRunInfo', ExtEtchID) If Error_Services('NoError') then LogData<4> = 'Call to Gan_Services("GetRunInfo", ':ExtEtchID:') was successful.' Logging_Services('AppendLog', objLog, LogData, @RM, @FM, True$) end else LogData<4> = 'Error Calling Gan_Services("GetRunInfo", ':ExtEtchID:').' Logging_Services('AppendLog', objLog, LogData, @RM, @FM, True$) end ExtEtchRecipes<0, -1> = GaNEtchInfo<1,1> LogData<4> = 'Calling Gan_Services("ConsumeExtEtchID", ':ExtEtchID:').' Logging_Services('AppendLog', objLog, LogData, @RM, @FM, True$) GaN_Services('ConsumeExtEtchID', ExtEtchID) If Error_Services('NoError') then LogData<4> = 'Call to Gan_Services("ConsumeExtEtchID", ':ExtEtchID:') was successful.' Logging_Services('AppendLog', objLog, LogData, @RM, @FM, True$) end else ErrorMessage = Error_Services('GetMessage') LogData<4> = 'Error Calling Gan_Services("ConsumeExtEtchID", ':ExtEtchID:'). Error message: ':ErrorMessage Logging_Services('AppendLog', objLog, LogData, @RM, @FM, True$) end end else ExtEtchRecipes = 'Not Applicable' end Next ExtEtchID LastExtEtchRecipe = ExtEtchRecipes<0, NumExtEtchIDs> Set_Property(@Window:'.ETCH_RECIPE', 'TEXT', LastExtEtchRecipe) ReactRunRec = Database_Services('ReadDataRow', 'REACT_RUN', RDSNo) If Error_Services('NoError') then ReactRunRec = SelExtEtchIDs ReactRunRec = ExtEtchRecipes Database_Services('WriteDataRow', 'REACT_RUN', RDSNo, ReactRunRec, True$, False$, True$) If Error_Services('NoError') then For each IntEtchID in SelIntEtchIDs using @VM setting vPos LogData<4> = 'Calling Gan_Services("ConsumeIntEtchID", ':IntEtchID:').' Logging_Services('AppendLog', objLog, LogData, @RM, @FM, True$) GaN_Services('ConsumeIntEtchID', IntEtchID) If Error_Services('NoError') then LogData<4> = 'Call to Gan_Services("ConsumeIntEtchID", ':IntEtchID:') was successful.' Logging_Services('AppendLog', objLog, LogData, @RM, @FM, True$) end else ErrorMessage = Error_Services('GetMessage') LogData<4> = 'Error Calling Gan_Services("ConsumeIntEtchID", ':IntEtchID:'). Error message: ':ErrorMessage Logging_Services('AppendLog', objLog, LogData, @RM, @FM, True$) end Next IntEtchID // Update the UI Row = 1 ; // Etch Configuration Row Set_Property(@Window:'.OLE_REACTOR_EDT', "OLE.CellText[2; ":Row:"]", 'Complete') Set_Property(@Window:'.CMB_GAN_RUN_ID', 'ENABLED', True$) end else ErrorMessage = Error_Services('GetMessage') LogData<4> = 'Error writing REACT_RUN record: ':RDSNo:'. Error message: ':ErrorMessage:'.' Logging_Services('AppendLog', objLog, LogData, @RM, @FM, True$) end end else ErrorMessage = Error_Services('GetMessage') LogData<4> = 'Error reading REACT_RUN record: ':RDSNo:'. Error message: ':ErrorMessage:'.' Logging_Services('AppendLog', objLog, LogData, @RM, @FM, True$) end end else ErrorMessage = Error_Services('GetMessage') LogData<4> = 'Error writing RUN_STAGE record: ':RunStageKey:'. Error message: ':ErrorMessage:'.' Logging_Services('AppendLog', objLog, LogData, @RM, @FM, True$) end end else ErrorMessage = Error_Services('GetMessage') LogData<4> = 'Error reading RUN_STAGE record: ':RunStageKey:'. Error message: ':ErrorMessage:'.' Logging_Services('AppendLog', objLog, LogData, @RM, @FM, True$) end end end else ErrorMsg = 'Reactor number is missing. Unable to complete ETCH stage.' ErrMsg(ErrorMsg) end end If Error_Services('NoError') then LogData<4> = 'Dropdown event successful.' Logging_Services('AppendLog', objLog, LogData, @RM, @FM, True$) end else LogData<4> = 'Error in dropdown event.' Logging_Services('AppendLog', objLog, LogData, @RM, @FM, True$) end LogData<4> = 'End dropdown event.' Logging_Services('AppendLog', objLog, LogData, @RM, @FM, True$) end event //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Internal GoSubs //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// Setup_OLE_Controls: NumReactorCols = 2 NumReactorRows = 4 NumMetCols = 10 NumMetRows = 21 NumDispCols = 14 NumDispRows = 8 NumNCRCols = 9 NumNCRRows = 8 ReactorCtrlList = '' MetCtrlList = '' DispCtrlList = '' ReactorToolIDArray = '' MetToolIDArray = '' GaNStageArray = Database_Services('ReadDataRow', 'APP_INFO', 'GAN_STAGES') Set_Property(@Window, '@GAN_STAGES', GaNStageArray) ReactorStageIndex = 1 MetStageIndex = 1 For each Row in GaNStageArray using @FM setting fPos StageDesc = Row<0,2> ToolClassIDs = Row<0,3> RunType = Row<0,5> Begin Case Case RunType EQ 'Reactor' ReactorCtrlList = StageDesc ReactorStageIndex += 1 Case RunType EQ 'Metrology' MetCtrlList = StageDesc TempArray = '' MetCtrlList = 'Select' For each ToolClassID in ToolClassIDs using @SVM setting svPos ToolIDs = Xlate('TOOL_CLASS', ToolClassID, 'TOOL', 'X') ProdTools = '' For each ToolID in ToolIDs using @VM setting vPos CurrMode = Xlate('TOOL', ToolID, 'CURR_MODE', 'X') If CurrMode EQ 'PROD' then ProdTools<0, -1> = ToolID Next ToolID Convert @VM to @STM in ProdTools TempArray = SRP_Array('Join', TempArray, ProdTools, 'OR', @STM) Next ToolClassID If TempArray[-1, 1] EQ @STM then TempArray[-1, 1] = '' MetToolIDArray = TempArray MetStageIndex += 1 End Case Next Row RDSNo = Get_Property(@Window : '.RDS_NO', 'DEFPROP') ReactRunRec = Database_Services('ReadDataRow', 'REACT_RUN', RDSNo) WfrIDs = ReactRunRec Scribes = Xlate('REACT_RUN', RDSNo, 'WFR_SCRIBES', 'X') CarrSlotIDs = ReactRunRec Slots = ReactRunRec NumWfrs = DCount(Scribes, @VM) Set_Property(@Window, '@SCRIBES', Scribes) Set_Property(@Window, '@CARRSLOTIDS', CarrSlotIDs) Set_Property(@Window, '@NUMWFRS', NumWfrs) Set_Property(@Window, '@WFRIDS', WfrIDs) Set_Property(@Window, '@SLOTS', Slots) NumDummyWfrs = 0 DummyPockets = '' NumEmptyWfrs = 0 EmptyPockets = '' For each Scribe in Scribes using @VM setting vPos DummyID = GanRunID[1,7]:'D' EmptyID = GaNRunID[1,7]:'E' If Scribe[1,8] EQ DummyID then NumDummyWfrs += 1 DummyPockets<1, vPos> = True$ end If Scribe[1,8] EQ EmptyID then NumEmptyWfrs += 1 EmptyPockets<1, vPos> = True$ end Next Scribe Set_Property(@Window, '@DUMMYPOCKETS', DummyPockets) Set_Property(@Window, '@EMPTYPOCKETS', EmptyPockets) SuscUnloaded = False$ If NumWfrs GT 0 then // Wafers have not yet been unloaded from the susceptor. We will use this flag to // deactivate various control elements. SuscUnloaded = True$ end ReactorStageCtrl = @Window:'.OLE_REACTOR_EDT' MetStageCtrl = @Window:'.OLE_METROLOGY_EDT' DispStageCtrl = @Window:'.OLE_DISP_EDT' NCRCtrl = @Window:'.OLE_NCR_EDT' HeaderFontArray = 'Segoe UI':@SVM:8:@SVM:700 ReactorDimArray = NumReactorCols :@FM: NumReactorRows MetDimArray = NumMetCols :@FM: NumMetRows DispDimArray = NumDispCols :@FM: NumDispRows NCRDimArray = NumNCRCols :@FM: NumNCRRows Set_Property(@Window, '@METDIMARRAY', MetDimArray) Set_Property(@Window, '@DISPDIMARRAY', DispDimArray) Set_Property(ReactorStageCtrl, "OLE.CellFont[All; All]", 'Segoe UI':@SVM:8) Set_Property(ReactorStageCtrl, "OLE.Dimension", ReactorDimArray) Set_Property(ReactorStageCtrl, "OLE.CellFont[1;All]", HeaderFontArray) Set_Property(ReactorStageCtrl, "OLE.LIST", ReactorCtrlList) Set_Property(ReactorStageCtrl, "OLE.HeaderFont[All; 1]", HeaderFontArray) Set_Property(ReactorStageCtrl, "OLE.HeaderFont[1; All]", HeaderFontArray) Set_Property(MetStageCtrl, "OLE.CellFont[All; All]", 'Segoe UI':@SVM:8) Set_Property(MetStageCtrl, "OLE.Dimension", MetDimArray) Set_Property(MetStageCtrl, "OLE.CellFont[1;All]", HeaderFontArray) Set_Property(MetStageCtrl, "OLE.LIST", MetCtrlList) Set_Property(MetStageCtrl, "OLE.HeaderFont[All; 1]", HeaderFontArray) Set_Property(MetStageCtrl, "OLE.HeaderFont[1; All]", HeaderFontArray) Set_Property(DispStageCtrl, "OLE.CellFont[All; All]", 'Segoe UI':@SVM:8) Set_Property(DispStageCtrl, "OLE.Dimension", DispDimArray) Set_Property(DispStageCtrl, "OLE.HeaderFont[All; 1]", HeaderFontArray) Set_Property(DispStageCtrl, "OLE.HeaderFont[1; All]", HeaderFontArray) Set_Property(NCRCtrl, "OLE.CellFont[All; All]", 'Segoe UI':@SVM:8) Set_Property(NCRCtrl, "OLE.Dimension", NCRDimArray) Set_Property(NCRCtrl, "OLE.HeaderFont[All; 1]", HeaderFontArray) Set_Property(NCRCtrl, "OLE.HeaderFont[1; All]", HeaderFontArray) ScribesCopy = Scribes Convert @VM to '' in ScribesCopy HeaderTitles = "Stage":@VM:"Tool ID" If ScribesCopy NE '' then For each Scribe in Scribes using @VM setting vPos SlotID = Field(CarrSlotIDs<0, vPos>, '.', 2, 1) HeaderTitles<0, -1> = Scribe:' (':SlotID:')' Next Scribe end else DefWfrTitles = '' For WfrIndex = 1 to NumWfrs DefWfrTitles<1, -1> = 'Wafer ':WfrIndex Next WfrIndex HeaderTitles = "Stage":@VM:"Tool ID":@VM:DefWfrTitles end ReactorNo = Get_Property(@Window, '@REACTOR') ReactorHeaderTitles = "Stage":@VM:"Status" Set_Property(ReactorStageCtrl, "OLE.TitleList", ReactorHeaderTitles) Set_Property(ReactorStageCtrl, "OLE.HeaderMerge[1; 2]", 1:@FM:NumReactorRows) Set_Property(ReactorStageCtrl, "OLE.HeaderText[1; 2]", 'Reactor ':ReactorNo) Set_Property(ReactorStageCtrl, "OLE.HeaderAlignment[All; 1]", 'C':@FM:'C':@FM:'L') Set_Property(ReactorStageCtrl, "OLE.CellAlignment[All; All]", 'C':@FM:'C':@FM:'L') Set_Property(ReactorStageCtrl, "OLE.CellAlignment[1; All]", 'C':@FM:'L':@FM:'L') Set_Property(ReactorStageCtrl, "OLE.AllowDeletions", False$) Set_Property(ReactorStageCtrl, "OLE.AllowInserts", False$) Set_Property(MetStageCtrl, "OLE.TitleList", HeaderTitles) Set_Property(MetStageCtrl, "OLE.HeaderMerge[1; 2]", 1:@FM:NumMetRows) Set_Property(MetStageCtrl, "OLE.HeaderText[1; 2]", 'Metrology') Set_Property(MetStageCtrl, "OLE.HeaderAlignment[All; 1]", 'C':@FM:'C':@FM:'L') Set_Property(MetStageCtrl, "OLE.CellAlignment[All; All]", 'C':@FM:'C':@FM:'L') Set_Property(MetStageCtrl, "OLE.CellAlignment[1; All]", 'C':@FM:'L':@FM:'L') Set_Property(MetStageCtrl, "OLE.AllowDeletions", False$) Set_Property(MetStageCtrl, "OLE.AllowInserts", False$) DispHeaderTitles = 'Slot':@VM:'Wfr ID':@VM:'Scribe':@VM:'Grade':@VM:'Reason':@VM:'RDS NCR':@VM:'WMO NCR':@VM | :'Ship':@VM:'Ship ID':@VM:'Internal':@VM:'External':@VM:'Retain':@VM:'Retain Box':@VM:'Retain Slot' Set_Property(DispStageCtrl, "OLE.TitleList", DispHeaderTitles) Set_Property(DispStageCtrl, "OLE.HeaderMerge[1; 2]", 1:@FM:NumDispRows) Set_Property(DispStageCtrl, "OLE.HeaderText[1; 2]", 'Disposition') Set_Property(DispStageCtrl, "OLE.HeaderAlignment[All; 1]", 'C':@FM:'C':@FM:'L') Set_Property(DispStageCtrl, "OLE.CellAlignment[All; All]", 'C':@FM:'C':@FM:'L') Set_Property(DispStageCtrl, "OLE.AllowDeletions", False$) Set_Property(DispStageCtrl, "OLE.AllowInserts", False$) NCRHeaderTitles = 'NCR':@VM:'Status':@VM:'Qty':@VM:'Responsible':@VM:'Stage':@VM:'Loss Desc':@VM:'Loss Comments' | :@VM:'Signature':@VM:'Date & Time' Set_Property(NCRCtrl, "OLE.TitleList", NCRHeaderTitles) Set_Property(NCRCtrl, "OLE.HeaderMerge[1; 2]", 1:@FM:NumNCRRows) Set_Property(NCRCtrl, "OLE.HeaderText[1; 2]", 'Scrap') Set_Property(NCRCtrl, "OLE.HeaderAlignment[All; 1]", 'C':@FM:'C':@FM:'L') Set_Property(NCRCtrl, "OLE.CellAlignment[All; All]", 'C':@FM:'C':@FM:'L') Set_Property(NCRCtrl, "OLE.AllowDeletions", False$) Set_Property(NCRCtrl, "OLE.AllowInserts", False$) // Set default header colors HeaderColorArray = '' HeaderColorArray<1> = 'Auto' HeaderColorArray<2> = 'None' HeaderColorArray<3> = 'None' HeaderColorArray<4> = OI_HOT_BLUE$ HeaderColorARray<5> = False$ Set_Property(ReactorStageCtrl, "OLE.HeaderColors[All; All]", HeaderColorArray) Set_Property(MetStageCtrl, "OLE.HeaderColors[All; All]", HeaderColorArray) Set_Property(DispStageCtrl, "OLE.HeaderColors[All; All]", HeaderColorArray) Set_Property(NCRCtrl, "OLE.HeaderColors[All; All]", HeaderColorArray) // Set header tooltips (wafer comments) For each WfrID in WfrIDs using @VM setting WfrIndex WfrComments = '' WfrComments = Xlate('WO_WFR', WfrID, 'COMMENTS', 'X') ColNo = WfrIndex + 3 If WfrComments NE '' then Set_Property(MetStageCtrl, "OLE.HeaderToolTip[":ColNo:";1]", WfrComments) // Set header to light cyan so the user knows there's a comment HeaderColors = Get_Property(MetStageCtrl, "OLE.HeaderColors[":ColNo:";1]") HeaderColors<2> = 'LightCyan' HeaderColors<4> = 'LightCyan' Set_Property(MetStageCtrl, "OLE.HeaderColors[":ColNo:";1]", HeaderColors) end Next WfrID // Qualify OLE events that we want to intercept Qualifier = '' Qualifier<1> = 1 Qualifier<4> = 0 ; * process synchronously (i.e. immediately) Send_Message(ReactorStageCtrl, 'QUALIFY_EVENT', 'OLE.OnClick', Qualifier) Send_Message(ReactorStageCtrl, 'QUALIFY_EVENT', 'OLE.OnButtonClick', Qualifier) Send_Message(ReactorStageCtrl, 'QUALIFY_EVENT', 'OLE.OnContextMenuClick', Qualifier) Send_Message(MetStageCtrl, 'QUALIFY_EVENT', 'OLE.OnClick', Qualifier) Send_Message(MetStageCtrl, 'QUALIFY_EVENT', 'OLE.PosChanged', Qualifier) Send_Message(MetStageCtrl, 'QUALIFY_EVENT', 'OLE.OnButtonClick', Qualifier) Send_Message(MetStageCtrl, 'QUALIFY_EVENT', 'OLE.OnComboClicked', Qualifier) Send_Message(MetStageCtrl, 'QUALIFY_EVENT', 'OLE.OnContextMenuClick', Qualifier) Send_Message(MetStageCtrl, 'QUALIFY_EVENT', 'OLE.OnHeaderDblClick', Qualifier) Send_Message(DispStageCtrl, 'QUALIFY_EVENT', 'OLE.OnCheckChanged', Qualifier) Send_Message(DispStageCtrl, 'QUALIFY_EVENT', 'OLE.AfterUpdate', Qualifier) Send_Message(DispStageCtrl, 'QUALIFY_EVENT', 'OLE.OnClick', Qualifier) Send_Message(DispStageCtrl, 'QUALIFY_EVENT', 'OLE.OnContextMenuClick', Qualifier) Send_Message(NCRCtrl, 'QUALIFY_EVENT', 'OLE.OnDblClick', Qualifier) // Setup Tool ID and Wafer status/action combo boxes CellTypeArray = "" CellTypeArray<1> = "Combo" CellTypeArray<2, 1> = "" CellTypeArray<2, 2> = "L" CellTypeArray<2, 3> = '' CellTypeArray<2, 4> = 1 ;// Column 1 contains the values we care about CellTypeArray<2, 5> = 1 ;// Auto fill on CellTypeArray<2, 6> = 0 ;// Case sensitive on CellTypeArray<2, 7> = 10 ;// 10 visible rows max CellTypeArray<2, 8> = 0 ;// Don't fire the OnOptionClick CellTypeArray<2, 9> = 1 ;// Reduce the list to partial matches CellTypeArray<2, 10> = 0 ;// Only show the drop down when the user types CellTypeArray<2, 11> = 0 ;// Do not use LIST Format CellTypeArray<2, 12> = 1 ;// Autofill on Tool ID name CellTypeArray<2, 13> = 1 ;// Hide dropdown when user clears cell CellTypeArray<2, 14> = 0 ;// Let navigation keys show the drop down CellTypeArray<2, 15> = 0 ;// Show the drop down regardless of the cell's contents CellTypeArray<2, 16> = 0 ;// Show the drop down during autofill CellTypeArray<2, 17> = 1 ;// Remove selection when user backspaces/deletes CellTypeArray<2, 18> = 0 ;// Show Popup while in read only mode CellTypeArray<2, 19> = 1 ;// Show Popup When Navigating CellTypeArray<2, 20> = 1 ;// Always Tab Out on Enter CellTypeArray<2, 21> = -1 ;// Always show the dropdown above when close to the screen bottom CellTypeArray<2, 23> = 1 ;// Limit possible values to those in dropdown // Store this for later use elsewhere Set_Property(@Window, '@COMBOBOX', CellTypeArray) For RowIndex = 1 to NumMetRows ThisComboArray = CellTypeArray ThisComboArray<2, 3> = MetToolIDArray Set_Property(MetStageCtrl, "OLE.CellType[2; ":RowIndex:"]", ThisComboArray) Next RowIndex // Cell selection style setup Set_Property(ReactorStageCtrl, "OLE.ResetSelPos", False$) ;// Prevent cell selection from being reset upon lost focus event Set_Property(MetStageCtrl, "OLE.ResetSelPos", False$) Set_Property(DispStageCtrl, "OLE.ResetSelPos", False$) Set_Property(NCRCtrl, "OLE.ResetSelPos", False$) ReactorSelStyleArray = Get_Property(ReactorStageCtrl, "OLE.SelectionStyle") ReactorSelStyleArray<8> = True$ MetSelStyleArray = Get_Property(MetStageCtrl, "OLE.SelectionStyle") MetSelStyleArray<8> = True$ ;// Keep cell highlighted when table loses focus DispSelStyleArray = Get_Property(DispStageCtrl, "OLE.SelectionStyle") DispSelStyleArray<8> = True$ ;// Keep cell highlighted when table loses focus NCRSelStyleArray = Get_Property(NCRCtrl, "OLE.SelectionStyle") NCRSelStyleArray<8> = True$ ;// Keep cell highlighted when table loses focus Set_Property(ReactorStageCtrl, 'OLE.SelectionStyle', ReactorSelStyleArray) Set_Property(MetStageCtrl, 'OLE.SelectionStyle', MetSelStyleArray) Set_Property(DispStageCtrl, 'OLE.SelectionStyle', DispSelStyleArray) Set_Property(NCRCtrl, 'OLE.SelectionStyle', MCRSelStyleArray) CellSelStyleArray = '' CellSelStyleArray<1> = 'White' ;// Selected cell foreground color CellSelStyleArray<2> = OI_BLUE$ ;// Selected cell background color CellSelStyleArray<3> = 'None' ;// Selected record (row) foreground color - none = default CellSelStyleArray<4> = OI_HOT_BLUE$ ;// Selected record (row) background color CellSelStyleArray<5> = 'None' ;// Selected field (column) foreground color - none = default CellSelStyleArray<6> = OI_HOT_BLUE$ ;// Selected field (column) background color Set_Property(ReactorStageCtrl, 'OLE.CellSelColors[2; All]', CellSelStyleArray) Set_Property(MetStageCtrl, 'OLE.CellSelColors[2-':NumDummyWfrs+2:'; All]', CellSelStyleArray) Set_Property(NCRCtrl, 'OLE.CellSelColors[All; All]', CellSelStyleArray) // Stage cell button style setup ButtonTypeArray = '' ButtonTypeArray<1> = 'Push Button' ButtonTypeArray<2> = '' ButtonTypeArray<2, 1> = False$ ButtonTypeArray<2, 2> = True$ ButtonTypeArray<2, 3> = True$ ButtonTypeArray<3> = 'None' ButtonTypeArray<4> = "Vertical(Gradient(":OI_HOT_BLUE$:", ":OI_HOT_BLUE$:"), Border(":OI_BLUE$:"))" ButtonTypeArray<5> = "Vertical(Gradient(":OI_CLICK_BLUE$:", ":OI_CLICK_BLUE$:"), Border(":OI_BLUE$:"))" ButtonTypeArray<6> = 'OD' ButtonTypeArray<7> = 'None' Set_Property(ReactorStageCtrl, "OLE.CellType[1; All]", ButtonTypeArray) Set_Property(MetStageCtrl, "OLE.CellType[1; All]", ButtonTypeArray) MetRowsEnabled = '' For RowIndex = 1 to NumMetRows MetRowsEnabled = False$ Next RowIndex // Get associated run stage keys and check them for assigned Tool IDs. If Tool ID is // set, then set the Tool ID combo box selection accordingly. ReactorStageList = Get_Property(ReactorStageCtrl, "OLE.ColumnData[1]") MetStageList = Get_Property(MetStageCtrl, "OLE.ColumnData[1]") ReactorStageIDList = '' MetStageIDList = '' For each StageDesc in ReactorStageList using @VM setting vPos ReactorStageIDList<1, vPos> = Gan_Services('GetStageID', StageDesc) Next StageDesc For each StageDesc in MetStageList using @VM setting vPos MetStageIDList<1, vPos> = Gan_Services('GetStageID', StageDesc) Next StageDesc Set_Property(@Window, '@METSTAGEIDLIST', MetStageIDList) RunStageKeys = ReactRunRec MetStages = ReactRunRec Set_Property(@Window, '@METTOOLIDARRAY', MetToolIDArray) // Protect and color dummy and empty wafer columns ColorArray = @FM:'OD' CellColorArray = 'None':@FM:'None':@FM:'None':@FM:'None':@FM:'None' For each Pocket in DummyPockets using @VM setting vPos If Pocket EQ True$ then ColNo = vPos + 2 Set_Property(MetStageCtrl,"OLE.CellProtection[":ColNo:"; All]", "Full") Set_Property(MetStageCtrl,"OLE.CellColors[":ColNo:"; All]", ColorArray) Set_Property(MetStageCtrl,"OLE.ColumnData[":ColNo:"]", '') Set_Property(MetStageCtrl,"OLE.HeaderColors[":ColNo+1:"; 1]", ColorArray) end Next Pocket For each Pocket in EmptyPockets using @VM setting vPos If Pocket EQ True$ then ColNo = vPos + 2 Set_Property(MetStageCtrl,"OLE.CellProtection[":ColNo:"; All]", "Full") Set_Property(MetStageCtrl,"OLE.CellColors[":ColNo:"; All]", ColorArray) Set_Property(MetStageCtrl,"OLE.ColumnData[":ColNo:"]", '') Set_Property(MetStageCtrl,"OLE.HeaderColors[":ColNo+1:"; 1]", ColorArray) end Next Pocket // Protect and color N/A wafer columns If NumWfrs < 8 then ; // 8 wafers make a full cassette in GaN StartCol = NumWfrs + 3 ; // Must add the three columns before the wafer columns Set_Property(MetStageCtrl,"OLE.CellProtection[":StartCol:"-":NumMetCols:"; All]", "Full") Set_Property(MetStageCtrl,"OLE.CellColors[":StartCol:"-":NumMetCols:"; All]", ColorArray) Set_Property(MetStageCtrl,"OLE.ColumnData[":StartCol:"-":NumMetCols:"]", '') Set_Property(MetStageCtrl,"OLE.HeaderColors[":StartCol+1:"-":NumMetCols+1:"; 1]", ColorArray) end // Get and set each cassette's current status for each reactor stage // Cassette level (RUN_STAGE) For each Stage in ReactorStageIDList using @VM setting StageIndex RunStageKey = RDSNo:'*':Stage If RowExists('RUN_STAGE', RunStageKey) then CurrStatus = Xlate('RUN_STAGE', RunStageKey, 'STATUS', 'X') DispStatus = '' Begin Case Case CurrStatus _EQC 'COMP' DispStatus = 'Complete' Case CurrStatus _EQC 'STOP' Begin Case Case Stage _EQC 'GROWTH' DispStatus = 'Unload' Case Otherwise$ DispStatus = 'Stop' End Case Case CurrStatus _EQC 'START' If Stage EQ 'GROWTH' then DispStatus = 'Load' end else DispStatus = 'Start' end Case CurrStatus _EQC 'SKIP' DispStatus = 'Skip' Case Otherwise$ DispStatus = 'X' End Case Set_Property(ReactorStageCtrl, "OLE.CellText[2; ":StageIndex:"]", DispStatus) Set_Property(ReactorStageCtrl, "OLE.CellProtection[2; ":StageIndex:"]", "RO") end Next Stage // Get and set each wafer's current status for each stage within the Metrology and Disposition edit tables. GoSub FillMetEditTable //////////////////////////////////// Code below here only runs once ////////////////////////////////////////// FirstPassComp = Get_Property(@Window, '@FIRSTPASS') If FirstPassComp EQ '' or FirstPassComp EQ False$ then Set_Property(@Window, '@FIRSTPASS', True$) // Disable resizing of the header row and header column // Resize header column to fit contents HeaderRowArray = Get_Property(MetStageCtrl, "OLE.HeaderRow[1]") HeaderColArray = Get_Property(MetStageCtrl, "OLE.HeaderColumn[1]") HeaderRowArray<3> = False$ HeaderColArray<1> = 80 HeaderColArray<3> = False$ Set_Property(MetStageCtrl, "OLE.HeaderColumn[1]", HeaderColArray) Set_Property(MetStageCtrl, "OLE.HeaderRow[1]", HeaderRowArray) // Disable resizing of columns as there is no need for this on this form StageColSize = Get_Property(MetStageCtrl, "OLE.DataColumn[1]") StageColSize<3> = False$ Set_Property(MetStageCtrl, "OLE.DataColumn[All]", StageColSize) // Resize the stage column to fit stage descriptions StageColSize<1> = 186 Set_Property(MetStageCtrl, "OLE.DataColumn[1]", StageColSize) WfrColSize = Get_Property(MetStageCtrl, "OLE.DataColumn[3]") WfrColSize<1> = 96 Set_Property(MetStageCtrl, "OLE.DataColumn[3-10]", WfrColSize) // Disable resizing of rows as there is no need for this on this form RowSizeProps = Get_Property(MetStageCtrl, "OLE.DataRow[1]") RowSizeProps<3> = False$ Set_Property(MetStageCtrl, "OLE.DataRow[All]", RowSizeProps) // Disable resizing of the header row and header column // Resize header column to fit contents HeaderRowArray = Get_Property(ReactorStageCtrl, "OLE.HeaderRow[1]") HeaderColArray = Get_Property(ReactorStageCtrl, "OLE.HeaderColumn[1]") HeaderRowArray<3> = False$ HeaderColArray<1> = 80 HeaderColArray<3> = False$ Set_Property(ReactorStageCtrl, "OLE.HeaderColumn[1]", HeaderColArray) Set_Property(ReactorStageCtrl, "OLE.HeaderRow[1]", HeaderRowArray) // Disable resizing of columns as there is no need for this on this form StageColSize = Get_Property(ReactorStageCtrl, "OLE.DataColumn[1]") StageColSize<3> = False$ Set_Property(ReactorStageCtrl, "OLE.DataColumn[All]", StageColSize) // Resize the stage column to fit stage descriptions StageColSize<1> = 186 Set_Property(ReactorStageCtrl, "OLE.DataColumn[1]", StageColSize) // Disable resizing of rows as there is no need for this on this form RowSizeProps = Get_Property(ReactorStageCtrl, "OLE.DataRow[1]") RowSizeProps<3> = False$ Set_Property(ReactorStageCtrl, "OLE.DataRow[All]", RowSizeProps) //////////////////////////////////// Setup Disposition OLE Edit Table ////////////////////////////////////////// // Disable resizing of the header row and header column // Resize header column to fit contents HeaderRowArray = Get_Property(DispStageCtrl, "OLE.HeaderRow[1]") HeaderColArray = Get_Property(DispStageCtrl, "OLE.HeaderColumn[1]") HeaderRowArray<3> = False$ HeaderColArray<1> = 80 HeaderColArray<3> = False$ Set_Property(DispStageCtrl, "OLE.HeaderColumn[1]", HeaderColArray) Set_Property(DispStageCtrl, "OLE.HeaderRow[1]", HeaderRowArray) // Disable resizing of columns as there is no need for this on this form StageColSize = Get_Property(DispStageCtrl, "OLE.DataColumn[1]") StageColSize<3> = False$ Set_Property(DispStageCtrl, "OLE.DataColumn[All]", StageColSize) // 1,034 px wide // Disposition OLE Edit Table WfrColSize = Get_Property(DispStageCtrl, "OLE.DataColumn[3]") WfrColSize<1> = 79 Set_Property(DispStageCtrl, "OLE.DataColumn[":COL$DISP_SLOT:"-":COL$DISP_RETAIN_BOX:"]", WfrColSize) // Slot column WfrColSize<1> = 30 Set_Property(DispStageCtrl, "OLE.DataColumn[":COL$DISP_SLOT:"]", WfrColSize) // Wfr ID column WfrColSize<1> = 86 Set_Property(DispStageCtrl, "OLE.DataColumn[":COL$DISP_WFR_ID:"]", WfrColSize) // Reason column WfrColSize<1> = 147 Set_Property(DispStageCtrl, "OLE.DataColumn[":COL$DISP_REASON:"]", WfrColSize) // NCR columns WfrColSize<1> = 85 Set_Property(DispStageCtrl, "OLE.DataColumn[":COL$DISP_RDS_NCR:"-":COL$DISP_WMO_NCR:"]", WfrColSize) // Ship column WfrColSize<1> = 60 Set_Property(DispStageCtrl, "OLE.DataColumn[":COL$DISP_SHIP:"]", WfrColSize) // Ship ID column WfrColSize<1> = 80 Set_Property(DispStageCtrl, "OLE.DataColumn[":COL$DISP_SHIP_ID:"]", WfrColSize) // Retain column WfrColSize<1> = 60 Set_Property(DispStageCtrl, "OLE.DataColumn[":COL$DISP_RETAIN:"]", WfrColSize) // Retain Slot columns WfrColSize<1> = 65 Set_Property(DispStageCtrl, "OLE.DataColumn[":COL$DISP_RETAIN_SLOT:"]", WfrColSize) // Internal column, External column, Retain column WfrColSize<1> = 50 Set_Property(DispStageCtrl, "OLE.DataColumn[":COL$DISP_INTERNAL:"-":COL$DISP_EXTERNAL:"]", WfrColSize) // Disable resizing of rows as there is no need for this on this form RowSizeProps = Get_Property(DispStageCtrl, "OLE.DataRow[1]") RowSizeProps<3> = False$ Set_Property(DispStageCtrl, "OLE.DataRow[All]", RowSizeProps) // Disable scrollbars Set_Property(DispStageCtrl, "OLE.ScrollBarsVisible", 'N':@FM:'N') CheckBoxArray = 'Check Box' CheckBoxArray<2,1> = True$ Set_Property(DispStageCtrl, "OLE.CellType[":COL$DISP_SHIP:"; All]", CheckBoxArray) Set_Property(DispStageCtrl, "OLE.CellType[":COL$DISP_RETAIN:"; All]", CheckBoxArray) Set_Property(DispStageCtrl, "OLE.CellType[":COL$DISP_INTERNAL:"; All]", CheckBoxArray) Set_Property(DispStageCtrl, "OLE.CellType[":COL$DISP_EXTERNAL:"; All]", CheckBoxArray) Set_Property(DispStageCtrl, "OLE.CellProtection[All; All]", 'RO') Set_Property(DispStageCtrl, "OLE.CellCheckEnabled[":COL$DISP_SHIP:"; All]", False$) Set_Property(DispStageCtrl, "OLE.CellCheckEnabled[":COL$DISP_RETAIN:"; All]", False$) Set_Property(DispStageCtrl, "OLE.CellCheckEnabled[":COL$DISP_INTERNAL:"; All]", False$) //////////////////////////////////// Setup NCR OLE Edit Table ////////////////////////////////////////////// // Disable resizing of the header row and header column // Resize header column to fit contents HeaderRowArray = Get_Property(NCRCtrl, "OLE.HeaderRow[1]") HeaderColArray = Get_Property(NCRCtrl, "OLE.HeaderColumn[1]") HeaderRowArray<3> = False$ HeaderColArray<1> = 80 HeaderColArray<3> = False$ Set_Property(NCRCtrl, "OLE.HeaderColumn[1]", HeaderColArray) Set_Property(NCRCtrl, "OLE.HeaderRow[1]", HeaderRowArray) // Disable resizing of columns as there is no need for this on this form ColSize = Get_Property(NCRCtrl, "OLE.DataColumn[1]") ColSize<3> = False$ ColSize<1> = 56 Set_Property(NCRCtrl, "OLE.DataColumn[":COL$NCR_NO:"]", ColSize) ColSize<1> = 45 Set_Property(NCRCtrl, "OLE.DataColumn[":COL$NCR_STATUS:"]", ColSize) ColSize<1> = 35 Set_Property(NCRCtrl, "OLE.DataColumn[":COL$NCR_REJ_QTY:"]", ColSize) ColSize<1> = 90 Set_Property(NCRCtrl, "OLE.DataColumn[":COL$NCR_RESP:"]", ColSize) ColSize<1> = 58 Set_Property(NCRCtrl, "OLE.DataColumn[":COL$NCR_STAGE:"]", ColSize) ColSize<1> = 140 Set_Property(NCRCtrl, "OLE.DataColumn[":COL$NCR_LOSS_DESC:"]", ColSize) ColSize<1> = 173 Set_Property(NCRCtrl, "OLE.DataColumn[":COL$NCR_LOSS_COMM:"]", ColSize) ColSize<1> = 100 Set_Property(NCRCtrl, "OLE.DataColumn[":COL$NCR_FIN_SIG:"]", ColSize) ColSize<1> = 120 Set_Property(NCRCtrl, "OLE.DataColumn[":COL$NCR_FIN_SIG_DTM:"]", ColSize) // Disable resizing of rows as there is no need for this on this form RowSizeProps = Get_Property(NCRCtrl, "OLE.DataRow[1]") RowSizeProps<3> = False$ Set_Property(NCRCtrl, "OLE.DataRow[All]", RowSizeProps) Set_Property(NCRCtrl, "OLE.CellProtection[":COL$NCR_NO:"-":COL$NCR_FIN_SIG_DTM:"; All]", 'SEL') // Color headers Set_Property(NCRCtrl, "OLE.HeaderColors[All; 1]", @FM:"{200, 200, 200}") // Set Loss Comments column to autosized so that the table resizes when scrollbars are necessary ColArray = Get_Property(NCRCtrl, "OLE.DataColumn[":COL$NCR_LOSS_COMM:"]") ColArray<4> = True$ Set_Property(NCRCtrl, "OLE.DataColumn[":COL$NCR_LOSS_COMM:"]", ColArray) end return AutoSelectToolID: EnabledColorArray = 'None':@FM:'None':@FM:'None':@FM:'None':@FM:'None' MetStageIDList = Get_Property(@Window, '@METSTAGEIDLIST') AllWfrIDs = Get_Property(@Window, '@WFRIDS') SingleWfrID = Get_Property(@Window, '@SINGLE_WFR_ID') If SingleWfrID NE '' then WfrIDs = SingleWfrID end else WfrIDs = AllWfrIDs end MetStageCtrl = @Window:'.OLE_METROLOGY_EDT' MetRowsEnabled = Get_Property(@Window, '@METROWSENABLED') MetToolIDArray = Get_Property(@Window, '@METTOOLIDARRAY') For each MetStage in MetStageIDList using @VM setting mPos If MetStage _NEC 'SPLIT' then RunStageWfrKey = '' For each WfrID in WfrIDs using @VM If WfrID NE '' then Locate WfrID in AllWfrIDs using @VM setting wPos then CurrWfrCol = wPos + 2 Convert '*' to '.' in WfrID Begin Case Case MetStage EQ 'UV_PRE' // Check if UV stage exists UVStageWfrKey = RDSNo:'*UV*':WfrID If RowExists('RUN_STAGE_WFR', UVStageWfrKey) then // Display this on the UV_PRE line RunStageWfrKey = UVStageWfrKey end else RunStageWfrKey = RDSNo:'*':MetStage:'*':WfrID end Case MetStage EQ 'CAN_PRE' // Check if CAN stage exists CanStageWfrKey = RDSNo:'*CAN*':WfrID If RowExists('RUN_STAGE_WFR', CanStageWfrKey) then // Display this on the CAN_PRE line RunStageWfrKey = CanStageWfrKey end else RunStageWfrKey = RDSNo:'*':MetStage:'*':WfrID end Case Otherwise$ RunStageWfrKey = RDSNo:'*':MetStage:'*':WfrID End Case KeyFound = RowExists('RUN_STAGE_WFR', RunStageWfrKey) If KeyFound EQ True$ then RunStageWfrRec = Database_Services('ReadDataRow', 'RUN_STAGE_WFR', RunStageWfrKey) ToolID = RunStageWfrRec If ToolID EQ '' then // Check to see how many tools exist for the current stage. If only one exists, then // auto-select it for convenience. ToolIDs = Gan_Services('GetToolIDs', MetStage, 'PROD') NumTools = DCount(ToolIDs, @VM) If NumTools EQ 1 then ToolID = ToolIDs<0, 1> RunStageWfrRec = ToolID Database_Services('WriteDataRow', 'RUN_STAGE_WFR', RunStageWfrKey, RunStageWfrRec, True$, False$, True$) end end If ToolID NE '' then Locate MetStage in MetStageIDList using @VM setting RowIndex then ThisComboArray = MetToolIDArray Convert @STM to @VM in ThisComboArray Locate ToolID in ThisComboArray using @VM setting vPos then Set_Property(MetStageCtrl, "OLE.CellComboSelPos[2; ":RowIndex:"]", vPos) end else Set_Property(MetStageCtrl, "OLE.CellText[2;":RowIndex:"]", ToolID) end // Tool ID is set, so enable wafer action dropdown menus. If ( (MetStage NE 'UV') and (MetStage NE 'UV_PRE') and (MetStage NE 'UV_PST') and (MetStage NE 'WARP') and (MetStage NE 'CAN') and (MetStage NE 'CAN_PRE') and (MetStage NE 'CAN_PST') and (MetStage NE 'WET_CLEAN') ) then Set_Property(MetStageCtrl,"OLE.CellProtection[":CurrWfrCol:"; ":RowIndex:"]","None") end MetRowsEnabled = True$ end end end end end Next WfrID end Next MetStage Set_Property(@Window, '@METROWSENABLED', MetRowsEnabled) return FillMetHeader: Scribes = Xlate('REACT_RUN', RDSNo, 'WAFER_SCRIBE', 'X') CarrSlotIDs = Xlate('REACT_RUN', RDSNo, 'CARR_SLOT_NO', 'X') Set_Property(@Window, '@SCRIBES', Scribes) Set_Property(@Window, '@CARRSLOTIDS', CarrSlotIDs) MetStageCtrl = @Window:'.OLE_METROLOGY_EDT' ScribesCopy = Scribes Convert @VM to '' in ScribesCopy HeaderTitles = "Stage":@VM:"Tool ID" If ScribesCopy NE '' then For each Scribe in Scribes using @VM setting vPos SlotID = CarrSlotIDs<0, vPos> HeaderTitles<0, -1> = Scribe:' (':SlotID:')' Next Scribe end else DefWfrTitles = '' For WfrIndex = 1 to NumWfrs DefWfrTitles<1, -1> = 'Wafer ':WfrIndex Next WfrIndex HeaderTitles = "Stage":@VM:"Tool ID":@VM:DefWfrTitles end Set_Property(MetStageCtrl, "OLE.TitleList", HeaderTitles) return EnableRows: // Enable rows and columns now that RUN_STAGE_WFR records have been created GaNRunID = Get_Property(@Window:'.CMB_GAN_RUN_ID', 'TEXT') RDSNo = Get_Property(@Window:'.RDS_NO', 'TEXT') MetStageCtrl = @Window:'.OLE_METROLOGY_EDT' Scribes = Xlate('REACT_RUN', RDSNo, 'PKT_SAT_ID', 'X') DummyPockets = '' NumDummyWfrs = 0 For each Scribe in Scribes using @VM setting vPos DummyID = GanRunID[1,7]:'D' If Scribe[1,8] EQ DummyID then NumDummyWfrs += 1 DummyPockets<1, vPos> = True$ end else DummyPockets<1, vPos> = False$ end Next Scribe NumWfrs = DCount(Scribes, @VM) Set_Property(@Window, '@DUMMYPOCKETS', DummyPockets) Set_Property(@Window, '@NUMWFRS', NumWfrs) MetDimArray = Get_Property(@Window, '@METDIMARRAY') NumMetCols = MetDimArray<1> DispDimArray = Get_Property(@Window, '@DISPDIMARRAY') NumDispCols = DispDimArray<1> EnabledColorArray = 'None':@FM:'None':@FM:'None':@FM:'None':@FM:'None' For each Pocket in DummyPockets using @VM setting vPos If Pocket EQ True$ then ColNo = vPos + 2 Set_Property(MetStageCtrl,"OLE.CellProtection[":ColNo:"; All]", "None") Set_Property(MetStageCtrl,"OLE.CellColors[":ColNo:"; All]", EnabledColorArray) Set_Property(MetStageCtrl,"OLE.ColumnData[":ColNo:"]", '') Set_Property(MetStageCtrl,"OLE.HeaderColors[":ColNo+1:"; 1]", EnabledColorArray) end Next Pocket // Protect and color empty wafer columns If NumWfrs GT 0 then ColOffset = 3 StartCol = ColOffset EndCol = NumWfrs + ColOffset Set_Property(MetStageCtrl,"OLE.CellProtection[":StartCol:"-":EndCol:"; 1-4]", "None") Set_Property(MetStageCtrl,"OLE.CellColors[":StartCol:"-":EndCol:"; 1-4]", EnabledColorArray) Set_Property(MetStageCtrl,"OLE.ColumnData[":StartCol:"-":EndCol:"]", '') Set_Property(MetStageCtrl,"OLE.HeaderColors[":StartCol+1:"-":EndCol+1:"; 1]", EnabledColorArray) end return FillDispEditTable: RDSNo = Get_Property(@Window:'.RDS_NO', 'TEXT') DispStageCtrl = @Window:'.OLE_DISP_EDT' ReactRunRec = Database_Services('ReadDataRow', 'REACT_RUN', RDSNo) DispCtrlArray = '' InWfrIDs = ReactRunRec NumWfrs = DCount(InWfrIDs, @VM) For WfrIndex = 1 to NumWfrs WfrID = InWfrIDs<0, WfrIndex> WOWfrRec = Database_Services('ReadDataRow', 'WO_WFR', WfrID) RDSNCRNo = WOWfrRec WMONCRNo = WOWfrRec ShipFlag = ReactRunRec InternalFlag = ReactRunRec ExternalFlag = ReactRunRec RetainFlag = ReactRunRec Grade = WOWfrRec Scribe = WOWfrRec RetainBox = WOWfrRec RetainSlot = WOWfrRec CriticalFailFlag = WOWfrRec DispCtrlArray = ReactRunRec DispCtrlArray = ReactRunRec DispCtrlArray = Scribe DispCtrlArray = Grade DispCtrlArray = RDSNCRNo DispCtrlArray = WMONCRNo DispCtrlArray = ShipFlag DispCtrlArray = ReactRunRec DispCtrlArray = InternalFlag DispCtrlArray = ExternalFlag DispCtrlArray = RetainFlag DispCtrlArray = RetainSlot DispCtrlArray = RetainBox MetComp = Gan_Services('GetMetrologyStatus', WfrID) DispComp = Gan_Services('GetDispStatus', WfrID) // The wafer scrap reason may vary between the disposition report and NCR. The wafer scrap reason obtained // from the disposition report is saved in the REACT_RUN record. First look for the reason documented in // the NCR. If no NCR value is available use the value obtained from the disposition report. Reason = '' If (RDSNCRNo NE '') then // Display the reason from the NCR record Reason = Xlate('NCR', RDSNCRNo, 'AC_DESC', 'X') end if (Reason EQ '') then // Display the reason from the Disposition report since none was found in the NCR Reason = ReactRunRec end DispCtrlArray = Reason // Updated code to not allow "Internal Characterization" wafers to be NCR'd If ( ( (Grade _EQC 'Scrap' and (InternalFlag EQ False$ or InternalFlag EQ '') ) or (ExternalFlag EQ True$) or (CriticalFailFlag EQ True$) ) or ( (Reason _EQC 'Lot Aborted') or (Reason _EQC 'Non-rotation') or (Reason _EQC 'Broken') or (Reason _EQC 'HB - Handling Breakage') ) ) | and (RDSNCRNo EQ '') | and ( (MetComp EQ True$) or (DispComp EQ True$) ) then // Convert NCR cell for this row into a check box CheckBoxArray = 'Check Box' CheckBoxArray<2,1> = True$ Set_Property(DispStageCtrl, "OLE.CellType[":COL$DISP_RDS_NCR:";":WfrIndex:"]", CheckBoxArray) end else // Reset cell back to a text type cell in case it was previously set to a check box Set_Property(DispStageCtrl, "OLE.CellType[":COL$DISP_RDS_NCR:";":WfrIndex:"]", 'Text') Set_Property(DispStageCtrl, "OLE.CellText[":COL$DISP_RDS_NCR:";":WfrIndex:"]", RDSNCRNo) end If ( (ShipFlag EQ True$) or (InternalFlag EQ True$) or (RetainFlag EQ True$) or (MetComp EQ False$) or (DispComp EQ False$) ) then Set_Property(DispStageCtrl, "OLE.CellCheckEnabled[":COL$DISP_EXTERNAL:";":WfrIndex:"]", False$) end else Set_Property(DispStageCtrl, "OLE.CellCheckEnabled[":COL$DISP_EXTERNAL:";":WfrIndex:"]", True$) end Next WfrIndex Set_Property(DispStageCtrl, "OLE.ARRAY", DispCtrlArray) GoSub EnableNCRButton return Event OLE_NCR_EDT.OnDblClick(Cell, Point, Button, Shift, Ctrl) Row = Field(Cell, ';', 2, 1) NCRNo = Get_Property(CtrlEntID, "OLE.CellText[":COL$NCR_NO:";":Row:"]") If RowExists('NCR', NCRNo) then Dialog_Box('NCR', @Window, NCRNo) GoSub FillNCREditTable end end event Event OLE_DISP_EDT.OnClick(Cell, Point, Button, Shift, Ctrl) Col = Field(Cell, ';', 1, 1) Row = Field(Cell, ';', 2, 1) If Col EQ COL$DISP_WFR_ID then If Button _EQC 'Right' then RDSNo = Get_Property(@Window:'.RDS_NO', 'TEXT') WfrID = Get_Property(CtrlEntID, "OLE.CellText[":COL$DISP_WFR_ID:";":Row:"]") Menu = '' MenuEnabled = False$ If RowExists('WO_WFR', WfrID) then MenuEnabled = True$ Menu<-1> = "CharStages" :@VM:"View Char Stages" :@VM:MenuEnabled Menu<-1> = "WaferTrace" :@VM:"View Wafer Trace" :@VM:MenuEnabled Send_Message(CtrlEntID, "OLE.ShowContextMenu", Point, Menu, WfrID) end end end event Event OLE_DISP_EDT.OnContextMenuClick(Item, UserData) RDSNo = Get_Property(@Window:'.RDS_NO', 'TEXT') Action = Item WfrID = UserData Begin Case Case Action _EQC 'CharStages' WfrSigProfile = obj_React_Run('GetWfrSigKeys', RDSNo:@RM:WfrID) TypeOver = '' TypeOver = WfrSigProfile Dummy = Popup(@Window, TypeOver, 'CHAR_WFR_STAGES') Case Action _EQC 'WaferTrace' TraceData = obj_WO_Wfr('TraceData', WfrID:@RM:'') TypeOver = '' TypeOver = TraceData Dummy = Popup(@Window, TypeOver, 'WAFER_TRACE') End Case end event //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Internal GoSubs //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// EnableNCRButton: Checkmarks = Get_Property(@Window:".OLE_DISP_EDT", "OLE.CellCheck[":COL$DISP_RDS_NCR:"; All]") Checksum = Sum(Checkmarks) If ( Checksum GT 0 ) then NCRButton = True$ end else NCRButton = False$ end Set_Property(@Window:'.PUB_CREATE_NCR', 'ENABLED', NCRButton) return FillNCREditTable: RDSNo = Get_Property(@Window:'.RDS_NO', 'TEXT') NCRCtrl = @Window:'.OLE_NCR_EDT' InWfrIDs = Get_Property(@Window, '@WFRIDS') NCRCtrlArray = '' NCRNos = '' RDSNCRs = Xlate('WO_WFR', InWfrIDs, 'RDS_NCR_NO', 'X') WMONCRs = Xlate('WO_WFR', InWfrIDs, 'WMO_NCR_NO', 'X') NCRNos = SRP_Array('Join', RDSNCRs, WMONCRs, 'OR', @VM) NCRNos = SRP_Array('Clean', NCRNos, 'Trim', @VM) If NCRNos NE '' then For each NCRNo in NCRNos using @VM setting nPos Database_Services('ActivateRecord', 'NCR', NCRNo) If Error_Services('NoError') then NCRCtrlArray = NCRNo NCRCtrlArray = {STATUS} NCRCtrlArray = {REJ_CNT} NCRCtrlArray = {LOSS_BY} NCRCtrlArray = {LOSS_STAGE} NCRCtrlArray = {LOSS_DESC} NCRCtrlArray = {LOSS_COMMENTS} NCRCtrlArray = OConv({AUTH_SHIP_SIG}, '[XLATE_CONV,LSL_USERS*FIRST_LAST]') NCRCtrlArray = OConv({AUTH_SHIP_SIG_DTM}, 'DT') end else NCRCtrlArray = NCRNo NCRCtrlArray = 'Error' NCRCtrlArray = 'Error' NCRCtrlArray = 'Error' NCRCtrlArray = 'Error' NCRCtrlArray = 'Error' NCRCtrlArray = 'Error' NCRCtrlArray = 'Error' NCRCtrlArray = 'Error' end Next NCRNo end else // No NCRs associated with this inbound cassette, so clear the NCR table. For nPos = 1 to 5 NCRCtrlArray = '' NCRCtrlArray = '' NCRCtrlArray = '' NCRCtrlArray = '' NCRCtrlArray = '' NCRCtrlArray = '' NCRCtrlArray = '' NCRCtrlArray = '' NCRCtrlArray = '' Next nPos end Set_Property(NCRCtrl, "OLE.ARRAY", NCRCtrlArray) return DismissPopup: PopupCtrl = @Window : '.OLE_POPUP' PopupVisible = Get_Property(PopupCtrl, 'OLE.Visible') If PopupVisible EQ True$ then Send_Message(PopupCtrl, 'OLE.Close') end return DisplayPopup: Set_Property('SYSTEM', 'CURSOR', 'H') BackColor = Get_Property(@Window, 'BACKCOLOR') ForeColor = Get_Property(@Window, 'FORECOLOR') CursorXPos = Field(Point, ',', 1, 1) CursorYPos = Field(Point, ',', 2, 1) FormSize = SRP_Get_Window_Rect(@Window) FormXPos = FormSize<1> FormYPos = FormSize<2> CtrlSize = Get_Property(CtrlEntID, 'SIZE') CtrlXPos = CtrlSize<1> CtrlYPos = CtrlSize<2> PopupWidth = 160 PopupHeight = 60 XPadding = 10 YPadding = 10 XOffset = 10 YOffset = 55 PopupXPos = FormXPos + CtrlXPos + CursorXPos + XOffset PopupYPos = FormYPos + CtrlYPos + CursorYPos + YOffset StatusBy = '' StatusDTM = '' RDSNo = Get_Property(@Window:'.RDS_NO', 'TEXT') ReactRunRec = Database_Services('ReadDataRow', 'REACT_RUN', RDSNo) StageDesc = Get_Property(CtrlEntID, 'OLE.CellText[1; ':Row:']') StageID = Gan_Services('GetStageID', StageDesc) Begin Case Case CtrlEntID _EQC @Window:'.OLE_REACTOR_EDT' // Cassette Level RunStageKey = RDSNo:'*':StageID RunStageRec = Database_Services('ReadDataRow', 'RUN_STAGE', RunStageKey) StageStatus = RunStageRec Begin Case Case StageStatus _EQC 'COMP' or StageStatus _EQC 'SKIP' StatusBy = RunStageRec StatusDTM = RunStageRec Case StageStatus _EQC 'START' InvActions = RunStageRec Locate 'START' in InvActions using @VM setting vPos then StatusBy = RunStageRec StatusDTM = RunStageRec end End Case Case CtrlEntID _EQC @Window:'.OLE_METROLOGY_EDT' // Wafer level ScribeHeader = Get_Property(CtrlEntID, 'OLE.HeaderText[':Column+1:'; 1]') Scribe = ScribeHeader[1, 'F '] Scribes = Xlate('REACT_RUN', RDSNo, 'WFR_SCRIBES', 'X') WfrIDs = ReactRunRec WfrID = '' Locate Scribe in Scribes using @VM setting vPos then WfrID = WfrIDs<0, vPos> end Convert '*' to '.' in WfrID RunStageWfrKey = RDSNo:'*':StageID:'*':WfrID RunStageWfrRec = Database_Services('ReadDataRow', 'RUN_STAGE_WFR', RunStageWfrKey) StageStatus = RunStageWfrRec Begin Case Case StageStatus _EQC 'COMP' or StageStatus _EQC 'SKIP' or StageStatus _EQC 'CHAR' or StageStatus _EQC 'DISP' StatusBy = RunStageWfrRec StatusDTM = RunStageWfrRec Case StageStatus _EQC 'START' InvActions = RunStageWfrRec Locate 'START' in InvActions using @VM setting vPos then StatusBy = RunStageWfrRec StatusDTM = RunStageWfrRec end End Case End Case If (StatusBy NE '') and (StatusDTM NE '') then HoverData = '' HoverData := OConv(StatusBy, '[XLATE_CONV,LSL_USERS*FIRST_LAST]') : @FM HoverData := OConv(StatusDTM, 'DT') NumLines = DCount(HoverData, @FM) ItemList = '' If HoverData NE '' then For Each Item in HoverData using @FM setting ItemCount ItemList = XPadding ; // X Position of item ItemList = (20 * (ItemCount - 1) ) ; // Y Position of item ItemList = PopupWidth - (2 * XPadding) ; // Width ItemList = PopupHeight - (2 * YPadding) ; // Height ItemList = Item ItemList = Forecolor ItemList = '' : @SVM : '' : @SVM : '700' : @SVM : '0' : @SVM : '0' ItemList = 'Left' : @SVM : 'Center' Next Item end Set_Property(PopupCtrl, 'OLE.Theme', 'Custom') Set_Property(PopupCtrl, 'OLE.Opacity', 255) Set_Property(PopupCtrl, 'OLE.Animation', 'N') Set_Property(PopupCtrl, 'OLE.Background', 'Vertical(Gradient(' : Backcolor : ', ' : Backcolor : '), Border(' : Backcolor : ' L=20))' : @FM : 'None' : @FM : 'None') Set_Property(PopupCtrl, 'OLE.ItemList', ItemList) Set_Property(PopupCtrl, 'OLE.ShowDelay', 1000) Set_Property(PopupCtrl, 'OLE.Size', 0 : @FM : 0 : @FM : PopupWidth : @FM : PopupHeight) Send_Message(PopupCtrl, 'OLE.ShowAt', PopupXPos, PopupYPos) end Set_Property('SYSTEM', 'CURSOR', 'A') return UpdateDispData: DispCtrl = @Window:'.OLE_DISP_EDT' RDSNo = Get_Property(@Window:'.RDS_NO', 'TEXT') Reactor = Get_Property(@Window, '@REACTOR') Scribes = Get_Property(@Window, '@SCRIBES') NumWfrs = Get_Property(@Window, '@NUMWFRS') GanRunID = Get_Property(@Window:'.CMB_GAN_RUN_ID', 'TEXT') EpiPart = Get_Property(@Window:'.EDL_WAFER_TRACK_PART', 'TEXT') GaNRecipe = Get_Property(@Window:'.GAN_RECIPE', 'TEXT') ReactRunRec = Database_Services('ReadDataRow', 'REACT_RUN', RDSNo) OrigReactRunRec = ReactRunRec WfrIDs = ReactRunRec CassDispComp = ReactRunRec If (CassDispComp EQ False$) or (CassDispComp EQ '') then Response = GaN_Services('PostDispositionRequest', RDSNo) If Response EQ True$ then Set_Property(@Window:'.STATUS_LINE', 'BACKCOLOR', GREEN$) Set_Property(@Window:'.STATUS_LINE', 'TEXT', 'Disposition report processed successfully.') end else Set_Property(@Window:'.STATUS_LINE', 'BACKCOLOR', YELLOW$) Set_Property(@Window:'.STATUS_LINE', 'TEXT', Response) end end return VerifyRecipe: GaNRunID = Get_Property(@Window:'.CMB_GAN_RUN_ID', 'TEXT') If GaNRunID NE '' then GaNRecipe = Get_Property(@Window:'.GAN_RECIPE', 'TEXT') Convert @Lower_Case to @Upper_Case in GaNRunID SchedRecipe = Xlate('GAN_SCHEDULE', GaNRunID, 'RECIPE', 'X') If GaNRecipe NE '' then If SchedRecipe _EQC GaNRecipe then // If the recipes match, then color the recipe ID bright green, otherwise // color it bright red and block the Run Configuration "Complete" event. Set_Property(@Window:'.GAN_RECIPE', 'BACKCOLOR', BGREEN$) Set_Property(@Window, '@RECIPEMISMATCH', False$) end else Set_Property(@Window:'.GAN_RECIPE', 'BACKCOLOR', BRED$) Set_Property(@Window, '@RECIPEMISMATCH', True$) end end end return VerifyScribes: RDSNo = Get_Property(@Window:'.RDS_NO', 'TEXT') If RDSNo NE '' then ScribeErrors = Xlate('REACT_RUN', RDSNo, 'SCRIBE_ERROR', 'X') DispCtrl = @Window:'.OLE_DISP_EDT' InWfrIDs = Xlate('REACT_RUN', RDSNo, 'IN_WFR_ID', 'X') NumWfrs = DCount(InWfrIDs, @VM) For WfrIndex = 1 to NumWfrs If ScribeErrors<0, WfrIndex> EQ True$ then // Color cell red ColorArray = 'None':@FM:RED$ end else // Color cell green ColorArray = 'None':@FM:BGREEN$ end Set_Property(DispCtrl, 'OLE.CellColors[':COL$DISP_SCRIBE:';':WfrIndex:']', ColorArray) Next WfrIndex end return EnableRunIDComboBox: RDSNo = Get_Property(@Window:'.RDS_NO', 'TEXT') EtchKey = RDSNo:'*ETCH' EtchStatus = Xlate('RUN_STAGE', EtchKey, 'STATUS', 'X') If EtchStatus _EQC 'COMP' then Set_Property(@Window:'.CMB_GAN_RUN_ID', 'ENABLED', True$) end else Set_Property(@Window:'.CMB_GAN_RUN_ID', 'ENABLED', False$) end return FillCommentsTable: RDSNo = Get_Property(@Window:'.RDS_NO', 'TEXT') CassComments = Xlate('REACT_RUN', RDSNo, 'CASS_COMMENTS', 'X') Set_Property(@Window:'.EDB_CASS_COMMENTS', 'TEXT', CassComments) Set_Property(@Window, '@COMMENTS', CassComments) return EnableDispButton: RDSNo = Get_Property(@Window:'.RDS_NO', 'TEXT') ReactRunRec = Database_Services('ReadDataRow', 'REACT_RUN', RDSNo) DispComp = ReactRunRec * WfrsDispReady = ReactRunRec DispCtrl = @Window:'.PUB_DISP' * ReadyForDisp = True$ * For each DispStatus in WfrsDispReady using @VM setting vPos * If (DispStatus EQ False$) or (DispStatus EQ '') then * ReadyForDisp = False$ * end * Until ReadyForDisp = False$ * Next DispStatus If DispComp EQ True$ then Set_Property(DispCtrl, 'TEXT', 'Open RDS') Set_Property(DispCtrl, 'ENABLED', True$) end else Set_Property(DispCtrl, 'TEXT', 'Close RDS') Set_Property(DispCtrl, 'ENABLED', True$) end * Begin Case * * Case (DispComp EQ False$) or (DispComp EQ '') and (ReadyForDisp EQ True$) * Set_Property(DispCtrl, 'TEXT', 'Close RDS') * Set_Property(DispCtrl, 'ENABLED', True$) * * Case (DispComp EQ False$) or (DispComp EQ '') and (ReadyForDisp EQ False$) * Set_Property(DispCtrl, 'TEXT', 'Close RDS') * Set_Property(DispCtrl, 'ENABLED', False$) * * Case (DispComp EQ True$) * Set_Property(DispCtrl, 'TEXT', 'Open RDS') * * End Case return UpdateRDSStatus: RDSNo = Get_Property(@Window:'.RDS_NO', 'TEXT') ReactRunRec = Database_Services('ReadDataRow', 'REACT_RUN', RDSNo) DispComp = ReactRunRec If DispComp EQ True$ then Set_Property(@Window:'.LBL_RDS_STATUS', 'TEXT', 'CLOSED') Set_Property(@Window:'.LBL_RDS_STATUS', 'FORECOLOR', BRED$) end else Set_Property(@Window:'.LBL_RDS_STATUS', 'TEXT', 'OPEN') Set_Property(@Window:'.LBL_RDS_STATUS', 'FORECOLOR', BGREEN$) end return EnableLotAbortButton: RDSNo = Get_Property(@Window:'.RDS_NO', 'TEXT') GrowthKey = RDSNo:'*GROWTH' GrowthStatus = Xlate('RUN_STAGE', GrowthKey, 'STATUS', 'X') // Need to check each wafer's current stage. If all wafers are at disposition, then // there is no need to enable the "Lot Abort" button. LotAbortAllowed = False$ WfrIDs = Xlate('REACT_RUN', RDSNo, 'IN_WFR_ID', 'X') For each WfrID in WfrIDs using @VM setting vPos CurrStage = Gan_Services('GetCurrStage', WfrID) If (CurrStage _NEC 'DISP') and (CurrStage _NEC 'G_PACK') and (CurrStage _NEC 'RETAIN') then LotAbortAllowed = True$ end Next WfrID If (GrowthStatus _EQC 'COMP') and (LotAbortAllowed EQ True$) then Set_Property(@Window:'.PUB_LOT_ABORT', 'ENABLED', True$) end else Set_Property(@Window:'.PUB_LOT_ABORT', 'ENABLED', False$) end return FillMetEditTable: GoSub AutoSelectToolID RDSNo = Get_Property(@Window:'.RDS_NO', 'TEXT') NumWfrs = Get_Property(@Window, '@NUMWFRS') MetStageIDList = Get_Property(@Window, '@METSTAGEIDLIST') AllWfrIDs = Get_Property(@Window, '@WFRIDS') SingleWfrID = Get_Property(@Window, '@SINGLE_WFR_ID') If SingleWfrID NE '' then // We only want need to update one column (wafer) WfrIDs = SingleWfrID MetStageIDList = Delete(MetStageIDList, 0, 1, 0) MetStageIDList = Delete(MetStageIDList, 0, 1, 0) MetStageIDList = Delete(MetStageIDList, 0, 1, 0) end else WfrIDs = AllWfrIDs If WfrIDs EQ '' then WfrIDs = Xlate('REACT_RUN', RDSNo, 'IN_WFR_ID', 'X') Set_Property(@Window, '@WFRIDS', WfrIDs) end end If NumWfrs EQ '' then NumWfrs = DCount(WfrIDs, @VM) Set_Property(@Window, '@NUMWFRS') end MetStageCtrl = @Window:'.OLE_METROLOGY_EDT' MetRowsEnabled = Get_Property(@Window, '@METROWSENABLED') CellTypeArray = Get_Property(@Window, '@COMBOBOX') ColorArray = @FM:'OD' CellColorArray = 'None':@FM:'None':@FM:'None':@FM:'None':@FM:'None' EnabledColorArray = CellColorArray // Get and set each wafer's current status for each stage within the Metrology edit table. EndCol = NumWfrs + 2 For each WfrID in WfrIDs using @VM ReadyToSplit = Gan_Services('ReadyToSplit', WfrID) ReadyToStart = Gan_Services('ReadyToStart', RDSNo, WfrID) Locate WfrID in AllWfrIDs using @VM setting WfrIndex then CurrWfrCol = WfrIndex + 2 end For each Stage in MetStageIDList using @VM setting StageIndex Destructive = Gan_Services('IsDestStage', Stage) If SingleWfrID NE '' then CurrWfrRow = StageIndex + 3 end else CurrWfrRow = StageIndex end BackgroundColor = 'None' If WfrID NE '' then Convert '*' to '.' in WfrID Begin Case Case Stage EQ 'UV_PRE' // Check if UV stage exists UVStageWfrKey = RDSNo:'*UV*':WfrID If RowExists('RUN_STAGE_WFR', UVStageWfrKey) then // Display this on the UV_PRE line RunStageWfrKey = UVStageWfrKey end else RunStageWfrKey = RDSNo:'*':Stage:'*':WfrID end Case Stage EQ 'CAN_PRE' // Check if CAN stage exists CanStageWfrKey = RDSNo:'*CAN*':WfrID If RowExists('RUN_STAGE_WFR', CanStageWfrKey) then // Display this on the CAN_PRE line RunStageWfrKey = CanStageWfrKey end else RunStageWfrKey = RDSNo:'*':Stage:'*':WfrID end Case Otherwise$ RunStageWfrKey = RDSNo:'*':Stage:'*':WfrID End Case SplitKey = RDSNo:'*SPLIT*':WfrID SplitStatus = (Xlate('RUN_STAGE_WFR', SplitKey, 'STATUS', 'X') _EQC 'CHAR') If SplitStatus EQ True$ then MetRowsEnabled = True$ Convert '.' to '*' in WfrID If (Stage _EQC 'SPLIT') and (ReadyToSplit EQ True$) then Set_Property(MetStageCtrl,"OLE.CellProtection[":CurrWfrCol:";":CurrWfrRow:"]", "None") Set_Property(MetStageCtrl,"OLE.CellColors[":CurrWfrCol:";":CurrWfrRow:"]", EnabledColorArray) Set_Property(MetStageCtrl,"OLE.CellColors[":COL$MET_STAGE:'-':COL$MET_TOOL_ID:";":CurrWfrRow:"]", EnabledColorArray) Set_Property(MetStageCtrl,"OLE.CellProtection[":COL$MET_STAGE:'-':COL$MET_TOOL_ID:";":CurrWfrRow:"]", "None") end ThisComboArray = CellTypeArray If RowExists('RUN_STAGE_WFR', RunStageWfrKey) then UnRxStage = Gan_Services('GetUnRxStatus', RDSNo, Stage) If UnRxStage EQ True$ then BackgroundColor = YELLOW$ CurrStatus = Xlate('RUN_STAGE_WFR', RunStageWfrKey, 'STATUS', 'X') ToolID = Xlate('RUN_STAGE_WFR', RunStageWfrKey, 'TOOL_ID', 'X') // Has another stage has already begun for this wafer? DispStatus = '' Begin Case Case CurrStatus _EQC 'COMP' DispStatus = 'Complete' MetActionArray = 'Complete' If ( ( (Stage _EQC 'CAN') or (Stage _EQC 'WET_CLEAN') or (Stage _EQC 'CAN_PRE') or (Stage _EQC 'CAN_PST') ) and (ReadyToStart EQ True$) and ( (ToolID NE '') or (ToolID NE 'Select') ) ) then MetActionArray<2> = 'Start' Case CurrStatus _EQC 'START' DispStatus = 'Start' MetActionArray = 'Stop' Case CurrStatus _EQC 'STOP' DispStatus = 'Stop' MetActionArray = 'Complete' Case CurrStatus _EQC 'SKIP' DispStatus = 'Skip' MetActionArray = 'Unskip' Case CurrStatus _EQC 'CHAR' DispStatus = 'Characterize' MetActionArray = '' // If any metrology stages after split have been started and/or completed, then withdraw // will not be an option. CanWithdraw = Gan_Services('EligibleToWithdrawWfr', RDSNo, WfrID) If CanWithdraw EQ True$ then MetActionArray = 'Withdraw' Case CurrStatus _EQC 'DISP' DispStatus = 'Disposition' MetActionArray = '' // If G_PACK or RETAIN have been completed, then withdraw will not be an option. CanWithdraw = Gan_Services('EligibleToWithdrawWfr', RDSNo, WfrID) If CanWithdraw EQ True$ then MetActionArray = 'Withdraw' Case CurrStatus _EQC 'INIT' DispStatus = 'X' If Stage _NEC 'SPLIT' then // Need to check if stage is prescribed or not. If UnRxStage EQ True$ then MetActionArray = 'Remove' end else MetActionArray = 'Skip' end If ( (ReadyToStart EQ True$) and (ToolID NE '') and (ToolID NE 'Select') )then Temp = MetActionArray MetActionArray = 'Start' MetActionArray<2> = Temp end end else MetActionArray = 'Characterize' MetActionArray<2> = 'Disposition' If ReadyToSplit EQ False$ then ColorArray = 'None':@FM:BackgroundColor:@FM:'White':@FM:OI_BLUE$:@FM:'None' Set_Property(MetStageCtrl,"OLE.CellProtection[":CurrWfrCol:";":CurrWfrRow:"]", "FUL") Set_Property(MetStageCtrl,"OLE.CellColors[":CurrWfrCol:";":CurrWfrRow:"]", ColorArray) Set_Property(MetStageCtrl,"OLE.CellColors[":COL$MET_TOOL_ID:";":CurrWfrRow:"]", ColorArray) Set_Property(MetStageCtrl,"OLE.CellProtection[":COL$MET_TOOL_ID:";":CurrWfrRow:"]", "FUL") end end End Case Convert @FM to @STM in MetActionArray ThisComboArray<2, 3> = MetActionArray Set_Property(MetStageCtrl, "OLE.CellType[":CurrWfrCol:";":CurrWfrRow:"]", ThisComboArray) // Cassette/Wafer status/action combo boxes // Need to check current status and set the dropdown options accordingly // Combo box selection options should be context aware. (e.g. "Skip" should not be an option if a // wafer has already started on a tool.) If (Stage _EQC 'XRD') or (Stage _EQC 'AFM') or (Stage _EQC 'RPM') | or (Stage _EQC 'PR') or (Stage _EQC 'SCOPE') or (Stage _EQC 'RTA') | or (Stage _EQC 'HALL') or (Stage _EQC 'EBEAM') or (Stage _EQC 'RTA_HALL') | or (Stage _EQC 'HALL_PGAN') or (Stage _EQC 'BV') or (Stage _EQC 'JV_XRD') | or (Stage _EQC 'BV100%') then If ReadyToSplit EQ False$ then Set_Property(MetStageCtrl, "OLE.CellProtection[":CurrWfrCol:";":CurrWfrRow:"]", "FUL") end else Set_Property(MetStageCtrl, "OLE.CellProtection[":CurrWfrCol:";":CurrWfrRow:"]", "None") end RowEnabled = MetRowsEnabled If (Destructive EQ True$) then // Set row text color to red If (RowEnabled EQ True$) then DestEditArray = 'Red':@FM:BackgroundColor:@FM:'White':@FM:OI_BLUE$:@FM:'None' Set_Property(MetStageCtrl,"OLE.CellProtection[":CurrWfrCol:";":CurrWfrRow:"]", "None") Set_Property(MetStageCtrl,"OLE.CellColors[":CurrWfrCol:";":CurrWfrRow:"]", DestEditArray) Set_Property(MetStageCtrl,"OLE.CellProtection[":COL$MET_STAGE:'-':COL$MET_TOOL_ID:";":CurrWfrRow:"]", "None") Set_Property(MetStageCtrl,"OLE.CellColors[":COL$MET_STAGE:'-':COL$MET_TOOL_ID:";":CurrWfrRow:"]", DestEditArray) end else DestEditArray = 'Red':@FM:'OD':@FM:'None':@FM:'None':@FM:'None' Set_Property(MetStageCtrl,"OLE.CellProtection[":CurrWfrCol:";":CurrWfrRow:"]", "None") Set_Property(MetStageCtrl,"OLE.CellColors[":CurrWfrCol:";":CurrWfrRow:"]", DestEditArray) Set_Property(MetStageCtrl,"OLE.CellProtection[":COL$MET_STAGE:'-':COL$MET_TOOL_ID:";":CurrWfrRow:"]", "None") Set_Property(MetStageCtrl,"OLE.CellColors[":COL$MET_STAGE:'-':COL$MET_TOOL_ID:";":CurrWfrRow:"]", DestEditArray) end end else // Set row text color to default (i.e. 'None') If (RowEnabled EQ True$) then ColorArray = 'None':@FM:BackgroundColor:@FM:'White':@FM:OI_BLUE$:@FM:'None' Set_Property(MetStageCtrl,"OLE.CellProtection[":CurrWfrCol:";":CurrWfrRow:"]", "None") Set_Property(MetStageCtrl,"OLE.CellColors[":CurrWfrCol:";":CurrWfrRow:"]", ColorArray) Set_Property(MetStageCtrl,"OLE.CellProtection[":COL$MET_STAGE:'-':COL$MET_TOOL_ID:";":CurrWfrRow:"]", "None") Set_Property(MetStageCtrl,"OLE.CellColors[":COL$MET_STAGE:'-':COL$MET_TOOL_ID:";":CurrWfrRow:"]", ColorArray) end else ColorArray = 'None':@FM:'OD':@FM:'None':@FM:'None':@FM:'None' Set_Property(MetStageCtrl,"OLE.CellProtection[":CurrWfrCol:";":CurrWfrRow:"]", "None") Set_Property(MetStageCtrl,"OLE.CellColors[":CurrWfrCol:";":CurrWfrRow:"]", ColorArray) Set_Property(MetStageCtrl,"OLE.CellProtection[":COL$MET_STAGE:'-':COL$MET_TOOL_ID:";":CurrWfrRow:"]", "None") Set_Property(MetStageCtrl,"OLE.CellColors[":COL$MET_STAGE:'-':COL$MET_TOOL_ID:";":CurrWfrRow:"]", ColorArray) end end end Set_Property(MetStageCtrl, "OLE.CellText[":CurrWfrCol:"; ":CurrWfrRow:"]", DispStatus) If ( ( (CurrStatus EQ 'COMP') and (Stage NE 'CAN') and (Stage NE 'WET_CLEAN') and (Stage NE 'CAN_PRE') and (Stage NE 'CAN_PST') ) or (Stage EQ 'UV') or (Stage EQ 'UV_PRE') or (Stage EQ 'UV_PST') or (Stage EQ 'WARP') ) then Set_Property(MetStageCtrl, "OLE.CellText[":CurrWfrCol:"; ":CurrWfrRow:"]", DispStatus) Set_Property(MetStageCtrl, "OLE.CellProtection[":CurrWfrCol:"; ":CurrWfrRow:"]", "FUL") end If ( (Stage _EQC 'CAN') or (Stage _EQC 'CAN_PRE') or (Stage _EQC 'CAN_PST') ) and (CurrStatus _EQC 'START') then Set_Property(MetStageCtrl, "OLE.CellProtection[":CurrWfrCol:"; ":CurrWfrRow:"]", "FUL") end end else // RunStageWfr record for this stage is unprescribed. Add option for users to add the stage. MetActionArray = 'Add' Convert @FM to @STM in MetActionArray ThisComboArray = CellTypeArray ThisComboArray<2, 3> = MetActionArray Set_Property(MetStageCtrl, "OLE.CellType[":CurrWfrCol:";":CurrWfrRow:"]", ThisComboArray) Set_Property(MetStageCtrl, "OLE.CellText[":CurrWfrCol:"; ":CurrWfrRow:"]", '') If (Stage _EQC 'CAN_PRE') or (Stage _EQC 'CAN_PST') or (Stage _EQC 'XRD') | or (Stage _EQC 'AFM') or (Stage _EQC 'RPM') or (Stage _EQC 'PR') or (Stage _EQC 'SCOPE') | or (Stage _EQC 'RTA')or (Stage _EQC 'HALL') or (Stage _EQC 'EBEAM') | or (Stage _EQC 'RTA_HALL') or (Stage _EQC 'HALL_PGAN') or (Stage _EQC 'BV') | or (Stage _EQC 'JV_XRD' ) or (Stage _EQC 'BV100%') then RowEnabled = MetRowsEnabled If ( (StageIndex LE 7) or (SplitStatus EQ True$) ) then If Destructive EQ True$ then DestEditArray = 'Red':@FM:'None':@FM:'White':@FM:OI_BLUE$:@FM:'None' EnabledColorArray = DestEditArray end else EnabledColorArray = 'None':@FM:'None':@FM:'None':@FM:'None':@FM:'None' end Set_Property(MetStageCtrl,"OLE.CellProtection[":CurrWfrCol:";":CurrWfrRow:"]", "None") Set_Property(MetStageCtrl,"OLE.CellColors[":CurrWfrCol:";":CurrWfrRow:"]", EnabledColorArray) Set_Property(MetStageCtrl,"OLE.CellColors[":COL$MET_STAGE:'-':COL$MET_TOOL_ID:";":CurrWfrRow:"]", EnabledColorArray) Set_Property(MetStageCtrl,"OLE.CellProtection[":COL$MET_STAGE:'-':COL$MET_TOOL_ID:";":CurrWfrRow:"]", "None") end else If Destructive EQ True$ then DisabledColorArray = 'Red':@FM:'OD':@FM:'None':@FM:'None':@FM:'None' end else DisabledColorArray = 'None':@FM:'OD':@FM:'None':@FM:'None':@FM:'None' end Set_Property(MetStageCtrl,"OLE.CellProtection[":CurrWfrCol:";":CurrWfrRow:"]", "FUL") Set_Property(MetStageCtrl,"OLE.CellColors[":CurrWfrCol:";":CurrWfrRow:"]", DisabledColorArray) end end end end RowEnabled = MetRowsEnabled DisabledColorArray = 'None':@FM:'OD':@FM:'None':@FM:'None':@FM:'None' EnabledColorArray = 'None':@FM:'None':@FM:'None':@FM:'None':@FM:'None' If RowEnabled EQ False$ then If Destructive EQ True$ then DestEditArray = 'Red':@FM:'OD':@FM:'None':@FM:'None':@FM:'None' DisabledColorArray = DestEditArray end Set_Property(MetStageCtrl,"OLE.CellProtection[":COL$MET_STAGE:'-':COL$MET_TOOL_ID:";":CurrWfrRow:"]", "FUL") Set_Property(MetStageCtrl,"OLE.CellColors[":COL$MET_STAGE:'-':COL$MET_TOOL_ID:";":CurrWfrRow:"]", DisabledColorArray) end else If Destructive EQ True$ then DestEditArray = 'Red':@FM:'None':@FM:'White':@FM:OI_BLUE$:@FM:'None' EnabledColorArray = DestEditArray end Set_Property(MetStageCtrl,"OLE.CellProtection[":COL$MET_STAGE:'-':COL$MET_TOOL_ID:";":CurrWfrRow:"]", "None") Set_Property(MetStageCtrl,"OLE.CellColors[":COL$MET_STAGE:'-':COL$MET_TOOL_ID:";":CurrWfrRow:"]", EnabledColorArray) end Next Stage Next WfrID Set_Property(@Window, '@METROWSENABLED', MetRowsEnabled) return Abort: Utility('DESTROY', @Window) return