
proc APSSRSetIOCAveraging {args} {
    set num2Ave 128
    set filterCoeff 1
    set enable 1
    set BPMList ""
    #BPMList argument is no longer needed (obselete)
    set cavputCommand "exec cavput"
    APSStrictParseArguments {num2Ave filterCoeff enable cavputCommand BPMList}
    
    set pendIOTime 10
    set NBIOCList ""
    set XrayIOCList ""
    set statusDir /home/helios/oagData/sr/BPMStatus
    
    #  puts [exec date] 
    
    if [catch {exec sddsprocess $statusDir/config.sdds -pipe=out \
                 "-match=col,ElectronicsType=Narrowband" -nowarnings\
                 -filter=col,NonexistentH,0,0,NonexistentV,0,0,& \
                 -scan=col,Sector,DeviceName,S%ld,type=long \
                 "-define=col,Sector1,Sector 2 mod" \
                 | sddsprocess -pipe -filter=col,Sector1,0.5,1 \
                 | sddssort -pipe -col=Sector -unique \
		 | sdds2stream -pipe -col=Sector} NBIOCList] {
        return -code error "APSSRSetIOCAveraging (Error1 -- sddsprocess command): $NBIOCList"
    }
    
    if [catch {exec sddsprocess $statusDir/config.sdds -pipe=out \
                   -match=col,ElectronicsType=Xray -noWarnings \
                   -filter=col,NonexistentV,0,0 \
                   -scan=col,Sector,DeviceName,S%ld,type=long \
                   "-define=col,Sector1,Sector 2 mod" \
                   | sddsprocess -pipe -filter=col,Sector1,0.5,1 \
                   | sddssort -pipe -col=Sector -unique \
                   | sdds2stream -pipe -col=Sector} XrayIOCList] {
        return -code error "APSSRSetIOCAveraging (Error2 -- sddsprocess command): $XrayIOCList"
    }
    set NBnum2Ave [expr int($num2Ave / 5)]
    if !$NBnum2Ave {
        set NBnum2Ave1 1
    }
    set XrayNum2Ave [expr int($num2Ave / 5)]
    if !$XrayNum2Ave {
        set XrayNum2Ave 1
    }
    # puts "process done: [exec date]"
    if [llength $NBIOCList] {
        if [catch {eval $cavputCommand -pendIOTime=$pendIOTime \
                       -list=S:bpm \
                       -list=[join $NBIOCList ,] \
                       -list=P0:msAve:Num2AveAO=$NBnum2Ave,P0:mswAve:CoeffAO=$filterCoeff \
                   } results ] {
            return -code error "APSSRSetIOCAveraging (Error3 - cavput command): $results"
        }
    }
    # puts [join $XrayIOCList ,]
    if [llength $XrayIOCList] {
        if [catch {eval $cavputCommand -pendIOTime=$pendIOTime \
                       -list=S:bpm \
                       -list=[join $XrayIOCList ,] \
                       -list=Xray:msAve:Num2AveAO=$XrayNum2Ave,Xray:mswAve:CoeffAO=$filterCoeff \
                   } results ] {
            return -code error "APSSRSetIOCAveraging (Error4 -- cavput command): $results"
        }
    }
    # note this list has to be changed manually when new FPGA bpms are installed.
    # monopulse bpms no longer exist after FPGA bpm installed on 40 sectors Jan. 2014
    if {0} {
    if [catch {eval $cavputCommand -pendIOTime=$pendIOTime \
                 -list=S:bpm \
                 -list=[join [APSGetMonopulseBPMIOCList] ,] \
                 -list=:msAve:Num2AveAO=$num2Ave,:mswAve:CoeffAO=$filterCoeff \
             } results ] {
        return -code error "APSSRSetIOCAveraging (Error5 -- cavput command): $results"
    }
    }
    if {$enable} {
        set bpmList [exec sddsprocess $statusDir/config.sdds -pipe=out -nowarnings\
                         -filter=col,NonexistentV,0,0 "-match=col,ElectronicsType=FPGA,!" \
                         | sdds2stream -pipe -col=DeviceName]
        if {[catch {exec cavput -pendIOTime=$pendIOTime -list=[join $bpmList ,] \
                        -list=:msAve:AveEnbBO=Enable -pend=30} result]} {
            return -code error "APSSRSetIOCAveraging (Error6 -- sddsprocess and cavput command): $result"
        }
    }
    #  puts [exec date]
    return -code ok
}

proc APSSRTransferBPMAdjustedValues {args} {
    set msType ""
    set plane ""
    set saveSnapshot 1
    set statusCallback APSNoOp
    set excludeConfigFileList ""
    
    APSStrictParseArguments {msType plane saveSnapshot statusCallback excludeConfigFileList} 
    set snapDir /home/helios/oagData/sr/orbitSetpointSnapshots
    set statusDir /home/helios/oagData/sr/BPMStatus

    if {-1==[lsearch -exact {ms msAve mswAve} $msType]} {
        return -code error "APSSRTransferBPMAdjustedValues (1): Invalid msType value."
    }
    if {-1==[lsearch -exact {x y both} $plane]} {
        return -code error "APSSRTransferBPMAdjustedValues (2): Invalid plane value."
    }

    if [string compare $plane "both"]==0 {
        set plane {x y}
    }
    set snapshot ""
    if $saveSnapshot {
        eval $statusCallback {"Taking backup snapshot."}
        if [catch {APSSaveMachine -machine SROrbitSetPt \
                     -description "Routine save: autosave prior to setpoint transfer."} snapshot] {
            return -code error "APSSRTransferBPMAdjustedValues (3): $snapshot"
        }
        eval $statusCallback {"Snapshot done."}
    }
    
    set planeIndex -1
    set waveformFileDir /home/helios/oagData/sr/orbitControllaw/waveforms
    set fileList ""
    set bpmTypeList ""
    foreach coord $plane {
        incr planeIndex
        set startTime [lindex [exec timeconvert -now] end]
        eval $statusCallback {"Transfering plane $coord..."}
        set excludeList ""
        if [llength $excludeConfigFileList] {
            set excludeFile [lindex $excludeConfigFileList $planeIndex]
            set tmpFile /tmp/[APSTmpString]
            APSAddToTempFileList $tmpFile
            if [catch {exec sddsprocess $excludeFile $tmpFile -nowarning \
                         -filter=column,Flag,1,1 \
                         -match=parameter,NameType=MonitorNames} result] {
                return -code error "APSSRTransferBPMAdjustedValues (4): $result"
            }
            if [catch {APSGetSDDSColumn -fileName $tmpFile -column Name \
                         -page 0} excludeList] {
                return -code error "APSSRTransferBPMAdjustedValues (5): $excludeList"
            }
        }
        if [catch \
              {exec cavget -list=S -range=beg=1,end=40 \
                 -list=A:P1,A:P2,A:P3,A:P4,B:P5,B:P4,B:P3,B:P2,B:P1 \
                 -list=:${msType}:${coord}:AdjustedCC -label -pend=30} adjustedList] {
            return -code error "APSSRTransferBPMAdjustedValues (6): $adjustedList"
        }
        
        set P0List [exec sddsprocess $statusDir/config.sdds -pipe=out \
                      -match=col,DeviceName=*:P0 \
                      -filter=col,NonexistentH,0,0,NonexistentV,0,0,& \
                      | sdds2stream -pipe -col=DeviceName]
        if {[llength $P0List]} {
            if {[catch {exec cavget -list=[join $P0List ,] \
                          -list=:${msType}:${coord}:AdjustedCC -label -pend=30} adjustedListP0]} {
                return -code error "APSSRTransferBPMAdjustedValues (7): $adjustedListP0"
            } 
            set adjustedList [concat $adjustedList $adjustedListP0]
        }
        if [string match $coord y] {
            # calls APSSRTransferBPMList for the BM Xray bpms if y-plane is requested.
            if [catch {exec sddsprocess $statusDir/config.sdds -pipe=out \
                           -match=col,DeviceName=*BM:P? -noWarning \
                           -filter=col,NonexistentV,0,0 \
                           | sdds2stream -pipe -col=DeviceName} BMBPMList] {
                return -code error "APSSRTransferBPMAdjustedValues (8): $BMBPMList"
            }
            # Remove BM bpms that are in the exclude list
            # 
            set BMBPMList1 ""
            foreach bpm $BMBPMList {
                if {[lsearch -exact $excludeList $bpm]==-1} {
                    lappend BMBPMList1 $bpm
                }
            }
            if [llength $BMBPMList1] {
                if [catch {APSSRTransferBPMList -list $BMBPMList1 \
                             -msType $msType -plane y \
                         } result] {
                    return -code error "APSSRTransferBPMAdjustedValues(9) -- APSSRTransferBPMList: $result"
                }
            }
        }
        set length [llength $adjustedList]
        set setpointList ""
        set bpmList ""
        set valueList ""
        for {set index 0} {$index<$length} {incr index 2} {
            set index1 [expr $index + 1]
            set value [lindex $adjustedList $index1]
            if [string compare ? $value] {
                regexp {(S.*:P.):.*} [lindex $adjustedList $index] match root
                if {[llength $excludeList]==0 || \
                      [lsearch -exact $excludeList $root]==-1} {
                    eval lappend setpointList ${root}:ms:${coord}:SetpointAO=$value
                    lappend bpmList $root
                }
            }
        }
        if {[llength $setpointList] && \
              [catch {exec cavput -list=[join $setpointList ,] -pend=30} result]} {
            return -code error "APSSRTransferBPMAdjustedValues (10): $result"
        }
        #get raw data for transferring to vector adjust
        if [catch {exec cavget -list=[join $bpmList ,] -list=:ms:${coord} -pend=30} valueList] {
            return -code error "APSSRTransferBPMAdjustedValues (11): $valueList"
        }
        set tmpData(ColumnNames) "DeviceName Waveform"
        set tmpData(ColumnInfo.DeviceName) "type SDDS_STRING"
        set tmpData(ColumnInfo.Waveform) "type SDDS_DOUBLE"
        set tmpData(Column.DeviceName) ""
        set tmpData(Column.Waveform) ""
        set tmpData(Column.DeviceName) [list $bpmList]
        set tmpData(Column.Waveform) [list $valueList]
        set tmpfile /tmp/[APSTmpString]
        APSAddToTmpFileList -ID APSSRTransferBPMAdjusts -fileList "$tmpfile $tmpfile.rf $tmpfile.p0"
        if [catch {sdds save $tmpfile tmpData} result] {
            return -code error "APSSRTransferBPMAdjustedValues (12): $result"
        }
        set wfFile $waveformFileDir/rf[string toupper $coord]BpmInfo.sdds
        if [catch {exec sddsconvert $wfFile -pipe=out \
                     -retain=column,Index,DeviceName \
                     -retain=parameter,WaveformPV \
                     | sddsxref -pipe=in $tmpfile \
                     $tmpfile.rf \
                     -fillIn -nowarning \
                     -match=DeviceName -take=Waveform  \
                 } result] {
            return -code error "APSSRTransferBPMAdjustedValues (13) (sddsxref): $result"
        }
        lappend fileList $tmpfile.rf
        if {[lsearch $bpmList S11B:P1]>=0 || [lsearch $bpmList S12A:P1]>=0 || \
              [llength $P0List] } {
            set wfFile $waveformFileDir/p0[string toupper $coord]BpmInfo.sdds
            if [catch {exec sddsconvert $wfFile -pipe=out \
                         -retain=column,Index,DeviceName \
                         -retain=parameter,WaveformPV \
                         | sddsxref -pipe=in $tmpfile \
                         $tmpfile.p0 \
                         -fillIn -nowarning \
                         -match=DeviceName -take=Waveform  \
                     } result] {
                return -code error "APSSRTransferBPMAdjustedValues (14) (sddsxref): $result"
            }
            lappend fileList $tmpfile.p0
        }
    }
    set output /tmp/[APSTmpString]
    APSAddToTmpFileList -ID APSSRTransferBPMAdjustedValues -fileList "$output"
    if [catch {eval exec sddscombine $fileList -pipe=out \
                 | sddsprocess -pipe=in $output -reedit=par,WaveformPV,%/:Out/:Adjust/ } result] {
        return -code error "APSSRTransferBPMAdjustedValues (15) -- sddscombine: $result"
    }
    if [catch {exec sddswput $output} result] {
        return -code error "APSSRTransferBPMAdjustedValues (16) -- sddswput: $result"
    }
    return $snapshot
}

