# Enables selected booster power supply ramps to standby level if the
# ramps are disabled.  The AFG gain is first set to the standby
# level and the supply ramp is enabled.  If disabling selected magnet
# ramps is desired, the AFG gain is first set to the standby level
# then the ramp is disabled and the supply is left on.

proc APSMpBoosterPSEnableDisableRamps {args} {

    global status
    
    set magnet ""
    set state1 disable
    set coldStart 0
    set standbyGainLevel 0.4
    set BM 0
    set QF 0
    set QD 0
    set SF 0
    set SD 0
    set BMgain $standbyGainLevel
    set QFgain $standbyGainLevel
    set QDgain $standbyGainLevel
    set SFgain $standbyGainLevel
    set SDgain $standbyGainLevel

    APSStrictParseArguments {magnet state1 coldStart standbyGainLevel BM QF QD SF SD BMgain QFgain QDgain SFgain SDgain}

    if {[llength $magnet]} {
        set $magnet 1
    }

    set magnets ""
    foreach m "BM QF QD SF SD" {
        if {[set $m]} {
            append magnets "$m "
        }
    }

    if {![llength $magnets]} {
        APSMpReturn ok
    }

    if {$standbyGainLevel > 1 || $standbyGainLevel < 0} {
        APSMpReturn error "Power supply gain can only be set in the range 0 <= gain <= 1."
    }

    set magnetList ""
    foreach magnet $magnets {
        set magnetIndex [lsearch -exact "BM QF QD SF SD" ${magnet}]
        APSMpStep "Getting rampstate for booster magnet power supply $magnet..."
        if {[catch {APScavget -list=It:Ddg4chan${magnetIndex}.GATE -pendIoTime=20} rampstate]} {
            APSMpReturn error "APSMpBoosterPSEnableDisableRamps: $rampstate"
        }
        #Select a subset of PS that are not already in the desired state
        if {($state1 == "enable") && ($rampstate =="Disabled")} {
            append magnetList "$magnet "
        } elseif {($state1 == "disable") && ($rampstate == "Enabled")} {
            append magnetList "$magnet "
        } else {
            set $magnet 0
        }
    }
    set magnets $magnetList
    if {![llength $magnets]} {
        APSMpReturn ok
    }
    #Disable slope and zero
    APSMpStep "Disable slope and zero for $magnets" -desc "Disable slope and zero for magnets"
    if {[catch {APSMpBoosterDisableSlopeAndZero -BM $BM -QF $QF -QD $QD -SF $SF -SD $SD} results]} {
        if {[APSPEMTKDialog .warningDialog -text "APSMpBoosterPSEnableDisableRamps: Problem occurred while disabling slope and zero\n$results"] == 1} {
            APSMpReturn error "APSMpBoosterPSEnableDisableRamps: $results"
        }
    }
    #Set gain to standby or 0 if specified
    APSMpStep  "Setting gain factor for $magnets to standby or 0 if turning off while in DC mode."
    if {[catch {APSMpBoosterPSSetGain -BM $BM -QF $QF -QD $QD -SF $SF -SD $SD -BMgain $BMgain -QFgain $QFgain -QDgain $QDgain -SFgain $SFgain -SDgain $SDgain} results]} {
        if {[APSPEMTKDialog .warningDialog -text "APSMpBoosterPSEnableDisableRamps: Problem occurred while setting gain to $magnets to proper gain\n$results"] == 1} {
            APSMpReturn error "APSMpBoosterPSEnableDisableRamps: $results"
        }
    }
    
    APSWaitWithUpdate -waitSeconds 2
    #Load safety ramps if needed
    if {$state1=="enable"} {
	if {$coldStart == 1} {
	    APSMpStep "Loading Safety Ramps"
	    if {[catch {loadSafetyRamps2 -BM $BM -QF $QF -QD $QD -SF $SF -SD $SD} results]} {
                if {[APSPEMTKDialog .warningDialog -text "APSMpBoosterPSEnableDisableRamps: Problem occurred while loading safety ramps\n$results"] == 1} {
                    APSMpReturn error "APSMpBoosterPSEnableDisableRamps: $results"
                }
	    }
	}
    }
    foreach magnet $magnets {
        set magnetIndex [lsearch -exact "BM QF QD SF SD" ${magnet}]
        if {$state1=="enable"} {
            #Enable disabled ramps
            APSMpStep  "Enabling ${magnet} power supply ramp."
            if {[catch {APScavput -list=It:Ddg4chan${magnetIndex}.GATE=Enabled -pendIoTime=20} results]} {
                if {[APSPEMTKDialog .warningDialog -text "APSMpBoosterPSEnableDisableRamps: Channel access problem for It:Ddg4chan${magnetIndex}.GATE\n$results"] == 1} {
                    APSMpReturn error "APSMpBoosterPSEnableDisableRamps: $results"
                }
            }
        } elseif {$state1=="disable"} {
            #Disable enabled ramps
            APSMpStep  "Disabling ${magnet} power supply ramp."
            if {[catch {APScavput -list=It:Ddg4chan${magnetIndex}.GATE=Disabled -pendIoTime=20} results]} {
                if {[APSPEMTKDialog .warningDialog -text "APSMpBoosterPSEnableDisableRamps: Channel access problem for It:Ddg4chan${magnetIndex}.GATE\n$results"] == 1} {
                    APSMpReturn error "APSMpBoosterPSEnableDisableRamps: $results"
                }
            }
        }
    }
    APSWaitWithUpdate -waitSeconds 2
    APSMpReturn ok
}

