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