proc APSSRTransferBPMList {args} {
    set msType ""
    set list ""
    set plane ""
    APSStrictParseArguments {list plane msType}

    if ![llength $list] {
        return
    }
    set waveformFileDir /home/helios/oagData/sr/orbitControllaw/waveforms
    switch -regexp $plane {
        [xy] {
            if [catch {exec cavget \
                         -list=[join $list ,] -list=:ms:${plane}:SetpointAO \
                         -pend=30 -dryRun} PVlist] {
                return -code error "APSSRTransferBPMList (1) -- cavget: $PVlist"
            }
            if [catch {exec cavget \
                         -list=[join $list ,] \
                         -list=:${msType}:${plane}:AdjustedCC \
                         -pend=30} adjustedList] {
                return -code error "APSSRTransferBPMList (2) - cavget: $adjustedList"
            }
            set planes $plane
        }
        both {
            if [catch {exec cavget \
                         -list=[join $list ,] -list=:ms: \
                         -list=x,y -list=:SetpointAO \
                         -pend=30 -dryRun } PVlist] {
                return -code error "APSSRTransferBPMList (3) -- cavget: $PVlist"
            }
            if [catch {exec cavget \
                         -list=[join $list ,] \
                         -list=:${msType}: -list=x,y -list=:AdjustedCC  \
                         -pend=30 \
                     } adjustedList] {
                return -code error "APSSRTransferBPMList (4) - cavget: $adjustedList"
            }
            set planes {x y}
        }
    }
    set length [llength $PVlist]
    set setpointList ""
    set excludeList ""
    set bpmList ""
    foreach PV $PVlist value $adjustedList {
        if [string compare ? $value] {
            regexp {(S.*:P.):.*} $PV {} root 
            if {![llength $excludeList] && \
                  [lsearch -exact $excludeList $root]==-1} {
                eval lappend setpointList $PV=$value
                lappend bpmList $root
            }
        }
    }
    
    if {[llength $setpointList] && \
            [catch {exec cavput -list=[join $setpointList ,] -pend=30 \
                    } result]} {
        return -code error "TransferBPMList (5) -- cavput: $result"
    }
    #transfer vector adjust
    
    set pvTypes ""
    if {[string match *P0* $bpmList]} {
        lappend pvTypes p0
    }
    if {[string match {S*[AB]:P[1-5]*} $bpmList]} {
        lappend pvTypes rf
    }
    if [string match *BM* $bpmList] {
        lappend pvTypes bm
    }
    if [string match *ID* $bpmList] {
        lappend pvTypes id
    }
    set fileList ""
    set tmpRoot /tmp/[APSTmpString]
    foreach coord $planes {
        set Data(ColumnNames) "DeviceName Waveform"
        set Data(ColumnInfo.DeviceName) "type SDDS_STRING"
        set Data(ColumnInfo.Waveform) "type SDDS_DOUBLE"
        set Data(Column.DeviceName) ""
        set Data(Column.Waveform) ""
        if [catch {exec cavget -list=[join $bpmList ,] -list=:ms:$coord -pend=30} valueList] {
            return -code error $result
        }
        set Data(Column.DeviceName) [list $bpmList]
        set Data(Column.Waveform) [list $valueList]
        APSAddToTmpFileList -ID 1 -fileList "$tmpRoot.${coord}0"
        if [catch {sdds save $tmpRoot.${coord}0 Data} result] {
            return -code error "APSRefreshVectorAdjust2: $result"
        }
        foreach type $pvTypes {
            if {[string compare $type bm]==0} {
                if [string compare $coord x]==0 continue
                set waveformFile $waveformFileDir/bmBpmInfo.sdds
            } else {
                set waveformFile $waveformFileDir/${type}[string toupper $coord]BpmInfo.sdds
            }
            APSAddToTmpFileList -ID 1 -fileList "$tmpRoot.${coord}0 $tmpRoot.all $tmpRoot.data"
            APSAddToTmpFileList -ID 1 -fileList "$tmpRoot.${coord}1 $tmpRoot.${coord}2 $tmpRoot.$type.$coord"
            if [catch {exec sddsconvert $waveformFile \
                         -rename=par,[string  toupper $coord]AdjustWaveformPV=WaveformPV \
                           $tmpRoot.all 
                exec sddswget $tmpRoot.all $tmpRoot.data } result] {
                return -code error "APSTransferBPMList (6) -- sddsconvert: $result"
            }
            if [catch {exec sddsxref $tmpRoot.all $tmpRoot.${coord}0 $tmpRoot.${coord}1 -match=DeviceName \
                           -nowarnings -take=Waveform 
                exec sddsselect $tmpRoot.data $tmpRoot.${coord}0 $tmpRoot.${coord}2 -invert -match=DeviceName 
                exec sddscombine $tmpRoot.${coord}1 $tmpRoot.${coord}2 -merge -pipe=out | \
                           sddssort -pipe=in -col=Index $tmpRoot.$type.$coord } result] {
                return -code error "APSTransferBPMList (7) -- sddsxref: $result"
            }
            lappend fileList $tmpRoot.$type.$coord
        }
    }
    APSAddToTmpFileList -ID 1 -fileList "$tmpRoot.out"
    if [catch {eval exec sddscombine $fileList -pipe=out | \
                 sddsprocess -pipe=in $tmpRoot.out -reedit=par,WaveformPV,%/:Out/:Adjust/ } result] {
        return -code error "APSSRTransferBPMList (8) -- sddsprocess : $result"
    }
    if [catch {exec sddswput $tmpRoot.out} result] {
        return -code error "APSSRTransferBPMList (9) -- sddswput: $result"
    }
}

proc APSSRGetWorkingP0SectorsList {args} {
    set iocs 0
    APSStrictParseArguments {iocs}

    set statusDir /home/helios/oagData/sr/BPMStatus
    set tmpfile /tmp/[APSTmpString]
    if [catch {exec sddsprocess $statusDir/config.sdds -pipe=out \
                 -match=col,DeviceName=*B:P0 \
                 -filter=col,NonexistentH,0,0,NonexistentV,0,0,& \
                 -filter=col,OkForSteeringH,1,1,OkForSteeringV,1,1,& \
                 | sddsconvert -pipe -retain=col,DeviceName \
                 | sddsprocess -pipe=in ${tmpfile}BP0 \
                 -scan=col,Sector,DeviceName,S%d,type=long
        exec sddsprocess $statusDir/config.sdds -pipe=out \
                 -match=col,DeviceName=*A:P0 \
                 -filter=col,NonexistentH,0,0,NonexistentV,0,0,& \
                 -filter=col,OkForSteeringH,1,1,OkForSteeringV,1,1,& \
                 | sddsconvert -pipe -retain=col,DeviceName \
                 | sddsprocess -pipe=in ${tmpfile}AP0 \
                 -scan=col,Sector,DeviceName,S%d,type=long \
                 "-redefine=col,Sector,Sector 1 -,type=long" \
             } result ] {
        return -code error "GetWorkingP0SectorsList (1) - sddsprocess: $result"
    }
    # check that both BP0 and AP0 of the same sector are ok.
    if [catch {exec sddsselect ${tmpfile}BP0 ${tmpfile}AP0 -pipe=out \
                 -equate=Sector \
                 | sdds2stream -col=Sector -pipe } P0List ] {
        return -code error "GetWorkingP0SectorsList (2) -- sddsselect: $P0List"
    }
    if {$iocs} {
        set iocList ""
        foreach sector $P0List {
            if [expr ${sector}%2] {
                lappend iocList $sector
            }
        }
        set P0List $iocList
    }
    return $P0List
}

proc APSSRMeasureBPMoffsetInfo {} {
    return "This procedure prepares the storage ring beam for BPM offset measurement. Several steps are to be followed manually before the offset measurement application is run. "
}
proc APSSRMeasureBPMoffset {} {
    APSMpStep TurnOffCOrbitCorrection -desc "Turn off DC orbit correction"
    APSMpStep SetupBPMAverging -desc "Setup BPM averaging"
    APSMpStep SetupRTOrbitCorrection -desc "Setup RT orbit correction"
    APSMpStep LaunchMeasurementScreens -desc "Launch BPM offset"
    APSMpStep
}

