#!/bin/sh  
# \
exec oagwish "$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)]
APSDebugPath

set CVSRevisionAuthor "\$Revision: 1.7 $ \$Author: borland $"

proc MakeApplication {} {
    global CVSRevisionAuthor status
    APSApplication . -name "IS1 Top Up Setpoint Feed Forward" -version $CVSRevisionAuthor

    set status "Ready..."
    APSScrolledStatus .status -parent .userFrame -textVariable status \
      -width 60 -height 15

    APSFrameGrid .fg -parent .userFrame -yList {label i0 i120 i240} \
      -xList {label interval setpoint} -width 25 -packOption "-side top"

    label .userFrame.fg.label.i0.l1 -text "refill" 
    pack .userFrame.fg.label.i0.l1 
    label .userFrame.fg.label.i120.l2 -text "top-up" 
    pack .userFrame.fg.label.i120.l2 
    label .userFrame.fg.label.i240.l3 -text "top-up" 
    pack .userFrame.fg.label.i240.l3 

    label .userFrame.fg.interval.label.l4 -text "interval (s)"  -width 14
    pack .userFrame.fg.interval.label.l4
    label .userFrame.fg.setpoint.label.l5 -text "setpoint (V)" -width 14
    pack .userFrame.fg.setpoint.label.l5

    global Setpoint Interval WidgetList
    set setpointList  [list 640 637 633] 
    foreach yPos {i0 i120 i240} interval {0.5 120 240} setpoint $setpointList {
        set Setpoint($interval) $setpoint
        set Interval($interval) $interval
        APSLabeledOutput .interval.$yPos.label -parent .userFrame.fg \
          -label "" -textVariable Interval($interval) \
          -width 10 
        APSLabeledEntry .setpoint.$yPos.label -parent .userFrame.fg \
          -label "" -textVariable Setpoint($interval) \
          -width 10 
        lappend WidgetList .userFrame.fg.setpoint.$yPos.label.entry
    }

    APSButton .run -parent .userFrame -text Run -command RunFF
    APSButton .stop -parent .userFrame -text Stop -command AbortFF 
    APSButton .info -parent .userFrame -text Info -command \
      "exec medm -x -attach -macro RCPV=APS:RunControlSlot0RC ./sr/psApp/APSRunControlSingle.adl &"
}

proc RunFF {} {
    global Setpoint WidgetList

    APSDisableButton .userFrame.run.button
    foreach item $WidgetList {
        $item configure -state disable
    }
    foreach item [array names Setpoint] {
        lappend intervalList $item
    }
    set intervalList [lsort $intervalList]
    foreach item $intervalList {
        lappend setpointList $Setpoint($item)
    }

    global abortFF
    set abortFF 0
    APSEnableButton .userFrame.stop.button

    APSRunIS1TopUpFeedForward -intervalList $intervalList \
      -setpointList $setpointList -abortVariable abortFF \
      -statusCallback StatusCallback 
}

proc AbortFF {} {
    global abortFF WidgetList
    set abortFF 1


    foreach item $WidgetList {
        $item configure -state normal
    }
    APSEnableButton .userFrame.run.button
    APSDisableButton .userFrame.stop.button
}

proc StatusCallback {text} {
    global status abortFF
    APSSetVarAndUpdate status "$text"
    if $abortFF {
        AbortFF
    }
}