#Loads selected booster magnet safety ramps.

proc loadSafetyRamps2 {args} {
    
    global status apsNetworkDomain
    
    set BM 0
    set QF 0
    set QD 0
    set SF 0
    set SD 0
    set magvarlist "BM QF QD SF SD"
    set magnetlist "BM QF QD SF SD"
    set noWarning 0

    APSStrictParseArguments {BM QF QD SF SD noWarning}
    
    set listindex 0
    set selectlist ""
    set safetyrampdir "/home/helios/oagData/booster/ramps"
    set notInAutoList ""
    
    if {([string compare $apsNetworkDomain "accel.ntw0rk"] == 0) || ([string compare $apsNetworkDomain "aps4.anl.gov"] == 0)} {
        foreach magnet $magnetlist {
            if {[set $magnet]==1} {
                APSMpStep "Loading safety ramp for $magnet..."
                lappend selectlist $magnet
                if {[catch {APSFileCopy -from ${safetyrampdir}/current/${magnet}Vref.afg100 -to ${safetyrampdir}/current/${magnet}Vref.afg100.old} results]} {
                    if {[APSPEMTKDialog .warningDialog -text "loadSafetyRamps2: Problem copying file\n$results"] == 1} {
                        APSMpReturn error "loadSafetyRamps2: $results"
                    }                    
                }
                if {[catch {APSFileCopy -from ${safetyrampdir}/safety/${magnet}Vref.afg100 -to ${safetyrampdir}/current/${magnet}Vref.afg100} results]} {
                    if {[APSPEMTKDialog .warningDialog -text "loadSafetyRamps2: Problem copying file\n$results"] == 1} {
                        APSMpReturn error "loadSafetyRamps2: $results"
                    }                    
                }
                if {[catch {exec rampload ${safetyrampdir}/current/${magnet}Vref.afg100} results]} {
                    if {[APSPEMTKDialog .warningDialog -text "loadSafetyRamps2: error running rampload ${safetyrampdir}/current/${magnet}Vref.afg100\n$results"] == 1} {
                        APSMpReturn error "loadSafetyRamps2: $results"
                    }
                }
                if {[catch {APScavget -list=B:${magnet}:VoltageRT.MODE} autoState]} {
                    APSMpReturn error "loadSafetyRamps2: $autoState"
                }
                if {$autoState!="AUTO"} {
                    lappend notInAutoList $magnet
                }
                APSWaitWithUpdate -waitSeconds 2
            }
            incr listindex
        }
        if {$selectlist!="" && $notInAutoList==""} { 
            APSMpStep "Safety ramp(s) for $selectlist loaded."
        } elseif {$selectlist!="" && $notInAutoList!=""} {
            if {!$noWarning} {
                APSMpStep "Safety ramp(s) for $selectlist loaded.  Auto mode NOT activated for $notInAutoList."
                APSAlertBox .alert -errorMessage "Warning:  Auto mode NOT activated for $notInAutoList."
            }
        }
    }
    APSMpReturn ok
}