proc APSMpSRUncogBPMInfo {} {
    return "This procedure sets the monopulse bpm timing to normal fixed timing. RTFB loops should be open. It is ok to have the gaps closed."
}

proc APSMpSRUncogBPM {} {
    APSMpStep CheckConditions -desc "Check orbit correction, RTFB and ID gaps conditions"
    APSInfoWindow .info -infoMessage "If beam is present, check RTFB, orbit correction and ID gaps. Make sure that RTFB loops are open, orbit correction suspended (or aborted)." -modal 1
    if {[tk_dialog2 .warningDialog "Warning Message" \
           "You are about to stop bpm cogging (i.e. set \"uncog\" mode). Are you sure?" \
           warning -1 "Yes, because I personally checked\nthat RTFB loops are open and\nID gaps are open." "Yes, because there is\nno beam present." Cancel] == 2} {
        APSMpReturn ok 0
    }
    APSMpStep StopCogging -desc "Stop bpm timing cogging"
    #exec /home/helios/SR/bin/uncog 
    if [catch {APSSRCogBPM -cogstate nocog} result] {
        APSMpReturn error "APSMpSRUncogBPM (1): $result"
    }
    APSMpReturn ok 0
}


proc APSMpSRCog324FastBPMInfo {} {
    return "This procedure sets the monopulse bpm timing in cogging mode. Used for 324 bunch pattern. Should not be turned on with RTFB loops closed unless all 324 buckets have been filled."
}

proc APSMpSRCog324FastBPM {} {
    APSMpStep CheckConditions -desc "Check orbit correction, RTFB and ID gaps conditions"
    APSInfoWindow .info -infoMessage "Check RTFB and orbit correction and ID gaps. Make sure that RTFB loops are open, orbit correction suspended (or aborted)." -modal 1
    if {[tk_dialog2 .warningDialog "Warning Message" \
           "You are about to start bpm cogging (i.e. set \"cogging\" mode). Are you sure?" \
           warning -1 "Yes, because I personally checked\nthat RTFB loops are open and\nID gaps are open." "Yes, because there is\nno beam present." Cancel] == 2} {
        APSMpReturn ok 0
    }
    APSMpStep StartCogging -desc "Start bpm timing cogging"
    # exec /home/helios/SR/bin/cog324Fast 
    if [catch {APSSRCogBPM -cogstate "324 Singlets"} result] {
        APSMpReturn error "APSMpSRCog324FastBPM: $result"
    }
    APSMpReturn ok 0
}

proc APSMpSRCog1+22SingletsInfo {} {
    return "This procedure sets the monopulse bpm timing in cogging mode. Used for 1+22 singlets fill pattern."
}

proc APSMpSRCog1+22Singlets {} {
    APSMpStep CheckConditions -desc "Check orbit correction, RTFB and ID gaps conditions"
    APSInfoWindow .info -infoMessage "Check RTFB and orbit correction and ID gaps. Make sure that RTFB loops are open, orbit correction suspended (or aborted)." -modal 1
    if {[tk_dialog2 .warningDialog "Warning Message" \
           "You are about to start bpm cogging (i.e. set \"cogging\" mode). Are you sure?" \
           warning -1 "Yes, because I personally checked\nthat RTFB loops are open and\nID gaps are open." "Yes, because there is\nno beam present." Cancel] == 2} {
        APSMpReturn ok 0
    }
    APSMpStep StartCogging -desc "Start bpm timing cogging"
    #exec /home/helios/SR/daily/0307/29/1/cogging/cog1+22Singlets
    if [catch {APSSRCogBPM -cogstate 1+22Singlets} result] {
        APSMpReturn error "APSMpSrCog1+22Singlets: $result"
    }
    APSMpReturn ok 0
}

proc APSMpSRCog24SingletsInfo {} {
    return "This procedure sets the monopulse bpm timing in cogging mode. Used for 24 singlets fill pattern."
}

proc  APSMpSRCog24Singlets {} {
    APSMpStep CheckConditions -desc "Check orbit correction, RTFB and ID gaps conditions"
    APSInfoWindow .info -infoMessage "Check RTFB and orbit correction and ID gaps. Make sure that RTFB loops are open, orbit correction suspended (or aborted)." -modal 1
    if {[tk_dialog2 .warningDialog "Warning Message" \
           "You are about to start bpm cogging (i.e. set \"cogging\" mode). Are you sure?" \
           warning -1 "Yes, because I personally checked\nthat RTFB loops are open and\nID gaps are open." "Yes, because there is\nno beam present." Cancel] == 2} {
        APSMpReturn ok 0
    }
    APSMpStep StartCogging -desc "Start bpm timing cogging"
    #exec /home/helios/SR/daily/0211/05/1/cogging/cog24Singlets
    if [catch {APSSRCogBPM -cogstate "24 Singlets"} result] {
        APSMpReturn error "APSMpSRCog24Singlets: $result"
    }
    APSMpReturn ok 0
}

proc APSMpSRBTMStatusInfo {args} {
    return "This procedure is used to determine whether the bpm timing is in cogging mode or not. In cogging mode the 40 plots that appear in one frame will have points scattered. In non-cogging mode the plots will have only one point non-zero. An exec log will print out the value of the S<n>Bpm:TimingModeMO PV of each timing module. Running this procedure is safe at any time.\n\n Tjis procedure is obsolete because the BpmTime pvs are non-existent."
}

proc APSMpSRBTMStatus {args} {
    #this proc is converted from /home/helios/ASDOPS/bin/cogTest 
    global tcl_platform
    if {$tcl_platform(os) == "Linux"} {
	set domain [exec dnsdomainname]
    } else {
	set domain [exec domainname]
    }
    APSMpStep "$domain"
    if {([string compare "accel.ntw0rk" $domain]==0) || ([string compare "aps4.anl.gov" $domain]==0)} {
        if [catch {exec cavput -list=S -range=beg=1,end=40 \
                     -list=BpmTime:RamContentsWF.PROC=1 -pend=30} result] {
            APSMpStep "Error in getting cogging status: $result"
        }
    } else {
        APSAlertBox .alert -type warning -name warning  -errorMessage "You are running on oxygen, the RAM contents may not be refrehsed."
    }
    set ramPVList ""
    for {set i 1} {$i<41} {incr i} {
        lappend ramPVList S${i}BpmTime:RamContentsWF.VAL
    }
    set tmpfile /tmp/[APSTmpString]
    APSAddToTmpFileList -ID 1 -fileList $tmpfile
    if [catch {exec sddswmonitor -PVnames=[join $ramPVList ,] $tmpfile} result] {
        APSMpReturn error "APSMpSRBTMStatus: $result"
    }
    exec sddsplot -col=Index,S* $tmpfile -grap=dot -sep=1 -layout=8,5 &
    #exec /home/helios/ASDOPS/bin/cogTest &
    APSExecLog .coggingStatus -unixCommand "cavget -list=S -range=beg=1,end=40 -list=BpmTime:CogModeMO -labeled -pend=30"
    .coggingStatus.buttonRow.ok.button configure \
      -command "[.coggingStatus.buttonRow.ok.button cget -command]; set coggingStatusDone 1"
    .coggingStatus.buttonRow.cancel.button configure \
      -command "[.coggingStatus.buttonRow.cancel.button cget -command]; set coggingStatusDone 1"
    .coggingStatus.buttonRow.abort.button configure \
      -command "[.coggingStatus.buttonRow.abort.button cget -command]; set coggingStatusDone 1"
    wm protocol .coggingStatus WM_DELETE_WINDOW {set coggingStatusDone 1}
    
    tkwait variable coggingStatusDone

    APSMpReturn ok 0
}

proc APSMpSRBTMSetupInfo {} {
    return "This procedure loads the BSP100 BPM timing control RAM waveform for selected bunch pattern. The old cogging BTM pvs have been retired."
}

proc APSMpSRBTMSetupDialog {args} {
    global APSMpSRBTMSetup
    set pem 1
    APSStrictParseArguments {frame pem}
    if !$pem {
        set APSMpSRBTMSetup(cancel) 0
        APSDialogBox .btm -name "Set SR Cogging" -cancelCommand "set APSMpSRBTMSetup(cancel) 1"
        set frame .btm.userFrame
    }
    
    #remove "1+22Singlets" since it no longer in use
    APSRadioButtonFrame .rb -parent $frame \
      -label "BTM (cogging) pattern Choice:" -buttonList {"Uncog BPM for hybrid mode" "324 Singlets" "24 Singlets" "561 Hybrid for studies only"} \
      -valueList {nocog "324singlets" "24singlets" "hybrid561"} -variable "APSMpSRBTMSetup(cog)"
    # The cogstats are nocog=0, "1+22Singlets"=1, "24 Singlets"=2 "hybrid 561"=3, "hybrid"=4,
    #"324 Singlets"=5, "Custom"=6
    if !$pem {
        tkwait window .btm
        if $APSMpSRBTMSetup(cancel) {
            APSMpReturn error "BTM setup was cancelled."
        }
    }
}

