#
# $Log: not supported by cvs2svn $
# Revision 1.32  2007/12/13 15:54:01  soliday
# Added code to automatically reset the MPEOB if it needs to be.
#
# Revision 1.31  2007/12/07 17:09:36  soliday
# Added code to better handle MPEOB faults.
#
# Revision 1.30  2007/02/20 16:04:49  soliday
# Updated so that it now uses a 14 minute conditiong time. Which gets converted
# into cycles which ends up being 15-18 minutes of actual conditioning.
#
# Revision 1.29  2006/05/23 14:24:58  soliday
# Added acis checks.
#
# Revision 1.28  2006/04/20 16:06:50  soliday
# Updated APsMpPARLETStartUp so that it now uses the APSMpPARLETCondition routine.
#
# Revision 1.27  2005/05/27 18:44:23  soliday
# Removed VM:LP:VAL2 valve
#
# Revision 1.26  2005/04/07 16:20:03  soliday
# Updated to identify limited save files and not allow the operator to use them.
#
# Revision 1.25  2003/10/28 16:42:46  borland
# Fixed incorrect variable name ("electron" instead of "particle") in
# APSStrictParseArguments call in APSMpPARLETStartup.
#
# Revision 1.24  2003/10/28 15:50:02  soliday
# These PAR procedures now alert the user if no SCR file has been chosen.
#
# Revision 1.23  2003/10/27 20:13:54  borland
# Added aperture-clearing for PAR bypass.
# Put catch statements around APSMpJoin commands.
# Added status messages inside loops for conditioning and kicker warmup.
#
# Revision 1.22  2002/09/30 16:32:14  soliday
# The PAR RF system is now brought up to full power.
#
# Revision 1.21  2001/02/22 20:55:18  borland
# Switched to LPL system from PLET.
#
# Revision 1.20  2000/06/26 17:33:55  borland
# Now uses APSAddSCRDialog to allow selection of the SCR file.
# Uses the SCR file, if any, for configuration of the standardization.
# Also, does a more thorough job of setting the number of cycles for
# a given desired minutes of standardization.
#
# Revision 1.19  2000/05/02 14:55:27  borland
# Added more detailed steps descriptions.
#
# Revision 1.18  2000/04/26 16:40:22  soliday
# Added APSMpStep proc options.
#
# Revision 1.17  1999/11/08 20:07:00  borland
# Added controls for excluding LTP:B1 from standardization for LTP and
# PAR/LET startup.
#
# Revision 1.16  1999/07/28 00:43:16  borland
# Replaced 325MeVReference with 325MeVPreferredRFGun.
#
# Revision 1.15  1999/07/27 15:21:03  borland
# Default energy is now 325 MeV and default snapshot is PLET-325MeVPreferredRFGun.gz,
# per G. Banks request.
#
# Revision 1.14  1998/10/01 20:35:08  borland
# Should work now for positrons/electrons.
#
# Revision 1.13  1998/07/28 19:33:40  borland
# Removed option for PAR rf startup until it is brought up to date.
#
# Revision 1.12  1998/01/09 19:06:32  borland
# Changed name of PLET refernce file from PLET-Reference to PLET-400MeVReference
#
# Revision 1.11  1997/05/05 17:21:17  borland
# Improved help text for several procedures.
#
# Revision 1.10  1997/04/18 00:37:55  borland
# Default energy changed to 400MeV.  Turn on/off of rf and pulsed magnets fixed.
# Ramps rf setpoints up to avoid high reflected power.  Fixed turn on of PAR
# DC supplies.  Added combined PAR/LET stop conditioning.
#
# Revision 1.9  1996/11/23 01:14:22  borland
# Fixed MPEOB check.
#
# Revision 1.8  1996/11/22 20:18:05  borland
# Added check of MPEOB buttons prior to attempting DCPS turn on.
#
# Revision 1.7  1996/10/09 22:46:44  borland
# Reduced default conditioning times to 5 minutes.
#
# Revision 1.6  1996/10/08 21:44:11  borland
# Reduced default standardization time to 10 minutes.
#
# Revision 1.5  1996/09/20 17:14:31  borland
# Use catch statements around APSMpJoin to provide some error reporting
# from PAR, LTP, and PTB startup subprocedures.
#
# Revision 1.4  1996/08/07 21:27:20  borland
# Added -mode Automatic options to PAR, LTP, and PTB.  Made information dialog
# boxes for manual steps more obviously manual.
#
# Revision 1.3  1996/07/27 15:48:45  borland
# Added control of DCPS, PulsedPS, and rfSystem turn on to PARLET startup.
#
# Revision 1.2  1996/07/27 15:29:02  borland
# Now has default restoreFile of PLET-400MeVReference.gz
#
# Revision 1.1  1996/07/26 22:14:14  borland
# New versions using parallel procedure execution and catching of errors.
# Also much better organized and tested than previous versions.
#
#
set controlFilesDir /home/helios/oagData/controlFiles

