#!/bin/sh  
# \
  exec oagtclsh "$0" "$@"

set auto_path [linsert $auto_path 0  /usr/local/oag/apps/lib/$env(HOST_ARCH)]
set auto_path [linsert $auto_path 0 /usr/local/oag/lib_patch/$env(HOST_ARCH)]

APSStandardSetup

proc APSPEMCheckPVs {args} {
    set pvList ""
    set desiredList ""
    set or 0
    set greaterThan 0
    set greaterThanOrEqualTo 0
    set lessThan 0
    set lessThanOrEqualTo 0
    set difference 0
    set absDifference 0
    set numerical 0
    set allowContinue 1
    set allowRecheck 1
    set noDialogs 0
    set message ""
    APSStrictParseArguments {pvList desiredList numerical allowContinue allowRecheck message or greaterThan greaterThanOrEqualTo lessThan lessThanOrEqualTo difference absDifference noDialogs}
    if {($or && ([llength $pvList] > 1))} {
        return -code error "Problem with arguments to APSPEMCheckPVs"
    }
    if {[expr $or + $greaterThan + $greaterThanOrEqualTo + $lessThan + $lessThanOrEqualTo + $difference + $absDifference] > 1} {
        return -code error "Problem with arguments to APSPEMCheckPVs"
    }
    while {1} {
        set messageText $message
        if {$numerical} {
            if {[catch {APScavget -list=[join $pvList ,] -pend=5 -printErrors -numerical} results]} {
                return -code error "Problem reading PVs: ${pvList}: $results"
            }
        } else {
            if {[catch {APScavget -list=[join $pvList ,] -pend=5 -printErrors} results]} {
                return -code error "Problem reading PVs: ${pvList}: $results"
            }
        }
        if {$or} {
            set pass 0
            set pv $pvList
            set result $results
            foreach desired $desiredList {
                if {$desired == $result} {
                    set pass 1
                }
            }
            if {!$pass} {
                append messageText " ${pv}=$result"
            }
        } elseif {$greaterThan} {
            set pass 1
            foreach pv $pvList desired $desiredList result $results {
                if {$desired >= $result} {
                    append messageText " ${pv}=$result"
                    if {!$allowContinue && !$allowRecheck} {
                        return -code error "$messageText"
                    }
                    set pass 0
                    break
                }
            }
        } elseif {$greaterThanOrEqualTo} {
            set pass 1
            foreach pv $pvList desired $desiredList result $results {
                if {$desired > $result} {
                    append messageText " ${pv}=$result"
                    if {!$allowContinue && !$allowRecheck} {
                        return -code error "$messageText"
                    }
                    set pass 0
                    break
                }
            }
        } elseif {$lessThan} {
            set pass 1
            foreach pv $pvList desired $desiredList result $results {
                if {$desired <= $result} {
                    append messageText " ${pv}=$result"
                    if {!$allowContinue && !$allowRecheck} {
                        return -code error "$messageText"
                    }
                    set pass 0
                    break
                }
            }
        } elseif {$lessThanOrEqualTo} {
            set pass 1
            foreach pv $pvList desired $desiredList result $results {
                if {$desired < $result} {
                    append messageText " ${pv}=$result"
                    if {!$allowContinue && !$allowRecheck} {
                        return -code error "$messageText"
                    }
                    set pass 0
                    break
                }
            }
        } elseif {$difference} {
            set desiredDiff $desiredList
            if {[llength $results] != 2} {
                return -code error "Problem with arguments to APSPEMCheckPVs"
            }
            set diff [expr [lindex $results 0] - [lindex $results 1]]
            if {$diff <= $desiredDiff} {
                set pass 1
            } else {
                append messageText " diff=$diff"
                set pass 0
            }
            set results $diff
        } elseif {$absDifference} {
            set desiredDiff $desiredList
            if {[llength $results] != 2} {
                return -code error "Problem with arguments to APSPEMCheckPVs"
            }
            set absDiff [expr abs([lindex $results 0] - [lindex $results 1])]
            if {$absDiff <= $desiredDiff} {
                set pass 1
            } else {
                append messageText " absDiff=$absDiff"
                set pass 0
            }
            set results $absDiff
        } else {
            set pass 1
            foreach pv $pvList desired $desiredList result $results {
                if {$desired != $result} {
                    append messageText " ${pv}=$result"
                    if {!$allowContinue && !$allowRecheck} {
                        return -code error "$messageText"
                    }
                    set pass 0
                    break
                }
            }
        }
        if {$pass || $noDialogs} {
            return $results
        } else {
            if {!$allowContinue && !$allowRecheck} {
                return -code error "$messageText"
            } elseif {$allowContinue && !$allowRecheck} {
                set answer [APSPEMTKDialog .warningDialog \
                              -text "$messageText" \
                              -strings {Continue "Abort Procedure"}]
                if {$answer == 0} {
                    return
                }
                return -code error "Aborted"
            } elseif {!$allowContinue && $allowRecheck} {
                set answer [APSPEMTKDialog .warningDialog \
                              -text "$messageText" \
                              -strings {Recheck "Abort Procedure"}]
                if {$answer == 0} {
                    continue
                }
                return -code error "Aborted"
            } else {
                set answer [APSPEMTKDialog .warningDialog \
                              -text "$messageText" \
                              -strings {Continue Recheck "Abort Procedure"}]
                if {$answer == 0} {
                    return
                } elseif {$answer == 1} {
                    continue
                }
                return -code error "Aborted"
            }
        }
    }
}

proc TurnOnK400InitialChecks {args} {
    set klystron K2
    APSStrictParseArguments {klystron}
    set klyNum [string range $klystron 1 1]
    set useDLLRF 0
    if {$klystron == "K2"} {
        set useDLLRF 0
        if {[catch {APScavget -list=L-${klystron}:LLRF:digitalSystemInUse -pend=5 -num -printErrors} useDLLRF]} {
            APSMpReturn error "Error checking for analog or digital LLRF: $useDLLRF"
        }
    }
    if {$useDLLRF} {
        if {$klystron == "K2"} {
            set fullyAttenuatedAmp 4000
        }
    }
    
    APSMpStep "Reset ACIS Inibit"
    set pv L${klyNum}:LL:miscResetBO
    if {[catch {APScavput -list=$pv=1 -pend=5} result]} {
        APSMpReturn error "Problem setting ${pv}: $result"
    }
    set pv L${klyNum}:DA:AcisResetBO
    if {[catch {APScavput -list=$pv=1 -pend=5} result]} {
        APSMpReturn error "Problem setting ${pv}: $result"
    }
    APSWaitWithUpdate -waitSeconds 2
    
    APSMpStep "Perform a reset"
    set pv L-${klystron}:Mod:Rst:Cmd
    if {[catch {APScavput -list=$pv=1 -pend=5} result]} {
        return -code error "Problem setting ${pv}: $result"
    }
    APSWaitWithUpdate -waitSeconds 5
    if {[catch {APScavput -list=$pv=1 -pend=5} result]} {
        return -code error "Problem setting ${pv}: $result"
    }
    APSWaitWithUpdate -waitSeconds 10

    if {$useDLLRF} {
        APSMpStep "Check if $klystron LLRF is on"
        if {[catch {APSPEMCheckPVs -pvList "L${klyNum}:LL:lockRfCtrlBI L${klyNum}:LL:readyCC" \
                      -desiredList "0 0" \
                      -numerical 1 \
                      -noDialogs 1} result]} {
            APSMpReturn error $result
        }
        
        if {([lindex $result 0] != 0) || ([lindex $result 1] != 0)} {
            APSMpStep "Turn off $klystron LLRF"
            set pv L${klyNum}:LL:lockRfOffBO
            if {[catch {APScavput -list=$pv=1 -num -pend=5} result]} {
                APSMpReturn error "Problem setting ${pv}: $result"
            }
            APSWaitWithUpdate -waitSeconds 3
            APSMpStep "Verify $klystron LLRF is off"
            if {[catch {APSPEMCheckPVs -pvList "L${klyNum}:LL:lockRfCtrlBI L${klyNum}:LL:readyCC" \
                          -desiredList "0 0" \
                          -numerical 1 \
                          -message "${klystron} K400 LLRF failed to turn off. Turn off LLRF and check again."} result]} {
                APSMpReturn error $result
            }
        }

        APSMpStep "Clear $klystron Libera RF Enable Interlock State"
        set pv L-${klystron}:LLRF:InterlockStateC
        if {[catch {APScavput -list=$pv=0 -num -pend=5} result]} {
            APSMpReturn error "Problem setting ${pv}: $result"
        }
        APSWaitWithUpdate -waitSeconds 1

        APSMpStep "Check $klystron Libera RF Enable Interlock State"
        if {[catch {APSPEMCheckPVs -numerical 1 -pvList L-${klystron}:LLRF:InterlockStateM \
                      -desiredList 0 \
                      -message "${klystron} Libera RF Enabled failed to clear. Reset RF Enable and check again"} result]} {
            return -code error $result
        }

#        APSMpStep "Turn on $klystron Libera RF Output"
#        set pv L-${klystron}:LLRF:RfOnOffC
#        if {[catch {APScavput -list=$pv=1 -num -pend=5} result]} {
#            APSMpReturn error "Problem setting ${pv}: $result"
#        }
#        APSWaitWithUpdate -waitSeconds 1

#        APSMpStep "Check $klystron Libera RF Output"
#        if {[catch {APSPEMCheckPVs -numerical 1 -pvList L-${klystron}:LLRF:RfOnOffM \
#                      -desiredList 1 \
#                      -message "${klystron} Libera RF output failed to turn on. Enable RF Output and check again"} result]} {
#            return -code error $result
#        }

        APSMpStep "Set $klystron DLLRF amp to the fully attenuated setting"
        set pv L-${klystron}:LLRF:DSP:FF_AmpC
        if {[catch {APScavput -list=$pv=$fullyAttenuatedAmp -pend=5} result]} {
            APSMpReturn error "Problem setting ${pv}: $result"
        }

        APSMpStep "Read and set DLLRF Phase Setpoint to reinitialize it"
        set pv L-${klystron}:LLRF:DSP:FF_PhaseSetpointC
        if {[catch {APScavget -list=$pv -pend=5} result]} {
            APSMpReturn error "Problem reading ${pv}: $result"
        }
        if {[catch {APScavput -list=$pv=$result -pend=5} result]} {
            APSMpReturn error "Problem setting ${pv}: $result"
        }
        
    }

    APSMpStep "Clear $klystron Libera RF Enable Interlock State"
    set pv L-${klystron}:LLRF:InterlockStateC
    if {[catch {APScavput -list=$pv=0 -pend=5} result]} {
        APSMpReturn error "Problem setting ${pv}: $result"
    }
    APSWaitWithUpdate -waitSeconds 5

    if {[catch {APSPEMCheckPVs -pvList L${klyNum}:LL:lockPersonnelAccBI \
                  -desiredList Normal \
                  -message "${klystron} K400 ACIS inhibit failed to clear. Reset ACIS and check again."} result]} {
        return -code error $result
    }

    APSMpStep "Check for remote access"
    if {[catch {APSPEMCheckPVs -pvList L-${klystron}:Mod:BI:OpMode \
                  -desiredList Remote \
                  -message "${klystron} K400 Access level not set to Remote"} result]} {
        return -code error $result
    }

    APSMpStep "Check Modbus"
    if {[catch {APSPEMCheckPVs -pvList L-${klystron}:Mod:Asyn.CNCT \
                  -desiredList Connect \
                  -message "${klystron} K400 Modbus not indicating connected"} result]} {
        return -code error $result
    }
    
    APSMpStep "Check forward power calibration"
    if {[catch {APSPEMCheckPVs -pvList L-${klystron}:Mod:DI:RfFwdWfAttenOffset-I.SEVR \
                  -desiredList  NO_ALARM\
                  -message "${klystron} K400 Forward power calibration may be incorrect"} result]} {
        return -code error $result
    }
    
    APSMpStep "Check reflected power calibration"
    if {[catch {APSPEMCheckPVs -pvList L-${klystron}:Mod:DI:RfRflWfAttenOffset-I.SEVR \
                  -desiredList NO_ALARM \
                  -message "${klystron} K400 Reflected power calibration may be incorrect"} result]} {
        return -code error $result
    }
    
    APSMpStep "Check water flow"
    if {[catch {APSPEMCheckPVs -pvList L-${klystron}:Mod:SumFlowAlarmM.SEVR \
                  -desiredList NO_ALARM \
                  -message "${klystron} K400 Water flow fault indicated"} result]} {
        return -code error $result
    }
    
    APSMpStep "Check system status"
    if {[catch {APSPEMCheckPVs -pvList L-${klystron}:Mod:Sts:I \
                  -desiredList "0 8" \
                  -or 1 \
                  -allowContinue 0 \
                  -allowRecheck 0 \
                  -message "${klystron} K400 Fault detected"} result]} {
        return -code error $result
    }
}