proc APSMpSRBTMSetup {args} {
    global APSMpSRBTMSetup
    set APSMpSRBTMSetup(cog) nocog
    
    set cog ""
    APSStrictParseArguments {cog}
    APSMpStep init -promptDialog "APSMpSRBTMSetupDialog -frame "
    if [string length $cog] {
        set APSMpSRBTMSetup(cog) $cog
    }
    
    APSMpStep CheckConditions -desc "Check orbit correction, RTFB and ID gaps conditions"
   
    #APSInfoWindow .info -infoMessage "Check RTFB and orbit correction and ID gaps. Make sure that RTFB loops are open, orbit correction suspended (or aborted)." -modal 1
    #the cogstats are nocog=0, "1+22Singlets"=1, "24 Singlets"=2 "hybrid 561"=3, "hybrid"=4,
    #"324 Singlets"=5, "Custom"=6
    
    set cogstateList {nocog 1+22singlets "24singlets" "hybrid561" hybrid "324singlets" "custom"}
    set cogmode [lsearch $cogstateList $APSMpSRBTMSetup(cog)]
    
    if {$cogmode<0} {
        APSMpReturn error "Unknown cogging mode provided - $APSMpSRBTMSetup(cog)"
    }
    set referenceFile /home/helios/oagData/sr/bunchPatterns/bunchPatternFillRef.$APSMpSRBTMSetup(cog)
    #do not check for nocog mode (which has not reference pattern)
    if [file exist $referenceFile] {
        #compare current pattern with selected reference pattern
        set tmpfile /tmp/[APSTmpString]
        APSAddToTmpFileList -ID setupcog -fileList $tmpfile
        if [catch {exec sddswget -pv=Mt:S:FillPatternWF.VAL $tmpfile} result] {
            APSMpReturn error "Unable to read Mt:S:FillPatternWF.VAL waveform: $result"
        }
        if [catch {exec sddsdiff -col=Index,Waveform $referenceFile $tmpfile} result] {
            set answer [APSMultipleChoice [APSUniqueName .] -modal 1 -name Warning \
                            -type warning -beep continuous \
                            -question "The selected BTM (i.e. cogging) pattern ($APSMpSRBTMSetup(cog)) does not match the current fill pattern, there are two possible reasons:\n\n1)The BTM pattern does not match the fill pattern;\n\n2)The BTM and fill patterns do match, but the injection is incomplete. In this case, press \"Abort\" and restart the pem after injection is completed.\n\nIn general pressing \"Continue\" will result in a different BTM pattern from what is expected, and therefore give misleading or noisy orbit data.\n\n Continue or abort?" \
                            -returnList {Continue Abort} -labelList {Continue Abort} ]
            
            if {$answer=="Abort"} {
                APSMpReturn error "APSMpBTMSetup was aborted due to mis-match of fill-pattern!"
            }
        }
    }
    if {$APSMpSRBTMSetup(cog) !="nocog"} {
        #check current
        if [catch {exec cavget -list=S-DCCT:CurrentM -pend=30} current] {
            APSMpReturn error "APSMpBTMSetup: $current"
        }
        if {$current<15.0} {
            set answer [APSMultipleChoice [APSUniqueName .] -modal 1 -name Warning \
                            -type warning -beep continuous \
                            -question "The storage ring current ($current) is less than 15mA. It is likely that the resulting BTM pattern won't be what is expected.\n\nContinue or abort?" \
                            -returnList {Continue Abort} -labelList {Continue Abort} ]
            
            if {$answer=="Abort"} {
                APSMpReturn error "APSMpBTMSetup was aborted due to the storage ring current is less than 15mA."
            }
        }
    }
   
    global apshpFilterCutoffVert apshpFilterCutoffHoriz apshpFilterInitialVert apshpFilterInitialHoriz apshpFilterRampPoints apshpFilterRampInterval
    APSMpSetRTFBGlobalParameters -readonly 1
    # determine if any loops are closed
    if [catch {exec cavget -list=SRFB:GBL:LoopStatusBI.VAL -pend=30} RTFBLoopStatus] {
        APSMpReturn error $RTFBLoopStatus
    }
    if {$RTFBLoopStatus=="On"} {
        APSMpStep OpenRTFBLoops -desc "Open RTFB loops."
        if [catch {APSMpRTFBResetOpenLoops -hpFilterInitialVert $apshpFilterInitialVert \
                     -hpFilterInitialHoriz $apshpFilterInitialHoriz } result] {
            APSMpReturn error "APSMpRTFBPreReboot3: $result"
        }
    }

    #setup BSP-100 BPMs timing
    switch $APSMpSRBTMSetup(cog) {
        nocog {
            set reference SBPMWaveform-singleBunch.gz
        }
        hybrid561 {
            set reference SBPMWaveform-hybrid.gz
        }
        24singlets {
            set reference SBPMWaveform-24singlets.gz
        }
        324singlets {
            set reference SBPMWaveform-324singlets.gz
        }
        default {
            set reference ""
        }
    }
    set scrDir /home/helios/oagData/SCR/snapshots/SBPMWaveform
    if {[string length $reference]  && [file exist $scrDir/$reference]} {
        #rearm theS35, S38 FPGA BPMs
        #APSMpStep "Setup FPGA bpm triggers, and arm FPGA bpms."
        #if [catch {APSSetupFPGABpmTriggers} result] {
        #    APSMpReturn error "APSMpSRBTMSetup10 -- unable to re-arm FPGA BPMs: $result"
        #}
        set timingFile [file readlink $scrDir/$reference]
        APSMpStep "Setup FPGA bpm timing."
        if [catch {exec sddscasr $timingFile -restore -pendIOTime=60  \
                     -waveform=directory=$scrDir,onefile,rootname=[file root [file tail $timingFile]],extension=.waveform.gz} result] {
            APSMpReturn error "APSMpSRBTMSetup11 -- unable to setup BSP-100 BPM timing: $result"
        }
    }
    if {$RTFBLoopStatus=="On"} {
        APSMpStep CloseRTFBLoops -desc "Close RTFB loops."
        if [catch {APSMpRTFBCloseLoops -hpFilterCutoffVert $apshpFilterCutoffVert \
                     -hpFilterCutoffHoriz $apshpFilterCutoffHoriz \
                     -hpFilterInitialVert $apshpFilterInitialVert \
                     -hpFilterInitialHoriz $apshpFilterInitialHoriz \
                     -hpFilterRampPoints $apshpFilterRampPoints \
                     -hpFilterRampInterval $apshpFilterRampInterval } result] {
            APSMpReturn error "APSMpSRBTMSetup12: $result"
        }
    }
    APSMpReturn ok
    
}



