
proc APSSetBoosterRampToCurrent {args} {
    set plane ""
    set vertical 0
    set horizontal 0
    set CorrNames {B1C0 B1C1 B1C2 B1C3 B1C4 B1C5 B1C6 B1C7 B1C8 B1C9 \
                     B2C0 B2C1 B2C2 B2C3 B2C4 B2C5 B2C6 B2C7 B2C8 B2C9 \
                     B3C0 B3C1 B3C2 B3C3 B3C4 B3C5 B3C6 B3C7 B3C8 B3C9 \
                     B4C0 B4C1 B4C2 B4C3 B4C4 B4C5 B4C6 B4C7 B4C8 B4C9}
    APSStrictParseArguments {plane}
    if ![string length $plane] {
        set plane both
    }
    switch $plane {
        h -
        v {
            set Plane [string toupper $plane]
        }
        both {
            set Plane {H V}
        }
    }
    #get the current at offTime from the rampTable
    set putList ""
    foreach pl $Plane {
        foreach corr $CorrNames {
            set values [exec caget -t ${corr}${pl}:rampRAMPTABLE]
            set points [exec caget -t ${corr}${pl}:rampRAMPTABLE.NORD]
            set setpoint [lindex $values [expr $points -1]]
            set rate [exec caget -t ${corr}${pl}:rampRAMPTABLE.HIGH]
            set current [expr $setpoint * $rate]
            lappend putList ${corr}${pl}:CurrentAO=$current
        }
    }
    if [catch {exec cavput -list=[join $putList ,] -pend=30} result] {
        return -code error $result
    }
}

proc APSSetBoosterCorrPowerSupplies {args} {
    #turn on or off booster corrector power supplies
    set CorrNames {B1C0 B1C1 B1C2 B1C3 B1C4 B1C5 B1C6 B1C7 B1C8 B1C9 \
                     B2C0 B2C1 B2C2 B2C3 B2C4 B2C5 B2C6 B2C7 B2C8 B2C9 \
                     B3C0 B3C1 B3C2 B3C3 B3C4 B3C5 B3C6 B3C7 B3C8 B3C9 \
                     B4C0 B4C1 B4C2 B4C3 B4C4 B4C5 B4C6 B4C7 B4C8 B4C9}
    set plane ""
    #switch: on or off
    set switch off
    set fast 0
    set rawOnly 0
    set statusVar ""
    #rawOnly=1, raw only supplies and fast
    #fast=1: will not load zero ramps before turning off.
    #        or will not perform initialization before turning on
    APSStrictParseArguments {plane switch fast rawOnly statusVar}
    if ![string length $plane] {
        return -code error "APSSetBoosterCorrPowerSupplies: plane is not provided."
    }
    
    #initialize correctors before turning on the power supplies
    if {$switch=="on" && !$fast} {
        if [catch {APSInitializeBoosterCorrector -plane $plane -statusVar $statusVar} result] {
            return -code error "APSSetBoosterCorrPowerSupplies: $result"
        }
    }
    #zero ramps before turning off power supplies
    if {$switch=="off" && !fast} {
        
    }

}

proc APSInitializeBoosterCorrector {args} {
    #perform sequence to initialize ramp control
    set plane ""
    set dir /home/helios/oagData/booster/orbitCorr
    set statusVar ""
    APSStrictParseArguments {plane statusVar}
    if ![string length $plane] {
        return -code error "APSInitializeBoosterCorrector: The plane for initializing correctors is not provided."
    }
    switch $plane {
        h {
            set loadfile $dir/booster.zero.h.ramp
        }
        v {
            set loadfile $dir/booster.zero.v.ramp
        }
        both {
            set loadfile $dir/booster.zero.ramp
        }
        default {
            return -code error "APSInitializeBoosterCorrector: invalid plane value given!"
        }
    }
    if [string length $statusVar] {
	APSSetVarAndUpdate $statusVar "Initializing booster correctors..."
    }
    if [catch {exec cavput -list=B:BM:InitSEQ=1 -pend=30} result] {
        return -code error "APSInitializeBoosterCorrector: $result"
    }
    if [string length $statusVar] {
        APSSetVarAndUpdate $statusVar "Performing first rampload using $loadfile..."
    }
    if [catch {exec rampload $loadfile} result] {
        return -code error "APSInitializeBoosterCorrector: $result"
    }
    if [string length $statusVar] {
        APSSetVarAndUpdate $statusVar "Performing AUTO..."
    }
    if [catch {exec cavput -list=B:BM:AutoSEQ=1 -pend=30} result] {
        return -code error "APSInitializeBoosterCorrector: $result"
    }
    if [string length $statusVar] {
        APSSetVarAndUpdate $statusVar "Performing second rampload using $loadfile..."
    }
    if [catch {exec rampload $loadfile} result] {
        return -code error "APSInitializeBoosterCorrector: $result"
    }
    if [string length $statusVar] {
        APSSetVarAndUpdate $statusVar "Performing ACTIVATE..."
    }
    if [catch {APSSetBoosterForeground -plane $plane} result] {
	return -code error $result
    }
    if [string length $statusVar] {
        APSSetVarAndUpdate $statusVar "Setting CurrentAO's..."
    }
    if [catch {APSSetBoosterRampToCurrent -plane $plane} result] {
        return -code error "APSInitializeBoosterCorrector: $result"
    }
    if [string length $statusVar] {
        APSSetVarAndUpdate $statusVar "initialize booster correctors done."
    }
}