proc TurnOnK400BringUpToStandby {args} {
    set klystron K2
    APSStrictParseArguments {klystron}
    if {$klystron == "K2"} {
        set filamentCurrentTolerance .05
    }

    APSMpStep "Check state"
    if {[catch {APSPEMCheckPVs -pvList L-${klystron}:Mod:State-RB \
                  -desiredList 1 \
                  -greaterThanOrEqualTo 1 \
                  -allowContinue 0 \
                  -allowRecheck 0 \
                  -message "${klystron} K400 State found to be less than 1, unable to continue."} k400state]} {
        return -code error $k400state
    }

    if {$k400state == 1} {
        APSMpStep "Perform a reset"
        set pv L-${klystron}:Mod:Rst:Cmd
        if {[catch {APScavput -list=$pv=1 -pend=5} result]} {
            return -code error "Problem setting ${pv}: $result"
        }
        APSWaitWithUpdate -waitSeconds 5

        APSMpStep "Select Stand-by mode"
        set pv L-${klystron}:Mod:State-Sel
        if {[catch {APScavput -list=$pv=1 -pend=5} result]} {
            return -code error "Problem setting ${pv}: $result"
        }
        APSMpStep "Pausing 40 seconds"
        APSWaitWithUpdate -waitSeconds 40

        APSMpStep "Check state"
        if {[catch {APSPEMCheckPVs -pvList L-${klystron}:Mod:State-RB \
                      -desiredList 5 \
                      -allowContinue 0 \
                      -allowRecheck 0 \
                      -message "${klystron} K400 Failed to enter Stand-by mode."} k400state]} {
            return -code error $k400state
        }

        APSMpStep "Check system status"
        if {[catch {APSPEMCheckPVs -pvList L-${klystron}:Mod:Sts:I \
                      -desiredList "0 8" \
                      -or 1 \
                      -allowContinue 0 \
                      -allowRecheck 0 \
                      -message "${klystron} K400 Fault detected when verifying Stand-by mode"} result]} {
            return -code error $result
        }

        APSMpStep "Ensure filament current reaches expected value"
        if {[catch {APSPEMCheckPVs -pvList "L-${klystron}:Mod-FPS:I:I L-${klystron}:Mod-Fil:I:I" \
                      -desiredList "$filamentCurrentTolerance" \
                      -absDifference 1 \
                      -noDialogs 1} absDiff]} {
            return -code error $absDiff
        }
        if {$absDiff> $filamentCurrentTolerance} {
            APSMpStep "Pausing 30 seconds"
            APSWaitWithUpdate -waitSeconds 30
            if {[catch {APSPEMCheckPVs -pvList "L-${klystron}:Mod-FPS:I:I L-${klystron}:Mod-Fil:I:I" \
                          -desiredList "$filamentCurrentTolerance" \
                          -absDifference 1 \
                          -message "${klystron} K400 Filament current readback differs from setpoint by more than $filamentCurrentTolerance"} result]} {
                return -code error $result
            }
        }

        APSMpStep "Ensure warmup timer started"
        if {[catch {APSPEMCheckPVs -pvList L-${klystron}:Mod:Time:State-I \
                      -desiredList .001 \
                      -greaterThanOrEqualTo 1 \
                      -message "${klystron} K400 Filament timer not started"} result]} {
            return -code error $result
        }

        APSMpStep "Check state"
        if {[catch {APSPEMCheckPVs -pvList L-${klystron}:Mod:State-RB \
                      -desiredList 5 \
                      -allowContinue 0 \
                      -allowRecheck 0 \
                      -message "${klystron} K400 Failed to enter Stand-by mode."} k400state]} {
            return -code error $k400state
        }

        APSMpStep "Check system status"
        if {[catch {APSPEMCheckPVs -pvList L-${klystron}:Mod:Sts:I \
                      -desiredList "0 8" \
                      -or 1 \
                      -allowContinue 0 \
                      -allowRecheck 0 \
                      -message "${klystron} K400 Fault detected when verifying Stand-by mode"} result]} {
            return -code error $result
        }
    }  
}