proc APSMpPARLETStartUpInfo {} {
    return "This procedure starts up the PAR and LET in one sequence.  Once you start the procedure, you will be given the opportunity to specify the beam energy, the SCR file to use, and conditioning time for DC magnets. You can also choose not to start up certain subsystems."
}

proc APSMpPARLETStartUp {args} {
    global status controlFilesDir PLETSnapshotDir

    set energy [APSPARLETDefaultEnergy]
    set restoreFile ""
    set conditioningTime 14
    set DCPS 1
    set PulsedPS 1
    set rfSystems 1
    set particle electron
    set standardizeLTPB1 1

    set PARdipole 1
    set PARquads 1
    set PARsextupoles 1
    set PARcorrectors 1
    set LTPdipole 1
    set LTPquads 1
    set LTPcorrectors 1
    set PTBdipole 1
    set PTBquads 1
    set PTBcorrectors 1

    APSStrictParseArguments {energy conditioningTime restoreFile DCPS PulsedPS rfSystems particle standardizeLTPB1 PARdipole PARquads PARsextupoles PARcorrectors LTPdipole LTPquads LTPcorrectors PTBdipole PTBquads PTBcorrectors}
    global execMode

    if {$execMode != "Automatic"} {
        if {[catch {exec cavget -list=ACIS:LAOL_INH_GUN,ACIS:LBL_GUN_INH,ACIS:LA_BP_MODE,ACIS:LB_BP_MD -num -pend=20} acisState]} {
            APSMpReturn error "APSMpPARLETStartUp: $acisState"
        }
        if {([lindex $acisState 0] == 1) || ([lindex $acisState 1] == 1)} {
            if {[APSPEMTKDialog .warningDialog \
                   -text "Linac/PAR is in an acis inhibit state."] == 1} {
                APSMpReturn error "APSMpPARLETStartUp: Linac/PAR is in an acis inhibit state."
            }
        } elseif {([lindex $acisState 2] == 0) || ([lindex $acisState 3] == 0)} {
            if {[APSPEMTKDialog .warningDialog \
                   -text "Linac/PAR is in an acis trip state."] == 1} {
                APSMpReturn error "APSMpPARLETStartUp: Linac/PAR is in an acis trip state."
            }
        }
    }

    if {$standardizeLTPB1 == 0} {
        set LTPdipole 0
    }
    if {$DCPS == 0} {
        set PARdipole 0
        set PARquads 0
        set PARsextupoles 0
        set PARcorrectors 0
        set LTPdipole 0
        set LTPquads 0
        set LTPcorrectors 0
        set PTBdipole 0
        set PTBquads 0
        set PTBcorrectors 0
    }

    set ShortFilename $restoreFile

    APSMpStep init -promptDialog APSMpPARLETStartUpInitDialog \
      -vars {energy particle ShortFilename conditioningTime DCPS PulsedPS rfSystems standardizeLTPB1 PARdipole PARquads PARsextupoles PARcorrectors LTPdipole LTPquads LTPcorrectors PTBdipole PTBquads PTBcorrectors}
    set restoreFile $ShortFilename
    global APSMpPARLETStartUp
    set restoreFileFN $APSMpPARLETStartUp(Filename)

    if {($PARdipole) || ($PARquads) || ($PARsextupoles) || ($PARcorrectors) || ($LTPdipole) || ($LTPquads) || ($LTPcorrectors) || ($PTBdipole) || ($PTBquads) || ($PTBcorrectors)} {
        set DCPS 1
    }

    set paramString ""
    foreach param {energy conditioningTime DCPS PulsedPS rfSystems restoreFile particle standardizeLTPB1 PARdipole PARquads PARsextupoles PARcorrectors LTPdipole LTPquads LTPcorrectors PTBdipole PTBquads PTBcorrectors} {
        append paramString "$param=\"[set $param]\" "
    }
    catch {APSLogScriptAction -procedure APSMpPARLETStartUp -action initialize \
               -state ok -parameters $paramString}

    if {[string length $restoreFile] && ![file exists $PLETSnapshotDir/$restoreFile]} {
        APSMpReturn error "File [file tail $restoreFile] not found."
    }
    if {![llength $restoreFile]} {
        APSMpReturn error "No SCR file selected."
    }
    if {[catch {exec sdds2stream $PLETSnapshotDir/$restoreFile -parameter=SnapshotDescription -page=1 -noquotes} results]} {
        APSMpReturn error "APSMpPARLETStartUp: Invalid SCR file"
    }    
    if {[string first "Limited save:" $results] != -1} {
        APSMpReturn error "APSMpPARLETStartUp: LIMITED SAVE SCR files cannot be used for this procedure."
    }


    if $DCPS {
        #Check MPEOB
        APSMpStep "Check that the MPEOBs are pulled out"
        while {1} {
            if {[catch {APSPLETMPEOBsAreOut} mpeob]} {
                if {[APSPEMTKDialog .warningDialog -text "APSMpPARLETStartUp: Error checking MPEOB: $mpeob"] == 1} {
                    APSMpReturn error "APSMpPARLETStartUp: Error checking MPEOB: $mpeob"
                }
                continue
            }
            if {!$mpeob} {
                if {[APSPEMTKDialog .warningDialog -text "APSMpPARLETStartUp: Both MPEOBs must be pulled out to start DCPS."] == 1} {
                    APSMpReturn error "APSMpPARLETStartUp: Both MPEOBs must be pulled out to start DCPS."
                }
                continue
            }
            break
        }
    }

    set parallelMode Automatic
    if $DCPS {
        APSMpStep "Turn on and condition selected DC PS" -proc "APSMpPARLETCondition"
        set dcpsID \
          [APSMpParallel -mode $parallelMode \
             -procedure \
             "APSMpPARLETCondition -conditioningTime $conditioningTime -SCRFile $restoreFileFN -PARdipole $PARdipole -PARquads $PARquads -PARsextupoles $PARsextupoles -PARcorrectors $PARcorrectors -LTPdipole $LTPdipole -LTPquads $LTPquads -LTPcorrectors $LTPcorrectors -PTBdipole $PTBdipole -PTBquads $PTBquads -PTBcorrectors $PTBcorrectors"]
    }
    APSMpStep "Startup LTP" -proc "APSMpLTPStartUp"
    set ltpID \
      [APSMpParallel -mode $parallelMode \
         -procedure \
         "APSMpLTPStartUp -energy $energy -particle $particle -restoreFile $restoreFile -conditioningTime $conditioningTime -DCPS 0 -standardizeB1 0 -restoreDCPS 0"]

    APSMpStep "Startup PAR" -proc "APSMpPARStartUp"
    set parID \
      [APSMpParallel -mode $parallelMode \
         -procedure \
         "APSMpPARStartUp -energy $energy -restoreFile $restoreFile -conditioningTime $conditioningTime  -DCPS 0 -PulsedPS $PulsedPS -rfSystems $rfSystems -restoreDCPS 0"]

    APSMpStep "Startup PTB" -proc "APSMpPTBStartUp"
    set ptbID \
      [APSMpParallel -mode $parallelMode \
         -procedure \
         "APSMpPTBStartUp -energy $energy -restoreFile $restoreFile -conditioningTime $conditioningTime -DCPS 0 -restoreDCPS 0"]

    APSMpStep "Wait For Startup of PAR/LTP/PTB"
    if [catch {APSMpJoin $parID} parReturn] {
        APSMpReturn error "Error from PAR startup: $parReturn"
    }
    if [catch {APSMpJoin $ltpID} ltpReturn] {
        APSMpReturn error "Error from LTP startup: $ltpReturn"
    }
    if [catch {APSMpJoin $ptbID} ptbReturn] {
        APSMpReturn error "Error from PTB startup: $ptbReturn"
    }
    if $DCPS {
        if [catch {APSMpJoin $dcpsID} dcpsReturn] {
            APSMpReturn error "Error from APSMpPARLETCondition: $dcpsReturn"
        }
    }


    APSMpStep "Operator Action: Send Linac Beam"
    APSInfoWindow .sendLinacBeam -name sendLinacBeam \
      -infoMessage "Operator action: Send LINAC beam." \
      -modal 1

    APSMpStep "Operator Action: Turn On LTP Controllaw"
    APSInfoWindow .turnonLTPcontrollaw -name TurnOnLTPcontrollaw \
      -infoMessage "Operator action: Turn on LTP controllaw." -modal 1

    APSMpStep "Operator Action: Open Triple Stop"
    APSInfoWindow .openTripleStop -name openTripleStop \
      -infoMessage "Operator action: Open PTB triple stop." -modal 1

    APSMpReturn ok
}	