proc APSSetBoosterCorrectorValue {args} {
    set rampbias 0
    set rampload 1
    set setfg 1
    set value 0.0
    set ontime 0.0
    set offtime 236.439589
    set endtime 250.0
    set corrector ""
    set plane ""
    set statusVar ""
    APSStrictParseArguments {rampbias rampload setfg corrector value plane statusVar}
    set CorrNames {B1C0 B1C1 B1C2 B1C3 B1C4 B1C5 B1C6 B1C7 B1C8 B1C9 \
                     B2C0 B2C1 B2C2 B2C3 B2C4 B2C5 B2C6 B2C7 B2C8 B2C9 \
                     B3C0 B3C1 B3C2 B3C3 B3C4 B3C5 B3C6 B3C7 B3C8 B3C9 \
                     B4C0 B4C1 B4C2 B4C3 B4C4 B4C5 B4C6 B4C7 B4C8 B4C9}
    if {![string length $corrector] && ![string length $plane]} {
        return -code error "Either corrector or plan has to be provided."
    }
    set plane [string toupper $plane]
    if ![string length $corrector] {
        switch $plane {
            H -
            V {
                set planes [string toupper $plane]
            }
            BOTH {
                set planes {H V}
            }
            defautl {
                return -code error "Invalid plane given."
            }
        }
        foreach pl $planes {
            foreach corr $CorrNames {
                lappend corrList ${corr}${pl}
            }
        }
    } else {
        set corrList $corrector
    }
    if [catch {exec cavget -list=It:Bs:StartRamp2BsIp -pend=30} RampStartOffsetTime] {
        return -code error "$RampStartOffsetTime"
    }
    if [catch {exec cavget -list=It:Ddg4chan6.DLY -pend=30} RampStartDelay] {
        return -code error "$RampStartDelay"
    }
    if [string length $statusVar] {
	APSSetVarAndUpdate $statusVar "Creating ramp table ..."
    }
    set injection [expr $RampStartOffsetTime - $RampStartDelay]
    set offvalue [expr $value /19.0]
    set val [expr $offvalue * ($injection-$ontime)/($offtime-$ontime)]
    set timeList [list 0.0 $injection $offtime $endtime]
    set valList [list 0.0 $val $offvalue $offvalue]
    set tmpRoot /tmp/[APSTmpString]
    set output(Description.Text) "Corrector ramps"
    set output(Description.Contents) "booster ramp"
    set output(ParameterNames) "ControlName ControlType RampBias CorrName CorrCurrentAO"
    set output(ParameterInfo.ControlName) "type SDDS_STRING"
    set output(ParameterInfo.ControlType) "type SDDS_STRING"
    set output(ParameterInfo.RampBias) "type SDDS_DOUBLE"
    set output(ParameterInfo.CorrName) "type SDDS_STRING"
    set output(ParameterInfo.CorrCurrentAO) "type SDDS_STRING"
    set output(ColumnNames) "RampTime RampSetpoint"
    set output(ColumnInfo.RampTime) "type SDDS_DOUBLE"
    set output(ColumnInfo.RampSetpoint) "type SDDS_DOUBLE"
    set ControlNameData ""
    set ControlTypeData ""
    set RampBiasData ""
    set CorrNameData ""
    set CorrCurrentAOData ""
    set RampTimeData ""
    set RampSetpointList ""
    set putList ""
    foreach corr $corrList {
        lappend ControlNameData ${corr}:rampRAMPTABLE
        lappend ControlTypeData pv
        lappend RampBiasData 0.0
        lappend CorrNameData $corr
        lappend CorrCurrentAOData $corr:CurrentAO

        lappend RampTimeData $timeList
        lappend RampSetpointList $valList
        lappend putList ${corr}:CurrentAO=$value
    }
    set output(Parameter.ControlName) $ControlNameData
    set output(Parameter.ControlType) $ControlTypeData
    set output(Parameter.RampBias) $RampBiasData
    set output(Parameter.CorrName) $CorrNameData
    set output(Parameter.CorrCurrentAO) $CorrCurrentAOData
    set output(Column.RampTime) $RampTimeData
    set output(Column.RampSetpoint) $RampSetpointList
    if [catch {sdds save $tmpRoot.ramp output} result] {
        return -code error $result
    }
    if $rampload {
	if [string length $statusVar] {
	    APSSetVarAndUpdate $statusVar "Loading ramp table ..."
	}
        if [catch {exec rampload $tmpRoot.ramp} result] {
            return -code error $result
        }
	after 2000
	#wait for light to be green (loading ramp with no errors)
	if [string length $statusVar] {
	    APSSetVarAndUpdate $statusVar "Waiting  for light to be green ..."
	}
	if [catch {APSWaitForBoosterCorrectorLight -corrname $corrList -color green} result] {
	    return -code error $result
	}
	if [catch {APSWaitForBoosterCorrectorPact -corrname $corrList} result] {
	    return -code error $result
	}
    }
    if $setfg {
	if [string length $statusVar] {
	    APSSetVarAndUpdate $statusVar "Setting foreground ..."
	}
        if [catch {APSSetBoosterForeground -corrname $corrList} result] {
	    return -code error $result
	}
    }
    
    if [catch {exec cavput -list=[join $putList ,] -pend=30} result] {
        return -code error $result
    }
}

