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

4349 lines
212 KiB
Plaintext

Compile function DBW_GAN_RDS_PROD_EVENTS(CtrlEntId, Event, @PARAMS)
/***********************************************************************************************************************
Name : DBW_GAN_RDS_PROD_EVENTS
Description : Commuter module for the DBW_GAN_RDS_PROD 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 DBW_GAN_RDS_PROD
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, Unlock, Error_Services, Disposition_Services
DECLARE SUBROUTINE 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_Date
$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 WO_LOG_EQUATES
$INSERT GAN_PARAMS_EQUATES
$INSERT GAN_PARAM_CONFIG_EQUATES
$INSERT NCR_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$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_ROOT_CAUSE TO 6
EQU COL$DISP_RDS_NCR TO 7
EQU COL$DISP_WMO_NCR TO 8
EQU COL$DISP_SHIP_ID TO 9
EQU COL$DISP_RETAIN_BOX TO 10
EQU COL$DISP_RETAIN_SLOT TO 11
// 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)
If CreateParam NE '' then
RDSNo = CreateParam
Set_Property(@Window:'.RDS_NO', 'TEXT', RDSNo)
Post_Event(@Window, 'READ')
end
SRP_Show_Window(@Window, 'SYSTEM', 'C', 'C', 1, '', False$, False$, '', 1)
End Event
Event WINDOW.READ()
RDSNo = Get_Property(@Window:'.RDS_NO', 'TEXT')
If RDSNo NE '' then
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 'E') or (TechType EQ '') ) then
ParentWindow = Get_Property(@Window, "PARENT")
Start_Window('REACT_RUN', 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)
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$)
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
* 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)
* 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)
If GaNEtchInfo NE '' then
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
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)
If MetDone EQ True$ then
Set_Property(@Window:'.PUB_UPDATE_DISP', 'ENABLED', True$)
end
Until MetDone EQ True$
Next WfrID
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 EnableCloseRDSButton
GoSub UpdateRDSStatus
GoSub EnableLotAbortButton
GoSub EnableImportMetDataButton
GoSub FillDispStageCtrl
* update the gauge
Msg(@Window, MsgUp, 100, MSGINSTUPDATE$)
Msg(@Window, MsgUp) ;* take down the gauge
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
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
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(CtrlEntID, 'TEXT')
If ReactRunKey NE '' then
RDSNo = Get_Property(@Window, '@RDSNO')
If ReactRunKey NE RDSNo then
ReactorType = Xlate('REACT_RUN', ReactRunKey, 'REACTOR_TYPE', 'X')
If ReactorType _EQC 'GAN' then
If RowExists('REACT_RUN', ReactRunKey) then
Post_Event(@Window, 'READ')
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_EA_DATA.CLICK()
RDSNo = Get_Property(@Window:'.RDS_NO', 'TEXT')
Engineering_Services('UpdateAll', RDSNo)
end event
Event PUB_CLOSE_RDS.CLICK()
RDSNo = Get_Property(@Window:'.RDS_NO', 'TEXT')
AllWfrsComp = GaN_Services('ReadyToClose', RDSNo)
If AllWfrsComp EQ True$ then
MsgText = 'Are you sure you want to close this RDS? Once closed an RDS cannot be re-opened.'
MsgHead = 'Warning'
Response = Msg(@WINDOW,'','YESNO','',MsgHead:@FM:MsgText)
If Response EQ Yes$ then
GaN_Services('CloseRDS', RDSNo)
GoSub FillDispEditTable
GoSub EnableCloseRDSButton
GoSub UpdateRDSStatus
// 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
end else
Dialog_Box('NDW_WAFER_STATUS', @Window, RDSNo)
end
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
IF Get_Status(errCode) THEN
ErrMsg(errCode)
end else
// Mark wafers as scrap
ReactRunRec = Database_Services('ReadDataRow', 'REACT_RUN', RDSNo)
Grades = Xlate('REACT_RUN', RDSNo, 'WFR_GRADES', 'X')
WfrIDs = ReactRunRec<REACT_RUN_IN_WFR_ID$>
OutSlotIDs = ReactRunRec<REACT_RUN_OUT_SLOT_ID$>
For each RejWfrID in RejWfrIDs using @VM setting vPos
Locate RejWfrID in WfrIDs using @VM setting wPos then
Grades<0, wPos> = 'Scrap'
// Check if this wafer is in an outbound cassette. If so,
// then remove it. Wafers cannot be shipped and scrapped at the same time.
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
WOWfrRec = Database_Services('ReadDataRow', 'WO_WFR', RejWfrID)
WOWfrRec<WO_WFR_GRADE$> = 'Scrap'
WOWfrRec<WO_WFR_RDS_NCR_NO$> = NCRNo
Database_Services('WriteDataRow', 'WO_WFR', RejWfrID, WOWfrRec, True$, False$, True$)
Next RejWfrID
Dialog_Box('NCR', @Window, NCRNo)
PrevCursor = Set_Property('SYSTEM', 'CURSOR', 'H')
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)
Disposition_Services('AutoDispositionRun', RDSNo)
Msg(@Window, MsgUp, 20, MSGINSTUPDATE$)
GoSub FillMetEditTable
Msg(@Window, MsgUp, 40, MSGINSTUPDATE$)
GoSub FillDispEditTable
Msg(@Window, MsgUp, 60, MSGINSTUPDATE$)
GoSub FillNCREditTable
Msg(@Window, MsgUp, 80, MSGINSTUPDATE$)
GoSub EnableCloseRDSButton
Msg(@Window, MsgUp, 100, MSGINSTUPDATE$)
Msg(@Window, MsgUp)
PrevCursor = Set_Property('SYSTEM', 'CURSOR', 'A')
end
GoSub EnableNCRButton
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 EQ 'UV') or (CurrStage EQ 'UV_PRE') or (CurrStage EQ 'UV_PST') or (CurrStage EQ 'WARP') or (CurrStage EQ 'CAN') or (CurrStage EQ 'CAN_PRE') or (CurrStage EQ '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')
// 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
Disposition_Services('AutoDispositionWfr', WfrID)
Next WfrID
GoSub FillMetEditTable
GoSub FillDispEditTable
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') or (SelStageID EQ 'PLATO') ) 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)
Set_Property(@Window:'.OLE_METROLOGY_EDT' , "OLE.Redraw", False$)
Set_Property(@Window:'.OLE_DISP_STAGE_EDT' , "OLE.Redraw", False$)
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')
ANKO = Xlate('PROD_SPEC', PSNo, 'ANKO', 'X')
ANKOMetPockets = Xlate('PROD_SPEC', PSNo, 'ANKO_MET_POCKETS', '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')
GaN_Services('GetGaNMetrologyData', RDSNo, 'GROWTH')
GaN_Services('GetGaNMetrologyData', RDSNo, 'TEMP')
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(ErrorMesssages)
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
GoSub ReadCurrParams
GoSub FillDispStageCtrl
GoSub ColorTabs
GoSub EnableTabs
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'
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
InWfrIDs = ReactRunRec<REACT_RUN_IN_WFR_ID$>
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_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'
GaNRunID = Get_Property(@Window:'.CMB_GAN_RUN_ID', 'TEXT')
RunInfo = Gan_Services('GetRunInfo', GaNRunID)
PocketNos = RunInfo<3>
Scribes = RunInfo<4>
// 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 WOWfrID in InWfrIDs using @VM setting vPos
If WOWfrID NE '' then
ANKOMetPocket = ANKOMetPockets<0, vPos>
GaN_Services('RemoveWfrFromWIP', WOWfrID)
WOWfrRec = Database_Services('ReadDataRow', 'WO_WFR', WOWfrID)
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'
WOWfrRec<WO_WFR_POCKET$> = PocketNos<0, vPos>
WOWfrRec<WO_WFR_SCRIBE$> = Scribes<0, vPos>
Database_Services('WriteDataRow', 'WO_WFR', WOWfrID, WOWfrRec, True$, False$, True$)
Gan_Services('MoveWfrToQueue', WOWfrID, NextLocQID)
If ( (ANKO EQ True$) and (ANKOMetPocket EQ True$) ) then
GaN_Services('CreateRunStageWfr', RDSNo, 'XRD', WOWfrID)
GaN_Services('CreateRunStageWfr', RDSNo, 'PR', WOWfrID)
end
end
Next WOWfrID
// 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
GoSub FillDispStageHeader
// 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
Set_Property(@Window:'.OLE_METROLOGY_EDT' , "OLE.Redraw", True$)
Set_Property(@Window:'.OLE_DISP_STAGE_EDT' , "OLE.Redraw", True$)
end event
Event OLE_METROLOGY_EDT.OnContextMenuClick(Item, UserData)
PrevCursor = Set_Property('SYSTEM', 'CURSOR', 'H')
// Suppress redraw until all properties are set
Set_Property(@Window:'.OLE_METROLOGY_EDT', "OLE.Redraw", False$)
Set_Property(@Window:'.OLE_DISP_STAGE_EDT', "OLE.Redraw", False$)
Set_Property(@Window:'.OLE_DISP_EDT', "OLE.Redraw", False$)
Set_Property(@Window:'.OLE_NCR_EDT', "OLE.Redraw", False$)
SelCell = UserData
Row = Field(SelCell, ';', 2)
RowData = Get_Property(CtrlEntID, "OLE.RecordData[":Row:"]")
RDSNo = Get_Property(@Window : '.RDS_NO', 'TEXT')
ReactRunRec = Database_Services('ReadDataRow', 'REACT_RUN', RDSNo)
InWfrIDs = ReactRunRec<REACT_RUN_IN_WFR_ID$>
CritStages = ReactRunRec<REACT_RUN_GAN_CRITICAL_STAGES$>
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()
NextStage = Gan_Services('GetNextRxStage', RDSNo, StageID)
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'
Def = ""
If StageID NE 'WET_CLEAN' then
Def<MCAPTION$> = "Stopping Stage and Retrieving SPC Data..."
end else
Def<MCAPTION$> = "Stopping Stage..."
end
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)
NumWfrs = Get_Property(@Window, '@NUMWFRS')
Increment = Int(100 / NumWfrs) + 1
OkToComplete = True$
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)
Locate StageID in CritStages using @VM setting vPos then
If StageID EQ 'PLATO' then
GaN_Services('GetPlatoData', RDSNo, ToolID)
end else
GaN_Services('GetGaNMetrologyData', RDSNo, StageID, ToolID, WfrID)
end
end
If Error_Services('HasError') then
DataMissingFlags = ReactRunRec<REACT_RUN_DATA_MISSING$>
DataDisabledFlags = ReactRunRec<REACT_RUN_MISSING_DATA_VALID_DISABLED$>
For each MissingFlag in DataMissingFlags using @VM setting vPos
DisabledFlag = DataDisabledFlags<0, vPos>
If MissingFlag and Not(DisabledFlag) then OkToComplete = False$
Next MissingFlag
end
end
* update the gauge
Msg(@Window, MsgUp, (Increment * WaferIndex), MSGINSTUPDATE$)
Next WfrID
Msg(@Window, MsgUp, 90, MSGINSTUPDATE$)
Msg(@Window, MsgUp, 100, MSGINSTUPDATE$)
Msg(@Window, MsgUp) ;* take down the gauge
If OkToComplete EQ True$ then
Def = ""
Def<MCAPTION$> = "Auto-Completing Stage..."
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)
For each WfrID in InWfrIDs using @VM setting vPos
FormattedWfrID = WfrID
Swap '*' with '.' in FormattedWfrID
RunStageWfrKey = RDSNo:'*':StageID:'*':FormattedWfrID
StageStatus = Xlate('RUN_STAGE_WFR', RunStageWfrKey, 'STATUS', 'X')
If StageStatus EQ 'STOP' then GaN_Services('CompleteWaferStage', RDSNo, WfrID, StageID)
* update the gauge
Msg(@Window, MsgUp, (Increment * vPos), MSGINSTUPDATE$)
Next WfrID
Msg(@Window, MsgUp, 90, MSGINSTUPDATE$)
Engineering_Services('PostEARequest', RDSNo, StageID)
If NextStage EQ 'SPLIT' then GaN_Services('SplitSelection', RDSNo)
Msg(@Window, MsgUp, 100, MSGINSTUPDATE$)
Msg(@Window, MsgUp) ;* take down the gauge
end else
ErrorMsg = 'Warning: Auto-complete failed. Unable to find ':StageID:' data in SPC.':CRLF$
ErrorMsg := 'Verify metrology data, then attempt to complete the stage again.'
Error_Services('Add', ErrorMsg)
ErrMsg(ErrorMsg)
end
If Error_Services('NoError') then Disposition_Services('AutoDispositionRun', RDSNo)
GoSub ReadCurrParams
GoSub FillDispStageCtrl
GoSub ColorTabs
GoSub FillDispEditTable
Case Action _EQC 'COMP'
NumWfrs = Get_Property(@Window, '@NUMWFRS')
Increment = Int(100 / NumWfrs) + 1
OkToComplete = True$
If StageID NE 'WET_CLEAN' then
Def = ""
Def<MCAPTION$> = "Retrieving SPC Data..."
Def<MTYPE$> = "G"
Def<MEXTENT$> = 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)
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 'STOP' then
Locate StageID in CritStages using @VM setting vPos then
If StageID EQ 'PLATO' then
GaN_Services('GetPlatoData', RDSNo, ToolID)
end else
GaN_Services('GetGaNMetrologyData', RDSNo, StageID, ToolID, WfrID)
end
end
If Error_Services('HasError') then
DataMissingFlags = ReactRunRec<REACT_RUN_DATA_MISSING$>
DataDisabledFlags = ReactRunRec<REACT_RUN_MISSING_DATA_VALID_DISABLED$>
For each MissingFlag in DataMissingFlags using @VM setting vPos
DisabledFlag = DataDisabledFlags<0, vPos>
If MissingFlag and Not(DisabledFlag) then OkToComplete = False$
Next MissingFlag
end
end
* update the gauge
Msg(@Window, MsgUp, (Increment * WaferIndex), MSGINSTUPDATE$)
Next WfrID
Msg(@Window, MsgUp, 100, MSGINSTUPDATE$)
Msg(@Window, MsgUp) ;* take down the gauge
end
If OkToComplete EQ True$ then
Def = ""
Def<MCAPTION$> = "Completing Stage..."
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)
For each WfrID in InWfrIDs using @VM setting vPos
FormattedWfrID = WfrID
Swap '*' with '.' in FormattedWfrID
RunStageWfrKey = RDSNo:'*':StageID:'*':FormattedWfrID
StageStatus = Xlate('RUN_STAGE_WFR', RunStageWfrKey, 'STATUS', 'X')
If StageStatus EQ 'STOP' then GaN_Services('CompleteWaferStage', RDSNo, WfrID, StageID)
* update the gauge
Msg(@Window, MsgUp, (Increment * vPos), MSGINSTUPDATE$)
Next WfrID
If ( (NextStage EQ 'SPLIT') and (PSNo NE 5191) and (PSNo NE 5192) ) then GaN_Services('SplitSelection', RDSNo)
Msg(@Window, MsgUp, 90, MSGINSTUPDATE$)
If Error_Services('NoError') then
Disposition_Services('AutoDispositionRun', RDSNo)
GoSub ReadCurrParams
GoSub FillDispStageCtrl
GoSub ColorTabs
GoSub FillDispEditTable
end
Engineering_Services('PostEARequest', RDSNo, StageID)
Msg(@Window, MsgUp, 100, MSGINSTUPDATE$)
Msg(@Window, MsgUp) ;* take down the gauge
end else
ErrorMsg = 'Warning: Complete stage failed. Unable to find ':StageID:' data in SPC.':CRLF$
ErrorMsg := 'Verify metrology data, then attempt to complete the stage again.'
Error_Services('Add', ErrorMsg)
ErrMsg(ErrorMsg)
end
Case Action _EQC 'SKIP'
For each WfrID in InWfrIDs using @VM setting vPos
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
If ( (NextStage EQ 'SPLIT') and (PSNo NE 5191) ) then
Gan_Services('SplitSelection', RDSNo)
If Error_Services('NoError') then
Disposition_Services('AutoDispositionRun', RDSNo)
GoSub ReadCurrParams
GoSub FillDispStageCtrl
GoSub ColorTabs
GoSub FillDispEditTable
end
end
Case Action _EQC 'UNSKIP'
For each WfrID in InWfrIDs using @VM setting vPos
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
GoSub FillMetEditTable
// Re-enable redraw now that all properties are set
Set_Property(@Window:'.OLE_METROLOGY_EDT', "OLE.Redraw", True$)
Set_Property(@Window:'.OLE_DISP_STAGE_EDT', "OLE.Redraw", True$)
Set_Property(@Window:'.OLE_DISP_EDT', "OLE.Redraw", True$)
Set_Property(@Window:'.OLE_NCR_EDT', "OLE.Redraw", True$)
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 PUB_IMPORT_MET_DATA.CLICK()
Def = ""
Def<MCAPTION$> = "Importing..."
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)
RDSNo = Get_Property(@Window:'.RDS_NO', 'TEXT')
GaN_Services('ClearScribeErrors', RDSNo)
MetStageCtrl = @Window:'.OLE_METROLOGY_EDT'
GaNParamKeys = Xlate('REACT_RUN', RDSNo, 'GAN_PARAM_KEYS', 'X')
MetStageList = ''
AllStageList = Database_Services('ReadDataRow', 'APP_INFO', 'GAN_MET_STAGES')
For each GaNParamKey in GaNParamKeys using @VM
Stage = Field(GaNParamKey, '*', 2, 1)
MetStageList<0, -1> = Stage
Next GaNParamKey
InWfrIDs = Get_Property(@Window, '@WFRIDS')
For each Stage in MetStageList using @VM
If ( (Stage EQ 'GROWTH') or (Stage EQ 'TEMP') ) then
Gan_Services('GetGaNMetrologyData', RDSNo, Stage)
end else
Locate Stage in AllStageList using @FM setting Row then
Msg(@Window, MsgUp, (Row * 5), MSGINSTUPDATE$)
ToolType = GaN_Services('GetStageID', Stage)
Tool = Get_Property(@Window : '.OLE_METROLOGY_EDT', 'OLE.CellText[2; ':Row:']')
WaferIndex = 1 ; // Just use the first wafer's status to determine if the stage is complete.
StageStatus = Get_Property(@Window : '.OLE_METROLOGY_EDT', 'OLE.CellText[':(WaferIndex + 2):'; ':Row:']')
If ( (Stage EQ 'CAN_PRE') or (Stage EQ 'CAN_PST') or (Stage EQ 'JV_XRD') ) then GaN_Services('VerifyWaferScribes', RDSNo, Tool)
Begin Case
Case ( ( (ToolType EQ 'UV') or (ToolType EQ 'UV_PRE') or (ToolType EQ 'UV_PST') or (ToolType EQ 'WARP') or (ToolType EQ 'CAN') or (ToolType EQ 'CAN_PRE') or (ToolType EQ 'CAN_PST') ) and (StageStatus EQ 'Complete') )
Gan_Services('GetGaNMetrologyData', RDSNo, ToolType, Tool)
Case ( (ToolType EQ 'PLATO') and (StageStatus EQ 'Complete') )
// Plato has a unique service and query
GaN_Services('GetPlatoData', RDSNo, Tool)
Case StageStatus EQ 'Complete'
// Default case for all other stages
For each WfrID in InWfrIDs using @VM setting WaferIndex
StageStatus = Get_Property(@Window : '.OLE_METROLOGY_EDT', 'OLE.CellText[':(WaferIndex + 2):'; ':Row:']')
If StageStatus EQ 'Complete' then Gan_Services('GetGaNMetrologyData', RDSNo, ToolType, Tool, WfrID)
Next WfrID
End Case
end
end
Next Stage
Disposition_Services('AutoDispositionRun', RDSNo)
Msg(@Window, MsgUp, 90, MSGINSTUPDATE$)
GoSub ReadCurrParams
GoSub FillDispStageCtrl
Msg(@Window, MsgUp, 95, MSGINSTUPDATE$)
GoSub ColorTabs
GoSub FillDispEditTable
GoSub VerifyScribes
GoSub EnableCloseRDSButton
Msg(@Window, MsgUp, 100, MSGINSTUPDATE$)
Msg(@Window, MsgUp) ;* take down the gauge
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')
PSNo = Xlate('REACT_RUN', RDSNo, 'PS_NO', 'X')
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$>
CritStages = ReactRunRec<REACT_RUN_GAN_CRITICAL_STAGES$>
ToolID = Get_Property(@Window : '.OLE_METROLOGY_EDT', 'OLE.CellText[2; ':Row:']')
CurrDTM = DateTime()
WfrIndex = Column - 2
PartNo = Get_Property(@Window:'.EPI_PART_NO', 'TEXT')
Reactor = Get_Property(@Window, '@REACTOR')
RunID = Get_Property(@Window:'.CMB_GAN_RUN_ID', 'TEXT')
SelStage = Get_Property(CtrlEntID, "OLE.CellText[":Column:";":Row:"]")
ToolType = GaN_Services('GetStageID', SelStage)
Tool = Get_Property(@Window : '.OLE_METROLOGY_EDT', 'OLE.CellText[2; ':Row:']')
MetParameter = ''
Abort = False$
NextStage = Gan_Services('GetNextRxStage', RDSNo, StageID)
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 if the stage is CAN.
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 EQ 'INIT') or (StageID EQ 'CAN') or (StageID EQ 'CAN_PRE') or (StageID EQ 'CAN_PST') ) 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>
Begin Case
Case Action _EQC 'START'
Gan_Services('StartWaferStage', RDSNo, WfrID, StageID, ToolID)
Case Action _EQC 'STOP'
OkToComplete = True$
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)
Locate StageID in CritStages using @VM setting vPos then
GaN_Services('GetGaNMetrologyData', RDSNo, StageID, ToolID, WfrID)
end
If Error_Services('HasError') then
DataMissingFlags = ReactRunRec<REACT_RUN_DATA_MISSING$>
DataDisabledFlags = ReactRunRec<REACT_RUN_MISSING_DATA_VALID_DISABLED$>
For each MissingFlag in DataMissingFlags using @VM setting vPos
DisabledFlag = DataDisabledFlags<0, vPos>
If MissingFlag and Not(DisabledFlag) then OkToComplete = False$
Next MissingFlag
end
end
If ( (StageID EQ 'CAN_PRE') or (StageID EQ 'CAN_PST') or (StageID EQ 'JV_XRD') or (StageID EQ 'PLATO') ) then
GaN_Services('VerifyWaferScribes', RDSNo, ToolID)
GoSub VerifyScribes
end
If OkToComplete EQ True$ then
FormattedWfrID = WfrID
Swap '*' with '.' in FormattedWfrID
RunStageWfrKey = RDSNo:'*':StageID:'*':FormattedWfrID
StageStatus = Xlate('RUN_STAGE_WFR', RunStageWfrKey, 'STATUS', 'X')
If StageStatus EQ 'STOP' then GaN_Services('CompleteWaferStage', RDSNo, WfrID, StageID)
Engineering_Services('PostEARequest', RDSNo, StageID)
If NextStage EQ 'SPLIT' then GaN_Services('SplitSelection', RDSNo)
end
Case Action _EQC 'Complete'
OkToComplete = True$
If StageID NE 'WET_CLEAN' then
FormattedWfrID = WfrID
Swap '*' with '.' in FormattedWfrID
RunStageWfrKey = RDSNo:'*':StageID:'*':FormattedWfrID
StageStatus = Xlate('RUN_STAGE_WFR', RunStageWfrKey, 'STATUS', 'X')
If StageStatus EQ 'STOP' then
Locate StageID in CritStages using @VM setting vPos then
GaN_Services('GetGaNMetrologyData', RDSNo, StageID, ToolID, WfrID)
end
If Error_Services('HasError') then
DataMissingFlags = ReactRunRec<REACT_RUN_DATA_MISSING$>
DataDisabledFlags = ReactRunRec<REACT_RUN_MISSING_DATA_VALID_DISABLED$>
For each MissingFlag in DataMissingFlags using @VM setting vPos
DisabledFlag = DataDisabledFlags<0, vPos>
If MissingFlag and Not(DisabledFlag) then OkToComplete = False$
Next MissingFlag
end
end
end
If ( (StageID EQ 'CAN_PRE') or (StageID EQ 'CAN_PST') or (StageID EQ 'JV_XRD') ) then
GaN_Services('VerifyWaferScribes', RDSNo, ToolID)
GoSub VerifyScribes
end
If OkToComplete EQ True$ then
FormattedWfrID = WfrID
Swap '*' with '.' in FormattedWfrID
RunStageWfrKey = RDSNo:'*':StageID:'*':FormattedWfrID
StageStatus = Xlate('RUN_STAGE_WFR', RunStageWfrKey, 'STATUS', 'X')
If StageStatus EQ 'STOP' then GaN_Services('CompleteWaferStage', RDSNo, WfrID, StageID)
Engineering_Services('PostEARequest', RDSNo, StageID)
end else
ErrorMsg = 'Warning: Complete stage failed. Unable to find ':StageID:' data in SPC.':CRLF$
ErrorMsg := 'Verify metrology data, then attempt to complete the stage again.'
Error_Services('Add', ErrorMsg)
ErrMsg(ErrorMsg)
end
Case Action _EQC 'SKIP'
Gan_Services('SkipWaferStage', RDSNo, WfrID, StageID)
Case Action _EQC 'UNSKIP'
Gan_Services('UnskipWaferStage', RDSNo, WFrID, StageID)
Case Action _EQC 'ADD'
Gan_Services('AddWaferStage', RDSNo, WfrID, StageID, ToolID)
Case Action _EQC 'REMOVE'
Gan_Services('RemoveWaferStage', RDSNo, WfrID, StageID)
Case Action _EQC 'CHARACTERIZE'
If Not( Memberof(@User4, 'GAN_WIP_SUPERVISOR') ) then
Response = Dialog_Box('NDW_VERIFY_USER', @Window, @User4 : @FM : 'GAN_WIP_SUPERVISOR')
Valid = Response<1>
end else
Valid = True$
end
If Valid EQ True$ then
Gan_Services('CharacterizeWafer', RDSNo, WfrID)
end else
Abort = True$
end
Case Action _EQC 'DISPOSITION'
If Not( Memberof(@User4, 'GAN_WIP_SUPERVISOR') ) then
Response = Dialog_Box('NDW_VERIFY_USER', @Window, @User4 : @FM : 'GAN_WIP_SUPERVISOR')
Valid = Response<1>
end else
Valid = True$
end
If Valid EQ True$ then
Gan_Services('DispositionWfr', RDSNo, WfrID)
end else
Abort = True$
end
Case Action _EQC 'WITHDRAW'
If Not( Memberof(@User4, 'GAN_WIP_SUPERVISOR') ) then
Response = Dialog_Box('NDW_VERIFY_USER', @Window, @User4 : @FM : 'GAN_WIP_SUPERVISOR')
Valid = Response<1>
end else
Valid = True$
end
If Valid EQ True$ then
Gan_Services('WithdrawWfr', RDSNo, WfrID)
end else
Abort = True$
end
Case Otherwise$
End Case
end
If Error_Services('HasError') then
Errmsg(Error_Services('GetMessage'))
end
If Abort EQ False$ then
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
Disposition_Services('AutoDispositionRun', RDSNo)
GoSub ReadCurrParams
GoSub FillDispEditTable
GoSub FillMetEditTable
GoSub ColorTabs
GoSub EnableCloseRDSButton
end
PrevCursor = Set_Property('SYSTEM', 'CURSOR', 'A')
end event
Event OLE_DISP_EDT.OnCheckChanged(Cell, OldValue, NewValue)
Col = Field(Cell, ';', 1, 1)
Row = Field(Cell, ';', 2, 1)
NCRButton = ''
Begin Case
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
Event OLE_TAB.SelChanged(Index, PrevIndex)
GoSub FillDispStageCtrl
end event
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Internal GoSubs
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Setup_OLE_Controls:
NumReactorCols = 2
NumReactorRows = 4
NumMetCols = 10
NumMetRows = 21
NumDispCols = 11
NumDispRows = 8
NumNCRCols = 9
NumNCRRows = 5
ReactorCtrlList = ''
MetCtrlList = ''
DispCtrlList = ''
DispParamCtrlList = 'LSL':@FM:'USL'
ReactorToolIDArray = ''
MetToolIDArray = ''
RDSNo = Get_Property(@Window : '.RDS_NO', 'DEFPROP')
PSNo = Xlate('RDS', RDSNo, 'PROD_SPEC_ID', 'X')
ReactRunRec = Database_Services('ReadDataRow', 'REACT_RUN', RDSNo)
DefaultGaNStageArray = Database_Services('ReadDataRow', 'APP_INFO', 'GAN_STAGES')
GaNStageArray = ''
MetStageOrder = ReactRunRec<REACT_RUN_GAN_STAGE_ROUTE$>
If MetStageOrder NE '' then
For each StageID in MetStageOrder using @VM
Done = False$
For each Row in DefaultGaNStageArray using @FM
ThisRowStage = Row<0, 1>
If ThisRowStage EQ StageID then
GaNStageArray<-1> = Row
Done = True$
end
Until Done EQ True$
Next Row
Next StageID
end else
GaNStageArray = DefaultGaNStageArray
end
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
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'
DispCtrl = @Window:'.OLE_DISP_EDT'
NCRCtrl = @Window:'.OLE_NCR_EDT'
DispParamCtrl = @Window:'.OLE_DISP_PARAM_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(@Window, '@NCRDIMARRAY', NCRDimArray)
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(DispCtrl, "OLE.CellFont[All; All]", 'Segoe UI':@SVM:8)
Set_Property(DispCtrl, "OLE.Dimension", DispDimArray)
Set_Property(DispCtrl, "OLE.HeaderFont[All; 1]", HeaderFontArray)
Set_Property(DispCtrl, "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"
ScribeHeaderTitles = ''
If ScribesCopy NE '' then
For each Scribe in Scribes using @VM setting vPos
SlotID = Field(CarrSlotIDs<0, vPos>, '.', 2, 1)
ScribeHeaderTitles<0, -1> = Scribe:' (':SlotID:')'
Next Scribe
HeaderTitles<0, -1> = ScribeHeaderTitles
Set_Property(@Window, '@SCRIBE_HEADER_TITLES', ScribeHeaderTitles)
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:'Inbound':@VM:'Scribe':@VM:'Grade':@VM:'Reason':@VM:'Root Cause':@VM:'RDS NCR':@VM:'WMO NCR':@VM
DispHeaderTitles := 'Outbound':@VM:'Retain Box':@VM:'Retain Slot'
Set_Property(DispCtrl, "OLE.TitleList", DispHeaderTitles)
Set_Property(DispCtrl, "OLE.HeaderText[1; 2]", 'Disposition')
Set_Property(DispCtrl, "OLE.HeaderAlignment[All; 1]", 'C':@FM:'C':@FM:'L')
Set_Property(DispCtrl, "OLE.CellAlignment[":COL$DISP_SLOT:"-":COL$DISP_GRADE:"; All]", 'C':@FM:'C':@FM:'L')
Set_Property(DispCtrl, "OLE.CellAlignment[":COL$DISP_REASON:"-":COL$DISP_ROOT_CAUSE:"; All]", 'C':@FM:'L':@FM:'L')
Set_Property(DispCtrl, "OLE.CellAlignment[":COL$DISP_RDS_NCR:"-":COL$DISP_RETAIN_SLOT:"; All]", 'C':@FM:'C':@FM:'L')
Set_Property(DispCtrl, "OLE.AllowDeletions", False$)
Set_Property(DispCtrl, "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(DispCtrl, "OLE.HeaderColors[All; All]", HeaderColorArray)
Set_Property(NCRCtrl, "OLE.HeaderColors[All; All]", HeaderColorArray)
Set_Property(DispParamCtrl, "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(DispCtrl, 'QUALIFY_EVENT', 'OLE.OnCheckChanged', Qualifier)
Send_Message(DispCtrl, 'QUALIFY_EVENT', 'OLE.OnClick', Qualifier)
Send_Message(DispCtrl, 'QUALIFY_EVENT', 'OLE.OnContextMenuClick', Qualifier)
Send_Message(DispCtrl, 'QUALIFY_EVENT', 'OLE.OnComboClicked', Qualifier)
Send_Message(NCRCtrl, 'QUALIFY_EVENT', 'OLE.OnDblClick', Qualifier)
// Process BeforeUpdate event synchronously
Qualifier<4> = 1
Send_Message(DispCtrl, 'QUALIFY_EVENT', 'OLE.BeforeUpdate', 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(DispCtrl, "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(DispCtrl, "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(DispCtrl, '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 LT 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 else
StartCol = 3
Set_Property(MetStageCtrl,"OLE.CellProtection[":StartCol:"-":NumMetCols:"; All]", "None")
Set_Property(MetStageCtrl,"OLE.CellColors[":StartCol:"-":NumMetCols:"; All]", CellColorArray)
Set_Property(MetStageCtrl,"OLE.ColumnData[":StartCol:"-":NumMetCols:"]", '')
Set_Property(MetStageCtrl,"OLE.HeaderColors[":StartCol+1:"-":NumMetCols+1:"; 1]", CellColorArray)
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
GoSub SetupDispEDT
GoSub SetupTabCtrl
GoSub SetupDispStageCtrl
GoSub ReadCurrParams
GoSub FillDispStageCtrl
GoSub ColorTabs
GoSub EnableTabs
//////////////////////////////////// Code below here only runs once //////////////////////////////////////////
FirstPassComp = Get_Property(@Window, '@FIRSTPASS')
If FirstPassComp EQ '' or FirstPassComp EQ False$ then
// Color headers
Set_Property(MetStageCtrl, "OLE.HeaderColors[All; 1]", @FM:"{200, 200, 200}")
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)
// Color headers
Set_Property(ReactorStageCtrl, "OLE.HeaderColors[All; 1]", @FM:"{200, 200, 200}")
//////////////////////////////////// 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
FillMetEditTable:
RDSNo = Get_Property(@Window:'.RDS_NO', 'TEXT')
WfrIDs = Get_Property(@Window, '@WFRIDS')
NumWfrs = Get_Property(@Window, '@NUMWFRS')
MetStageIDList = Get_Property(@Window, '@METSTAGEIDLIST')
If WfrIDs EQ '' then
WfrIDs = Xlate('REACT_RUN', RDSNo, 'IN_WFR_ID', 'X')
Set_Property(@Window, '@WFRIDS', WfrIDs)
end
If NumWfrs EQ '' then
NumWfrs = DCount(WfrIDs, @VM)
Set_Property(@Window, '@NUMWFRS')
end
GoSub AutoSelectToolID
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 Stage in MetStageIDList using @VM setting StageIndex
For each WfrID in WfrIDs using @VM setting WfrIndex
BackgroundColor = 'None'
CurrWfrRow = StageIndex
CurrWfrCol = WfrIndex + 2
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
ReadyToSplit = Gan_Services('ReadyToSplit', 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?
ReadyToStart = Gan_Services('ReadyToStart', RDSNo, WfrID)
DispStatus = ''
Begin Case
Case CurrStatus _EQC 'COMP'
DispStatus = 'Complete'
MetActionArray = 'Complete'
If ( ( (Stage _EQC 'CAN_PST') or (Stage _EQC 'WET_CLEAN') or (Stage _EQC 'CAN_PRE') ) 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
Destructive = Gan_Services('IsDestStage', Stage)
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') or (Stage _EQC 'WET_CLEAN') ) 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_PST') or (Stage _EQC 'CAN_PRE') 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 EQ 'BV100%') then
Destructive = Gan_Services('IsDestStage', Stage)
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
Next WfrID
Destructive = Gan_Services('IsDestStage', Stage)
RowEnabled = MetRowsEnabled<StageIndex>
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:";":StageIndex:"]", "FUL")
Set_Property(MetStageCtrl,"OLE.CellColors[":COL$MET_STAGE:'-':COL$MET_TOOL_ID:";":StageIndex:"]", 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:";":StageIndex:"]", "None")
Set_Property(MetStageCtrl,"OLE.CellColors[":COL$MET_STAGE:'-':COL$MET_TOOL_ID:";":StageIndex:"]", EnabledColorArray)
end
Next Stage
Set_Property(@Window, '@METROWSENABLED', MetRowsEnabled)
return
AutoSelectToolID:
EnabledColorArray = 'None':@FM:'None':@FM:'None':@FM:'None':@FM:'None'
MetStageIDList = Get_Property(@Window, '@METSTAGEIDLIST')
WfrIDs = Get_Property(@Window, '@WFRIDS')
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 setting wPos
If WfrID NE '' 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
Next WfrID
end
Next MetStage
Set_Property(@Window, '@METROWSENABLED', MetRowsEnabled)
return
FillDispStageHeader:
DispStageCtrl = @Window:'.OLE_DISP_STAGE_EDT'
ScribeHeaderTitles = Get_Property(@Window, '@SCRIBE_HEADER_TITLES')
HeaderRowTitles = 'LSL':@VM:'Target':@VM:'USL':@VM:ScribeHeaderTitles
Set_Property(DispStageCtrl, "OLE.TitleList", HeaderRowTitles)
Set_Property(DispStageCtrl, "OLE.HeaderColors[All; 1]", @FM:"{200, 200, 200}")
return
FillMetHeader:
Scribes = Xlate('REACT_RUN', RDSNo, 'WFR_SCRIBES', '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"
ScribeHeaderTitles = ''
If ScribesCopy NE '' then
For each Scribe in Scribes using @VM setting vPos
SlotID = CarrSlotIDs<0, vPos>
ScribeHeaderTitles<0, -1> = Scribe:' (':SlotID:')'
Next Scribe
HeaderTitles<0, -1> = ScribeHeaderTitles
Set_Property(@Window, '@SCRIBE_HEADER_TITLES', ScribeHeaderTitles)
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)
Set_Property(MetStageCtrl, "OLE.HeaderColors[All; 1]", @FM:"{200, 200, 200}")
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-6]", "None")
Set_Property(MetStageCtrl,"OLE.CellColors[":StartCol:"-":EndCol:"; 1-6]", 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')
DispCtrl = @Window:'.OLE_DISP_EDT'
DispDimArray = Get_Property(@Window, '@DISPDIMARRAY')
NumDispRows = DispDimArray<2>
Set_Property(DispCtrl, "OLE.HeaderMerge[1; 2]", 1:@FM:NumDispRows)
ReactRunRec = Database_Services('ReadDataRow', 'REACT_RUN', RDSNo)
DispCtrlArray = ''
ComboBoxArray = Get_Property(@Window, '@COMBOBOX')
InWfrIDs = ReactRunRec<REACT_RUN_IN_WFR_ID$>
NumWfrs = DCount(InWfrIDs, @VM)
RDSClosed = ReactRunRec<REACT_RUN_DISP_COMPLETE$>
ScribeErrors = ReactRunRec<REACT_RUN_SCRIBE_ERROR$>
PSNo = Xlate('REACT_RUN', RDSNo, 'PS_NO', 'X')
ANKO = Xlate('PROD_SPEC', PSNo, 'ANKO', 'X')
For WfrIndex = 1 to NumWfrs
ScribeError = ScribeErrors<0, WfrIndex>
Row = WfrIndex
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$>
NCRReq = ReactRunRec<REACT_RUN_NCR_REQ$, WfrIndex>
DispReady = ReactRunRec<REACT_RUN_WFRS_DISP_READY$, WfrIndex>
Grade = WOWfrRec<WO_WFR_GRADE$>
Scribe = WOWfrRec<WO_WFR_SCRIBE$>
Reason = ReactRunRec<REACT_RUN_DISP_REASON$, WfrIndex>
WfrChar = ReactRunRec<REACT_RUN_CHAR_WFR_FLAG$, WfrIndex>
RetainBox = WOWfrRec<WO_WFR_RETAIN_BOX$>
RetainSlot = WOWfrRec<WO_WFR_RETAIN_SLOT$>
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_RDS_NCR, WfrIndex> = RDSNCRNo
DispCtrlArray<COL$DISP_WMO_NCR, WfrIndex> = WMONCRNo
DispCtrlArray<COL$DISP_SHIP_ID, WfrIndex> = ReactRunRec<REACT_RUN_OUT_SLOT_ID$, WfrIndex>
DispCtrlArray<COL$DISP_GRADE, WfrIndex> = Grade
If RDSNCRNo NE '' then
// Display the reason from the NCR record
LossCode = Xlate('NCR', RDSNCRNo, 'LOSS_CODE', 'X')
DispCtrlArray<COL$DISP_REASON, WfrIndex> = Xlate('NCR', RDSNCRNo, 'LOSS_DESC', 'X')
DispCtrlArray<COL$DISP_ROOT_CAUSE, WfrIndex> = Xlate('NCR', RDSNCRNo, 'AC_DESC', 'X')
end else
// Display the reason from the REACT_RUN record
LossCode = ''
DispCtrlArray<COL$DISP_REASON, WfrIndex> = ReactRunRec<REACT_RUN_DISP_REASON$, WfrIndex>
DispCtrlArray<COL$DISP_ROOT_CAUSE, WfrIndex> = ''
end
DispCtrlArray<COL$DISP_RETAIN_SLOT, WfrIndex> = RetainSlot
DispCtrlArray<COL$DISP_RETAIN_BOX, WfrIndex> = RetainBox
MetComp = GaN_Services('GetMetrologyStatus', WfrID)
DispComp = GaN_Services('GetDispStatus', WfrID)
CharType = Gan_Services('GetCharType', WfrID)
If ( ( (WfrChar NE True$) or (CharType EQ 'Light') ) and (RDSClosed NE True$) and (RDSNCRNo EQ '') ) then
// Reset cell back to a text cell in case it was previously set to a check box
Set_Property(DispCtrl, "OLE.CellType[":COL$DISP_RDS_NCR:";":WfrIndex:"]", 'Text')
Set_Property(DispCtrl, "OLE.CellText[":COL$DISP_RDS_NCR:";":WfrIndex:"]", '')
// Convert NCR cell for this row into a check box
CheckBoxArray = 'Check Box'
CheckBoxArray<2,1> = True$
Set_Property(DispCtrl, "OLE.CellType[":COL$DISP_RDS_NCR:";":WfrIndex:"]", CheckBoxArray)
end else
// Reset cell back to a text cell in case it was previously set to a check box
Set_Property(DispCtrl, "OLE.CellType[":COL$DISP_RDS_NCR:";":WfrIndex:"]", 'Text')
Set_Property(DispCtrl, "OLE.CellText[":COL$DISP_RDS_NCR:";":WfrIndex:"]", RDSNCRNo)
end
Begin Case
Case ScribeError EQ True$
ColorArray = 'None':@FM:ORANGE$
Case Grade _EQC 'Scrap'
ColorArray = 'None':@FM:RED$
Case DispReady EQ True$
// Color scribe cell green to indicate that the wafer is ready to be placed in an outbound cassette.
// Color scribe cell within disposition edit table green
ColorArray = 'None':@FM:BGREEN$
Case Otherwise$
ColorArray = 'None':@FM:'None'
End Case
Set_Property(DispCtrl, 'OLE.CellColors[':COL$DISP_SCRIBE:';':WfrIndex:']', ColorArray)
If RDSClosed NE True$ then
// Enable editing of the cell
Set_Property(DispCtrl, 'OLE.CellProtection[':COL$DISP_REASON:';':WfrIndex:']', 'None')
end
Next WfrIndex
Set_Property(DispCtrl, "OLE.ARRAY", DispCtrlArray)
GoSub EnableNCRButton
return
Event OLE_NCR_EDT.OnDblClick(Cell, Point, Button, Shift, Ctrl)
DispCtrlArray = Get_Property(@Window:'.OLE_DISP_EDT', "OLE.ARRAY")
Row = Field(Cell, ';', 2, 1)
RDSNCRNos = DispCtrlArray<COL$DISP_RDS_NCR>
WMONCRNos = DispCtrlArray<COL$DISP_WMO_NCR>
NCRNos = SRP_Array('Join', RDSNCRNos, WMONCRNos, 'OR', @VM)
NCRNo = Get_Property(CtrlEntID, "OLE.CellText[":COL$NCR_NO:";":Row:"]")
If RowExists('NCR', NCRNo) then
PreNCRRec = Database_Services('ReadDataRow', 'NCR', NCRNo)
PostNCRRec = ''
Dialog_Box('NCR', @Window, NCRNo)
If RowExists('NCR', NCRNo) then PostNCRRec = Database_Services('ReadDataRow', 'NCR', NCRNo)
If PreNCRRec NE PostNCRRec then
RDSNo = Get_Property(@Window:'.RDS_NO', 'TEXT')
PrevCursor = Set_Property('SYSTEM', 'CURSOR', 'H')
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)
Disposition_Services('AutoDispositionRun', RDSNo)
Msg(@Window, MsgUp, 20, MSGINSTUPDATE$)
Msg(@Window, MsgUp, 40, MSGINSTUPDATE$)
GoSub FillDispEditTable
Msg(@Window, MsgUp, 60, MSGINSTUPDATE$)
GoSub FillNCREditTable
Msg(@Window, MsgUp, 80, MSGINSTUPDATE$)
GoSub EnableCloseRDSButton
Msg(@Window, MsgUp, 100, MSGINSTUPDATE$)
GoSub EnableNCRButton
Msg(@Window, MsgUp)
PrevCursor = Set_Property('SYSTEM', 'CURSOR', 'A')
end
end
end event
Event OLE_DISP_STAGE_EDT.OnClick(Cell, Point, Button, Shift, Ctrl)
If Button EQ 'Right' then
Col = Field(Cell, ';', 1, 1)
Row = Field(Cell, ';', 2, 1)
CellColorArray = Get_Property(@Window, '@COLOR_ARRAY')
SelTabIndex = Get_Property(@Window:".OLE_TAB", "OLE.SelectedTab")
CaptionList = Get_Property(@Window:".OLE_TAB", "OLE.CaptionList")
StageID = Field(CaptionList, ',', SelTabIndex, 1)
BackColor = CellColorArray<SelTabIndex, Row, Col-3>
CellText = Get_Property(CtrlEntID, "OLE.CellText[":Col:";":Row:"]")
Begin Case
Case CellText EQ 'Multi'
PopupCtrl = @Window : '.OLE_POPUP'
PopupVisible = Get_Property(PopupCtrl, 'OLE.Visible')
If PopupVisible EQ True$ then
GoSub DismissPopup
end
GoSub DisplayMetPopup
Case BackColor EQ 'Yellow'
PopupCtrl = @Window : '.OLE_POPUP'
PopupVisible = Get_Property(PopupCtrl, 'OLE.Visible')
If PopupVisible EQ True$ then
GoSub DismissPopup
end
GoSub DisplayStageDisPopup
End Case
end
end event
Event OLE_DISP_STAGE_EDT.OnHeaderClick(Cell, Point, Button, Shift, Ctrl)
If Button EQ 'Right' then
Col = Field(Cell, ';', 1, 1)
Row = Field(Cell, ';', 2, 1)
Scribe = Get_Property(CtrlEntID, "OLE.HeaderText[":Col:";":Row:"]")
Scribe = Scribe[1, 'F ']
RDSNo = Get_Property(@Window:'.RDS_NO', 'TEXT')
Scribes = Get_Property(@Window, '@SCRIBES')
RDSNo = Get_Property(@Window:'.RDS_NO', 'TEXT')
RDSClosed = Xlate('REACT_RUN', RDSNo, 'DISP_COMPLETE', 'X')
Locate Scribe in Scribes using @VM setting WfrIndex then
ReactRunRec = Database_Services('ReadDataRow', 'REACT_RUN', RDSNo)
DataValidationDisabled = ReactRunRec<REACT_RUN_MISSING_DATA_VALID_DISABLED$, WfrIndex>
DataIsMissing = ReactRunRec<REACT_RUN_DATA_MISSING$, WfrIndex>
DataOutOfSpec = ReactRunRec<REACT_RUN_DATA_OUT_OF_SPEC$, WfrIndex>
If RDSClosed EQ True$ then
Enabled = False$
end else
Enabled = True$
end
Menu = ''
Begin Case
Case DataValidationDisabled EQ True$
Menu<-1> = 'ENABLE' :@VM: 'Enable Data Validation' :@VM: Enabled
Case ( ( (DataValidationDisabled NE True$) and (DataIsMissing EQ True$) ) or (DataOutOfSpec EQ True$) )
Menu<-1> = 'DISABLE' :@VM: 'Disable Data Validation' :@VM: Enabled
Case Otherwise$
Menu<-1> = 'DISABLE' :@VM: 'Disable Data Validation' :@VM: False$
End Case
// Note you must pass all variables when calling Send_Message otherwise the call will fail
User = ''
Locate Scribe in Scribes using @VM setting WfrIndex then
User = WfrIndex
end
Send_Message(CtrlEntID, "OLE.ShowContextMenu", Point, Menu, User)
end
end
end event
Event OLE_DISP_STAGE_EDT.OnContextMenuClick(Item, UserData)
Abort = False$
If Not( Memberof(@User4, 'GAN_WIP_SUPERVISOR') ) then
MsgText = 'A member of the "GAN_WIP_SUPERVISOR" group must override.'
Response = Msg(@Window, '', 'OVERRIDE', '', MsgText)
If Response EQ Yes$ then
// Verify credentials
Response = Dialog_Box('NDW_VERIFY_USER', @WINDOW, @USER4:@FM:'GAN_WIP_SUPERVISOR')
Valid = Response<1>
If Valid NE True$ then Abort = True$
end else
Abort = True$
end
end
If Abort EQ False$ then
RDSNo = Get_Property(@Window:'.RDS_NO', 'TEXT')
ReactRunRec = Database_Services('ReadDataRow', 'REACT_RUN', RDSNo)
WfrIDs = ReactRunRec<REACT_RUN_IN_WFR_ID$>
Action = Item
WfrIndex = UserData
WfrID = WfrIDs<0, WfrIndex>
TabCount = Get_Property(@Window:'.OLE_TAB', 'OLE.TabCount')
CellColorArray = Get_Property(@Window, '@COLOR_ARRAY')
Begin Case
Case Action EQ 'DISABLE'
ReactRunRec<REACT_RUN_MISSING_DATA_VALID_DISABLED$, WfrIndex> = True$
ReactRunRec<REACT_RUN_MISSING_DATA_VALID_USER$, WfrIndex> = @User4
ReactRunRec<REACT_RUN_MISSING_DATA_VALID_DTM$, WfrIndex> = Datetime()
Case Action EQ 'ENABLE'
ReactRunRec<REACT_RUN_MISSING_DATA_VALID_DISABLED$, WfrIndex> = False$
ReactRunRec<REACT_RUN_MISSING_DATA_VALID_USER$, WfrIndex> = ''
ReactRunRec<REACT_RUN_MISSING_DATA_VALID_DTM$, WfrIndex> = ''
End Case
For TabIndex = 1 to TabCount
ThisTabCellColorArray = CellColorArray<TabIndex>
Convert @VM to @FM in ThisTabCellColorArray
Convert @SVM to @VM in ThisTabCellColorArray
ThisTabCellColorArray = SRP_Array('Rotate', ThisTabCellColorArray, @FM, @VM)
ThisWaferCellColorArray = ThisTabCellColorArray<WfrIndex>
Stage = Get_Property(@Window:'.OLE_TAB', "OLE.TabCaption[":TabIndex:"]")
Swap ' ' with '_' in Stage
Swap '*' with '.' in WfrID
RunStageWfrKey = RDSNo:'*':Stage:'*':WfrID
ParamOutOfSpec = Xlate('RUN_STAGE_WFR', RunStageWfrKey, RUN_STAGE_WFR_PARAM_OUT_OF_SPEC$, 'X')
DataOutOfSpec = False$
DataMissing = False$
For each Value in ParamOutOfSpec using @VM
If Value EQ 1 then DataOutOfSpec = True$
If Value EQ -1 then DataMissing = True$
Next Value
Begin Case
Case Action EQ 'DISABLE'
Begin Case
Case DataOutOfSpec EQ True$
Swap 'Red' with 'SlateBlue L=75' in ThisWaferCellColorArray
Case DataMissing EQ True$
Swap 'Yellow' with 'SlateBlue L=75' in ThisWaferCellColorArray
End Case
Case Action EQ 'ENABLE'
Begin Case
Case DataOutOfSpec EQ True$
Swap 'SlateBlue L=75' with 'Red' in ThisWaferCellColorArray
Case DataMissing EQ True$
Swap 'SlateBlue L=75' with 'Yellow' in ThisWaferCellColorArray
End Case
End Case
ThisTabCellColorArray<WfrIndex> = ThisWaferCellColorArray
ThisTabCellColorArray = SRP_Array('Rotate', ThisTabCellColorArray, @FM, @VM)
Convert @VM to @SVM in ThisTabCellColorArray
Convert @FM to @VM in ThisTabCellColorArray
CellColorArray<TabIndex> = ThisTabCellColorArray
Next TabIndex
Set_Property(@Window, '@COLOR_ARRAY', CellColorArray)
Database_Services('WriteDataRow', 'REACT_RUN', RDSNo, ReactRunRec, True$, False$, True$)
Disposition_Services('AutoDispositionRun', RDSNo)
GoSub ColorCells
GoSub ColorTabs
GoSub FillDispEditTable
GoSub EnableCloseRDSButton
end
end event
Event OLE_DISP_EDT.OnClick(Cell, Point, Button, Shift, Ctrl)
Col = Field(Cell, ';', 1, 1)
Row = Field(Cell, ';', 2, 1)
Begin Case
Case Col EQ COL$DISP_WFR_ID
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 Case
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
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.
NCRDimArray = Get_Property(@Window, '@NCRDIMARRAY')
NumRows = NCRDimArray<2>
For nPos = 1 to NumRows
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
If RowExists('RUN_STAGE_WFR', RunStageWfrKey) then
RunStageWfrRec = Database_Services('ReadDataRow', 'RUN_STAGE_WFR', RunStageWfrKey)
end else
// This may be an old run that has a CAN stage instead of a CAN_PRE stage
If StageID EQ 'CAN_PRE' then
RunStageWfrKey = RDSNo:'*CAN*':WfrID
If RowExists('RUN_STAGE_WFR', RunStageWfrKey) then
RunStageWfrRec = Database_Services('ReadDataRow', 'RUN_STAGE_WFR', RunStageWfrKey)
end
end
end
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
DisplayMetPopup:
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 = 130
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)
TabIndex = Get_Property(@Window:'.OLE_TAB', 'OLE.SelectedTab')
Stage = Get_Property(@Window:'.OLE_TAB', 'OLE.TabCaption[':TabIndex:']')
WfrIndex = Col - 3
InWfrIDs = Get_Property(@Window, '@WFRIDS')
WfrID = InWfrIDs<0, WfrIndex>
Convert '*' to '.' in WfrID
RunStageWfrKey = RDSNo:'*':Stage:'*':WfrID
RunStageWfrRec = Database_Services('ReadDataRow', 'RUN_STAGE_WFR', RunStageWfrKey)
ParamValues = RunStageWfrRec<RUN_STAGE_WFR_MET_PARAM_VALUES$>
OutOfSpec = RunStageWfrRec<RUN_STAGE_WFR_PARAM_OUT_OF_SPEC$>
RowParamValues = ParamValues<0, Row>
RowOutOfSpec = OutOfSpec<0, Row>
ColorArray = ''
Convert @SVM to @FM in RowParamValues
HoverData = 'Index | Value'
For each Value in RowParamValues setting Index
HoverData := @FM:Index:' | ':Value
If RowOutOfSpec<0, 0, Index> EQ True$ then
ColorArray<Index> = 'Red'
end else
ColorArray<Index> = 'None'
end
Next Value
NumLines = DCount(HoverData, @FM)
PopupHeight = (25 * (NumLines) )
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> = ( 25 * (ItemCount - 1) ) ; // Y Position of item
ItemList<ItemCount,SRP_POPUP.RECTANGLE,3> = PopupWidth - (2 * XPadding) ; // Width
ItemList<ItemCount,SRP_POPUP.RECTANGLE,4> = 25 ; // Height
ItemList<ItemCount,SRP_POPUP.CAPTION> = Item
ItemList<ItemCount,SRP_POPUP.COLORS> = ColorArray<ItemCount - 1>
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)
Set_Property('SYSTEM', 'CURSOR', 'A')
return
DisplayStageDisPopup:
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)
WfrStages = ReactRunRec<REACT_RUN_WFR_STAGE$>
Locate StageID in WfrStages using @VM setting StageIndex then
DisabledBy = ReactRunRec<REACT_RUN_MISSING_DATA_VALID_USER$, StageIndex>
DisabledDTM = ReactRunRec<REACT_RUN_MISSING_DATA_VALID_DTM$, StageIndex>
If (DisabledBy NE '') and (DisabledDTM NE '') then
HoverData = ''
HoverData := OConv(DisabledBy, '[XLATE_CONV,LSL_USERS*FIRST_LAST]') : @FM
HoverData := OConv(DisabledDTM, '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
end
Set_Property('SYSTEM', 'CURSOR', 'A')
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
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
EnableCloseRDSButton:
RDSNo = Get_Property(@Window:'.RDS_NO', 'TEXT')
ReactRunRec = Database_Services('ReadDataRow', 'REACT_RUN', RDSNo)
ScribeError = Sum(ReactRunRec<REACT_RUN_SCRIBE_ERROR$>)
DispComp = ReactRunRec<REACT_RUN_DISP_COMPLETE$>
DispCtrl = @Window:'.PUB_CLOSE_RDS'
If ( (DispComp NE True$) and ( Not(ScribeError) ) ) then
Set_Property(DispCtrl, 'ENABLED', True$)
end else
Set_Property(DispCtrl, 'ENABLED', False$)
end
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
EnableImportMetDataButton:
RDSNo = Get_Property(@Window:'.RDS_NO', 'TEXT')
UserAuthorized = Memberof(@User4, 'GAN_WIP_SUPERVISOR')
RDSClosed = Xlate('REACT_RUN', RDSNo, 'DISP_COMPLETE', 'X')
Enabled = ( (RDSClosed NE True$) and (UserAuthorized EQ True$) )
Set_Property(@Window:'.PUB_IMPORT_MET_DATA', 'ENABLED', Enabled)
return
ResetColorArrays:
PSNo = Get_Property('PROD_SPEC.PROD_SPEC_ID', 'TEXT')
PartNo = Get_Property(@Window, '@CURR_PART_NO')
GaNParamStages = Get_Property(@Window, '@GAN_PARAM_STAGES')
CellColorArray = ''
For each Stage in GaNParamStages using @VM setting TabIndex
GaNParamConfigKey = PSNo:'*':PartNo:'*':Stage
GaNParamConfigRec = Database_Services('ReadDataRow', 'GAN_PARAM_CONFIG', GaNParamConfigKey)
ParamNames = GaNParamConfigRec<GAN_PARAM_CONFIG.PARAM_NAME$>
For each ParamName in ParamNames using @VM setting RowPos
CellColorArray<TabIndex, RowPos, 1> = 'None'
CellColorArray<TabIndex, RowPos, 2> = 'None'
CellColorArray<TabIndex, RowPos, 3> = 'None'
CellColorArray<TabIndex, RowPos, 4> = 'None'
CellColorArray<TabIndex, RowPos, 5> = 'None'
Next ParamName
Next Stage
Set_Property(@Window, '@COLOR_ARRAY', CellColorArray)
return
SetupTabCtrl:
RDSNo = Get_Property(@Window:'.RDS_NO', 'TEXT')
PSNo = Xlate('REACT_RUN', RDSNo, 'PS_NO', 'X')
Set_Property(@Window, '@PS_NO', PSNo)
PartNos = Xlate('PROD_SPEC', PSNo, 'PROD_VER_EPI_PART_NO', 'X')
NumPartNos = DCount(PartNos, @VM)
CurrPartNo = Field(PartNos, @VM, NumPartNos)
Set_Property(@Window, '@CURR_PART_NO', CurrPartNo)
GaNParamStages = Xlate('APP_INFO', 'GAN_PARAM_STAGES', '', 'X')
TabCtrl = @Window:'.OLE_TAB'
NumTabs = DCount(GaNParamStages, @VM)
Set_Property(TabCtrl, "OLE.TabCount", NumTabs)
Convert @VM to ',' in GaNParamStages
Convert '_' to ' ' in GaNParamStages
Set_Property(TabCtrl, "OLE.CaptionList", GaNParamStages)
FontArray = 'Segoe UI':@SVM:9:@SVM:700
Set_Property(TabCtrl, "OLE.Font", FontArray)
Set_Property(TabCtrl, "OLE.SelectFont", FontArray)
// Qualify OLE events that we want to intercept
Qualifier = ''
Qualifier<1> = 1
Qualifier<4> = 0 ; * process synchronously
Send_Message(TabCtrl, 'QUALIFY_EVENT', 'OLE.SelChanged', Qualifier)
return
SetupDispStageCtrl:
DispStageCtrl = @Window:'.OLE_DISP_STAGE_EDT'
ScribeHeaderTitles = Get_Property(@Window, '@SCRIBE_HEADER_TITLES')
HeaderRowTitles = 'LSL':@VM:'Target':@VM:'USL':@VM:ScribeHeaderTitles
DispStageDimArray = 12:@FM:1
Set_Property(DispStageCtrl, "OLE.Dimension", DispStageDimArray)
Set_Property(DispStageCtrl, "OLE.TitleList", HeaderRowTitles)
HeaderFontArray = 'Segoe UI':@SVM:8:@SVM:700
Set_Property(DispStageCtrl, "OLE.HeaderFont[All; All]", HeaderFontArray)
HeaderColArray = 181:@FM:True$:@FM:False$:@FM:False$
Set_Property(DispStageCtrl, "OLE.HeaderColumn[1]", HeaderColArray)
Set_Property(DispStageCtrl, "OLE.HeaderText[1; 1]", "Metrology Limits")
// Disable resizing of columns as there is no need for this on this form
StageColSize = Get_Property(DispStageCtrl, "OLE.DataColumn[1]")
StageColSize<1> = 55
StageColSize<3> = False$
Set_Property(DispStageCtrl, "OLE.DataColumn[1-3]", StageColSize)
StageColSize<1> = 96
Set_Property(DispStageCtrl, "OLE.DataColumn[4-11]", StageColSize)
Set_Property(DispStageCtrl, "OLE.CellProtection[All; All]", 'Read Only')
// Qualify OLE events that we want to intercept
Qualifier = ''
Qualifier<1> = 1
Qualifier<4> = 0 ; * process synchronously (i.e. immediately)
Send_Message(DispStageCtrl, 'QUALIFY_EVENT', 'OLE.OnClick', Qualifier)
Send_Message(DispStageCtrl, 'QUALIFY_EVENT', 'OLE.OnHeaderClick', Qualifier)
Send_Message(DispStageCtrl, 'QUALIFY_EVENT', 'OLE.OnContextMenuClick', Qualifier)
return
ReadCurrParams:
RDSNo = Get_Property(@Window:'.RDS_NO', 'TEXT')
ReactRunRec = Database_Services('ReadDataRow', 'REACT_RUN', RDSNo)
ValidationDisFlags = ReactRunRec<REACT_RUN_MISSING_DATA_VALID_DISABLED$>
MetStageCtrl = @Window:'.OLE_METROLOGY_EDT'
MetStageList = Get_Property(MetStageCtrl, "OLE.ColumnData[1]")
Reactor = 'R':Get_Property(@Window, '@REACTOR')
RunNo = Get_Property(@Window:'.CMB_GAN_RUN_ID', 'TEXT')
Scribes = Get_Property(@Window, '@SCRIBES')
InWfrIDs = Get_Property(@Window, '@WFRIDS')
PSNo = Get_Property(@Window, '@PS_NO')
If PSNo NE '' then
GaNParamStages = Xlate('APP_INFO', 'GAN_PARAM_STAGES', '', 'X')
GaNParamKeys = Xlate('REACT_RUN', RDSNo, 'GAN_PARAM_KEYS', 'X')
ParameterList = ''
ParamNameList = ''
MetNameList = ''
CellColorArray = ''
ParamOutOfSpec = ''
GaNParamKeysPrime = SRP_Array('Rotate', GaNParamKeys, @VM, '*')
ConfigGaNParamStages = GaNParamKeysPrime<0, 2>
Set_Property(@Window, '@GAN_PARAM_STAGES', GaNParamStages)
Convert '*' to @VM in ConfigGaNParamStages
For each GaNParamKey in GaNParamKeys using @VM
MetType = Field(GaNParamKey, '*', 2)
Locate MetType in GaNParamStages using @VM setting TabPos then
StageID = MetType
StageDesc = GaN_Services('GetStageDesc', MetType)
ToolType = MetType
GaNParamRec = Database_Services('ReadDataRow', 'GAN_PARAMS', GaNParamKey)
PartNo = Field(GaNParamKey, '*', 1)
ParamNames = GaNParamRec<GAN_PARAMS.PARAM_NAME$>
MetNames = GaNParamRec<GAN_PARAMS.MET_NAME$>
Locate StageDesc in MetStageList using @VM setting StageRowPos then
Tool = Get_Property(@Window : '.OLE_METROLOGY_EDT', 'OLE.CellText[2; ':StageRowPos:']')
end
MetParameter = ''
ParamValues = ''
MetData = ''
For each WfrID in InWfrIDs using @VM setting WaferIndex
Convert '*' to '.' in WfrID
Begin Case
Case StageID 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:'*':StageID:'*':WfrID
end
Case StageID 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:'*':StageID:'*':WfrID
end
Case Otherwise$
RunStageWfrKey = RDSNo:'*':StageID:'*':WfrID
End Case
If RowExists('RUN_STAGE_WFR', RunStageWfrKey) then
RunStageWfrRec = Database_Services('ReadDataRow', 'RUN_STAGE_WFR', RunStageWfrKey)
TheseParamValues = RunStageWfrRec<RUN_STAGE_WFR_MET_PARAM_VALUES$>
TheseOutOfSpecValues = RunStageWfrRec<RUN_STAGE_WFR_PARAM_OUT_OF_SPEC$>
If Index(TheseParamValues, @SVM, 1) GT 0 then
For each FlagSet in TheseOutOfSpecValues using @VM setting ParamIndex
ValueSet = TheseParamValues<0, ParamIndex>
NumVals = DCount(ValueSet, @SVM)
If NumVals GT 1 then
ParamValues<WaferIndex, ParamIndex> = 'Multi'
OutOfSpec = ( Sum(TheseOutOfSpecValues<1, ParamIndex>) > 0 )
end else
ParamValues<WaferIndex, ParamIndex> = ValueSet
OutOfSpec = TheseOutOfSpecValues<1, ParamIndex>
end
ParamOutOfSpec<WaferIndex, ParamIndex> = OutOfSpec
Next FlagSet
end else
ParamValues<WaferIndex> = TheseParamValues
ParamOutOfSpec<WaferIndex> = TheseOutOfSpecValues
end
end else
ParamValues<WaferIndex> = ''
ParamOutOfSpec<WaferIndex> = ''
end
Next WfrID
ParamValues = SRP_Array('Rotate', ParamValues, @FM, @VM)
ParamOutOfSpec = SRP_Array('Rotate', ParamOutOfSpec, @FM, @VM)
Convert @VM to @SVM in ParamValues
Convert @VM to @SVM in ParamOutOfSpec
Convert @FM to @VM in ParamOutOfSpec
ParamOutOfSpec = SRP_Array('Rotate', ParamOutOfSpec, @VM, @SVM)
For each WfrID in InWfrIDs using @VM setting WaferIndex
ValidDisabled = ValidationDisFlags<0, WaferIndex>
WfrParamOutOfSpec = ParamOutOfSpec<0, WaferIndex>
If ValidDisabled EQ True$ then
Swap '-1' with 'SlateBlue L=75' in WfrParamOutOfSpec
Swap 1 with 'SlateBlue L=75' in WfrParamOutOfSpec
end else
Swap '-1' with 'Yellow' in WfrParamOutOfSpec
end
ParamOutOfSpec<0, WaferIndex> = WfrParamOutOfSpec
Next WfrID
ParamOutOfSpec = SRP_Array('Rotate', ParamOutOfSpec, @VM, @SVM)
Swap 1 with 'Red' in ParamOutOfSpec
Swap 0 with 'None' in ParamOutOfSpec
CellColorArray<TabPos> = ParamOutOfSpec
For each ParamName in ParamNames using @VM setting RowPos
MetName = MetNames<0, RowPos>
MetNameList<TabPos, RowPos> = ParamName
ParamNameList<TabPos, RowPos> = MetName
ParameterList<TabPos, RowPos, 1> = GaNParamRec<GAN_PARAMS.LSL$, RowPos>
ParameterList<TabPos, RowPos, 2> = GaNParamRec<GAN_PARAMS.TARGET$, RowPos>
ParameterList<TabPos, RowPos, 3> = GaNParamRec<GAN_PARAMS.USL$, RowPos>
If ParamValues NE '' then ParameterList<TabPos, RowPos, 4> = ParamValues<RowPos>
Next ParamName
end
Next GaNParamKey
Set_Property(@Window, '@NAME_LIST', ParamNameList)
Set_Property(@Window, '@VALUE_LIST', ParameterList)
Set_Property(@Window, '@ORIG_VALUE_LIST', ParameterList)
Set_Property(@Window, '@ORIG_MET_LIST', MetNameList)
Set_Property(@Window, '@COLOR_ARRAY', CellColorArray)
end
return
FillDispStageCtrl:
DispStageCtrl = @Window:'.OLE_DISP_STAGE_EDT'
TabCtrl = @Window:'.OLE_TAB'
TabIndex = Get_Property(TabCtrl, 'OLE.SelectedTab')
HeaderTitles = Get_Property(@Window, '@NAME_LIST')<TabIndex>
ParameterList = Get_Property(@Window, '@VALUE_LIST')<TabIndex>
NumCols = 11
NumRows = DCount(ParameterList, @VM)
DispStageDimArray = NumCols:@FM:NumRows
Set_Property(DispStageCtrl, "OLE.Dimension", DispStageDimArray)
Convert @VM to @FM in ParameterList
Convert @SVM to @VM in ParameterList
Set_Property(@Window:'.OLE_DISP_STAGE_EDT', 'OLE.LIST', ParameterList)
Convert @VM to @FM in HeaderTitles
Convert @SVM to @VM in HeaderTitles
For each HeaderTitle in HeaderTitles using @FM setting RowIndex
Set_Property(DispStageCtrl, "OLE.HeaderText[1; ":RowIndex + 1:"]", HeaderTitle)
Next HeaderTitle
Set_Property(DispStageCtrl, "OLE.HeaderAlignment[1; 2-":NumRows + 1:"]", 'C':@FM:'L':@FM:'L')
Set_Property(DispStageCtrl, "OLE.CellAlignment[All; All]", 'C':@FM:'R':@FM:'L')
Set_Property(DispStageCtrl, "OLE.HeaderAlignment[All; 1]", 'C':@FM:'C':@FM:'L')
// Color headers
Set_Property(DispStageCtrl, "OLE.HeaderColors[All; 1]", @FM:"{200, 200, 200}")
// Color limit columns
Set_Property(DispStageCtrl, "OLE.CellColors[1-3; All]", @FM:"{240, 240, 240}")
// Bold limit text
BoldFontArray = 'Segoe UI':@SVM:8:@SVM:700
Set_Property(DispStageCtrl, "OLE.CellFont[1-3; All]", BoldFontArray)
GoSub ColorCells
return
ColorCells:
TabIndex = Get_Property(@Window:'.OLE_TAB', 'OLE.SelectedTab')
CellColorArray = Get_Property(@Window, '@COLOR_ARRAY')<TabIndex>
DispStageCtrl = @Window:'.OLE_DISP_STAGE_EDT'
DimArray = Get_Property(DispStageCtrl, "OLE.Dimension")
NumCols = DimArray<1>
NumRows = DimArray<2>
For Row = 1 to NumRows
For Col = 1 to NumCols
CellColor = CellColorArray<0, Row, Col>
If CellColor EQ '' then CellColor = 'None'
Set_Property(DispStageCtrl, 'OLE.CellColors[':Col+3:';':Row:']', @FM:CellColor)
Next Col
Next Row
return
ColorTabs:
TabCtrl = @Window:'.OLE_TAB'
RDSNo = Get_Property(@Window:'.RDS_NO', 'TEXT')
ReactRunRec = Database_Services('ReadDataRow', 'REACT_RUN', RDSNo)
GaNParamStages = Get_Property(@Window, '@GAN_PARAM_STAGES')
CellColorArray = Get_Property(@Window, '@COLOR_ARRAY')
WfrStages = ReactRunRec<REACT_RUN_WFR_STAGE$>
For each Stage in GaNParamStages using @VM setting TabIndex
ThisCellColorArray = CellColorArray<TabIndex>
GoSub ColorTab
Next Stage
return
EnableTabs:
SelTabIndex = Get_Property(@Window:".OLE_TAB", "OLE.SelectedTab")
GaNParamStages = Get_Property(@Window, '@GAN_PARAM_STAGES')
NameArray = Get_Property(@Window, '@NAME_LIST')
For each Stage in GaNParamStages using @VM setting TabIndex
ThisNameArray = NameArray<TabIndex>
GoSub EnableTab
Next Stage
SelTabVisible = Get_Property(@Window:'.OLE_TAB', 'OLE.TabVisible[':SelTabIndex:']')
If SelTabVisible EQ False$ then
For TabIndex = 1 to 12
TabVisible = Get_Property(@Window:'.OLE_TAB', 'OLE.TabVisible[':TabIndex:']')
Until TabVisible EQ True$
Next TabIndex
If TabVisible EQ True$ then Set_Property(@Window:".OLE_TAB", "OLE.SelectedTab", TabIndex)
end
return
EnableTab:
If ThisNameArray EQ '' then
Set_Property(@Window:'.OLE_TAB', 'OLE.TabVisible[':TabIndex:']', False$)
end else
Set_Property(@Window:'.OLE_TAB', 'OLE.TabVisible[':TabIndex:']', True$)
end
return
ColorTab:
GaNMetStages = Database_Services('ReadDataRow', 'APP_INFO', 'GAN_MET_STAGES')
Locate Stage in GaNMetStages using @FM setting sPos then
PostSplit = (sPos GT 6)
end else
PostSplit = False$
end
WfrChar = (Sum(ReactRunRec<REACT_RUN_CHAR_WFR_FLAG$>) GT 0)
NumRows = DCount(ThisCellColorArray, @VM)
NumCols = DCount(ThisCellColorArray, @SVM)
MetFailed = False$
MetMissing = False$
ValidDisabled = False$
For Row = 1 to NumRows
For Col = 1 to NumCols
CellColor = ThisCellColorArray<0, Row, Col>
If CellColor EQ 'Red' then
MetFailed = True$
end
If CellColor EQ 'Yellow' then
MetMissing = True$
end
If CellColor EQ 'SlateBlue L=75' then
ValidDisabled = True$
end
Until MetFailed EQ True$
Next Col
Until MetFailed EQ True$
Next Row
Begin Case
Case MetFailed EQ True$
Colors = ""
Colors<1, 2> = "Vertical(Gradient(Red L=80, Red L=90), Border(Red))"
Colors<2, 2> = "Vertical(Gradient(Red L=90, Red L=95), Border(Red))"
Colors<3, 2> = "Vertical(Gradient(Red L=85, Red L=95), Border(Red))"
Colors<4, 1> = "Gray"
Colors<4, 2> = "Vertical(Gradient(Gray L=80, Gray L=90), Border(Gray))"
Colors<5> = "Vertical(Gradient(Red L=95, Red L=80), Border(Red))"
Set_Property(TabCtrl, "OLE.TabColors[":TabIndex:"]", Colors)
Case MetMissing EQ True$
Colors = ""
Colors<1, 2> = "Vertical(Gradient(Yellow L=80, Yellow L=90), Border(Yellow))"
Colors<2, 2> = "Vertical(Gradient(Yellow L=90, Yellow L=95), Border(Yellow))"
Colors<3, 2> = "Vertical(Gradient(Yellow L=85, Yellow L=95), Border(Yellow))"
Colors<4, 1> = "Gray"
Colors<4, 2> = "Vertical(Gradient(Gray L=80, Gray L=90), Border(Gray))"
Colors<5> = "Vertical(Gradient(Yellow L=95, Yellow L=80), Border(Yellow))"
Set_Property(TabCtrl, "OLE.TabColors[":TabIndex:"]", Colors)
Case ValidDisabled EQ True$
Colors = ""
Colors<1, 2> = "Vertical(Gradient(Blue L=80, Blue L=90), Border(Blue))"
Colors<2, 2> = "Vertical(Gradient(Blue L=90, Blue L=95), Border(Blue))"
Colors<3, 2> = "Vertical(Gradient(Blue L=85, Blue L=95), Border(Blue))"
Colors<4, 1> = "Gray"
Colors<4, 2> = "Vertical(Gradient(Gray L=80, Gray L=90), Border(Gray))"
Colors<5> = "Vertical(Gradient(Blue L=95, Blue L=80), Border(Blue))"
Set_Property(TabCtrl, "OLE.TabColors[":TabIndex:"]", Colors)
Case ( ( (PostSplit EQ True$) and (WfrChar EQ False$) ) or (NumRows EQ 0) )
Null
Case Otherwise$
Colors = ""
Colors<1, 2> = "Vertical(Gradient(Green L=80, Green L=90), Border(Green))"
Colors<2, 2> = "Vertical(Gradient(Green L=90, Green L=95), Border(Green))"
Colors<3, 2> = "Vertical(Gradient(Green L=85, Green L=95), Border(Green))"
Colors<4, 1> = "Gray"
Colors<4, 2> = "Vertical(Gradient(Gray L=80, Gray L=90), Border(Gray))"
Colors<5> = "Vertical(Gradient(Green L=95, Green L=80), Border(Green))"
Set_Property(TabCtrl, "OLE.TabColors[":TabIndex:"]", Colors)
End Case
return
SetupDispEDT:
DispCtrl = @Window:'.OLE_DISP_EDT'
// Disable resizing of the header row and header column
// Resize header column to fit contents
HeaderRowArray = Get_Property(DispCtrl, "OLE.HeaderRow[1]")
HeaderColArray = Get_Property(DispCtrl, "OLE.HeaderColumn[1]")
HeaderRowArray<3> = False$
HeaderColArray<1> = 80
HeaderColArray<3> = False$
Set_Property(DispCtrl, "OLE.HeaderColumn[1]", HeaderColArray)
Set_Property(DispCtrl, "OLE.HeaderRow[1]", HeaderRowArray)
// Disable resizing of columns as there is no need for this on this form
StageColSize = Get_Property(DispCtrl, "OLE.DataColumn[1]")
StageColSize<3> = False$
Set_Property(DispCtrl, "OLE.DataColumn[All]", StageColSize)
WfrColSize = Get_Property(DispCtrl, "OLE.DataColumn[1]")
// Set column widths
WfrColSize<1> = 30
Set_Property(DispCtrl, "OLE.DataColumn[":COL$DISP_SLOT:"]", WfrColSize)
WfrColSize<1> = 79
Set_Property(DispCtrl, "OLE.DataColumn[":COL$DISP_WFR_ID:"-":COL$DISP_SCRIBE:"]", WfrColSize)
WfrColSize<1> = 50
Set_Property(DispCtrl, "OLE.DataColumn[":COL$DISP_GRADE:"]", WfrColSize)
WfrColSize<1> = 244
Set_Property(DispCtrl, "OLE.DataColumn[":COL$DISP_REASON:"]", WfrColSize)
WfrColSize<1> = 69
Set_Property(DispCtrl, "OLE.DataColumn[":COL$DISP_RDS_NCR:"-":COL$DISP_WMO_NCR:"]", WfrColSize)
WfrColSize<1> = 81
Set_Property(DispCtrl, "OLE.DataColumn[":COL$DISP_SHIP_ID:"]", WfrColSize)
WfrColSize<1> = 70
Set_Property(DispCtrl, "OLE.DataColumn[":COL$DISP_RETAIN_BOX:"-":COL$DISP_RETAIN_SLOT:"]", WfrColSize)
WfrColSize<4> = True$ ; // Set this column autosize property to true
Set_Property(DispCtrl, "OLE.DataColumn[":COL$DISP_ROOT_CAUSE:"]", WfrColSize)
// Disable resizing of rows as there is no need for this on this form
RowSizeProps = Get_Property(DispCtrl, "OLE.DataRow[1]")
RowSizeProps<3> = False$
Set_Property(DispCtrl, "OLE.DataRow[All]", RowSizeProps)
// Disable scrollbars
Set_Property(DispCtrl, "OLE.ScrollBarsVisible", 'N':@FM:'N')
// Color headers
Set_Property(DispCtrl, "OLE.HeaderColors[All; 1]", @FM:"{200, 200, 200}")
// Set edit mode of cells if and when we enable them
EditArray = 'E'
EditArray<2> = 'O'
Set_Property(DispCtrl, "OLE.CellEditMode[All; All]", EditArray)
// Disable editing of all cells
Set_Property(DispCtrl, "OLE.CellProtection[All; All]", 'Full')
// Do not allow scrolling past the bottom right cell.
// This prevents scrolling when tabbing out of the bottom right cell.
Set_Property(DispCtrl, "OLE.FreezePos", COL$DISP_RETAIN_SLOT:@FM:8)
return
Abort:
Utility('DESTROY', @Window)
return
VerifyScribes:
RDSNo = Get_Property(@Window:'.RDS_NO', 'TEXT')
If RDSNo NE '' then
DispCtrl = @Window:'.OLE_DISP_EDT'
ReactRunRec = Database_Services('ReadDataRow', 'REACT_RUN', RDSNo)
InWfrIDs = ReactRunRec<REACT_RUN_IN_WFR_ID$>
ScribeErrors = ReactRunRec<REACT_RUN_SCRIBE_ERROR$>
DispReadyFlags = ReactRunRec<REACT_RUN_WFRS_DISP_READY$>
NumWfrs = DCount(InWfrIDs, @VM)
For WfrIndex = 1 to NumWfrs
WfrKey = InWfrIDs<0, WfrIndex>
ScribeError = ScribeErrors<0, WfrIndex>
DispReady = DispReadyFlags<0, WfrIndex>
Grade = Xlate('WO_WFR', WfrKey, 'GRADE', 'X')
Begin Case
Case ScribeError EQ True$
ColorArray = 'None':@FM:ORANGE$
Case Grade _EQC 'Scrap'
ColorArray = 'None':@FM:RED$
Case DispReady EQ True$
// Color scribe cell green to indicate that the wafer is ready to be placed in an outbound cassette.
// Color scribe cell within disposition edit table green
ColorArray = 'None':@FM:BGREEN$
Case Otherwise$
ColorArray = 'None':@FM:'None'
End Case
Set_Property(DispCtrl, 'OLE.CellColors[':COL$DISP_SCRIBE:';':WfrIndex:']', ColorArray)
Next WfrIndex
end
return