proc TurnOnK400BringUpToHVMode {args} {
    set klystron K2
    APSStrictParseArguments {klystron}
    set klyNum [string range $klystron 1 1]
    set useDLLRF 0
    if {$klystron == "K2"} {
        set useDLLRF 0
        if {[catch {APScavget -list=L-${klystron}:LLRF:digitalSystemInUse -pend=5 -num -printErrors} useDLLRF]} {
            return -code error "Error checking for analog or digital LLRF: $useDLLRF"
        }
    }
    if {$klystron == "K2"} {
        set filamentWarmupTimerDurationCheckPeriod 61
        set ccpsReadbackTolerance 10
    }

    APSMpStep "Check state"
    if {[catch {APSPEMCheckPVs -pvList L-${klystron}:Mod:State-RB \
                  -desiredList 5 \
                  -greaterThanOrEqualTo 1 \
                  -allowContinue 0 \
                  -allowRecheck 0 \
                  -message "${klystron} K400 State found to be less than 5, unable to continue."} k400state]} {
        return -code error $k400state
    }

    if {$k400state == 5} {
        APSMpStep "Check system status"
        if {[catch {APSPEMCheckPVs -pvList L-${klystron}:Mod:Sts:I \
                      -desiredList "0 8" \
                      -or 1 \
                      -allowContinue 0 \
                      -allowRecheck 0 \
                      -message "${klystron} K400 Fault detected when verifying Stand-by mode"} result]} {
            return -code error $result
        }

        APSMpStep "Ensure warmup timer has finished"
        set maxTime [expr [clock seconds] + $filamentWarmupTimerDurationCheckPeriod * 60]
        set pv L-${klystron}:Mod:Time:State-I
        while {[clock seconds] < $maxTime} {
            if {[catch {APScavget -list=$pv -pend=5} result]} {
                return -code error "Problem reading ${pv}: $result"
            }
            if {$result != 0} {
                APSMpStep "Pausing 30 seconds"
                APSWaitWithUpdate -waitSeconds 30
            } else {
                break
            }
        }
        if {[catch {APSPEMCheckPVs -pvList L-${klystron}:Mod:Time:State-I \
                      -desiredList 0 \
                      -message "${klystron} K400 Filament timer has been running longer than expected"} result]} {
            return -code error $result
        }

        APSMpStep "Check state"
        if {[catch {APSPEMCheckPVs -pvList L-${klystron}:Mod:State-RB \
                      -desiredList 5 \
                      -allowContinue 0 \
                      -allowRecheck 0 \
                      -message "${klystron} K400 Failed to complete Stand-by filament warmup period."} k400state]} {
            return -code error $k400state
        }

        if {!$useDLLRF} {
            APSMpStep "Check for ACIS Inhibit"
            if {[catch {APSPEMCheckPVs -pvList L${klyNum}:LL:lockPersonnelAccBI \
                          -desiredList Normal \
                          -message "${klystron} K400 ACIS exists. Reset ACIS and check again."} result]} {
                return -code error $result
            }
        }

        APSMpStep "Perform a reset"
        set pv L-${klystron}:Mod:Rst:Cmd
        if {[catch {APScavput -list=$pv=1 -pend=5} result]} {
            return -code error "Problem setting ${pv}: $result"
        }
        APSWaitWithUpdate -waitSeconds 5

        APSMpStep "Set CCPS setpoint to default value"
        set pv L-${klystron}:Mod:CcpsTripRstValue
        if {[catch {APScavget -list=$pv -pend=5 -printErrors} CcpsTripRstValue]} {
            return -code error "Problem reading ${pv}: $CcpsTripRstValue"
        }
        set pv L-${klystron}:Mod-CCPS:E:SP
        if {[catch {APScavput -list=$pv=$CcpsTripRstValue -pend=5} result]} {
            return -code error "Problem setting ${pv}: $result"
        }
        APSWaitWithUpdate -waitSeconds 1

        APSMpStep "Compare CCPS readback to desired value"
        if {[catch {APSPEMCheckPVs -pvList L-${klystron}:Mod-CCPS:E:I \
                      -desiredList $CcpsTripRstValue \
                      -message "${klystron} K400 CCPS setpoint does not match the default low setpoint."} result]} {
            return -code error $result
        }

        APSMpStep "Select HV mode"
        set pv L-${klystron}:Mod:State-Sel
        if {[catch {APScavput -list=$pv=2 -pend=5} result]} {
            return -code error "Problem setting ${pv}: $result"
        }
        APSMpStep "Pausing 30 seconds"
        APSWaitWithUpdate -waitSeconds 30

        APSMpStep "Perform a reset"
        set pv L-${klystron}:Mod:Rst:Cmd
        if {[catch {APScavput -list=$pv=1 -pend=5} result]} {
            return -code error "Problem setting ${pv}: $result"
        }
        APSWaitWithUpdate -waitSeconds 5
        if {[catch {APScavput -list=$pv=1 -pend=5} result]} {
            return -code error "Problem setting ${pv}: $result"
        }
        APSWaitWithUpdate -waitSeconds 10

        APSMpStep "Check state"
        if {[catch {APSPEMCheckPVs -pvList L-${klystron}:Mod:State-RB \
                      -desiredList 9 \
                      -allowContinue 0 \
                      -allowRecheck 0 \
                      -message "${klystron} K400 Failed to enter HV mode."} k400state]} {
            return -code error $k400state
        }

        APSMpStep "Check system status"
        set pv L-${klystron}:Mod:Sts:I
        if {[catch {APSPEMCheckPVs -pvList $pv \
                      -desiredList "0 8" \
                      -or 1 \
                      -allowContinue 0 \
                      -allowRecheck 0 \
                      -message "${klystron} K400 Fault detected when verifying HV mode"} result]} {
            return -code error $result
        }
        if {$result == 8} {
            set warningMessage "${klystron} K400 warning was detected when verifying HV mode. You can continue to bring up the system but the RF Group must be informed of the warnings."
            set answer [APSPEMTKDialog .warningDialog \
                          -text "$warningMessage ${pv}=$result" \
                          -strings "Continue"]
        }

        APSMpStep "Check PS1 and PS2 readbacks"
        if {[catch {APSPEMCheckPVs -pvList "L-${klystron}:Mod-PS:1:E:I L-${klystron}:Mod-CCPS:E:I" \
                      -desiredList "$ccpsReadbackTolerance" \
                      -absDifference 1 \
                      -noDialogs 1} result1]} {
            return -code error $result1
        }
        if {[catch {APSPEMCheckPVs -pvList "L-${klystron}:Mod-PS:2:E:I L-${klystron}:Mod-CCPS:E:I" \
                      -desiredList "$ccpsReadbackTolerance" \
                      -absDifference 1 \
                      -noDialogs 1} result2]} {
            return -code error $result2
        }
        if {($result1 > $ccpsReadbackTolerance) || ($result2 > $ccpsReadbackTolerance)} {
            APSMpStep "Perform reset"
            set pv L-${klystron}:Mod:Rst:Cmd
            if {[catch {APScavput -list=$pv=1 -pend=5} result]} {
                return -code error "Problem setting ${pv}: $result"
            }
            APSWaitWithUpdate -waitSeconds 5
            
            APSMpStep "Select HV mode"
            set pv L-${klystron}:Mod:State-Sel
            if {[catch {APScavput -list=$pv=2 -pend=5} result]} {
                return -code error "Problem setting ${pv}: $result"
            }
            APSMpStep "Pausing 30 seconds"
            APSWaitWithUpdate -waitSeconds 30

            APSMpStep "Recheck PS1 readback"
            if {[catch {APSPEMCheckPVs -pvList "L-${klystron}:Mod-PS:1:E:I L-${klystron}:Mod-CCPS:E:I" \
                          -desiredList "$ccpsReadbackTolerance" \
                          -absDifference 1 \
                          -message "${klystron} K400 PS1 voltage readback is greater than $ccpsReadbackTolerance V from setpoint."} result]} {
                return -code error $result
            }

            APSMpStep "Recheck PS2 readback"
            if {[catch {APSPEMCheckPVs -pvList "L-${klystron}:Mod-PS:2:E:I L-${klystron}:Mod-CCPS:E:I" \
                          -desiredList "$ccpsReadbackTolerance" \
                          -absDifference 1 \
                          -message "${klystron} K400 PS1 voltage readback is greater than $ccpsReadbackTolerance V from setpoint."} result]} {
                return -code error $result
            }
        }
        
        APSMpStep "Check state"
        if {[catch {APSPEMCheckPVs -pvList L-${klystron}:Mod:State-RB \
                      -desiredList 9 \
                      -allowContinue 0 \
                      -allowRecheck 0 \
                      -message "${klystron} K400 Switch to HV mode failed."} k400state]} {
            return -code error $k400state
        }

        APSMpStep "Check system status"
        set pv L-${klystron}:Mod:Sts:I
        if {[catch {APSPEMCheckPVs -pvList $pv \
                      -desiredList "0 8" \
                      -or 1 \
                      -allowContinue 0 \
                      -allowRecheck 0 \
                      -message "${klystron} K400 Fault detected when verifying HV mode"} result]} {
            return -code error $result
        }
        if {$result == 8} {
            set warningMessage "${klystron} K400 warning was detected when verifying HV mode. You can continue to bring up the system but the RF Group must be informed of the warnings."
            set answer [APSPEMTKDialog .warningDialog \
                          -text "$warningMessage ${pv}=$result" \
                          -strings "Continue"]
        }
    }
}

proc TurnOnK400BringUpToTrigMode {args} {
    set klystron K2
    APSStrictParseArguments {klystron}
    if {$klystron == "K2"} {
        set ccpsReadbackTolerance 10
        set cvdRangeMin 210
        set cvdRangeMax 240
    }

    APSMpStep "Check state"
    if {[catch {APSPEMCheckPVs -pvList L-${klystron}:Mod:State-RB \
                  -desiredList 9 \
                  -greaterThanOrEqualTo 1 \
                  -allowContinue 0 \
                  -allowRecheck 0 \
                  -message "${klystron} K400 State found to be less than 9, unable to continue."} k400state]} {
        return -code error $k400state
    }

    if {$k400state == 9} {

        APSMpStep "Check PS1 and PS2 readbacks"
        if {[catch {APSPEMCheckPVs -pvList "L-${klystron}:Mod-PS:1:E:I L-${klystron}:Mod-CCPS:E:I" \
                      -desiredList "$ccpsReadbackTolerance" \
                      -absDifference 1 \
                      -noDialogs 1} result1]} {
            return -code error $result1
        }
        if {[catch {APSPEMCheckPVs -pvList "L-${klystron}:Mod-PS:2:E:I L-${klystron}:Mod-CCPS:E:I" \
                      -desiredList "$ccpsReadbackTolerance" \
                      -absDifference 1 \
                      -noDialogs 1} result2]} {
            return -code error $result2
        }
        if {($result1 > $ccpsReadbackTolerance) || ($result2 > $ccpsReadbackTolerance)} {
            APSMpStep "Perform reset"
            set pv L-${klystron}:Mod:Rst:Cmd
            if {[catch {APScavput -list=$pv=1 -pend=5} result]} {
                return -code error "Problem setting ${pv}: $result"
            }
            APSWaitWithUpdate -waitSeconds 5
            
            APSMpStep "Select HV mode"
            set pv L-${klystron}:Mod:State-Sel
            if {[catch {APScavput -list=$pv=2 -pend=5} result]} {
                return -code error "Problem setting ${pv}: $result"
            }
            APSMpStep "Pausing 30 seconds"
            APSWaitWithUpdate -waitSeconds 30

            APSMpStep "Recheck PS1 readback"
            if {[catch {APSPEMCheckPVs -pvList "L-${klystron}:Mod-PS:1:E:I L-${klystron}:Mod-CCPS:E:I" \
                          -desiredList "$ccpsReadbackTolerance" \
                          -absDifference 1 \
                          -message "${klystron} K400 PS1 voltage readback is greater than $ccpsReadbackTolerance V from setpoint."} result]} {
                return -code error $result
            }

            APSMpStep "Recheck PS2 readback"
            if {[catch {APSPEMCheckPVs -pvList "L-${klystron}:Mod-PS:2:E:I L-${klystron}:Mod-CCPS:E:I" \
                          -desiredList "$ccpsReadbackTolerance" \
                          -absDifference 1 \
                          -message "${klystron} K400 PS1 voltage readback is greater than $ccpsReadbackTolerance V from setpoint."} result]} {
                return -code error $result
            }
        }


        APSMpStep "Check system status"
        set pv L-${klystron}:Mod:Sts:I
        if {[catch {APSPEMCheckPVs -pvList $pv \
                      -desiredList "0 8" \
                      -or 1 \
                      -allowContinue 0 \
                      -allowRecheck 0 \
                      -message "${klystron} K400 Fault detected when verifying HV mode"} result]} {
            return -code error $result
        }
        if {$result == 8} {
            set warningMessage "${klystron} K400 warning was detected when verifying HV mode. You can continue to bring up the system but the RF Group must be informed of the warnings."
            set answer [APSPEMTKDialog .warningDialog \
                          -text "$warningMessage ${pv}=$result" \
                          -strings "Continue"]
        }

        APSMpStep "Check that CVD is reading 0"
        if {[catch {APSPEMCheckPVs -pvList L-${klystron}:Mod-CVD:E:I \
                      -desiredList .1 \
                      -lessThan 1 \
                      -message "${klystron} K400 CVD readback issue detected, should be 0 in HV mode."} result]} {
            return -code error $result
        }

        APSMpStep "Select Trig mode"
        set pv L-${klystron}:Mod:State-Sel
        if {[catch {APScavput -list=$pv=3 -pend=5} result]} {
            return -code error "Problem setting ${pv}: $result"
        }
        APSMpStep "Pausing 10 seconds"
        APSWaitWithUpdate -waitSeconds 10

        APSMpStep "Check state"
        if {[catch {APSPEMCheckPVs -pvList L-${klystron}:Mod:State-RB \
                      -desiredList 13 \
                      -allowContinue 0 \
                      -allowRecheck 0 \
                      -message "${klystron} K400 Failed to enter Trig mode."} k400state]} {
            return -code error $k400state
        }

        APSMpStep "Check system status"
        set pv L-${klystron}:Mod:Sts:I
        if {[catch {APSPEMCheckPVs -pvList $pv \
                      -desiredList "0 8" \
                      -or 1 \
                      -allowContinue 0 \
                      -allowRecheck 0 \
                      -message "${klystron} K400 Fault detected when verifying Trig mode"} result]} {
            return -code error $result
        }
        if {$result == 8} {
            set warningMessage "${klystron} K400 warning was detected when verifying Trig mode. You can continue to bring up the system but the RF Group must be informed of the warnings."
            set answer [APSPEMTKDialog .warningDialog \
                          -text "$warningMessage ${pv}=$result" \
                          -strings "Continue"]
        }

        APSMpStep "Check the CVD reading"
        if {[catch {APSPEMCheckPVs -pvList L-${klystron}:Mod-CVD:E:I \
                      -desiredList $cvdRangeMin \
                      -greaterThanOrEqualTo 1 \
                      -message "${klystron} K400 CVD readback should be greater than $cvdRangeMin in Trig mode."} result]} {
            return -code error $result
        }
        if {[catch {APSPEMCheckPVs -pvList L-${klystron}:Mod-CVD:E:I \
                      -desiredList $cvdRangeMax \
                      -lessThanOrEqualTo 1 \
                      -message "${klystron} K400 CVD readback should be less than $cvdRangeMax in Trig mode."} result]} {
            return -code error $result
        }
    }
}

