open-insight/LSL2/STPROC/REACT_RUN_EVENTS.txt
Infineon\StieberD 7762b129af pre cutover push
2024-09-04 20:33:41 -07:00

3313 lines
161 KiB
Plaintext

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<MCAPTION$> = "Loading..."
Def<MTYPE$> = "G"
Def<MEXTENT$> = 100 ; // 100%
Def<MTEXTWIDTH$> = 400
Def<MCOL$> = -2 ;* message h-pos in pixels, or -2 (center screen, the default), -1 (center parent)
Def<MROW$> = -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<REACT_RUN_IN_WFR_ID$>
RunPriority = ReactRunRec<REACT_RUN_RUN_PRI$>
Set_Property(@Window:'.COMBO_PRIORITY', 'TEXT', RunPriority)
GaNRunID = ReactRunRec<REACT_RUN_GAN_RUN_ID$>
GrowthKey = RDSNo:'*GROWTH'
GrowthRec = Database_Services('ReadDataRow', 'RUN_STAGE', GrowthKey)
InvActions = GrowthRec<RUN_STAGE_SPEC_INV_ACTION$>
Locate 'LOAD' in InvActions using @VM setting vPos then
LoadSig = GrowthRec<RUN_STAGE_SIA_COMP_BY$, vPos>
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<WO_WFR_SCRIBE$> = 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<WO_LOG_WAFER_TRACK_PART$>
Set_Property(@Window:'.EDL_WAFER_TRACK_PART', 'TEXT', SPCWaferTrackPart)
Reactor = ReactRunRec<REACT_RUN_REACTOR$>
If Reactor EQ '' then Reactor = GaN_Services('GetReactor', WONo)
Set_Property(@Window, '@REACTOR', Reactor)
ReactRunRec<REACT_RUN_REACTOR$> = 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<RunIndex>
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<RunIndex>
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<REACT_RUN_GAN_ETCH_RECIPE$, NumEtchIDs> = 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<REACT_RUN_IN_WFR_ID$>
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<REACT_RUN_DISP_COMPLETE$>
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<REACT_RUN_REACTOR$> = 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<MTEXT$> = 'You must have a record present...'
MsgInfo<MICON$> = '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<mtext$> = 'You must save this run data sheet first...'
MsgInfo<micon$> = '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<REACT_RUN_CASS_COMMENTS$> = 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<REACT_RUN_DISP_COMPLETE$>
WfrIDs = ReactRunRec<REACT_RUN_IN_WFR_ID$>
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<RUN_STAGE_WFR_COMP_BY$> = ''
RunStageWfrRec<RUN_STAGE_WFR_COMP_DTM$> = ''
RunStageWfrRec<RUN_STAGE_WFR_STATUS$> = '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<WO_WFR_LOC_DTM$>
NextPos = DCount(LocDTM, @VM) + 1
WOWfrRec<WO_WFR_LOC_DTM$, NextPos> = CurrDTM
WOWfrRec<WO_WFR_LOC_BY$, NextPos> = @USER4
WOWfrRec<WO_WFR_LOC_EVENT$, NextPos> = 'OPEN'
WOWfrRec<WO_WFR_TOOL_ID$, NextPos> = ''
WOWfrRec<WO_WFR_INV_LOC$, NextPos> = DispQ
Database_Services('WriteDataRow', 'WO_WFR', WfrID, WOWfrRec, True$, False$, True$)
Next WfrID
ReactRunRec<REACT_RUN_DISP_COMPLETE$> = 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<REACT_RUN_DISP_COMPLETE$> = 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<WfrIndex>
If RowSelected EQ True$ then
SlotNo = CarrSlotList<WfrIndex, COL$DISP_SLOT>
IF CarrSlotList<WfrIndex,COL$CARR_WFR_ID> NE '' Then
GoodLines += 1
RejWfrIDs<1,GoodLines> = CarrSlotList<WfrIndex,COL$DISP_WFR_ID>
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<REACT_RUN_CARR_WFR_GRADE$>
WfrIDs = ReactRunRec<REACT_RUN_IN_WFR_ID$>
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<REACT_RUN_CARR_WFR_GRADE$> = 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<REACT_RUN_OUT_SLOT_ID$>
WfrIDs = ReactRunRec<REACT_RUN_IN_WFR_ID$>
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<MTEXT$> = 'You must have a record present...'
MsgInfo<MICON$> = '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<mtext$> = 'You must save this run data sheet first...'
MsgInfo<micon$> = '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<REACT_RUN_CARR_WFR_ID$>
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<WO_LOG_WAFER_TRACK_PART$> = 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<REACT_RUN_GAN_RUN_ID$> = GaNRunID
ReactRunRec<REACT_RUN_GAN_RECIPE$> = GaNRunRecipe
ReactRunRec<REACT_RUN_GAN_SUSC_SERIAL$> = GanSuscSerial
* ReactRunRec<REACT_RUN_POCKET$> = PocketNos
ReactRunRec<REACT_RUN_PKT_SAT_ID$> = SatSerialNos
ReactRunRec<REACT_RUN_REACTOR$> = 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<WO_MAT_LOC_DTM$, -1> = CurrDTM
WOMatRec<WO_MAT_LOC_BY$, -1> = @User4
WOMatRec<WO_MAT_INV_LOC$, -1> = GrowthQ
Database_Services('WriteDataRow', 'WO_MAT', WOMatKey, WOMatRec, True$, False$, True$)
// 4
RunStageRec<RUN_STAGE_COMP_BY$> = @User4
RunStageRec<RUN_STAGE_COMP_DTM$> = CurrDTM
RunStageRec<RUN_STAGE_STATUS$> = '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<REACT_RUN_IN_WFR_ID$>
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<WO_WFR_LOC_DTM$>
NextIndex = DCount(LocDTMs, @VM) + 1
WOWfrRec<WO_WFR_LOC_DTM$, NextIndex> = CurrDTM
WOWfrRec<WO_WFR_LOC_BY$, NextIndex> = @User4
WOWfrRec<WO_WFR_INV_LOC$, NextIndex> = NextLocQID
WOWfrRec<WO_WFR_LOC_EVENT$, NextIndex> = '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<RUN_STAGE_COMP_BY$> = @User4
RunStageRec<RUN_STAGE_COMP_DTM$> = CurrDTM
RunStageRec<RUN_STAGE_STATUS$> = '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<WO_WFR_COMMENTS$> = 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<REACT_RUN_WFR_STAGE$>
UnRxStages = ReactRunRec<REACT_RUN_UNPRESCRIBED_WFR_STAGE$>
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<RUN_STAGE_WFR_TOOL_ID$> = ToolID
Database_Services('WriteDataRow','RUN_STAGE_WFR',RunStageWfrKey,RunStageWfrRec,True$,False$,True$)
end
end
end
Next WfrID
MetRowsEnabled<Row> = 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<REACT_RUN_IN_WFR_ID$>
For each WOWfrID in InWfrIDs using @VM setting vPos
ThisWOWfrRec = Database_Services('ReadDataRow', 'WO_WFR', WOWfrID)
LocDTMs = ThisWOWfrRec<WO_WFR_LOC_DTM$>
LocQs = ThisWOWfrRec<WO_WFR_INV_LOC$>
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<WO_WFR_LOC_DTM$> = 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<REACT_RUN_EXTERNAL$>
ExternalFlags<0, Row> = NewValue
ReactRunRec<REACT_RUN_EXTERNAL$> = 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<REACT_RUN_RUN_PRI$> = 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<RUN_STAGE_COMP_BY$> = @User4
RunStageRec<RUN_STAGE_COMP_DTM$> = CurrDTM
RunStageRec<RUN_STAGE_STATUS$> = 'COMP'
RunStageRec<RUN_STAGE_ETCH_IDS$> = 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<REACT_RUN_GAN_ETCH_ID$> = SelExtEtchIDs
ReactRunRec<REACT_RUN_GAN_ETCH_RECIPE$> = 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<ReactorStageIndex> = StageDesc
ReactorStageIndex += 1
Case RunType EQ 'Metrology'
MetCtrlList<MetStageIndex> = StageDesc
TempArray = ''
MetCtrlList<MetStageIndex, 2> = '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<MetStageIndex> = TempArray
MetStageIndex += 1
End Case
Next Row
RDSNo = Get_Property(@Window : '.RDS_NO', 'DEFPROP')
ReactRunRec = Database_Services('ReadDataRow', 'REACT_RUN', RDSNo)
WfrIDs = ReactRunRec<REACT_RUN_IN_WFR_ID$>
Scribes = Xlate('REACT_RUN', RDSNo, 'WFR_SCRIBES', 'X')
CarrSlotIDs = ReactRunRec<REACT_RUN_CARR_SLOT_ID$>
Slots = ReactRunRec<REACT_RUN_CARR_SLOT_NO$>
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<RowIndex>
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<RowIndex> = 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<REACT_RUN_RUN_STAGE_KEY$>
MetStages = ReactRunRec<REACT_RUN_WFR_STAGE$>
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<RUN_STAGE_WFR_TOOL_ID$>
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<RUN_STAGE_WFR_TOOL_ID$> = 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<RowIndex>
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<RowIndex> = 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<REACT_RUN_IN_WFR_ID$>
NumWfrs = DCount(InWfrIDs, @VM)
For WfrIndex = 1 to NumWfrs
WfrID = InWfrIDs<0, WfrIndex>
WOWfrRec = Database_Services('ReadDataRow', 'WO_WFR', WfrID)
RDSNCRNo = WOWfrRec<WO_WFR_RDS_NCR_NO$>
WMONCRNo = WOWfrRec<WO_WFR_WMO_NCR_NO$>
ShipFlag = ReactRunRec<REACT_RUN_CARR_WFR_SHIP$, WfrIndex>
InternalFlag = ReactRunRec<REACT_RUN_INTERNAL$, WfrIndex>
ExternalFlag = ReactRunRec<REACT_RUN_EXTERNAL$, WfrIndex>
RetainFlag = ReactRunRec<REACT_RUN_GAN_RET_WFR$, WfrIndex>
Grade = WOWfrRec<WO_WFR_GRADE$>
Scribe = WOWfrRec<WO_WFR_SCRIBE$>
RetainBox = WOWfrRec<WO_WFR_RETAIN_BOX$>
RetainSlot = WOWfrRec<WO_WFR_RETAIN_SLOT$>
CriticalFailFlag = WOWfrRec<WO_WFR_CRITICAL_FAILURE$>
DispCtrlArray<COL$DISP_SLOT, WfrIndex> = ReactRunRec<REACT_RUN_CARR_SLOT_NO$, WfrIndex>
DispCtrlArray<COL$DISP_WFR_ID, WfrIndex> = ReactRunRec<REACT_RUN_IN_WFR_ID$, WfrIndex>
DispCtrlArray<COL$DISP_SCRIBE, WfrIndex> = Scribe
DispCtrlArray<COL$DISP_GRADE, WfrIndex> = Grade
DispCtrlArray<COL$DISP_RDS_NCR, WfrIndex> = RDSNCRNo
DispCtrlArray<COL$DISP_WMO_NCR, WfrIndex> = WMONCRNo
DispCtrlArray<COL$DISP_SHIP, WfrIndex> = ShipFlag
DispCtrlArray<COL$DISP_SHIP_ID, WfrIndex> = ReactRunRec<REACT_RUN_OUT_SLOT_ID$, WfrIndex>
DispCtrlArray<COL$DISP_INTERNAL, WfrIndex> = InternalFlag
DispCtrlArray<COL$DISP_EXTERNAL, WfrIndex> = ExternalFlag
DispCtrlArray<COL$DISP_RETAIN, WfrIndex> = RetainFlag
DispCtrlArray<COL$DISP_RETAIN_SLOT, WfrIndex> = RetainSlot
DispCtrlArray<COL$DISP_RETAIN_BOX, WfrIndex> = 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<REACT_RUN_DISP_REASON$, WfrIndex>
end
DispCtrlArray<COL$DISP_REASON, WfrIndex> = 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<PDISPLAY$> = WfrSigProfile
Dummy = Popup(@Window, TypeOver, 'CHAR_WFR_STAGES')
Case Action _EQC 'WaferTrace'
TraceData = obj_WO_Wfr('TraceData', WfrID:@RM:'')
TypeOver = ''
TypeOver<PDISPLAY$> = 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<COL$NCR_NO, nPos> = NCRNo
NCRCtrlArray<COL$NCR_STATUS, nPos> = {STATUS}
NCRCtrlArray<COL$NCR_REJ_QTY, nPos> = {REJ_CNT}
NCRCtrlArray<COL$NCR_RESP, nPos> = {LOSS_BY}
NCRCtrlArray<COL$NCR_STAGE, nPos> = {LOSS_STAGE}
NCRCtrlArray<COL$NCR_LOSS_DESC, nPos> = {LOSS_DESC}
NCRCtrlArray<COL$NCR_LOSS_COMM, nPos> = {LOSS_COMMENTS}
NCRCtrlArray<COL$NCR_FIN_SIG, nPos> = OConv({AUTH_SHIP_SIG}, '[XLATE_CONV,LSL_USERS*FIRST_LAST]')
NCRCtrlArray<COL$NCR_FIN_SIG_DTM, nPos> = OConv({AUTH_SHIP_SIG_DTM}, 'DT')
end else
NCRCtrlArray<COL$NCR_NO, nPos> = NCRNo
NCRCtrlArray<COL$NCR_STATUS, nPos> = 'Error'
NCRCtrlArray<COL$NCR_REJ_QTY, nPos> = 'Error'
NCRCtrlArray<COL$NCR_RESP, nPos> = 'Error'
NCRCtrlArray<COL$NCR_STAGE, nPos> = 'Error'
NCRCtrlArray<COL$NCR_LOSS_DESC, nPos> = 'Error'
NCRCtrlArray<COL$NCR_LOSS_COMM, nPos> = 'Error'
NCRCtrlArray<COL$NCR_FIN_SIG, nPos> = 'Error'
NCRCtrlArray<COL$NCR_FIN_SIG_DTM, nPos> = 'Error'
end
Next NCRNo
end else
// No NCRs associated with this inbound cassette, so clear the NCR table.
For nPos = 1 to 5
NCRCtrlArray<COL$NCR_NO, nPos> = ''
NCRCtrlArray<COL$NCR_STATUS, nPos> = ''
NCRCtrlArray<COL$NCR_REJ_QTY, nPos> = ''
NCRCtrlArray<COL$NCR_RESP, nPos> = ''
NCRCtrlArray<COL$NCR_STAGE, nPos> = ''
NCRCtrlArray<COL$NCR_LOSS_DESC, nPos> = ''
NCRCtrlArray<COL$NCR_LOSS_COMM, nPos> = ''
NCRCtrlArray<COL$NCR_FIN_SIG, nPos> = ''
NCRCtrlArray<COL$NCR_FIN_SIG_DTM, nPos> = ''
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<RUN_STAGE_STATUS$>
Begin Case
Case StageStatus _EQC 'COMP' or StageStatus _EQC 'SKIP'
StatusBy = RunStageRec<RUN_STAGE_COMP_BY$>
StatusDTM = RunStageRec<RUN_STAGE_COMP_DTM$>
Case StageStatus _EQC 'START'
InvActions = RunStageRec<RUN_STAGE_SPEC_INV_ACTION$>
Locate 'START' in InvActions using @VM setting vPos then
StatusBy = RunStageRec<RUN_STAGE_SIA_COMP_BY$, vPos>
StatusDTM = RunStageRec<RUN_STAGE_SIA_COMP_DTM$, vPos>
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<REACT_RUN_IN_WFR_ID$>
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<RUN_STAGE_WFR_STATUS$>
Begin Case
Case StageStatus _EQC 'COMP' or StageStatus _EQC 'SKIP' or StageStatus _EQC 'CHAR' or StageStatus _EQC 'DISP'
StatusBy = RunStageWfrRec<RUN_STAGE_WFR_COMP_BY$>
StatusDTM = RunStageWfrRec<RUN_STAGE_WFR_COMP_DTM$>
Case StageStatus _EQC 'START'
InvActions = RunStageWfrRec<RUN_STAGE_WFR_SPEC_INV_ACTION$>
Locate 'START' in InvActions using @VM setting vPos then
StatusBy = RunStageWfrRec<RUN_STAGE_WFR_SIA_COMP_BY$, vPos>
StatusDTM = RunStageWfrRec<RUN_STAGE_WFR_SIA_COMP_DTM$, vPos>
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<ItemCount,SRP_POPUP.RECTANGLE,1> = XPadding ; // X Position of item
ItemList<ItemCount,SRP_POPUP.RECTANGLE,2> = (20 * (ItemCount - 1) ) ; // Y Position of item
ItemList<ItemCount,SRP_POPUP.RECTANGLE,3> = PopupWidth - (2 * XPadding) ; // Width
ItemList<ItemCount,SRP_POPUP.RECTANGLE,4> = PopupHeight - (2 * YPadding) ; // Height
ItemList<ItemCount,SRP_POPUP.CAPTION> = Item
ItemList<ItemCount,SRP_POPUP.COLORS> = Forecolor
ItemList<ItemCount,SRP_POPUP.FONT> = '' : @SVM : '' : @SVM : '700' : @SVM : '0' : @SVM : '0'
ItemList<ItemCount,SRP_POPUP.ALIGNMENT> = '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<REACT_RUN_IN_WFR_ID$>
CassDispComp = ReactRunRec<REACT_RUN_DISP_COMPLETE$>
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<REACT_RUN_DISP_COMPLETE$>
* WfrsDispReady = ReactRunRec<REACT_RUN_WFRS_DISP_READY$>
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<REACT_RUN_DISP_COMPLETE$>
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<StageIndex> = 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<StageIndex>
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<StageIndex>
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<CurrWfrRow>
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