proc APSMpBoosterResetAfterIOCReboot {args} {

    set BM 0
    set QF 0
    set QD 0
    set SF 0
    set SD 0
    set dc(BM) 0
    set dc(QF) 0
    set dc(QD) 0
    set dc(SF) 0
    set dc(SD) 0
    set nondc(BM) 0
    set nondc(QF) 0
    set nondc(QD) 0
    set nondc(SF) 0
    set nondc(SD) 0
    set magnetlist "BM QF QD SF SD"
    
    APSStrictParseArguments {BM QF QD SF SD}
    
    set selectlist ""
    set getStateCommand ""
    set dcinitCommands ""
    set dcautoCommands ""
    set nondcinitCommands ""
    set nondcautoCommands ""

    APSMpStep "Checking if auto mode is not activated"
    foreach magnet $magnetlist {
	lappend getStateCommand "B:${magnet}:VoltageRT.MODE"
    }
    if {[catch {APScavget -list=[join $getStateCommand ,] -num -pend=20} results]} {
	APSMpReturn error "APSMpBoosterResetAfterIOCReboot: $results"
    }
    foreach result $results magnet $magnetlist {
	if {([set $magnet]) && ($result != 0)} {
	    lappend selectlist $magnet
	} else {
            set $magnet 0
        }
    }
    if {$selectlist!=""} {
        set dclist ""
        set nondclist ""
        foreach magnet $selectlist {
            set state [APSMpBoosterPSCheckForValidRampControlState -magnet $magnet]
            if {$state != 1} {
                lappend dclist $magnet
                set dc($magnet) 1
                lappend dcinitCommands "B:${magnet}:VoltageRT.MODE=INIT"
                lappend dcautoCommands "B:${magnet}:VoltageRT.MODE=AUTO"
            } else {
                lappend nondclist $magnet
                set nondc($magnet) 1
                lappend nondcinitCommands "B:${magnet}:VoltageRT.MODE=INIT"
                lappend nondcautoCommands "B:${magnet}:VoltageRT.MODE=AUTO"
            }
        }


        if {$nondclist!=""} {
            #Disable Ramps
            foreach magnet $nondclist {
                set magnetIndex [lsearch -exact "BM QF QD SF SD" ${magnet}]
                APSMpStep  "Disabling ${magnet} power supply ramp."
                if {[catch {APScavput -list=It:Ddg4chan${magnetIndex}.GATE=Disabled -pendIoTime=20} results]} {
                    if {[APSPEMTKDialog .warningDialog -text "APSMpBoosterResetAfterIOCReboot: Channel access problem for It:Ddg4chan${magnetIndex}.GATE\n$results"] == 1} {
                        APSMpReturn error "APSMpBoosterResetAfterIOCReboot: $results"
                    }
                }
            }
            APSWaitWithUpdate -waitSeconds 2
            
            #Turn power supplies off
            APSMpStep "Turn power supplies off" -proc APSMpBoosterPSOnOff
            if {[catch {APSMpBoosterPSOnOff -BM $nondc(BM) -QF $nondc(QF) -QD $nondc(QD) -SF $nondc(SF) -SD $nondc(SD) -state1 off} results]} {
                if {[APSPEMTKDialog .warningDialog -text "APSMpBoosterResetAfterIOCReboot: Problem occurred while turning power supplies off\n$results"] == 1} {
                    APSMpReturn error "APSMpBoosterResetAfterIOCReboot: $results"
                }
            }
            APSWaitWithUpdate -waitSeconds 2
            
            APSMpStep "Setting to init mode" -desc "Setting to init mode if not in auto mode"
            if {[catch {APScavput -list=[join $nondcinitCommands ,] -pend=20} results]} {
                APSMpReturn error "APSMpBoosterResetAfterIOCReboot: $results"
            }
            APSSetVarAndUpdate status "$nondclist AFG(s) initialized."
            
            APSWaitWithUpdate -waitSeconds 2
            APSMpStep "Loading safety ramps"
            if {[catch {loadSafetyRamps2 -BM $nondc(BM) -QF $nondc(QF) -QD $nondc(QD) -SF $nondc(SF) -SD $nondc(SD) -noWarning 1} results]} {
                APSMpReturn error "APSMpBoosterResetAfterIOCReboot: $results"
            }
            APSWaitWithUpdate -waitSeconds 2
            
            APSMpStep "Setting to auto mode"
            if {[catch {APScavput -list=[join $nondcautoCommands ,] -pend=20} results]} {
                APSMpReturn error "APSMpBoosterResetAfterIOCReboot: $results"
            }
            APSWaitWithUpdate -waitSeconds 2

            #Set gain to .4
            APSMpStep  "Setting gain factor for $nondclist to .4"
            if {[catch {APSMpBoosterPSSetGain -BM $nondc(BM) -QF $nondc(QF) -QD $nondc(QD) -SF $nondc(SF) -SD $nondc(SD) -value .4} results]} {
                if {[APSPEMTKDialog .warningDialog -text "APSMpBoosterResetAfterIOCReboot: Problem occurred while setting gain to $nondclist to proper gain\n$results"] == 1} {
                    APSMpReturn error "APSMpBoosterResetAfterIOCReboot: $results"
                }
            }           
            APSWaitWithUpdate -waitSeconds 2
        }
        if {$dclist!=""} {
            #Set gain to 0 (This may not be needed)
            APSMpStep  "Setting gain factor for $dclist to 0"
            foreach magnet $dclist {
                if {[catch {APScavput -list=B:${magnet}:VoltageRT.GAIN=0 -pendIoTime=25} results]} {
                    if {[APSPEMTKDialog .warningDialog -text "APSMpBoosterResetAfterIOCReboot: Channel access problem for B:${magnet}:VoltageRT.GAIN\n$results"] == 1} {
                        APSMpReturn error "APSMpBoosterResetAfterIOCReboot: $results"
                    }
                }
            }
            APSWaitWithUpdate -waitSeconds 2

            APSMpStep "Setting to auto mode"
            if {[catch {APScavput -list=[join $dcautoCommands ,] -pend=20} results]} {
                APSMpReturn error "APSMpBoosterResetAfterIOCReboot: $results"
            }

            APSWaitWithUpdate -waitSeconds 2

            #Set gain to 0 (supplies will only take the 0 after the auto is set)
            APSMpStep  "Setting gain factor for $dclist to 0"
            if {[catch {APSMpBoosterPSSetGain -BM $dc(BM) -QF $dc(QF) -QD $dc(QD) -SF $dc(SF) -SD $dc(SD) -value 0} results]} {
                if {[APSPEMTKDialog .warningDialog -text "APSMpBoosterResetAfterIOCReboot: Problem occurred while setting gain to $dclist to proper gain\n$results"] == 1} {
                    APSMpReturn error "APSMpBoosterResetAfterIOCReboot: $results"
                }
            }           

            APSWaitWithUpdate -waitSeconds 10

            #Turn power supplies off
            foreach magnet $dclist {
                APSMpStep "Turning power supply $magnet off."
                if {[catch {exec cavput -list=B:${magnet}:OffBO=1} results]} {
                    if {[APSPEMTKDialog .warningDialog -text "APSMpBoosterResetAfterIOCReboot: Problem occurred while turning B:$magnet off\n$results"] == 1} {
                        APSMpReturn error "APSMpBoosterResetAfterIOCReboot: $results"
                    }
                }
            }

            APSWaitWithUpdate -waitSeconds 5

        }
	APSSetVarAndUpdate status "$selectlist AFG(s) set to AUTO. Reset procedure completed."
    }
    APSMpReturn ok
}