proc APSMpSRCoggingSetupObsolete {args} {
    global APSMpSRCoggingSetup
    set APSMpSRCoggingSetup(cog) 1
    for {set i 1} {$i <= 33} {incr i 2} {
        set APSMpSRCoggingSetup(S$i) 1
    }
    for {set i 35} {$i <= 40} {incr i} {
        set APSMpSRCoggingSetup(S$i) 1
    }
    APSMpStep init -promptDialog "APSMpSRCoggingSetupDialog -frame "
    APSMpStep CheckConditions -desc "Check orbit correction, RTFB and ID gaps conditions"
    APSInfoWindow .info -infoMessage "Check RTFB and orbit correction and ID gaps. Make sure that RTFB loops are open, orbit correction suspended (or aborted)." -modal 1

    if {$APSMpSRCoggingSetup(cog) == 1} {
        set message "You are about to stop bpm cogging (i.e. set \"uncog\" mode). Are you sure?"
    } else {
        set message "You are about to start bpm cogging (i.e. set \"cogging\" mode). Are you sure?"
    }
    if {[tk_dialog2 .warningDialog "Warning Message" $message \
           warning -1 "Yes, because I personally checked\nthat RTFB loops are open." "Yes, because there is\nno beam present." Cancel] == 2} {
        APSMpReturn ok 0
    }
    
    set subSectors ""
    for {set i 1} {$i <= 33} {incr i 2} {
        if {$APSMpSRCoggingSetup(S$i)} {
            set APSMpSRCoggingSetup(S[expr {$i + 1}]) 1
        } else {
            set APSMpSRCoggingSetup(S[expr {$i + 1}]) 0
        }
        append subSectors "$i "
    }
    for {set i 35} {$i <= 40} {incr i} {
        append subSectors "$i "
    }
    set pvVars ""
    foreach i $subSectors {
        if {$APSMpSRCoggingSetup(S$i)} {
            append pvVars "S${i}BpmLoadDefPatternsBO S${i}BpmBnchClkGenLoadPatBO S${i}Bpm:TimingModeMO "
        }
    }
    for {set i 1} {$i <= 40} {incr i} {
        if {$APSMpSRCoggingSetup(S$i)} {
            append pvVars "S${i}BpmTime:CogModeMO S${i}BpmTime:LoadCogPatBO S${i}BpmTime:TurnsInPatternP "
        }
    }

    if {![llength $pvVars]} {APSMpReturn ok}
    eval global $pvVars
    pv toggleErrorMode
    if {[catch {pv linkw $pvVars $pvVars} results]} {
        APSMpReturn error "APSMpSRCoggingSetup1: unable to connect to PVs: $results"
    }

    if {$APSMpSRCoggingSetup(cog) == 1} {
        #Uncog
        APSMpStep StopCogging -desc "Stop bpm timing cogging"
        foreach i $subSectors {
            if {$APSMpSRCoggingSetup(S$i)} {
                set S${i}BpmLoadDefPatternsBO 1
                if {[catch {pv putw S${i}BpmLoadDefPatternsBO} results]} {
                    APSMpReturn error "APSMpSRCoggingSetup2: unable to set PVs in sector $i: $results"
                }
            }
        }
        # disable BTM cogging
        foreach i $subSectors {
            if {$APSMpSRCoggingSetup(S$i)} {
                set S${i}Bpm:TimingModeMO 0
                if {[catch {pv putw S${i}Bpm:TimingModeMO} results]} {
                    APSMpReturn error "APSMpSRCoggingSetup3: unable to set PVs in sector $i: $results"
                }
            }
        }
        # a vectorized put to frank's new enumerated cogging pv's
        # 0 = nocog, 1="1+22Singlets", 2 = "24 Singlets" 3 = hybrid 561, 4 = hybrid
        for {set i 1} {$i <= 40} {incr i} {
            if {$APSMpSRCoggingSetup(S$i)} {
                set S${i}BpmTime:CogModeMO 0
                set S${i}BpmTime:LoadCogPatBO 1
                if {[catch {pv putw S${i}BpmTime:CogModeMO} results]} {
                    APSMpReturn error "APSMpSRCoggingSetup4: unable to set PVs in sector $i: $results"
                }
                if {[catch {pv putw S${i}BpmTime:LoadCogPatBO} results]} {
                    APSMpReturn error "APSMpSRCoggingSetup5: unable to set PVs in sector $i: $results"
                }
            }
        }
    } elseif {$APSMpSRCoggingSetup(cog) == 2} {
        #Cog 324 Fast BPM
        APSMpStep StartCogging -desc "Start bpm timing cogging"
        foreach i $subSectors {
            if {$APSMpSRCoggingSetup(S$i)} {
                set S${i}BpmBnchClkGenLoadPatBO 1
                if {[catch {pv putw S${i}BpmBnchClkGenLoadPatBO} results]} {
                    APSMpReturn error "APSMpSRCoggingSetup6: unable to set PVs in sector $i: $results"
                }
            }
        }
        for {set i 1} {$i <= 40} {incr i} {
            if {$APSMpSRCoggingSetup(S$i)} {
                set S${i}BpmTime:TurnsInPatternP 216
                if {[catch {pv putw S${i}BpmTime:TurnsInPatternP} results]} {
                    APSMpReturn error "APSMpSRCoggingSetup7: unable to set PVs in sector $i: $results"
                }
            }
        }
        set options ""
        set n 0
        for {set i 1} {$i <= 40} {incr i} {
            if {$APSMpSRCoggingSetup(S$i)} {
                if {$n == 0} {
                    append options "-match=parameter,WaveformPV=S${i}BpmTime:WriteRamWF"
                    set n 1
                } else {
                    append options ",WaveformPV=S${i}BpmTime:WriteRamWF,|"
                }
            }
        }
        for {set i 1} {$i <= 40} {incr i} {
            if {$APSMpSRCoggingSetup(S$i)} {
                set S${i}BpmTime:CogModeMO 0
                set S${i}BpmTime:LoadCogPatBO 1
                if {[catch {pv putw S${i}BpmTime:CogModeMO} results]} {
                    APSMpReturn error "APSMpSRCoggingSetup8: unable to set PVs in sector $i: $results"
                }
                #                if {[catch {pv putw S${i}BpmTime:LoadCogPatBO} results]} {
                #                    APSMpReturn error "APSMpSRCoggingSetup: unable to set PVs in sector $i: $results"
                #                }
            }
        }
        set fileName /tmp/[APSTmpString]
        APSAddToTempFileList $fileName
        if {[catch {exec sddsprocess /home/helios/oagData/sr/coggingTiming/324FastBPMmode.sdds $fileName $options} results]} {
            APSMpReturn error "APSMpSRCoggingSetup9: $results"
        }
        if {[catch {exec sddswput $fileName} results]} {
            APSMpReturn error "APSMpSRCoggingSetup10: $results"
        }
    } elseif {$APSMpSRCoggingSetup(cog) == 3} {
        #Cog 1+22 Singlets
        APSMpStep StartCogging -desc "Start bpm timing cogging"
        foreach i $subSectors {
            if {$APSMpSRCoggingSetup(S$i)} {
                set S${i}BpmBnchClkGenLoadPatBO 1
                if {[catch {pv putw S${i}BpmBnchClkGenLoadPatBO} results]} {
                    APSMpReturn error "APSMpSRCoggingSetup11: unable to set PVs in sector $i: $results"
                }
            }
        }
        # enable BTM cogging
        foreach i $subSectors {
            if {$APSMpSRCoggingSetup(S$i)} {
                set S${i}Bpm:TimingModeMO 1
                if {[catch {pv putw S${i}Bpm:TimingModeMO} results]} {
                    APSMpReturn error "APSMpSRCoggingSetup12: unable to set PVs in sector $i: $results"
                }
            }
        }
        # a vectorized put to frank's new enumerated cogging pv's
        # 0 = nocog, 1="1+22Singlets", 2 = "24 Singlets" 3 = hybrid 561, 4 = hybrid
        
        for {set i 1} {$i <= 40} {incr i} {
            if {$APSMpSRCoggingSetup(S$i)} {
                set S${i}BpmTime:CogModeMO 1
                set S${i}BpmTime:LoadCogPatBO 1
                if {[catch {pv putw S${i}BpmTime:CogModeMO} results]} {
                    APSMpReturn error "APSMpSRCoggingSetup13: unable to set PVs in sector $i: $results"
                }
                if {[catch {pv putw S${i}BpmTime:LoadCogPatBO} results]} {
                    APSMpReturn error "APSMpSRCoggingSetup14: unable to set PVs in sector $i: $results"
                }
            }
        }
    } elseif {$APSMpSRCoggingSetup(cog) == 4} {
        #Cog 24 Singlets
        APSMpStep StartCogging -desc "Start bpm timing cogging"
        foreach i $subSectors {
            if {$APSMpSRCoggingSetup(S$i)} {
                set S${i}BpmBnchClkGenLoadPatBO 1
                puts "S${i}BpmBnchClkGenLoadPatBO"
                if {[catch {pv putw S${i}BpmBnchClkGenLoadPatBO} results]} {
                    APSMpReturn error "APSMpSRCoggingSetup15: unable to set PVs in sector $i: $results"
                }
            }
        }
        # enable BTM cogging
        foreach i $subSectors {
            if {$APSMpSRCoggingSetup(S$i)} {
                set S${i}Bpm:TimingModeMO 1
                puts "S${i}Bpm:TimingModeMO"
                if {[catch {pv putw S${i}Bpm:TimingModeMO} results]} {
                    APSMpReturn error "APSMpSRCoggingSetup16: unable to set PVs in sector $i: $results"
                }
            }
        }
        # a vectorized put to frank's new enumerated cogging pv's
        # 0 = nocog, 1="1+22Singlets", 2 = "24 Singlets" 3 = hybrid 561, 4 = hybrid
        
        for {set i 1} {$i <= 40} {incr i} {
            if {$APSMpSRCoggingSetup(S$i)} {
                set S${i}BpmTime:CogModeMO 2
                set S${i}BpmTime:LoadCogPatBO 1
                puts "S${i}BpmTime:CogModeMO"
                puts "S${i}BpmTime:LoadCogPatBO"
                if {[catch {pv putw S${i}BpmTime:CogModeMO} results]} {
                    APSMpReturn error "APSMpSRCoggingSetup17: unable to set PVs in sector $i: $results"
                }
                if {[catch {pv putw S${i}BpmTime:LoadCogPatBO} results]} {
                    APSMpReturn error "APSMpSRCoggingSetup18: unable to set PVs in sector $i: $results"
                }
            }
        }
    } elseif {$APSMpSRCoggingSetup(cog) == 5} {
        #Cog 561 Hybrid
        APSMpStep StartCogging -desc "Start bpm timing cogging"
        foreach i $subSectors {
            if {$APSMpSRCoggingSetup(S$i)} {
                set S${i}BpmBnchClkGenLoadPatBO 1
                if {[catch {pv putw S${i}BpmBnchClkGenLoadPatBO} results]} {
                    APSMpReturn error "APSMpSRCoggingSetup19: unable to set PVs in sector $i: $results"
                }
            }
        }
        # enable BTM cogging
        foreach i $subSectors {
            if {$APSMpSRCoggingSetup(S$i)} {
                set S${i}Bpm:TimingModeMO 1
                if {[catch {pv putw S${i}Bpm:TimingModeMO} results]} {
                    APSMpReturn error "APSMpSRCoggingSetup20: unable to set PVs in sector $i: $results"
                }
            }
        }
        # a vectorized put to frank's new enumerated cogging pv's
        # 0 = nocog, 1="1+22Singlets", 2 = "24 Singlets" 3 = hybrid 561, 4 = hybrid
        
        for {set i 1} {$i <= 40} {incr i} {
            if {$APSMpSRCoggingSetup(S$i)} {
                set S${i}BpmTime:CogModeMO 3
                set S${i}BpmTime:LoadCogPatBO 1
                if {[catch {pv putw S${i}BpmTime:CogModeMO} results]} {
                    APSMpReturn error "APSMpSRCoggingSetup21: unable to set PVs in sector $i: $results"
                }
                if {[catch {pv putw S${i}BpmTime:LoadCogPatBO} results]} {
                    APSMpReturn error "APSMpSRCoggingSetup22: unable to set PVs in sector $i: $results"
                }
            }
        }
    } elseif {$APSMpSRCoggingSetup(cog) == 6} {
        #Hybrid
        APSMpStep StartCogging -desc "Start bpm timing cogging"
        foreach i $subSectors {
            if {$APSMpSRCoggingSetup(S$i)} {
                set S${i}BpmBnchClkGenLoadPatBO 1
                if {[catch {pv putw S${i}BpmBnchClkGenLoadPatBO} results]} {
                    APSMpReturn error "APSMpSRCoggingSetup23: unable to set PVs in sector $i: $results"
                }
            }
        }
        # enable BTM cogging
        foreach i $subSectors {
            if {$APSMpSRCoggingSetup(S$i)} {
                set S${i}Bpm:TimingModeMO 1
                if {[catch {pv putw S${i}Bpm:TimingModeMO} results]} {
                    APSMpReturn error "APSMpSRCoggingSetup24: unable to set PVs in sector $i: $results"
                }
            }
        }
        # a vectorized put to frank's new enumerated cogging pv's
        # 0 = nocog, 1="1+22Singlets", 2 = "24 Singlets" 3 = hybrid 561, 4 = hybrid
        
        for {set i 1} {$i <= 40} {incr i} {
            if {$APSMpSRCoggingSetup(S$i)} {
                set S${i}BpmTime:CogModeMO 4
                set S${i}BpmTime:LoadCogPatBO 1
                if {[catch {pv putw S${i}BpmTime:CogModeMO} results]} {
                    APSMpReturn error "APSMpSRCoggingSetup25: unable to set PVs in sector $i: $results"
                }
                if {[catch {pv putw S${i}BpmTime:LoadCogPatBO} results]} {
                    APSMpReturn error "APSMpSRCoggingSetup26: unable to set PVs in sector $i: $results"
                }
            }
        }
    }
    APSMpReturn ok
}