proc APSMpPARLETStartUpInitDialog {frame} {
    global APSMpPARLETStartUp

    pack [frame $frame.frame1]
    APSLabeledEntry .le1 -parent $frame.frame1 -label "Energy (MeV): " \
      -textVariable APSMpPARLETStartUp(energy) \
      -contextHelp "Enter the energy of the beam you will be using in MeV."
    APSRadioButtonFrame .rb1 -parent $frame.frame1 -label "Particle:               " \
      -variable APSMpPARLETStartUp(particle) -buttonList "Positron Electron" \
      -valueList "positron electron" -orientation horizontal \
      -contextHelp "Select the type of particle you are running from the LINAC."

    APSLabeledEntry .le2 -parent $frame.frame1 -label "Minutes for conditioning: " \
      -textVariable APSMpPARLETStartUp(conditioningTime) \
      -contextHelp "Enter the number of minutes you want to allow for conditioning.  The actual conditioning time may be longer, since each magnet must be put through at least one ramp cycle."

    pack [frame $frame.frame2]

    APSCheckButtonFrame .cb1 \
      -parent $frame.frame2 \
      -label "Systems: " \
      -packOption "-side left" \
      -buttonList {rf "Pulsed PS"} \
      -variableList {APSMpPARLETStartUp(rfSystems) APSMpPARLETStartUp(PulsedPS)} \
      -orientation vertical -allNone 1 -contextHelp \
      "Use to select or deselect systems to be included in startup."

    APSCheckButtonFrame .cb2 \
      -parent $frame.frame2 \
      -label "PAR PS" \
      -packOption "-side left" \
      -allNone 1 \
      -buttonList {"Dipole" "Quads" "Sextupoles" "Correctors"} \
      -variableList {APSMpPARLETStartUp(PARdipole) APSMpPARLETStartUp(PARquads) APSMpPARLETStartUp(PARsextupoles) APSMpPARLETStartUp(PARcorrectors)}

    APSCheckButtonFrame .cb3 \
      -parent $frame.frame2 \
      -label "LTP PS" \
      -packOption "-side left" \
      -allNone 1 \
      -buttonList {"Dipole" "Quads" "Correctors"} \
      -variableList {APSMpPARLETStartUp(LTPdipole) APSMpPARLETStartUp(LTPquads) APSMpPARLETStartUp(LTPcorrectors)}
    
    APSCheckButtonFrame .c4 \
      -parent $frame.frame2 \
      -label "PTB PS" \
      -packOption "-side left" \
      -allNone 1 \
      -buttonList {"Dipole" "Quads" "Correctors"} \
      -variableList {APSMpPARLETStartUp(PTBdipole) APSMpPARLETStartUp(PTBquads) APSMpPARLETStartUp(PTBcorrectors)}

#    APSRadioButtonFrame .rb2 -parent $frame -label "Standardize LTP:B1: " -variable APSMpPARLETStartUp(standardizeLTPB1) -buttonList {Yes No} -valueList {1 0} -orientation horizontal -contextHelp "Select whether to include LTP:B1 in the standardiation or not."

    APSAddSCRDialog .scr -parent $frame -system LPL -arrayName APSMpPARLETStartUp \
      -defaultFile $APSMpPARLETStartUp(ShortFilename)
}