proc APSSetBoosterForeground {args} {
    set corrname ""
    set setvalue 0
    set plane ""
    APSStrictParseArguments {corrname plane}
    set CorrNames {B1C0 B1C1 B1C2 B1C3 B1C4 B1C5 B1C6 B1C7 B1C8 B1C9 \
                     B2C0 B2C1 B2C2 B2C3 B2C4 B2C5 B2C6 B2C7 B2C8 B2C9 \
                     B3C0 B3C1 B3C2 B3C3 B3C4 B3C5 B3C6 B3C7 B3C8 B3C9 \
                     B4C0 B4C1 B4C2 B4C3 B4C4 B4C5 B4C6 B4C7 B4C8 B4C9}
    set planes ""
    if ![string length $corrname] {
	if [string length $plane] {
	    switch $plane {
		h -
		v {
		    set planes [string toupper $plane]
		}
		both {
		    set planes {H V}
		}
		default {
		    return -code error "APSSetBoosterForeground: Invalide plane provided!"
		}
	    }
	    foreach pl $planes {
		foreach corr $CorrNames {
		    lappend corrList ${corr}${pl}
		}
	    }
	} else {
	    return -code error "APSSetBoosterForeground: Either plane or corrname has to be provided for setting foreground."
	}
    } else {
	set corrList $corrname
    }
    if [catch {exec cavput -list=[join $corrList ,] \
		   -list=:rampRAMPTABLE.SWAP=$setvalue -pend=30} result] {
        return -code error $result
    }
    after 2000
    #wait for corrector light to be black (value=0) (ramp done)
    if [catch {APSWaitForBoosterCorrectorLight -corrname $corrList -color black} result] {
	return -code error $result
    }
    #wat for pact to be zero
    if [catch {APSWaitForBoosterCorrectorPact -corrname $corrList} result] {
	return -code error $result
    }
}

proc APSWaitForBoosterCorrectorLight {args} {
    #green =1, black=0
    set color ""
    set corrname ""
    APSStrictParseArguments {color corrname}
    
    switch $color {
	green {
	    set value 1
	}
	black {
	    set value 0
	}
	default {
	    return -code error "APSWaitForBoosterCorrectorLight: invalid color given"
	}
    }
    set timeout 100
    set timenow [clock seconds]
    while {1} {
	if [catch {exec cavget -list=[join $corrname ,] \
		       -list=:rampRAMPTABLE.NEWT -pend=30} values] {
	    return -code error "APSWaitForBoosterCorrectorLight: $result"
	}
	set error 0
	foreach val $values {
	    if {$val!=$value} {
		incr error
	    }
	}
	if !$error {
	    break
	}
	if {[clock seconds] > [expr $timenow + $timeout]} {
	    return -code error "APSWaitForBoosterCorrectorLight: time out with errors"
	}
	after 1000
    }
    return
}

proc APSWaitForBoosterCorrectorPact {args} {
    set corrname ""
    APSStrictParseArguments {corrname}
    #wait for pact to be zer0
    set timeout 100
    set timenow [clock seconds]
    while {1} {
	if [catch {exec cavget -list=[join $corrname ,] \
		       -list=:rampRAMPTABLE.PACT -pend=30} values] {
	    return -code error "APSWaitForBoosterCorrectorPact: $result"
	}
	set error 0
	foreach val $values {
	    if {$val!=0} {
		incr error
	    }
	}
	if !$error {
	    break
	}
	if {[clock seconds] > [expr $timenow + $timeout]} {
	    return -code error "APSWaitForBoosterCorrectorLight: time out with errors"
	}
	after 1000
    }
    return
}