proc APSMpExcludedBPMList {args} {
    set excludeP0s 0
    set excludeIDXrays 0
    set excludeBMXrays 0
    set excludeNbBPMs 0
    set excludeMpBPMs 0
    set excludeFPGABPMs 0
    set plane ""
    APSStrictParseArguments {excludeP0s excludeIDXrays excludeBMXrays excludeNbBPMs \
                         excludeMpBPMs plane excludeFPGABPMs}
    set config /home/helios/oagData/sr/BPMStatus/config.sdds
    set tmpfile /tmp/[APSTmpString]
    APSAddToTmpFileList -ID APSMpSRBPM -fileList $tmpfile
    set plane [string toupper $plane] 
    switch $plane {
        H -
        V {
            if [catch {exec sddsprocess $config  $tmpfile \
                         -filter=col,Nonexistent$plane,1,1 -noWarning} result] {
                return -code error "APSMpExcludedBPMList(1): $result"
            } 
        }
        default {
            if [catch {exec sddsprocess $config $tmpfile \
                         -filter=col,NonexistentH,1,1 \
                         -filter=col,NonexistentV,1,1 -noWarning } result] {
                return -code error "APSMpExcludedBPMList(2): $result"
            }
        }
    }
    if [catch {exec sdds2stream $tmpfile -col=DeviceName } excludeList ] {
         return -code error "APSMpExcludedBPMList(3): $execludeList"
    }
    set firstTerm 1
    set matchOption ""
    if $excludeP0s {
        set matchOption "-match=col,DeviceName=S*P0*"
        set firstTerm 0
    }
    if $excludeIDXrays {
        if $firstTerm {
            set matchOption "-match=col,DeviceName=S*ID*"
            set firstTerm 0
        } else {
            append matchOption ",DeviceName=S*ID*,|"
        }
    }
    if $excludeBMXrays {
        if $firstTerm {
            set matchOption "-match=col,DeviceName=S*BM*"
            set firstTerm 0
        } else {
            append matchOption ",DeviceName=S*BM*,|"
        }
    }
    if $excludeNbBPMs {
        if $firstTerm {
            set matchOption "-match=col,ElectronicsType=Narrowband"
            set firstTerm 0
        } else {
            append matchOption ",ElectronicsType=Narrowband,|"
        }
    }
    if $excludeMpBPMs {
        if $firstTerm {
            set matchOption "-match=col,ElectronicsType=Monopulse"
            set firstTerm 0
        } else {
            append matchOption ",ElectronicsType=Monopulse,|"
        }
    }
    if $excludeFPGABPMs {
        if $firstTerm {
            set matchOption "-match=col,ElectronicsType=FPGA"
            set firstTerm 0
        } else {
            append matchOption ",ElectronicsType=FPGA,|"
        }
    }
    if [string length $matchOption] {
        if [catch {exec sddsprocess $config -pipe=out $matchOption \
                     | sdds2stream -pipe -col=DeviceName } bpmList] {
            return -code error "APSMpExcludedBPMList(4): $bpmList"
        }
        set excludeList [concat $excludeList $bpmList]
    }
    return $excludeList
}

proc APSSRCogBPM {args} {
    set cogstate ""
    set customContentsFile ""
    APSStrictParseArguments {cogstate customContentsFile}

    # a vectorized put to frank's new enumerated cogging pv's
    # 0 = nocog, 1="1+22Singlets", 2 = "24 Singlets" 3 = hybrid 561, 4 = hybrid, 5="324 Singlets" 6=custom
    
    set cogstateList {nocog 1+22singlets "24 singlets" "hybrid 561" hybrid "324 singlets" "custom"}
    set cogstate [string tolower $cogstate]
    set cogvalue [lsearch $cogstateList $cogstate]
    if {$cogvalue<0} {
        return -code error "APSSRCogBPM (1): unknown cogging state - $cogstate given!"
    }
    if $cogstate=="custom" {
        if ![string length $customContentsFile] {
            return -code error "APSSRCogBPM: custom contents file not provided"
        }
        if ![file exists $customContentsFile] {
            return -code error "APSSRCogBPM (2): custom contents file - $customContentsFile does not exist"
        }
    }
    if [catch {exec cavput -pend=5 -list=S -range=begin=1,end=33,interval=2 \
                 -list=BpmLoadDefPatternsBO=1} result] {
        return -code error "APSSRCogBPM(3) - cavput: $result"
    }
    if [catch {exec cavput -pend=5 -list=S -range=begin=35,end=40 \
                 -list=BpmLoadDefPatternsBO=1} result] {
        return -code error "APSSRCogBPM(4) - cavput: $result"
    }
    if !$cogvalue {
        #disable BTM cogging
        if [catch {exec cavput -list=S -range=begin=1,end=40 -list=Bpm:TimingModeMO=0} result] {
            return -code error "APSSRCogBPM(5) - cavput: $result"
        }
    } else {
        # enable BTM cogging
        if [catch {exec cavput -list=S -range=begin=1,end=40 -list=Bpm:TimingModeMO=1} result] {
            return -code error "APSSRCogBPM(6) -cavput: $result"
        }
    }
    #noneed to setup BpmTime:TurnsInPatternP for preset patterns
    if [catch {exec cavput -list=S -range=begin=1,end=40 -list=BpmTime:CogModeMO=$cogvalue \
                 -pend=5} result] {
        return -code error "APSSRCogBPM(7) - cavput: $result"
    }
    if [catch {exec cavput -list=S -range=begin=1,end=40 -list=BpmTime:LoadCogPatBO=1 \
                 -pend=5 } result] {
        return -code error "APSSRCogBPM(8) - cavput: $result"
    }
    if $cogstate=="custom" {
        #the turns pattern should be obtained from customContentsFile (we do not have any now 
        # for test)
        if [catch {exec cavput -pend=5 -list=S -range=begin=1,end=40 \
                     -list=BpmTime:TurnsInPatternP=216} result] {
            return -code error "APSSRCogBPM(9) - cavput: error in setting turn pattern for 324 singlets: $result"
        }
        if [catch {exec sddswput $customContentsFile} result] {
            return -code error "APSSRCogBPM(10) - cavput: error in loading custom contents: $result"
        }
    }
}

proc APSMpForceApplyBPMbladeGainsInfo {} {
    return "This procedure sets \"force\" gain for xbpm pre-amplifiers. It 1st loads pvs from sbpm ref file from category \"Xray blade gain=10\" with filter *:?:gainMO and then reloads same pvs gainMO from sbpm ubop file."
}

proc APSMpForceApplyBPMbladeGainsInitDialog {frame} {
    global status APSMpForceApplyBPMbladeGains

    set status "select a SCR file"
    
    APSAddSCRDialog .scr -parent $frame -system SBPMs \
        -arrayName APSMpForceApplyBPMbladeGains \
        -defaultFile $APSMpForceApplyBPMbladeGains(ShortFilename)

    APSMpReturn ok
}

#This procedure has been placed in the attic
proc APSMpForceApplyBPMbladeGains {} {
    global APSMpForceApplyBPMbladeGains
    set SCRDir /home/helios/oagData/SCR/snapshots/SBPMs
    set referenceFile SBPMs-XrayBladeGain10.gz
    set ubopFile SBPMs-Preferred.gz
    APSMpStep init -promptDialog "APSMpPromptInitDialog"
    
    # if {[catch {APSLogScriptAction \
        #                -procedure APSMpForceApplyBPMbladeGains \
        #              -action initialize \
        #            -state ok \
        #          -parameters ShortFilename=$ShortFilename} result]} {
    #     APSMpReturn error "APSMpForceApplyBPMbladeGains: $result"
    # }
    APSMpStep "APSMpForceApplyBPMbladeGains started"
    APSMpStep "checking dc-orbit correction and RTFB control status ..."
    if [catch {exec cavget -list=S:RC:OrbitControlLawXC,S:RC:OrbitControlLawYC -list=.RUN} result1] {
        APSMpReturn error "APSMpForceApplyBPMbladeGains (1) - cavget: $result1"
    }
    if [catch {exec cavget -list=DP:S:OrbitControlLaw -list=X,Y -list=SDDS.RUN} result2] {
        APSMpReturn error "APSMpForceApplyBPMbladeGains (2) - cavget: $result2"
    }
    if [catch {exec cavget -list=SRFB:GBL: -list=H,V -list=LoopStatusBI.VAL -numerical} result3] {
        APSMpReturn error "APSMpForceApplyBPMbladeGains (3) - cavget: $result3"
    }
    set errorMessage ""
    if {[lindex $result1 0] || [lindex $result1 1]} {
        append errorMessage "Workstation DC orbit correction is running.\n"
    }
    if {[lindex $result2 0] || [lindex $result2 1]} {
        append errorMessage "Datapool DC orbit correction is running.\n"
    }
    if {[lindex $result3 0] || [lindex $result3 1]} {
        append errorMessage "RTFB control is running.\n"
    }
    
    if [string length $errorMessage] {
        APSAlertBox .alert -type error -name error -errorMessage "${errorMessage}\nPlease abort the above controls before running this pem."
        APSMpReturn error "APSMpForceApplyBPMbladeGains (4): $errorMessage."
    }
    set tmpRoot /tmp/[APSTmpString]
    APSAddToTmpFileList -ID 1 -fileList "$tmpRoot.ref $tmpRoot.user"
    if [catch {exec sddsprocess $SCRDir/$referenceFile $tmpRoot.ref \
                   -match=col,ControlName=*:?:gainMO
        exec sddsprocess $SCRDir/$ubopFile $tmpRoot.user \
                   -match=col,ControlName=*:?:gainMO } result] {
        APSMpReturn "APSMpForceApplyBPMbladeGains (5) - sddsprocess: $result"
    }
    APSMpStep "Restore gains from \"Xray blade gain=10\" reference file."
    if [catch {exec sddscasr $tmpRoot.ref -restore -pend=60} result] {
        APSMpReturn "APSMpForceApplyBPMbladeGains(restore blade gain from $referenceFile) (6) - sddscasr: $result"
    }
    after 3000
    APSMpStep "Restore gains from \"operator preferred\" file."
    if [catch {exec sddscasr $tmpRoot.user -restore -pend=60} result] {
        APSMpReturn "APSMpForceApplyBPMbladeGains (restore blade gain to user selected SCR - $ShortFilename) (7) - sddscasr: $result"
    }
    after 3000
    APSMpReturn ok
}

proc APSMpSRResetBPMAveragingInfo {} {
    return "This resets the averaging of xray BPMs and some rf BPMs."
}