proc APSMpBoosterResetAfterIOCRebootOld {args} {

    set BM 0
    set QF 0
    set QD 0
    set SF 0
    set SD 0
    set magnetlist "BM QF QD SF SD"
    
    APSStrictParseArguments {BM QF QD SF SD}
    
    set selectlist ""
    set getStateCommand ""
    set initCommands ""
    set autoCommands ""

    APSMpStep "Checking if auto mode is not activated"
    foreach magnet $magnetlist {
	lappend getStateCommand "B:${magnet}:VoltageRT.MODE"
    }
    if {[catch {APScavget -list=[join $getStateCommand ,] -num -pend=20} results]} {
	APSMpReturn error "APSMpBoosterResetAfterIOCReboot: $results"
    }
    foreach result $results magnet $magnetlist {
	if {([set $magnet]) && ($result != 0)} {
	    lappend selectlist $magnet
	    lappend initCommands "B:${magnet}:VoltageRT.MODE=INIT"
	    lappend autoCommands "B:${magnet}:VoltageRT.MODE=AUTO"
	} else {
            set $magnet 0
        }
    }
    if {$selectlist!=""} {
        #Disable Ramps
        foreach magnet $selectlist {
            set magnetIndex [lsearch -exact "BM QF QD SF SD" ${magnet}]
            APSMpStep  "Disabling ${magnet} power supply ramp."
            if {[catch {APScavput -list=It:Ddg4chan${magnetIndex}.GATE=Disabled -pendIoTime=20} results]} {
                if {[APSPEMTKDialog .warningDialog -text "APSMpBoosterResetAfterIOCReboot: Channel access problem for It:Ddg4chan${magnetIndex}.GATE\n$results"] == 1} {
                    APSMpReturn error "APSMpBoosterResetAfterIOCReboot: $results"
                }
            }
        }
        APSWaitWithUpdate -waitSeconds 2

        #Turn power supplies off
        APSMpStep "Turn power supplies off" -proc APSMpBoosterPSOnOff
        if {[catch {APSMpBoosterPSOnOff -BM $BM -QF $QF -QD $QD -SF $SF -SD $SD -state1 off} results]} {
            if {[APSPEMTKDialog .warningDialog -text "APSMpBoosterResetAfterIOCReboot: Problem occurred while turning power supplies off\n$results"] == 1} {
                APSMpReturn error "APSMpBoosterResetAfterIOCReboot: $results"
            }
        }
        APSWaitWithUpdate -waitSeconds 2

	APSMpStep "Setting to init mode" -desc "Setting to init mode if not in auto mode"
	if {[catch {APScavput -list=[join $initCommands ,] -pend=20} results]} {
	    APSMpReturn error "APSMpBoosterResetAfterIOCReboot: $results"
	}
	APSSetVarAndUpdate status "$selectlist AFG(s) initialized."
	
	APSWaitWithUpdate -waitSeconds 2
	APSMpStep "Loading safety ramps"
	if {[catch {loadSafetyRamps2 -BM $BM -QF $QF -QD $QD -SF $SF -SD $SD -noWarning 1} results]} {
	    APSMpReturn error "APSMpBoosterResetAfterIOCReboot: $results"
	}
	APSWaitWithUpdate -waitSeconds 2
	
	APSMpStep "Setting to auto mode"
	if {[catch {APScavput -list=[join $autoCommands ,] -pend=20} results]} {
	    APSMpReturn error "APSMpBoosterResetAfterIOCReboot: $results"
	}

	APSWaitWithUpdate -waitSeconds 2
        #Set gain 0 if specified
        APSMpStep  "Setting gain factor for $selectlist to .4"
        if {[catch {APSMpBoosterPSSetGain -BM $BM -QF $QF -QD $QD -SF $SF -SD $SD -value .4} results]} {
            if {[APSPEMTKDialog .warningDialog -text "APSMpBoosterResetAfterIOCReboot: Problem occurred while setting gain to $magnets to proper gain\n$results"] == 1} {
                APSMpReturn error "APSMpBoosterResetAfterIOCReboot: $results"
            }
        }
    
        APSWaitWithUpdate -waitSeconds 2

	APSSetVarAndUpdate status "$selectlist AFG(s) set to AUTO. Reset procedure completed."
    }
    APSMpReturn ok
}