proc TurnOnK400BringUpRFPower {args} {
    set klystron K2
    set ccpsSCRsetpoint 1200
    APSStrictParseArguments {klystron ccpsSCRsetpoint}
    set klyNum [string range $klystron 1 1]
    set useDLLRF 0
    if {$klystron == "K2"} {
        set useDLLRF 0
        if {[catch {APScavget -list=L-${klystron}:LLRF:digitalSystemInUse -pend=5 -num -printErrors} useDLLRF]} {
            return -code error "Error checking for analog or digital LLRF: $useDLLRF"
        }
        set cvdRangeMin 210
        set cvdRangeMax 240
        set ccpsStepSize 10
        set ccpsFirstPauseValue 1000
        set ccpsSecondPauseValue 1100
        set ccpsFinalValue 1200
        set forwardPowerMinFirstPause .3
        set forwardPowerMinSecondPause .6
        set forwardPowerMinFinalValue .8
        set sledExpectedMinMultiplier 4
    }

    if {$useDLLRF} {
        if {$klystron == "K2"} {
            set fullyAttenuatedAmp 4000
            set lowPowerAmp 12000
        }
    } else {
        if {$klystron == "K2"} {
            set attenuatorVoltageFullyAttenuated 3.2
            set attenuatorVoltageInitialStartup 2.8
        }
    }

    APSMpStep "Check state"
    if {[catch {APSPEMCheckPVs -pvList L-${klystron}:Mod:State-RB \
                  -desiredList 13 \
                  -greaterThanOrEqualTo 1 \
                  -allowContinue 0 \
                  -allowRecheck 0 \
                  -message "${klystron} K400 State found to be less than 13, unable to continue."} k400state]} {
        return -code error $k400state
    }

    if {$k400state == 13} {
        APSMpStep "Check system status"
        set pv L-${klystron}:Mod:Sts:I
        if {[catch {APSPEMCheckPVs -pvList $pv \
                      -desiredList "0 8" \
                      -or 1 \
                      -allowContinue 0 \
                      -allowRecheck 0 \
                      -message "${klystron} K400 Fault detected when verifying Trig mode"} result]} {
            return -code error $result
        }
        if {$result == 8} {
            set warningMessage "${klystron} K400 warning was detected when verifying Trig mode. You can continue to bring up the system but the RF Group must be informed of the warnings."
            set answer [APSPEMTKDialog .warningDialog \
                          -text "$warningMessage ${pv}=$result" \
                          -strings "Continue"]
        }

        APSMpStep "Ensure the CCPS readback is set to the default low value, compare to desired value"
        if {[catch {K400LowerCCPSToDefaultLowValue -klystron $klystron} result]} {
            return -code error $result
        }

        APSMpStep "Check the CVD reading"
        if {[catch {APSPEMCheckPVs -pvList L-${klystron}:Mod-CVD:E:I \
                      -desiredList $cvdRangeMin \
                      -greaterThanOrEqualTo 1 \
                      -allowContinue 0 \
                      -allowRecheck 0 \
                      -message "${klystron} K400 CVD readback is not in initial expected range for increasing RF power, should be greater than $cvdRangeMin"} result]} {
            return -code error $result
        }
        if {[catch {APSPEMCheckPVs -pvList L-${klystron}:Mod-CVD:E:I \
                      -desiredList $cvdRangeMax \
                      -lessThanOrEqualTo 1 \
                      -allowContinue 0 \
                      -allowRecheck 0 \
                      -message "${klystron} K400 CVD readback is not in initial expected range for increasing RF power, should be less than $cvdRangeMax"} result]} {
            return -code error $result
        }
        
        if {$useDLLRF} {
            APSMpStep "Set $klystron DLLRF amp to the fully attenuated setting"
            set pv L-${klystron}:LLRF:DSP:FF_AmpC
            if {[catch {APScavput -list=$pv=$fullyAttenuatedAmp -pend=5} result]} {
                APSMpReturn error "Problem setting ${pv}: $result"
            }
        } else {
            APSMpStep "Set Attn Ctrl voltage to ${attenuatorVoltageFullyAttenuated}V or higher"
            if {[catch {K400IncreaseAttn -klystron $klystron \
                          -attenuatorVoltageTarget $attenuatorVoltageFullyAttenuated} result]} {
                return -code error $result
            }
        }

        APSMpStep "Turn on LLRF, fault resets are left to the operator"
        set pv L${klyNum}:LL:lockRfOnBO
        if {[catch {APScavput -list=$pv=1 -num -pend=5} result]} {
            return -code error "Problem setting ${pv}: $result"
        }
        APSWaitWithUpdate -waitSeconds 3

        APSMpStep "Check if LLRF is on"
        if {[catch {APSPEMCheckPVs -pvList "L${klyNum}:LL:lockRfCtrlBI L${klyNum}:LL:readyCC" \
                      -desiredList "1 1" \
                      -numerical 1 \
                      -noDialogs 1} result]} {
            APSMpReturn error $result
        }
        if {([lindex $result 0] != 1) || ([lindex $result 1] != 1)} {
            APSMpStep "Try again to turn on LLRF, fault resets are left to the operator"
            set pv L${klyNum}:LL:lockRfOnBO
            if {[catch {APScavput -list=$pv=1 -num -pend=5} result]} {
                return -code error "Problem setting ${pv}: $result"
            }
            APSWaitWithUpdate -waitSeconds 3
            
            APSMpStep "Verify LLRF is on"
            if {[catch {APSPEMCheckPVs -pvList "L${klyNum}:LL:lockRfCtrlBI L${klyNum}:LL:readyCC" \
                          -desiredList "1 1" \
                          -numerical 1 \
                          -message "${klystron} K400 LLRF failed to turn on. Turn on LLRF and check again."} result]} {
                return -code error $result
            }
            APSMpStep "Check $klystron Libera RF Output"
            if {[catch {APSPEMCheckPVs -numerical 1 -pvList L-${klystron}:LLRF:RfOnOffM \
                      -desiredList 1 \
                      -message "${klystron} Libera RF output failed to turn on. Enable RF Output and check again"} result]} {
                return -code error $result
            }
        }

        if {$useDLLRF} {
            for {set value [expr $fullyAttenuatedAmp + 1000]} {$value <= $lowPowerAmp} {incr value 1000} {
                APSMpStep "Set $klystron DLLRF amp to $value"
                set pv L-${klystron}:LLRF:DSP:FF_AmpC
                if {[catch {APScavput -list=$pv=$value -pend=5} result]} {
                    APSMpReturn error "Problem setting ${pv}: $result"
                }
                APSWaitWithUpdate -waitSeconds 2
            }
            set pv L-${klystron}:LLRF:DSP:FF_AmpC
            if {[catch {APScavput -list=$pv=$lowPowerAmp -pend=5} result]} {
                APSMpReturn error "Problem setting ${pv}: $result"
            }
            APSWaitWithUpdate -waitSeconds 2
        } else {
            APSMpStep "Decrease Attn Ctrl voltage to ${attenuatorVoltageInitialStartup}V or less"
            if {[catch {K400DecreaseAttn -klystron $klystron \
                          -attenuatorVoltageTarget $attenuatorVoltageInitialStartup} result]} {
                return -code error $result
            }
        }

        APSMpStep "Adjust CCPS in ${ccpsStepSize}V increments up to ${ccpsFirstPauseValue}V"
        if {[catch {TurnOnK400RampCCPS -klystron $klystron -ccpsSCRsetpoint $ccpsSCRsetpoint \
                      -ccpsTarget $ccpsFirstPauseValue \
                      -ccpsStepSize $ccpsStepSize \
                      -klyForwardPowerTarget [expr $forwardPowerMinFirstPause * 1000000] \
                      -sledExpectedMinMultiplier $sledExpectedMinMultiplier \
                      -final 0} result]} {
            return -code error $result
        }

        APSMpStep "Adjust CCPS in ${ccpsStepSize}V increments up to ${ccpsSecondPauseValue}V"
        if {[catch {TurnOnK400RampCCPS -klystron $klystron -ccpsSCRsetpoint $ccpsSCRsetpoint \
                      -ccpsTarget $ccpsSecondPauseValue \
                      -ccpsStepSize $ccpsStepSize \
                      -klyForwardPowerTarget [expr $forwardPowerMinSecondPause * 1000000] \
                      -sledExpectedMinMultiplier $sledExpectedMinMultiplier \
                      -final 0} result]} {
            return -code error $result
        }

        APSMpStep "Adjust CCPS in ${ccpsStepSize}V increments up to ${ccpsFinalValue}V"
        if {[catch {TurnOnK400RampCCPS -klystron $klystron -ccpsSCRsetpoint $ccpsSCRsetpoint \
                      -ccpsTarget $ccpsFinalValue \
                      -ccpsStepSize $ccpsStepSize \
                      -klyForwardPowerTarget [expr $forwardPowerMinFinalValue * 1000000] \
                      -sledExpectedMinMultiplier $sledExpectedMinMultiplier \
                      -final 1} result]} {
            return -code error $result
        }

        if {0} {
            #This is don in LMOCS_Recover in a separate process
            APSMpStep "Decrease the attenuator voltage"
            if {[catch {K400DecreaseAttnInTrigState -klystron $klystron \
                          -SCRattnCtrlVoltage $SCRattnCtrlVoltage \
                          -SCRklystronForwardPower $SCRklystronForwardPower \
                          -SCRsledForwardPower $SCRsledForwardPower} result]} {
                return -code error $result
            }
        }
    }
}