proc APSRunIS1TopUpFeedForward {args} {
    set intervalList [list 0.5 120 240]
    set setpointList [list 640 637 633]
    set statusCallback ""
    set abortVariable ""

    APSStrictParseArguments {intervalList setpointList statusCallback abortVariable}
    if [llength $intervalList]<2 {
        return -code error "APSRunIS1TopUpFeedForward: intervalList too short"
    }
    if [llength $intervalList]!=[llength $setpointList] {
        return -code error "APSRunIS1TopUpFeedForward: interval and setpoint lists have different lengths"
    }
    if ![string length $statusCallback] {
        set statusCallback APSNoOp
    }
    if ![string length $abortVariable] {
        set abortVariable APSRunIS1TopUpFeedForwardDummyVar
    }
    foreach interval $intervalList setpoint $setpointList {
        set Setpoint($interval) $setpoint
    }

    eval $statusCallback {"APSRunIS1TopUpFeedForward: initializing"}

    global $abortVariable errorCode
    set $abortVariable 0

    set varList [list TopUpState TopUpIntervals TopUpWarning IS1Setpoint TopUpInterval]
    foreach var $varList {
        global $var
        set $var 0
    }

    set pvList [list Mt:TopUpAutoEnableC.VAL Mt:TopUpIntervals2Inject.VAL Mt:TopUpWarning.VAL S:IS1:VoltageSetSendAO Mt:TopUpIntervalP.VAL]

    if [pv linkw $varList $pvList] {
        return -code error "APSRunIS1TopUpFeedForward: pv problem: $errorCode"
    }

    set RCPV APS:RunControlSlot0RC
    catch {APSRunControlExit}
    if [catch {APSRunControlInit -pv $RCPV \
                 -description "Top-up IS1 Setpoint Feedforward" \
                 -timeout 10000} result] {
        return -code error "APSRunIS1TopUpFeedForward: $result"
    }

    while {![set $abortVariable]} {
        if [catch {APSRunControlPing} result] {
            catch {APSRunControlExit}
            set $abortVariable 1
            eval $statusCallback {"Run control permission removed."}
            return
        }
        if [pv getw $varList] {
            eval $statusCallback {"PV problem: $errorCode"}
            after 2000
            continue
        }
        if [string compare $TopUpState "Enable"]==0 {
            # wait for Injection warning to go on, then off
            set warningSeen 0
            set nowarningSeen 0
            eval $statusCallback {"[clock format [clock seconds] -format %H:%M:%S]: Waiting for top-up cycle to start"}
            while {!$nowarningSeen} {
                update
                if [set $abortVariable] {
                    eval $statusCallback {"Feedforward aborted."}
                    return
                }
                if [pv getw $varList] {
                    eval $statusCallback {"PV problem: $errorCode"}
                    after 2000
                }
                if [string compare $TopUpState "Disable"]==0 {
                    break
                }
                if [string compare $TopUpWarning "InjectWarn"]==0 {
                    set warningSeen 1
                }
                if $warningSeen {
                    if [string compare $TopUpWarning "NoWarning"]==0 {
                        set nowarningSeen 1
                    }
                }
                if [catch {APSRunControlPing} result] {
                    catch {APSRunControlExit}
                    set $abortVariable 1
                    eval $statusCallback {"Run control permission removed."}
                    return
                }
                after 1000
            }
            if $nowarningSeen {
                eval $statusCallback {"Top-up cycle detected."}
                APSWaitWithUpdate -waitSeconds 5 -updateInterval 1
                if [pv getw $varList] {
                    eval $statusCallback {"PV problem: $errorCode"}
                    continue
                }
                set interval [expr int(($TopUpIntervals+1)*$TopUpInterval)]
                eval $statusCallback {"Interval is $interval"}
                if [lsearch -exact [array names Setpoint] $interval]!=-1 {
                    set IS1Setpoint $Setpoint($interval)
                    eval $statusCallback {"Setpoint -> $IS1Setpoint"}
                    if [pv putw IS1Setpoint] {
                        eval $statusCallback {"PV problem: $errorCode"}
                        continue
                    }
                } else {
                    bell
                    eval $statusCallback {"No setpoint for that interval!"}
                }
            }
        } 
        if [string compare $TopUpState "Disable"]==0 {
            set IS1Setpoint $Setpoint(0.5)
            eval $statusCallback {"Top-up not running."}
            eval $statusCallback {"Setpoint -> $IS1Setpoint"}
            if [pv putw IS1Setpoint] {
                eval $statusCallback {"PV problem: $errorCode"}
                continue
            }
        }
        after 1000
    }
}

MakeApplication