proc APSMpBoosterDisableSlopeAndZero {args} {
    
    set magnet ""
    set BM 0
    set QF 0
    set QD 0
    set SF 0
    set SD 0

    APSStrictParseArguments {magnet BM QF QD SF SD}
    
    if {[llength $magnet]} {
        set $magnet 1
    }

    set magnets ""
    foreach m "BM QF QD SF SD" {
        if {[set $m]} {
            append magnets "$m "
        }
    }
    if {![llength $magnets]} {
        APSMpReturn ok
    }

    APSMpReturn ok
}

proc APSMpBoosterPSSetGain {args} {
    
    set magnet ""
    set value .4
    set BM 0
    set QF 0
    set QD 0
    set SF 0
    set SD 0
    set BMgain -1
    set QFgain -1
    set QDgain -1
    set SFgain -1
    set SDgain -1
    

    APSStrictParseArguments {magnet value BM QF QD SF SD BMgain QFgain QDgain SFgain SDgain}

    if {[llength $magnet]} {
        set $magnet 1
    }

    set magnets ""
    foreach m "BM QF QD SF SD" {
        if {[set $m]} {
            append magnets "$m "
            if {[set ${m}gain] < 0} {
                set ${m}gain $value
            }
        }
    }

    if {![llength $magnets]} {
        APSMpReturn ok
    }

    set redo 1
    while {$redo} {
        #Set Gain
        foreach magnet $magnets {
            if {[catch {APScavput -list=B:${magnet}:VoltageRT.GAIN=[set ${magnet}gain] -pendIoTime=25} results]} {
                if {[APSPEMTKDialog .warningDialog -text "APSMpBoosterPSSetGain: Channel access problem for B:${magnet}:VoltageRT.GAIN\n$results"] == 1} {
                    APSMpReturn error "APSMpBoosterPSSetGain: $results"
                }
            }
        }
        APSWaitWithUpdate -waitSeconds 2
        #check if swap/sync server is running or not
	if [catch {exec cavget -list=B:SwapSyncRC.RUN -pend=10 -printErrors} swap] {
	    return -code error "can not read swap sync server runcontrol: $swap"
	}
	if !$swap {
	    #Click Swap
	    foreach magnet $magnets {
		if {[catch {APScavput -list=B:${magnet}:VoltageRT.SWAP=1 -pendIoTime=25} results]} {
		    if {[APSPEMTKDialog .warningDialog -text "APSMpBoosterPSSetGain: Channel access problem for B:${magnet}:VoltageRT.SWAP\n$results"] == 1} {
			APSMpReturn error "APSMpBoosterPSSetGain: $results"
		    }
		}
	    }
	}
        APSWaitWithUpdate -waitSeconds 2

        #Check for swap error
        set redo 0
        foreach magnet $magnets {
            if {[catch {APScavget -list=B:${magnet}:VoltageRT.SEVR -pendIoTime=25} swapState]} {
                if {[APSPEMTKDialog .warningDialog -text "APSMpBoosterPSSetGain: Channel access problem for B:${magnet}:VoltageRT.SEVR\n$results"] == 1} {
                    APSMpReturn error "APSMpBoosterPSSetGain: $swapState"
                } else {
                    set swapState "MAJOR"
                }
            }
            if {$swapState=="MAJOR"} {
                set redo 1
                APSMpStep "Ramp for $magnet swapped. A swap error was indicated for ${magnet}."
            }
        }
        if {$redo} {
            continue
        }
        #check if swap/sync server is running or not
	if [catch {exec cavget -list=B:SwapSyncRC.RUN -pend=10 -printErrors} swap] {
	    return -code error "can not read swap sync server runcontrol: $swap"
	}
	if !$swap {
	    #Click Sync
	    if {[catch {APScavput -list=B:PSAFG100SyncBO=1 -numerical} results]} {
		if {[APSPEMTKDialog .warningDialog -text "APSMpBoosterPSSetGain: Channel access problem for B:PSAFG100SyncBO\n$results"] == 1} {
		    APSMpReturn error "APSMpBoosterPSSetGain: $results"
		}
	    }
	}
	APSWaitWithUpdate -waitSeconds 2
        #Check for sync error
        foreach magnet $magnets {
            if {[catch {APScavget -list=B:${magnet}:VoltageRT.NEWT -pendIoTime=25} newtState]} {
                if {[APSPEMTKDialog .warningDialog -text "APSMpBoosterPSSetGain: Channel access problem for B:${magnet}:VoltageRT.NEWT\n$results"] == 1} {
                    APSMpReturn error "APSMpBoosterPSSetGain: $newtState"
                } else {
                    set newtState 1
                }
            }
            if {$newtState != 0} {
                APSMpStep "Ramp for $magnet swapped. A sync error was indicated for ${magnet}."
                set redo 1
            }
        }
    }
    APSMpReturn ok
}