proc APSMpPARLETRemoveFlags {args} {
    set retries 5
    set beamline LTP
    APSStrictParseArguments {retries beamline}

    # remove screens
    set badState OPEN
    set outVal OUT
    switch $beamline {
        PAR {
            set flags P1:FL1,P1:FL2,P1:FL3,P1:FL4,P2:FL1,P2:FL2
        }
        LTP {
            lappend flags LTP:FL1,LTP:FL2,LTP:FL3
            set outVal out
        }
        PTB {
            lappend flags PTB:FL1,PTB:FL2,PTB:FL3
        }
        PB {
            lappend flags PB:FL:C1,PB:FL:C3,PB:FL:C4
            set outVal Out
        }
    }
    
    if {$beamline == "PB"} {
        if {[catch {exec cavput -list=PB:FL:C1,PB:FL:C3,PB:FL:C4 \
                        -list=:Act -list=1,2 -list=InC=$outVal} result]} {
            APSMpReturn error "Error sending command to remove flags: $result"
        }
    } else {
        for {set rep 0} {$rep<$retries} {incr rep} {
            if [catch {exec cavget -list=$flags -list=:act_out_bi -label} result] {
                APSMpReturn error "Error reading flag status: $result"
            }
            set inList [APSSearchAssociateListForValue -value $badState -list $result]
            if [llength $inList] {
                # for some reason this works better if I just try to remove all the flags
                if [catch {exec cavput -list=$flags -list=:act_cont_bo=$outVal} result] {
                    APSMpReturn error "Error sending command to remove flags: $result"
                }
                after 2000
            } else {
                break
            }
        }
        if {$rep==$retries} {
            APSMpReturn error "Unable to remove $beamline flags."
        }
    }
    APSMpReturn ok
}