proc K400IncreaseAttn {args} {
    set klystron K2
    set attenuatorVoltageTarget 0
    APSStrictParseArguments {klystron attenuatorVoltageTarget}
    set klyNum [string range $klystron 1 1]

    #Note: We are using the Attn Ctrl voltage as an objective instead of the klystron drive, this is different from previous method
    set pv L${klyNum}:MA:klyPosAI
    if {[catch {APScavget -list=$pv -pend=5 -printErrors} voltage]} {
        return -code error "Problem reading ${pv}: $voltage"
    }
    while {$voltage < $attenuatorVoltageTarget} {
        #Increase attenuation until less than $attenuatorVoltageTarget V is achieved for L${klyNum}:MA:klyPosAI
        if {1} {
            set pv L${klyNum}:MA:incKlyBO
            if {[catch {APScavput -list=$pv=1 -pend=5} result]} {
                return -code error "Problem setting ${pv}: $result"
            }
            APSWaitWithUpdate -waitSeconds 2
            if {[catch {APScavput -list=$pv=0 -pend=5} result]} {
                return -code error "Problem setting ${pv}: $result"
            }
            APSWaitWithUpdate -waitSeconds 2
        } else {
            set pv L${klyNum}:KY:DC2A:pwmCtlC
            if {[catch {APScavput -list=$pv=-1 -pend=5} result]} {
                return -code error "Problem setting ${pv}: $result"
            }
            APSWaitWithUpdate -waitSeconds 1
        }
        
        set pv L${klyNum}:MA:klyPosAI
        if {[catch {APScavget -list=$pv -pend=5 -printErrors} voltage]} {
            return -code error "Problem reading ${pv}: $voltage"
        }
    }
}

proc K400DecreaseAttn {args} {
    set klystron K2
    set attenuatorVoltageInitialStartup 0
    APSStrictParseArguments {klystron attenuatorVoltageTarget}
    set klyNum [string range $klystron 1 1]

    #Note: We are using the Attn Ctrl voltage as an objective instead of the klystron drive, this is different from previous method
    set pv L${klyNum}:MA:klyPosAI
    if {[catch {APScavget -list=$pv -pend=5 -printErrors} voltage]} {
        return -code error "Problem reading ${pv}: $voltage"
    }
    while {$voltage >= $attenuatorVoltageTarget} {
        #Decrease attenuation until less than $attenuatorVoltageTarget V is achieved for L${klyNum}:MA:klyPosAI
        if {1} {
            set pv L${klyNum}:MA:decKlyBO
            if {[catch {APScavput -list=$pv=1 -pend=5} result]} {
                return -code error "Problem setting ${pv}: $result"
            }
            APSWaitWithUpdate -waitSeconds 2
            if {[catch {APScavput -list=$pv=0 -pend=5} result]} {
                return -code error "Problem setting ${pv}: $result"
            }
            APSWaitWithUpdate -waitSeconds 2
        } else {
            set pv L${klyNum}:KY:DC2A:pwmCtlC
            if {[catch {APScavput -list=$pv=1 -pend=5} result]} {
                return -code error "Problem setting ${pv}: $result"
            }
            APSWaitWithUpdate -waitSeconds 1
        }

        set pv L${klyNum}:MA:klyPosAI
        if {[catch {APScavget -list=$pv -pend=5 -printErrors} voltage]} {
            return -code error "Problem reading ${pv}: $voltage"
        }
    }
}

proc K400DecreaseAttnInTrigState {args} {
    set klystron K2
    set SCRattnCtrlVoltage ""
    set SCRklystronForwardPower ""
    set SCRsledForwardPower ""
    APSStrictParseArguments {klystron SCRattnCtrlVoltage SCRklystronForwardPower SCRsledForwardPower}
    set klyNum [string range $klystron 1 1]

    set useDLLRF 0
    if {$klystron == "K2"} {
        set useDLLRF 0
        if {[catch {APScavget -list=L-${klystron}:LLRF:digitalSystemInUse -pend=5 -num -printErrors} useDLLRF]} {
            return -code error "Error checking for analog or digital LLRF: $useDLLRF"
        }
    }

    if {[catch {K400GetVacuumPVs -klystron $klystron} vacPVs]} {
        return -code error "$vacPVs"
    }
    global apsVacInit
    APSMpStep "Reading vacuum PVs before changing RF voltage"
    if {[catch {APScavget -list=[join $vacPVs ,] -pend=5 -printErrors} vacValues]} {
        return -code error "$vacValues"
    }
    foreach pv $vacPVs val $vacValues {
        set apsVacInit($pv) $val
    }
    if {$useDLLRF} {
        if {$klyNum == 2} {
            if {[catch {APScavget -list=LRFSCS:SW10:P2M -num -pend=5 -printErrors} K2toWaterLoad]} {
                return -code error "Error reading LRFSCS:SW10:P2M: $K2toWaterLoad"
            }
            if {$K2toWaterLoad == 1} {
                set SCRsledForwardPower 99e99
            }
        }
    }

    APSMpStep "Decrease the attenuator voltage"
    set checkWarn8 1
    while {1} {
        set pv1 L${klyNum}:MA:klyPosAI
        set pv2 L-${klystron}:LLRF:KlyFwd_PwrRemoteM
        set pv3 L-${klystron}:LLRF:SD:Fwd_PkPwrRemoteM
        if {[catch {APScavget -list=${pv1},${pv2},${pv3} -pend=5 -printErrors} results]} {
            return -code error "Problem reading ${pv1}, $pv2 and ${pv3}: $results"
        }
        set voltage [lindex $results 0]
        if {($voltage > $SCRattnCtrlVoltage) && \
              ([lindex $results 1] < $SCRklystronForwardPower) && \
              ([lindex $results 2] < $SCRsledForwardPower)} {
            #APSMpStep "Verify LLRF is on"
            if {[catch {APSPEMCheckPVs -pvList "L${klyNum}:LL:lockRfCtrlBI L${klyNum}:LL:readyCC" \
                          -desiredList "1 1" \
                          -numerical 1 \
                          -message "${klystron} K400 Attempting to decrease LLRF attenuation.  LLRF is off."} result]} {
                return -code error $result
            }

            #APSMpStep "Check state"
            if {[catch {APSPEMCheckPVs -pvList L-${klystron}:Mod:State-RB \
                          -desiredList 13 \
                          -allowContinue 0 \
                          -allowRecheck 0 \
                          -message "${klystron} K400 Tripped out of Trig mode during LLRF attenuation change."} k400state]} {
                return -code error $k400state
            }

            #APSMpStep "Check system status"
            set pv L-${klystron}:Mod:Sts:I
            if {[catch {APSPEMCheckPVs -pvList $pv \
                          -desiredList "0 8" \
                          -or 1 \
                          -allowContinue 0 \
                          -allowRecheck 0 \
                          -message "${klystron} K400 Fault detected when verifying Trig mode"} result]} {
                return -code error $result
            }
            if {$checkWarn8 && ($result == 8)} {
                set checkWarn8 0
                set warningMessage "${klystron} K400 warning was detected when verifying Trig mode. You can continue to bring up the system but the RF Group must be informed of the warnings."
                set answer [APSPEMTKDialog .warningDialog \
                              -text "$warningMessage ${pv}=$result" \
                              -strings "Continue"]
            }
            
            set ratio [expr $SCRattnCtrlVoltage / $voltage]
            if {$ratio < .9} {
                set holdTime 1
            } elseif {$ratio < .95} {
                set holdTime .3
            } elseif {$ratio < .98} {
                set holdTime .2
            } else {
                set holdTime .1
            }

            set pv L${klyNum}:KY:DC2A:pwmCtlC
            if {[catch {APScavput -list=$pv=$holdTime -pend=5} result]} {
                return -code error "Problem setting ${pv}: $result"
            }

            if {$holdTime == .1} {
                for {set i 1} {$i <= 10} {incr i} {
                    if {[catch {APScavget -list=${pv1},${pv2},${pv3} -pend=5 -printErrors} results]} {
                        return -code error "Problem reading ${pv1}, $pv2 and ${pv3}: $results"
                    }
                    set voltage [lindex $results 0]
                    if {($voltage > $SCRattnCtrlVoltage) && ([lindex $results 1] < $SCRklystronForwardPower) && ([lindex $results 2] < $SCRsledForwardPower)} {
                        #APSWaitWithUpdate -waitSeconds 1
                    } else {
                        return
                    }
                }
            } else {
                #APSWaitWithUpdate -waitSeconds 4
            }
            #APSMpStep "Checking vacuum"
            if {0} {
                if {[catch {K400CheckVacuumAndWait -klystron $klystron -vacPVs $vacPVs} result]} {
                    return -code error $result
                }
            } else {
                if {$klyNum == 5} {
                    set L5 1
                } else {
                    set L5 0
                }
                if {$klyNum == 2} {
                    set L2 1
                } else {
                    set L2 0
                }
                if {[catch {LMOCS_Recover_CheckVacuumAndWait -vacPVs $vacPVs -interval 5 -L2 $L2 -L5 $L5 -VacuumLimit 1e-7 -readings 3 -interval 2} result]} {
                    set answer [APSPEMTKDialog .warningDialog \
                                  -text "Vacuum levels are too high. $result" \
                                  -strings {"Rebaseline and Recheck" "Abort Procedure"}]
                    if {$answer == 1} {
                        return -code error $result
                    }
                    if {[catch {APScavget -list=[join $vacPVs ,] -pend=5 -printErrors} vacValues]} {
                        return -code error "$vacValues"
                    }
                    foreach pv $vacPVs val $vacValues {
                        set apsVacInit($pv) $val
                    }
                }
            }
        } else {
            break
        }
    }
}