#This procedure has been placed in the attic
proc APSMpSRResetBPMAveraging {args} {
    if [catch {APSSRCheckCorrectorMode -plane h} hCorrMode] {
        APSMpReturn error "APSMpSRResetBPMAveraging(1) - APSSRCheckCorrectorMode: $hCorrMode"
    }
     
    set XControllawRunning 0
    set YControllawRunning 0
    if [string compare $hCorrMode vector]==0 {
        foreach pl {X Y} {
            if [catch {exec cavget -list=DP:S:OrbitControlLaw${pl}SDDS.RUN -pend=30} result] {
                APSMpReturn error "APSMpSRResetBPMAveraging(2) - cavget: $result"
            }
            if {$result=="?"} {
                APSMpReturn error "APSMpSRResetBPMAveraging (3): can not read value of DP:S:OrbitControlLaw${pl}SDDS.RUN"
            }
            set ${pl}ControllawRunning $result
            if $result {
                set answer [APSMultipleChoice [APSUniqueName .] -modal 1 -name Warning \
                                -type warning   \
                                -question "The $pl dp orbit correction is running.\n\nAbort the controllaw and continue or Cancel reset xray bpm averaging?" \
                                -returnList {Continue Cancel} -labelList {Continue Cancel} ]
                
                if {$answer=="Cancel"} {
                    APSMpReturn error "APSMpSRResetBPMAveraging was cancelled."
                }
                APSMpStep "Abort [string tolower $pl] plane dp orbit correction" 
                if [catch {APSAbortSRControllaw -runControlPV DP:S:OrbitControlLaw${pl}SDDS } result] {
                    APSMpReturn error "APSMpSRResetBPMAveraging(4) - abortcontrollaw: $result"
                }
            }
        }
        after 2000
    } else {
        foreach plane {X Y} pl {h v} {
            if [catch {exec cavget -list=S:RC:OrbitControlLaw${plane}C.RUN -pend=30} result] {
                APSMpReturn error "APSMpSRResetBPMAveraging(5) - cavet: $result"
            }
            if {$result=="?"} {
                APSMpReturn error "APSMpSRResetBPMAveraging(6): can not read value of S:RC:OrbitControlLaw${plane}C.RUN"
            }
            set ${plane}ControllawRunning $result
            if $result {
                set answer [APSMultipleChoice [APSUniqueName .] -modal 1 -name Warning \
                                -type warning   \
                                -question "The $plane orbit correction is running.\n\nAbort the controllaw and continue or Cancel reset xray bpm averaging?" \
                                -returnList {Continue Cancel} -labelList {Continue Cancel} ]
                
                if {$answer=="Cancel"} {
                    APSMpReturn error "APSMpSRResetBPMAveraging was cancelled."
                }
                APSMpStep  "Suspend $plane orbit correction" 
                if [catch {APSSRControlOrbitCorrection -plane  $pl -action suspend \
                           } result] {
                    APSMpReturn error "APSMpSRResetBPMAveraging(7): $result"
                }
            }
        }
    }
    set UBOPFile /home/helios/oagData/SCR/snapshots/SBPMs/SBPMs-Preferred.gz
    set tmpFile /tmp/[APSTmpString]
    APSMpStep "Set BPM averaging to 10"
    APSAddToTmpFileList -ID resetxrayave -fileList "$tmpFile.set $tmpFile.set10"
    if [catch {exec sddsprocess $UBOPFile -match=col,ControlName=*msAve:Num2AveAO \
                   $tmpFile.set
        exec sddsprocess $UBOPFile -match=col,ControlName=*mswAve:CoeffAO \
                   $tmpFile.seta
        exec sddsprocess $tmpFile.set $tmpFile.set10 -reprint=col,ValueString,10 
        exec sddsprocess $tmpFile.seta $tmpFile.seta1 -reprint=col,ValueString,1    } result] {
        APSMpReturn error "APSMpSRResetBPMAveraging(8) -- sddsprocess: $result"
    }
    if [catch {exec sddscasr -restore $tmpFile.set10} result] {
        APSMpReturn error "APSMpSRResetBPMAveraging(9) -- sddscasr: $result"
    }
    after 2000
    if [catch {exec sddscasr -restore $tmpFile.set} result] {
        APSMpReturn error "APSMpSRResetBPMAveraging(10) - sddscasr: $result"
    }
    after 2000
    if [catch {exec sddscasr -restore $tmpFile.seta1} result] {
        APSMpReturn error "APSMpSRResetBPMAveraging(11) - sddscasr: $result"
    }
    after 2000
    if [catch {exec sddscasr -restore $tmpFile.seta} result] {
        APSMpReturn error "APSMpSRResetBPMAveraging(12) - sddscasr: $result"
    }
    if {$XControllawRunning || $YControllawRunning} {
        APSAlertBox .warning -type warning -name warning  -errorMessage "Orbit correction was aborted for reseting xray bpm averaging, you may need to restart it."
    }
    APSMpReturn ok
}

proc APSMpSRBPLDTripLimitAlarmValidationInfo {args} {
    return "It validates the BPLD trip limits."
}

proc APSMpSRBPLDTripLimitAlarmValidationInitDialog {frame} {
    global APSMpSRBPLDTripLimitAlarmValidation
    APSLabeledEntry .limit -parent $frame -label "Trip Limit:" \
        -width 25 -textVariable APSMpSRBPLDTripLimitAlarmValidation(limit)
}

#This procedure has been placed in the attic
proc APSMpSRBPLDTripLimitAlarmValidation {args} { 
    set limit 5
    APSMpStep init -promptDialog APSMpSRBPLDTripLimitAlarmValidationInitDialog \
        -vars {limit}
    
    #this request file is created by makeBPLDreqFile, run makeBPLDreqFile to update it
    set BPLDreqFile /home/helios/oagData/SCR/requestFiles/BPLDs.req 
    set tmpRoot /tmp/[APSTmpString]
    APSMpStep "Get bpld original values and processing..."
    if [catch {exec sddsprocess $BPLDreqFile -pipe=out \
                   -match=col,ControlName=*AO \
                   | sddsconvert -pipe=in -retain=col,ControlName $tmpRoot.ao } result] {
        APSMpReturn error "APSMpSRBPLDTripLimitAlarmValidation(1) - sddsprocesss: $result"
    }
    APSAddToTmpFileList -ID BPLDvalidation -fileList "$tmpRoot.ao"
    foreach plane {x y} {
        foreach ext {hi lo} value [list $limit -$limit] {
            APSAddToTmpFileList -ID BPLDvalidation -fileList "$tmpRoot.${plane}$ext $tmpRoot.${plane}$ext.orig  $tmpRoot.${plane}${ext}.set"
            if [catch {exec sddsprocess $tmpRoot.ao $tmpRoot.${plane}$ext \
                           -match=col,ControlName=*:dbpld:${plane}${ext}AO  \
                           -edit=col,RootName,ControlName,%/:dbpld:${plane}${ext}AO//   
                exec sddscasr $tmpRoot.${plane}${ext} $tmpRoot.${plane}$ext.orig -save -pend=30
                exec sddsprocess $tmpRoot.${plane}$ext -print=col,ValueString,$value \
                           $tmpRoot.${plane}${ext}.set 
            } result] {
                APSMpReturn error "APSMpSRBPLDTripLimitAlarmValidation(2) -- sddsprocess, sddscasr: $result"
            }
        }
    }
    if [catch {exec sddsprocess $tmpRoot.xhi $tmpRoot.lim \
                   -reedit=col,ControlName,%/xhiAO/LimErrCC/ } result] {
        APSMpReturn error "APSMpSRBPLDTripLimitAlarmValidation(3) - sddsprocess: $result"
    }
    APSAddToTmpFileList -ID BPLDvalidation -fileList "$tmpRoot.lim $tmpRoot.lim.orig $tmpRoot.lim.error $tmpRoot.lim.trip0"
    if [catch {exec sddscasr $tmpRoot.lim $tmpRoot.lim.orig -save -pend=30} result] {
        APSMpReturn error "APSMpSRBPLDTripLimitAlarmValidation(4) - sddscasr: $result"
    }
    if [catch {exec sddsprocess $tmpRoot.lim.orig $tmpRoot.lim.error \
                   -match=col,CAError=y -nowarnings} result] {
        APSMpReturn error "APSMpSRBPLDTripLimitAlarmValidation(5) - sddsprocess: $result"
    }
    set rows [exec sdds2stream $tmpRoot.lim.error -rows=bar]
    if $rows {
        set pvList [exec sdds2stream $tmpRoot.lim.error -col=ControlName]
        set answer [APSMultipleChoice [APSUniqueName .] -modal 1 -name Warning \
                        -type warning -beep continuous \
                        -question "Following limit PVs may not exit,\n[join $pvList]\n would you like to skip checking these sectors and continue or abort?" \
                        -returnList {Continue Abort} -labelList {Continue Abort} ]
       
        switch $answer {
            Abort {
                APSMpReturn error "APSMpSRBPLDTripLimitAlarmValidation was aborted due to non existent of limit pvs for [join $pvList ,]."
            }
            Continue {
                #
            }
        }
    }
    if [catch {exec sddsprocess $tmpRoot.lim.orig $tmpRoot.lim.trip0 \
                   -match=col,CAError=n -nowarnings \
                   -scan=col,Value,ValueString,%lf -filter=col,Value,1,100 } result] {
        APSMpReturn error "APSMpSRBPLDTripLimitAlarmValidation(6) - sddsprocess: $result"
    }
    set rows [exec sdds2stream $tmpRoot.lim.trip0 -rows=bar]
    if $rows {
        set pvList [exec sdds2stream $tmpRoot.lim.trip0 -col=RootName]
        set answer [APSMultipleChoice [APSUniqueName .] -modal 1 -name Warning \
                        -type warning -beep continuous \
                        -question "Following BPLDs \n[join $pvList]\n show alarm state already, so cannot validate them, would you like to skip these BPMs and continue or abort?" \
                        -returnList {Continue Abort} -labelList {Continue Abort} ]
        if {$answer=="Abort"} {
            APSMpReturn error "APSMpBPLDTripLimitAlarmValidation was aborted due to the alarm state on [join $pvList ,] BPLDs before validation. Please check them first."
        }
    }
    if [catch {exec sddsprocess $tmpRoot.lim.orig -pipe=out \
                   -match=col,CAError=n -nowarnings \
                   -scan=col,Value,ValueString,%lf \
                   | sddsprocess -pipe -nowarnings -filter=col,Value,0,0 \
                   | sddsconvert -pipe=in $tmpRoot.lim.good -retain=col,ControlName,RootName } result] {
        APSMpReturn error "APSMpSRBPLDTripLimitAlarmValidation(7) - sddsprocess: $result"
    }
    set rows1 [exec sdds2stream -rows=bar $tmpRoot.lim.orig]
    set rows2 [exec sdds2stream -rows=bar $tmpRoot.lim.good]
    if {$rows2==0} {
        APSMpReturn error "APSMpSRBPLDTripLimitAlarmValidation: there are no good BPMs for validating.!"
    }
    if {$rows2!=$rows1} {
        foreach plane {x y} {
            foreach ext {hi lo} value [list $limit -$limit] { 
                if [catch {exec sddsselect  $tmpRoot.${plane}$ext.orig $tmpRoot.lim.good \
                               -match=RootName $tmpRoot.${plane}$ext.orig.good
                    exec sddsselect  $tmpRoot.${plane}$ext.set $tmpRoot.lim.good \
                               -match=RootName $tmpRoot.${plane}$ext.set.good } result] {
                    APSMpReturn error "APSMpSRBPLDTripLimitAlarmValidation(8) - sddsselect: $result"
                }
                exec mv $tmpRoot.${plane}${ext}.set.good $tmpRoot.${plane}${ext}.set
                exec mv $tmpRoot.${plane}${ext}.orig.good $tmpRoot.${plane}${ext}.orig
            }
        }
    }
    APSMpStep "Enable PV limit writing ..."
    #state 0 "Unlimited" state 1 "Maintenance" state 2 "Studies" state 3 "User Beam"
    if [catch {exec cavget -list=S:bpm:accessControlMBBO -num -pend=30} origMode] {
        APSMpReturn error "APSMpSRBPLDTripLimitAlarmValidation(9) - cavget: $origMode"
    }
    if [catch {exec cavput -list=S:bpm:accessControlMBBO=1 -pend=30} result] {
        APSMpReturn error "APSMpSRBPLDTripLimitAlarmValidation(10) - cavput: $result"
    }
    set index 1
    set noTripList ""
    foreach plane {x y} {
        foreach ext {hi lo} value [list $limit  -$limit] {
            APSMpStep "Set $plane $ext limits to $value ..."
            if [catch {exec sddscasr -restore $tmpRoot.${plane}${ext}.set -pend=30} result] {
                APSMpReturn error "APSMpSRBPLDTripLimitAlarmValidation(11) - sddscasr: $result"
            }
            after 5000
            #check if trip occurred
            APSMpStep "Check if trip occurred..."
            APSAddToTmpFileList -ID BPLDvalidation -fileList "$tmpRoot.lim.$index"
            if [catch {exec sddscasr $tmpRoot.lim.good -pipe=out -save -pend=60 \
                           | sddsprocess -pipe \
                           -scan=col,Value,ValueString,%lf \
                           | sddsprocess -pipe=in $tmpRoot.lim.$index  \
                           -nowarnings -filter=col,Value,0,0} result] {
                APSMpReturn error "APSMpSRBPLDTripLimitAlarmValidation(12) - sddsprocess: $result"
            }
            set rows [exec sdds2stream $tmpRoot.lim.$index -rows=bare]
            if $rows {
                APSAddToTmpFileList -ID BPLDvalidation -fileList "$tmpRoot.${plane}${ext}.notrip"
                if [catch {exec sddsselect $tmpRoot.${plane}${ext} $tmpRoot.lim.$index \
                               -match=RootName $tmpRoot.${plane}${ext}.notrip } result] {
                    APSMpReturn error "APSMpSRBPLDTripLimitAlarmValidation(13) - sddsselect: $result"
                }
                set bpmName [exec sdds2stream -col=ControlName $tmpRoot.${plane}${ext}.notrip]
                lappend noTripList \n$bpmName
                APSAlertBox .info -type warning -beep once \
                    -errorMessage "Testing on $plane $ext limits\nSetting trip limit to $limit on following BPLDs did not cause the alarm state:\n$bpmName"
            } else {
                APSMpStep "Test on $plane $ext limits passed."
            }
            APSMpStep "Restore $plane $ext limits."
            #restore
            if [catch {exec sddscasr -restore $tmpRoot.${plane}${ext}.orig -pend=30} result] {
                APSMpReturn error "APSMpSRBPLDTripLimitAlarmValidation(14) - sddscasr: $result"
            }
            after 5000
            incr index
        }
    }
    if [catch {exec cavput -list=S:bpm:accessControlMBBO=$origMode -pend=30} result] {
        APSMpReturn error "APSMpSRBPLDTripLimitAlarmValidation(16) - cavput: $result"
    }
    
    if [llength $noTripList] {
        set noTripList [join $noTripList]
        APSAlertBox .info -type warning -beep once \
            -errorMessage "Setting trip limit to $limit on following BPLDs did not cause the alarm state:\n$noTripList" -modal 1
    } else {
        APSInfoWindow .info -infoMessage "BPLD trip alarm validation on limit $limit passed." -modal 1
    }
    APSMpReturn ok
}