proc APSMpPARLETClearAperture {args} {
    set retries 5
    set beamline LTP
    APSStrictParseArguments {retries beamline}
    
    if [catch {APSMpPARLETRemoveFlags -beamline $beamline -retries $retries} result] {
        APSMpReturn error "Unable to remove $beamline flags"
    }
    if {[string compare $beamline PAR] && \
          [catch {APSMpLTPPTBOpenValves -beamline $beamline -retries $retries} result]} {
        APSMpReturn error "Unable to open $beamline valves"
    }
    APSMpReturn ok
}

proc APSMpLTPPTBOpenValves {args} {
    set retries 5
    set beamline LTP
    APSStrictParseArguments {retries beamline}

    # open valves
    set valves 1,2
    if [string compare $beamline LTP]==0 {
        set line LP
        set valves 1
    } elseif [string compare $beamline PTB]==0 {
        set line PB
    } elseif [string compare $beamline PB]==0 {
        set line PBY
    } else {
        APSMpReturn error "Unknown beamline for valve opening: $beamline"
    }

    for {set rep 0} {$rep<$retries} {incr rep} {
        if [catch {exec cavget -list=VM:${line}:VAL -list=$valves \
                     -list=:fullOpenBI -label "-delim= "} result] {
            APSMpReturn error "Error reading valve status: $result"
        }
        set inList [APSSearchAssociateListForValue -notvalue open -list $result]
        if [llength $inList] {
            regsub -all {:fullOpenBI} $inList {} inList
            if [catch {exec cavput -list=[join $inList ,] \
                         -list=:openCmdBO=0} result] {
                APSMpReturn error "Error sending command to open valves: $result"
            }
            after 500
            if [catch {exec cavput -list=[join $inList ,] \
                         -list=:openCmdBO=1} result] {
                APSMpReturn error "Error sending command to open valves: $result"
            }
            after 2000
        } else {
            break
        }
    }

    if {$rep==$retries} {
        APSMpReturn error "Unable to open $beamline valves."
    }
    APSMpReturn ok
}

proc APSPLETMPEOBsAreOut {} {
    if [catch {APScavget -list=P: -list=Inside,Outside -list=MPEOBBI "-delim=" -numerical} result] {
        return -code error "APSPLETMPEOBsAreOut: $result"
    }
    if [string compare $result 11]==0 {
        return 1
    }
    if {[catch {APScavput -list=P:MPEOBresetBO=1} result]} {
	return -code error "APSPLETMPEOBsAreOut: $result"
    }
    set tries 1
    while {$tries < 30} {
	if [catch {APScavget -list=P: -list=Inside,Outside -list=MPEOBBI "-delim=" -numerical} result] {
	    return -code error "APSPLETMPEOBsAreOut: $result"
	}
	if [string compare $result 11]==0 {
	    if {[catch {APScavput -list=L5:AM1:PS2:resetBO=1} result]} {
		return -code error "APSPLETMPEOBsAreOut: $result"
	    }
	    APSWaitWithUpdate -waitSeconds 1
	    return 1
	}
	incr tries
	APSWaitWithUpdate -waitSeconds 1
    }
    
    return 0
}

proc APSMpPARLETStopConditioningInfo {} {
    return "This procedure stops PAR and LET magnet conditioning."
}

proc APSMpPARLETStopConditioning {} {
    if [catch {APSMpPARStopConditioning
        APSMpPTBStopConditioning
        APSMpLTPStopConditioning} result] {
        APSMpReturn error $result
    }
    APSMpReturn ok
}