#Called by LMOCS_Recover when useDLLRF=1
proc K400IncreaseLLRFampDrive {args} {
    set klystron K2
    set SCRllrfAmpDrive ""
    set SCRklystronForwardPower ""
    set SCRsledForwardPower ""
    APSStrictParseArguments {klystron SCRllrfAmpDrive SCRklystronForwardPower SCRsledForwardPower}
    set klyNum [string range $klystron 1 1]

    if {[catch {K400GetVacuumPVs -klystron $klystron} vacPVs]} {
        return -code error "$vacPVs"
    }
    global apsVacInit
    APSMpStep "Reading vacuum PVs before changing RF voltage"
    if {[catch {APScavget -list=[join $vacPVs ,] -pend=5 -printErrors} vacValues]} {
        return -code error "$vacValues"
    }
    foreach pv $vacPVs val $vacValues {
        set apsVacInit($pv) $val
    }
    if {$klyNum == 2} {
        if {[catch {APScavget -list=LRFSCS:SW10:P2M -num -pend=5 -printErrors} K2toWaterLoad]} {
            return -code error "Error reading LRFSCS:SW10:P2M: $K2toWaterLoad"
        }
        if {$K2toWaterLoad == 1} {
            set SCRsledForwardPower 99e99
        }
    }

    APSMpStep "Increase the LLRF amp drive"
    set checkWarn8 1
    while {1} {
        set pv1 L-${klystron}:LLRF:DSP:FF_AmpC
        set pv2 L-${klystron}:LLRF:KlyFwd_PwrRemoteM
        set pv3 L-${klystron}:LLRF:SD:Fwd_PkPwrRemoteM
        if {[catch {APScavget -list=${pv1},${pv2},${pv3} -pend=5 -printErrors} results]} {
            return -code error "Problem reading ${pv1}, $pv2 and ${pv3}: $results"
        }
        set amps [lindex $results 0]
        set kyPower [lindex $results 1]
        if {($amps < [expr $SCRllrfAmpDrive - .001]) && \
              ($kyPower < $SCRklystronForwardPower) && \
              ([lindex $results 2] < $SCRsledForwardPower)} {
            #APSMpStep "Verify LLRF is on"
            if {[catch {APSPEMCheckPVs -pvList "L${klyNum}:LL:lockRfCtrlBI L${klyNum}:LL:readyCC" \
                          -desiredList "1 1" \
                          -numerical 1 \
                          -message "${klystron} K400 Attempting to decrease LLRF attenuation.  LLRF is off."} result]} {
                return -code error $result
            }

            #APSMpStep "Check state"
            if {[catch {APSPEMCheckPVs -pvList L-${klystron}:Mod:State-RB \
                          -desiredList 13 \
                          -allowContinue 0 \
                          -allowRecheck 0 \
                          -message "${klystron} K400 Tripped out of Trig mode during LLRF attenuation change."} k400state]} {
                return -code error $k400state
            }

            #APSMpStep "Check system status"
            set pv L-${klystron}:Mod:Sts:I
            if {[catch {APSPEMCheckPVs -pvList $pv \
                          -desiredList "0 8" \
                          -or 1 \
                          -allowContinue 0 \
                          -allowRecheck 0 \
                          -message "${klystron} K400 Fault detected when verifying Trig mode"} result]} {
                return -code error $result
            }
            if {$checkWarn8 && ($result == 8)} {
                set checkWarn8 0
                set warningMessage "${klystron} K400 warning was detected when verifying Trig mode. You can continue to bring up the system but the RF Group must be informed of the warnings."
                set answer [APSPEMTKDialog .warningDialog \
                              -text "$warningMessage ${pv}=$result" \
                              -strings "Continue"]
            }
            
            set ratio [expr $kyPower / $SCRklystronForwardPower]
            if {$ratio < .67} {
                set amps [expr $amps + 1000]
            } elseif {$ratio < .90} {
                set amps [expr $amps + 500]
            } elseif {$ratio < .97} {
                set amps [expr $amps + 250]
            } else {
                set amps [expr $amps + 100]
            }
            if {$amps > $SCRllrfAmpDrive} {
                set amps $SCRllrfAmpDrive
            }
            APSMpStep "Set $klystron DLLRF amp to $amps"
            set pv L-${klystron}:LLRF:DSP:FF_AmpC
            if {[catch {APScavput -list=$pv=$amps -pend=5} result]} {
                APSMpReturn error "Problem setting ${pv}: $result"
            }
            APSWaitWithUpdate -waitSeconds 2

            #APSMpStep "Checking vacuum"
            if {0} {
                if {[catch {K400CheckVacuumAndWait -klystron $klystron -vacPVs $vacPVs} result]} {
                    return -code error $result
                }
            } else {
                if {$klyNum == 5} {
                    set L5 1
                } else {
                    set L5 0
                }
                if {$klyNum == 2} {
                    set L2 1
                } else {
                    set L2 0
                }
                if {[catch {LMOCS_Recover_CheckVacuumAndWait -vacPVs $vacPVs -interval 5 -L2 $L2 -L5 $L5 -VacuumLimit 1e-7 -readings 3 -interval 2} result]} {
                    set answer [APSPEMTKDialog .warningDialog \
                                  -text "Vacuum levels are too high. $result" \
                                  -strings {"Rebaseline and Recheck" "Abort Procedure"}]
                    if {$answer == 1} {
                        return -code error $result
                    }
                    if {[catch {APScavget -list=[join $vacPVs ,] -pend=5 -printErrors} vacValues]} {
                        return -code error "$vacValues"
                    }
                    foreach pv $vacPVs val $vacValues {
                        set apsVacInit($pv) $val
                    }
                }
            }
        } else {
            break
        }
    }
}

proc TurnOnK400RampCCPS {args} {
    set klystron K2
    set ccpsSCRsetpoint 1200
    set ccpsTarget 1000
    set ccpsStepSize 10
    set klyForwardPowerTarget 300000
    set sledExpectedMinMultiplier 4
    set final 0
    APSStrictParseArguments {klystron ccpsSCRsetpoint ccpsTarget ccpsStepSize klyForwardPowerTarget sledExpectedMinMultiplier final}
    set klyNum [string range $klystron 1 1]
    set checkWarn8 1

    set useDLLRF 0
    if {$klystron == "K2"} {
        set useDLLRF 0
        if {[catch {APScavget -list=L-${klystron}:LLRF:digitalSystemInUse -pend=5 -num -printErrors} useDLLRF]} {
            return -code error "Error checking for analog or digital LLRF: $useDLLRF"
        }
    }


    if {[catch {K400GetVacuumPVs -klystron $klystron} vacPVs]} {
        return -code error "$vacPVs"
    }
    global apsVacInit
    APSMpStep "Reading vacuum PVs before changing RF voltage"
    if {[catch {APScavget -list=[join $vacPVs ,] -pend=5 -printErrors} vacValues]} {
        return -code error "$vacValues"
    }
    foreach pv $vacPVs val $vacValues {
        set apsVacInit($pv) $val
    }

    set pv L-${klystron}:Mod-CCPS:E:SP
    if {[catch {APScavget -list=$pv -pend=5 -printErrors} setpoint]} {
        return -code error "Problem reading ${pv}: $setpoint"
    }
    while {$setpoint < $ccpsTarget} {
        APSMpStep "Compare the current CCPS setpoint to the desired SCR setpoint value"
        if {$setpoint >= $ccpsSCRsetpoint} {
            if {$final == 1} {
                set warningMessage "${klystron} K400 CCPS setpoint specified in the SCR is less than the normal 1200. Recovery will be done at this lower value."
                set answer [APSPEMTKDialog .warningDialog \
                              -text "$warningMessage" \
                              -strings "Continue"]
            }
            break
        }

        APSMpStep "Verify LLRF is on"
        if {[catch {APSPEMCheckPVs -pvList "L${klyNum}:LL:lockRfCtrlBI L${klyNum}:LL:readyCC" \
                      -desiredList "1 1" \
                      -numerical 1 \
                      -message "${klystron} K400 Attempting to ramp CCPS to ${ccpsTarget}.  LLRF is off."} result]} {
            return -code error $result
        }
        
        APSMpStep "Check state"
        if {[catch {APSPEMCheckPVs -pvList L-${klystron}:Mod:State-RB \
                      -desiredList 13 \
                      -allowContinue 0 \
                      -allowRecheck 0 \
                      -message "${klystron} K400 Tripped out of Trig mode during CCPS ramp up to ${ccpsTarget}"} k400state]} {
            return -code error $k400state
        }

        APSMpStep "Check system status"
        set pv L-${klystron}:Mod:Sts:I
        if {[catch {APSPEMCheckPVs -pvList $pv \
                      -desiredList "0 8" \
                      -or 1 \
                      -allowContinue 0 \
                      -allowRecheck 0 \
                      -message "${klystron} K400 Fault detected when verifying Trig mode"} result]} {
            return -code error $result
        }
        if {$checkWarn8 && ($result == 8)} {
            set checkWarn8 0
            set warningMessage "${klystron} K400 warning was detected when verifying Trig mode. You can continue to bring up the system but the RF Group must be informed of the warnings."
            set answer [APSPEMTKDialog .warningDialog \
                          -text "$warningMessage ${pv}=$result" \
                          -strings "Continue"]
        }
        
        APSMpStep "Raise CCPS setpoint by ${ccpsStepSize}V"
        set pv L-${klystron}:Mod-CCPS:E:SP
        if {[catch {APScavput -list=$pv=$ccpsStepSize -deltamode -pend=5} result]} {
            return -code error "Problem setting ${pv}: $result"
        }
        APSWaitWithUpdate -waitSeconds 2

        APSMpStep "Verify CCPS setpoint and readback match"
        if {[catch {APSPEMCheckPVs -pvList "L-${klystron}:Mod-CCPS:E:SP L-${klystron}:Mod-CCPS:E:I" \
                      -desiredList ".1" \
                      -absDifference 1 \
                      -message "${klystron} K400 CCPS is not following setpoint changes to $ccpsTarget"} result]} {
            return -code error $result
        }

        APSMpStep "Checking vacuum"
        if {0} {
            if {[catch {K400CheckVacuumAndWait -klystron $klystron -vacPVs $vacPVs} result]} {
                return -code error $result
            }
        } else {
            if {$klyNum == 5} {
                set L5 1
            } else {
                set L5 0
            }
            if {$klyNum == 2} {
                set L2 1
            } else {
                set L2 0
            }
            if {[catch {LMOCS_Recover_CheckVacuumAndWait -vacPVs $vacPVs -interval 5 -L2 $L2 -L5 $L5 -VacuumLimit 1e-7 -readings 1} result]} {
                set answer [APSPEMTKDialog .warningDialog \
                              -text "Vacuum levels are too high. $result" \
                              -strings {"Rebaseline and Recheck" "Abort Procedure"}]
                if {$answer == 1} {
                    return -code error $result
                }
                if {[catch {APScavget -list=[join $vacPVs ,] -pend=5 -printErrors} vacValues]} {
                    return -code error "$vacValues"
                }
                foreach pv $vacPVs val $vacValues {
                    set apsVacInit($pv) $val
                }
            }
        }

        set pv L-${klystron}:Mod-CCPS:E:SP
        if {[catch {APScavget -list=$pv -pend=5 -printErrors} setpoint]} {
            return -code error "Problem reading ${pv}: $setpoint"
        }
    }

    APSMpStep "Pause for 1 minute"
    APSWaitWithUpdate -waitSeconds 60

    APSMpStep "Checking vacuum"
    if {0} {
        if {[catch {K400CheckVacuumAndWait -klystron $klystron -vacPVs $vacPVs} result]} {
            return -code error $result
        }
    } else {
        if {$klyNum == 2} {
            set L2 1
        } else {
            set L2 0
        }
        if {$klyNum == 5} {
            set L5 1
        } else {
            set L5 0
        }
        if {[catch {LMOCS_Recover_CheckVacuumAndWait -vacPVs $vacPVs -interval 5 -L2 $L2 -L5 $L5 -VacuumLimit 1e-7} result]} {
            set answer [APSPEMTKDialog .warningDialog \
                          -text "Vacuum levels are too high. $result" \
                          -strings {"Rebaseline and Recheck" "Abort Procedure"}]
            if {$answer == 1} {
                return -code error $result
            }
            if {[catch {APScavget -list=[join $vacPVs ,] -pend=5 -printErrors} vacValues]} {
                return -code error "$vacValues"
            }
            foreach pv $vacPVs val $vacValues {
                set apsVacInit($pv) $val
            }
        }
    }

    if {$useDLLRF} {
        if {$klyNum == 2} {
            if {[catch {APScavget -list=LRFSCS:SW10:P2M -num -pend=5 -printErrors} K2toWaterLoad]} {
                return -code error "Error reading LRFSCS:SW10:P2M: $K2toWaterLoad"
            }
            if {$K2toWaterLoad == 1} {
                return
            }
        }
    }
    
    APSMpStep "Assess power readings"
    if {[catch {APSPEMCheckPVs -pvList L-${klystron}:LLRF:KlyFwd_PwrRemoteM \
                  -desiredList $klyForwardPowerTarget \
                  -greaterThanOrEqualTo 1 \
                  -message "${klystron} K400 Klystron forward power readback failed to reach $klyForwardPowerTarget W or greater."} result]} {
        return -code error $result
    }
    set pv L-${klystron}:LLRF:KlyFwd_PwrRemoteM
    if {[catch {APScavget -list=$pv -pend=5 -printErrors} klyForwardPower]} {
        return -code error "Problem reading ${pv}: $klyForwardPower"
    }
    if {[catch {APSPEMCheckPVs -pvList L-${klystron}:LLRF:SD:Fwd_PkPwrRemoteM \
                  -desiredList [expr $klyForwardPower * $sledExpectedMinMultiplier] \
                  -greaterThanOrEqualTo 1 \
                  -message "${klystron} K400 SLED power readback failed to reach $sledExpectedMinMultiplier times or greater the klystron forward power at CCPS ${klyForwardPower}."} result]} {
        return -code error $result
    }
}