proc APSSetupFPGABpmTriggers {args} {
    set enableMPS 0
    APSStrictParseArguments {enableMPS}
    
    global env  apsScriptUser apsScriptHost apsScriptCommand
    if [catch {exec sdds2stream /home/helios/oagData/sr/FPGAbpm/sectors.sdds -col=Sector} sectorList] {
	return -code error "APSSetupFPGABpmTriggers(1): $sectorList"
    }
    #disarm first
    if [catch {exec cavput -list=S -list=[join $sectorList ,] -list=A,B -list=:turn,:motion -list=:gtr:arm=0 -pend=60} result] {
        return -code error "APSSetupFPGABpmTriggers(1a): $result"
    }
    after 2000
    #then set trigger to event
    if [catch {exec cavput -list=S -list=[join $sectorList ,] -list=A,B \
                 -list=:motion,:turn -list=:gtr:trigger=event -pend=60 } result] {
        return -code error "APSSetupFPGABpmTriggers(1a): $result"
    }
    after 2000
    #finally arm it
    if [catch {exec cavput -list=S -list=[join $sectorList ,] -list=A,B -list=:scope:gtr:trigger=wrap -pend=60
	exec cavput -list=S -list=[join $sectorList ,] -list=A,B -list=:scope:gtr:autoRestart=no -pend=60
	exec cavput -list=S -list=[join $sectorList ,] -list=A,B -list=:turn,:motion -list=:gtr:arm=1 -pend=60} result] {:clientEvent33.OUT6
	return -code error "APSSetupFPGABpmTriggers(2): $result"
    }
    if $enableMPS {
        if [catch {exec cavput -list=S -list=[join $sectorList ,] -list=A,B -list=:clientEvent \
                     -list=2d.OUT4=0,2d.OUT6=0,2d.OUT7=0,2d.OUT5=0,33.OUT6=1,33.OUT4=1 -pend=30} result] {
            return -code error "APSSetupFPGABpmTriggers(3) Error setup mps dump event trigger: $result"
        }
    }
    #arm booster FPGA bpms
    if [catch {exec cavput -list=B1,B2,B3,B4 -list=C0,C2,C4,C8 -list=:turn:gtr:arm=1 -pend=30 } result] {
        return -code error "APSSetupFPGABpmTriggers(3): error arming booster FPGA bpms: $result"
    }
    if [catch {exec logMessage -sourceId=FPGABpmTriggerAudit \
                 -tag=User $env(USER) -tag=Host $env(HOST) \
                 -tag=Application $apsScriptCommand } result] {
        APSMpStep "Error in log message for arming FPGA bpms: $result"
    }
}

proc APSGetMonopulseBPMIOCList {args} {
    if [catch {exec sddsprocess /home/helios/oagData/sr/BPMStatus/config.sdds -match=col,ElectronicsType=Monopulse \
                 -filter=col,NonexistentH,0,0 -filter=col,NonexistentV,0,0 \
                 -pipe=out -reedit=col,ioc_name,%/iocs//%/bpm// \
                 | sddssort -pipe -col=ioc_name -unique -numericHigh \
                 | sdds2stream -pipe -col=ioc_name } iocList] {
        return -code error "APSGetMonopulseBPMIOCList: $iocList"
    }
    return [join $iocList]
}

proc APSGetFPGASectorList {args} {
    if [catch {exec sddsprocess /home/helios/oagData/sr/BPMStatus/config.sdds -match=col,ElectronicsType=FPGA \
                 -scan=col,Sector,DeviceName,S%ld,type=long -pipe=out \
                 -filter=col,NonexistentH,0,0 -filter=col,NonexistentV,0,0 \
                 | sddssort -pipe -col=Sector -unique -numericHigh \
                 | sdds2stream -pipe -col=Sector } sectorList] {
        return -code error "APSGetMonopulseBPMIOCList: $sectorList"
    }
    return [join $sectorList]
}

proc APSArmFPGABpm {args} {
    set subSector ""
    set type ""
    set application ""
    APSStrictParseArguments {subSector type application}
    global env 
    switch $type {
	"turn" -
	"motion" {
	}
	default {
	    return -code error "APSArmFPGABpm(1): Invalid type provided, should be turn or motion."
	}
    }
    #disarm first
    if [catch {exec cavput -list=${subSector}:${type}:gtr:arm=0 -pend=60} result] {
        return -code error "APSArmFPGABpm(2) Error is disamring ${subSector}:${type}:gtr:arm: $result"
    }
    after 2000
    #then set trigger to event
    if [catch {exec cavput -list=${subSector}:${type}:gtr:trigger=event -pend=60} result] {
	return -code error "APSArmFPGABpm(3): Error in setting trigger ${subSector}:${type}:gtr:trigger to event: $result"
    }
    after 2000
    #finally arm it
    if [catch {exec cavput -list=${subSector}:scope:gtr:trigger=wrap -pend=60
	exec cavput -list=$subSector:scope:gtr:autoRestart=no -pend=60
	exec cavput -list=${subSector}:${type}:gtr:arm=1 -pend=60} result] {
	return -code error  "APSArmFPGABpm(4): Error in arming ${subSector}:${type}: $result"
    }
   # if [catch {exec logMessage -sourceId=FPGABpmTriggerAudit \
   #              -tag=User $env(USER) -tag=Host $env(HOST) \
   #              -tag=Application $application } result] {
   #     return -code error "Error in log message for arming FPGA bpms: $result"
   # }
}