proc K400GetVacuumPVs {args} {
    set klystron K2
    APSStrictParseArguments {klystron}
    set klyNum [string range $klystron 1 1]
    set RF L$klyNum
    
    if {[catch {exec sdds2stream /home/helios/oagData/linac/Linac_RF_Recovery/${RF}vacuum.mon -col=ControlName} vacPVs]} {
        return -code error "$vacPVs"
    }
    return $vacPVs
}

proc K400CheckVacuum {args} {
    set klystron K2
    set vacuumLimit 1.0e-7
    set vacPVs ""
    APSStrictParseArguments {klystron vacuumLimit vacPVs}

    while {1} {
        if {[catch {APScavget -list=[join $vacPVs ,] -pend=5 -printErrors} vacValues]} {
            return -code error "$vacValues"
        }
        set highPVs ""
        foreach pv $vacPVs value $vacValues {
            if {$value > $vacuumLimit} {
                lappend highPVs $pv
            }
        }
        if {[llength $highPVs] > 0} {
            set answer [APSPEMTKDialog .warningDialog \
                          -text "[join $highPVs ,] vacuum is too high" \
                          -strings {Continue Recheck "Abort Procedure"}]
            if {$answer == 0} {
                return
            } elseif {$answer == 2} {
                return -code error "${klystron} K400 Vacuum check failed for: [join $highPVs ,]"
            }
        } else {
            return
        }
    }
}

proc K400CheckVacuumAndWait {args} {
    set klystron K2
    set vacuumLimit 1.0e-7
    set vacPVs ""
    set timeLimit 300
    APSStrictParseArguments {klystron vacuumLimit vacPVs timeLimit}

    set maxSteps [expr round($timeLimit / 5.0)]
    set step 0
    while {$step < $maxSteps} {
        incr step
        if {[catch {APScavget -list=[join $vacPVs ,] -pend=5 -printErrors} vacValues]} {
            return -code error "$vacValues"
        }
        if {$step >= $maxSteps} {
            set highPVs ""
            foreach pv $vacPVs value $vacValues {
                if {$value > $vacuumLimit} {
                    lappend highPVs $pv
                }
            }
            if {[llength $highPVs] == 0} {
                return
            }
            set answer [APSPEMTKDialog .warningDialog \
                          -text "[join $highPVs ,] vacuum is too high" \
                          -strings {Continue Recheck "Abort Procedure"}]
            if {$answer == 0} {
                return
            } elseif {$answer == 2} {
                return -code error "${klystron} K400 Vacuum check failed for: [join $highPVs ,]"
            }
            set step 0
            APSWaitWithUpdate -waitSeconds 5
            continue
        }
        foreach value $vacValues {
            if {$value > $vacuumLimit} {
                APSMpStep "Pausing for vacuum issue"
                APSWaitWithUpdate -waitSeconds 5
                continue
            }
        }
        return
    }
}

proc K400LowerCCPSToDefaultLowValue {args} {
    set klystron K2
    APSStrictParseArguments {klystron}
    if {$klystron == "K2"} {
        set ccpsStepSize 10
    }
    set pv L-${klystron}:Mod:CcpsTripRstValue
    if {[catch {APScavget -list=$pv -pend=5 -printErrors} CcpsTripRstValue]} {
        return -code error "Problem reading ${pv}: $CcpsTripRstValue"
    }
    set firstPass 1
    while {1} {
        if {[catch {APSPEMCheckPVs -pvList "L-${klystron}:Mod-CCPS:E:I L-${klystron}:Mod:CcpsTripRstValue" \
                      -desiredList .1 \
                      -difference 1 \
                      -noDialogs 1} diff]} {
            return -code error $diff
        }
        if {$diff > .1} {
            if {!$firstPass} {
                set answer [APSPEMTKDialog .warningDialog \
                              -text "${klystron} K400 Failed to set CCPS setpoint to the default low setpoint." \
                              -strings {Continue Recheck "Abort Procedure"}]
                if {$answer == 0} {
                    break
                } elseif {$answer == 2} {
                    return -code error "Aborted"
                }
            } else {
                set firstPass 0
            }
            APSMpStep "Lower CCPS setpoint to near default value"
            set pv L-${klystron}:Mod-CCPS:E:SP
            if {[catch {APScavget -list=$pv -pend=5 -printErrors} result]} {
                return -code error "Problem reading ${pv}: $result"
            }
            set steps [expr int(($result - $CcpsTripRstValue) / $ccpsStepSize)]
            if {$steps > 1000} {
                return -code error "Problem calculating CCPS readback ramp steps"
            }
            while {$steps > 0} {
                set pv L-${klystron}:Mod-CCPS:E:SP
                if {[catch {APScavput -list=$pv=-$ccpsStepSize -deltamode -pend=5} result]} {
                    return -code error "Problem setting ${pv}: $result"
                }
                APSWaitWithUpdate -waitSeconds 1
                incr steps -1
            }
            
            APSMpStep "Set CCPS setpoint to default value"
            set pv L-${klystron}:Mod-CCPS:E:SP
            if {[catch {APScavput -list=$pv=$CcpsTripRstValue -pend=5} result]} {
                return -code error "Problem setting ${pv}: $result"
            }
            APSWaitWithUpdate -waitSeconds 1
        } else {
            break
        }
    }
}

proc TurnOnK400Info {} {
    return "K400 modulator startup PEM."
}

proc TurnOnK400Dialog {frame} {
    global TurnOnK400
    
    APSAddSCRDialog .scr -parent $frame -system LPL -arrayName TurnOnK400 \
      -defaultFile $TurnOnK400(ShortFilename)
}

proc TurnOnK400 {args} {
    set klystron K2
    set SCRFile ""
    APSStrictParseArguments {klystron SCRFile}
    set ShortFilename [file tail $SCRFile]
    if {$klystron == ""} {
        APSMpReturn error "TurnOnK400: No klystron selected"
    } 
    set klyNum [string range $klystron 1 1]

    global execMode TurnOnK400
    if {$execMode == "Manual"} {
	set prefix "Press Continue to "
    } else {
	set prefix ""
    }
    if {![file exists $SCRFile]} {
        APSMpStep init -promptDialog "TurnOnK400Dialog" -vars "ShortFilename"
    }
    if {![string length $ShortFilename]} {
        APSMpReturn error "TurnOnK400: SCR file not choosen!"
    }
    if {![file exists /home/helios/oagData/SCR/snapshots/LPL/$ShortFilename]} {
        APSMpReturn error "SCR file $ShortFilename not found"
    }

    if {[catch {exec sddsselect /home/helios/oagData/SCR/snapshots/LPL/$ShortFilename \
                  /home/helios/oagData/pem/linac/filterFile -match=ControlName -pipe=out | \
                  sdds2stream -column=ControlName,ValueString -pipe=in} results]} {
	APSMpReturn error "TurnOnK400: Invalid SCR file"
    }

    set ccpsSCRsetpoint 1200
    set cvdVoltageSCR 235
    foreach {controlName valueString} $results {
	if {$controlName == "L-${klystron}:Mod-CCPS:E:SP"} {
	    set ccpsSCRsetpoint $valueString
        }
    }

    APSMpStep "${prefix}Run TurnOnK400InitialChecks"
    if {[catch {TurnOnK400InitialChecks -klystron $klystron} result]} {
        APSMpReturn error "TurnOnK400: $result"
    }
    APSMpStep "${prefix}Run TurnOnK400BringUpToStandby"
    if {[catch {TurnOnK400BringUpToStandby -klystron $klystron} result]} {
        APSMpReturn error "TurnOnK400: $result"
    }
    APSMpStep "${prefix}Run TurnOnK400BringUpToHVMode"
    if {[catch {TurnOnK400BringUpToHVMode -klystron $klystron} result]} {
        APSMpReturn error "TurnOnK400: $result"
    }
    APSMpStep "${prefix}Run TurnOnK400BringUpToTrigMode"
    if {[catch {TurnOnK400BringUpToTrigMode -klystron $klystron} result]} {
        APSMpReturn error "TurnOnK400: $result"
    }
    APSMpStep "${prefix}Run TurnOnK400BringUpRFPower"
    if {[catch {TurnOnK400BringUpRFPower -klystron $klystron -ccpsSCRsetpoint $ccpsSCRsetpoint} result]} {
        APSMpReturn error "TurnOnK400: $result"
    }
       
    if {$klystron == "K5"} {
        APSMpStep "${prefix}Suspend X LTP ControlLaw" -desc "Suspend X LTP ControlLaw"
        if [catch {APSMpLSuspendResumeRunControl \
                     -value "Suspend" \
                     -name "LTPControlLaw" \
                     -group "RunControlGroup" \
                     -deviceList X} result] {
        }
        APSMpStep "${prefix}Suspend Y LTP ControlLaw" -desc "Suspend X LTP ControlLaw"
        if [catch {APSMpLSuspendResumeRunControl \
                     -value "Suspend" \
                     -name "LTPControlLaw" \
                     -group "RunControlGroup" \
                     -deviceList Y} result] {
        }
    }
    
    #This ultimately calls K400DecreaseAttnInTrigState
    exec runProcGUI LMOCS_Recover -L${klyNum} 1 -SCRFile /home/helios/oagData/SCR/snapshots/LPL/$ShortFilename &

    APSMpStep "${prefix}Finished TurnOnK400 for $klystron"
    APSMpReturn ok
}

proc TurnOffK400Info {} {
    return "K400 modulator startup PEM."
}

proc TurnOffK400Dialog {frame} {
    global TurnOffK400
    
    checkbutton $frame.filament -text "Include Filament" \
      -variable $TurnOffK400(includeFilament) -compound right -image ::tk::icons::question
    pack $frame.filament -padx 80 -pady 100
}

proc TurnOffK400 {args} {
    set klystron K2
    set includeFilament 0
    set leaveInStandby 0
    set leaveAfterFullyAttenuated 0
    set noDialog 0
    set useDLLRF 0
    APSStrictParseArguments {klystron includeFilament leaveInStandby leaveAfterFullyAttenuated noDialog}
    if {$klystron == "K2"} {
        set useDLLRF 0
        if {[catch {APScavget -list=L-${klystron}:LLRF:digitalSystemInUse -pend=5 -num -printErrors} useDLLRF]} {
            APSMpReturn error "Error checking for analog or digital LLRF: $useDLLRF"
        }
    }
    if {$useDLLRF} {
        if {$klystron == "K2"} {
            set fullyAttenuatedAmp 4000
        }
    } else {
        if {$klystron == "K2"} {
            set attenuatorVoltageFullyAttenuated 3.2
        }
    }
    if {$klystron == ""} {
        APSMpReturn error "TurnOnK400: No klystron selected"
    } 
    set klyNum [string range $klystron 1 1]

    global execMode TurnOnK400
    if {$execMode == "Manual"} {
	set prefix "Press Continue to "
    } else {
	set prefix ""
    }

    if {($leaveAfterFullyAttenuated == 0) && ($leaveInStandby == 0) && ($noDialog == 0)} {
        APSMpStep init -promptDialog "TurnOffK400Dialog" -vars "includeFilament"
    }

    APSMpStep "Check state"
    set pv L-${klystron}:Mod:State-RB
    if {[catch {APScavget -list=$pv -pend=5} k400state]} {
        APSMpReturn error "Problem reading ${pv}: $k400state"
    }
    if {$k400state >= 9} {
        APSMpStep "Ensure the CCPS readback is set to the default low value, compare to desired value"
        if {[catch {K400LowerCCPSToDefaultLowValue -klystron $klystron} result]} {
            APSMpReturn error $result
        }
    }
    
    APSMpStep "Check if LLRF is on"
    if {[catch {APSPEMCheckPVs -pvList "L${klyNum}:LL:lockRfCtrlBI L${klyNum}:LL:readyCC" \
                  -desiredList "0 0" \
                  -numerical 1 \
                  -noDialogs 1} result]} {
        APSMpReturn error $result
    }

    if {([lindex $result 0] != 0) || ([lindex $result 1] != 0)} {
        APSMpStep "Turn off LLRF"
        set pv L${klyNum}:LL:lockRfOffBO
        if {[catch {APScavput -list=$pv=1 -num -pend=5} result]} {
            APSMpReturn error "Problem setting ${pv}: $result"
        }
        APSWaitWithUpdate -waitSeconds 3
        APSMpStep "Verify LLRF is off"
        if {[catch {APSPEMCheckPVs -pvList "L${klyNum}:LL:lockRfCtrlBI L${klyNum}:LL:readyCC" \
                      -desiredList "0 0" \
                      -numerical 1 \
                      -message "${klystron} K400 LLRF failed to turn off. Turn off LLRF and check again."} result]} {
            APSMpReturn error $result
        }
    }

    if {$useDLLRF} {
        APSMpStep "Lower $klystron DLLRF amp to the fully attenuated setting"
        set pv L-${klystron}:LLRF:DSP:FF_AmpC
        if {[catch {APScavput -list=$pv=$fullyAttenuatedAmp -pend=5} result]} {
            APSMpReturn error "Problem setting ${pv}: $result"
        }
        APSWaitWithUpdate -waitSeconds 2
    } else {
        APSMpStep "Set Attn Ctrl voltage to ${attenuatorVoltageFullyAttenuated}V or higher"
        if {[catch {K400IncreaseAttn -klystron $klystron \
                      -attenuatorVoltageTarget $attenuatorVoltageFullyAttenuated} result]} {
            APSMpReturn error $result
        }
        
        if {$leaveAfterFullyAttenuated} {
            APSMpReturn ok
        }
    }

    APSMpStep "Check state"
    set pv L-${klystron}:Mod:State-RB
    if {[catch {APScavget -list=$pv -pend=5} k400state]} {
        APSMpReturn error "Problem reading ${pv}: $k400state"
    }

    if {$k400state > 9} {
        APSMpStep "Select HV mode"
        set pv L-${klystron}:Mod:State-Sel
        if {[catch {APScavput -list=$pv=2 -pend=5} result]} {
            APSMpReturn error "Problem setting ${pv}: $result"
        }
        APSMpStep "Pausing 30 seconds"
        APSWaitWithUpdate -waitSeconds 30

        APSMpStep "Check state"
        if {[catch {APSPEMCheckPVs -pvList L-${klystron}:Mod:State-RB \
                      -desiredList 9 \
                      -message "${klystron} K400 Switch to HV mode failed."} k400state]} {
            APSMpReturn error $k400state
        }
    }

    if {$k400state > 5} {
        APSMpStep "Check that CVD is reading 0"
        if {[catch {APSPEMCheckPVs -pvList L-${klystron}:Mod-CVD:E:I \
                      -desiredList .1 \
                      -lessThan 1 \
                      -message "${klystron} K400 CVD readback issue detected, should be 0 in HV mode."} result]} {
            APSMpReturn error $result
        }

        APSMpStep "Select Stand-by mode"
        set pv L-${klystron}:Mod:State-Sel
        if {[catch {APScavput -list=$pv=1 -pend=5} result]} {
            APSMpReturn error "Problem setting ${pv}: $result"
        }
        APSMpStep "Pausing 40 seconds"
        APSWaitWithUpdate -waitSeconds 40

        APSMpStep "Check state"
        if {[catch {APSPEMCheckPVs -pvList L-${klystron}:Mod:State-RB \
                      -desiredList 5 \
                      -message "${klystron} K400 Switch to Stand-By mode failed."} k400state]} {
            APSMpReturn error $k400state
        }
    }

    if {$leaveInStandby} {
        APSMpReturn ok
    }

    if {$k400state > 1} {
        if {$includeFilament} {
            APSMpStep "Turning off filament heater"
            set answer [APSPEMTKDialog .warningDialog \
                          -text "Shutting off klystron $klystron filament heater will result in a one hour warm-up time upon restart. Do you want to continue?" \
                          -strings {Continue Skip}]
            if {$answer == 0} {
                APSMpStep "Select Off mode"
                set pv L-${klystron}:Mod:State-Sel
                if {[catch {APScavput -list=$pv=0 -pend=5} result]} {
                    APSMpReturn error "Problem setting ${pv}: $result"
                }
                APSMpStep "Pausing 140 seconds"
                APSWaitWithUpdate -waitSeconds 140
                
                APSMpStep "Check state"
                if {[catch {APSPEMCheckPVs -pvList L-${klystron}:Mod:State-RB \
                              -desiredList 1 \
                              -message "${klystron} K400 Switch to Off mode failed."} k400state]} {
                    APSMpReturn error $k400state
                }
            }
        } else {
            APSMpStep "Check state"
            if {[catch {APSPEMCheckPVs -pvList L-${klystron}:Mod:State-RB \
                          -desiredList 5 \
                          -message "${klystron} K400 Switch to Stand-By mode failed."} k400state]} {
                APSMpReturn error $k400state
            }
        }
    }

    APSMpStep "${prefix}Finished TurnOffK400 for $klystron"
    APSMpReturn ok
}


