#!/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)]

APSStandardSetup
set args $argv
set expert 0
APSStrictParseArguments {expert}
set CVSRevisionAuthor "Version 1.0, H. Shang"

proc BringUpGlobalMedm {args} {
    set dir /home/helios/MLS/C2/iocs/mps/B1/opi/adl
    exec medm -x $dir/GlobalBM_Trip_Pending_X.adl &
    exec medm -x $dir/GlobalBM_Trip_Pending_Y.adl &
}

proc SetStatus {text} {
    global status
    set status "$text"
    update
}
proc ControllawInfo {args} {
    set plane ""
    APSParseArguments {plane}
    switch $plane {
	h {
	    set runControlPV  "S:RC:OrbitControlLawXC"
	}
	v {
	    set runControlPV "S:RC:OrbitControlLawYC"
	}
    }
    exec medm -x -attach -macro RCPV=$runControlPV \
           /usr/local/iocapps/adlsys/sr/psApp/APSRunControlSingle.adl  &

}

proc SelectGroup {args} {
    global BPLD
    if $BPLD(useGroup) {
	APSEnableWidget .userFrame.sec1
	APSEnableWidget .userFrame.sec2
	APSDisableWidget .userFrame.sector
    } else {
	APSDisableWidget .userFrame.sec1
	APSDisableWidget .userFrame.sec2
	APSEnableWidget .userFrame.sector
    }
}


proc ClearFaults {args} {
    global BPLD
    SetStatus "Clear faults..."
    set sectorList [GetSectorList]
    if ![llength $sectorList] {
	SetStatus "No sectors chosen!"
	return
    }
    SetStatus "zero offsets [join $sectorList ,]..."
    if [catch {APScavput -list=[join $sectorList ,] \
		   -list=-LMPS:BM_ -list=X,Y -range=begin=1,end=28  -list=_Offset-SP=0 -pend=60} result] {
	return -code error "Error set BM bpm offsts to zero: $result"
    }
    
    SetStatus "reset..."
    if [catch {APScavput -list=[join $sectorList ,]  -list=-LMPS:UsrReset-SP=1 -pend=30 } result] {
	return -code error "Error reset to clear faults: $result"
    }
    SetStatus "done."
}

proc GetBPMs {args} {
    global BPLD
    set statusFile /home/helios/oagData/sr/BPMStatus/config.sdds
    set configFile /home/helios/oagData/sr/BPLD/BPLD_Config/config.sdds
    set tmpRoot /tmp/[APSTmpString]
    set sectorList  $BPLD(sectorList)
    switch $BPLD(bpmConfig) {
	Default {
	    if [catch {exec sddsprocess $configFile -filter=col,BMBPM,1,1 $tmpRoot.0} result] {
		return -code error "Error obtaining BM BPLD BPMs1: $result"
	    }
	}
	All {
	    if [catch {exec sddsprocess $statusFile $tmpRoot.0 \
			   "-filter=col,NonexistentH,0,0,NonexistentV,0,0,|" \
			   "-filter=col,OkForBMBPLDH,1,1,OkForBMBPLDV,1,1,|" } result] {
		return -code error "Error obtaining BM BPLD bpms2: $result"
	    }
	}
    }
    APSAddToTmpFileList -ID bm -fileList "$tmpRoot.0 $tmpRoot.1"
    foreach sector $sectorList {
	set sector0 [scan $sector S%ld]
	if [catch {exec sddsprocess $configFile -pipe=out -filter=col,BPLDSector,$sector0,$sector0 \
		       | sddsxref -pipe $tmpRoot.0 -match=DeviceName -nowarn \
		       | tee $tmpRoot.1 \
		       | sdds2stream -pipe=in -col=BPLDIndex } bpmList] {
	    return -code error "Error obtaining S$sector BM BPLD bpms: $bpmList"
	}
	set BPLD($sector.bpmIndexList) [join $bpmList]
	set BPLD($sector.bpmList) [exec sdds2stream -col=DeviceName $tmpRoot.1]
	set maskValue 0
	foreach bpm $bpmList {
	    set num [expr $bpm+3]
	    set Bit [format %X $num]
	    set maskValue [format %.0f [expr $maskValue + pow(2, $bpm-1)]]
	}
	set BPLD($sector.mask) $maskValue
    }
}

proc SetBMMask {args} {
    global BPLD
    SetStatus "Get BPMs..."
    set sectorList [GetSectorList]
    if ![llength $sectorList] {
	return -code error "Error: no sectors chosen!"
    }
    if [catch {GetBPMs} result] {
	return -code error "Error getting BM BPLD BPMs: $result"
    }
    set putList ""
    foreach sector $sectorList {
	lappend putList  ${sector}-LMPS:BPLD:BpmMask-SP=$BPLD($sector.mask)
    }
    SetStatus "Set BM masks for [join $sectorList ,]..."
    if [catch {APScavput -list=[join $putList ,] -pend=10} result] {
	return -code error "Error setting mask: $result"
    }
    SetStatus "done."
}

proc LoadDefaultLimits {args} {
    global apsSCRSnapDir apsSCRRequestDir BPLD

    
    set scrFile /home/helios/oagData/SCR/snapshots/SRBPLD/SRBPLD-DefaultBetaLimits.gz
    set apsSCRSnapDir /home/helios/oagData/SCR/snapshots
    set apsSCRRequestDir /home/helios/oagData/SCR/requestFiles
  
    set sectorList [GetSectorList]
    if ![llength $sectorList] {
	return -code error "No sectors chosen!"
    }
    set opt ""
    foreach sector $sectorList {
	if ![string length $opt] {
	    set opt -match=col,Beamline=$sector
	} else {
	    append opt ",Beamline=$sector,|"
	}
    }
    
    if [catch {eval exec sddsprocess $scrFile -pipe=out -match=col,Category=BM_BPLD_Limit $opt \
		   | sddscasr -pipe=in -restore } result] {
	return -code error "Error loading BM BPLD limits from SCR: $result"
    }
    SetStatus "Default SCR BM BPLD limits for double sector [join $sectorList] loaded."
}

proc WriteLogFileHeader {args} {
    set logFile ""
    APSParseArguments {logFile}
    global logFile logID archiveDir
    if ![string length $logFile] {
	set logFile $BPLD(archiveDir)/$BPLD(rootname).sdds
    }
    if ![file exist $logFile] {
	set BPLD(logID) [open $logFile a+]
	puts $BPLD(logID) "SDDS1"
	puts $BPLD(logID) "&column name=StartTime, type=string, &end"
	puts $BPLD(logID) "&column name=EndTime, type=string, &end"
	puts $BPLD(logID) "&column name=DoubleSector, type=long, &end"
	puts $BPLD(logID) "&column name=Limit, type=string, &end"
	puts $BPLD(logID) "&column name=Plane, type=string, &end"
	puts $BPLD(logID) "&column name=Result, type=string, &end"
	puts $BPLD(logID) "&column name=FaultDesc, type=string, &end"
	puts $BPLD(logID) "&data mode=ascii, no_row_counts=1, &end"
	exec chmod 777 $logFile
	flush $BPLD(logID)
    }
}

proc SetupValidation {args} {
    global BPLD
    if [catch {SetupPVLinks} result] {
	return -code error $result
    }
    
    if [catch {ClearFaults} result] {
	return -code error "Error clearing faults: $result"
    }
    
    SetStatus "To enable BM validation, it needs following conditions"
    SetStatus "1)the simulated hardware limit should be equal or greater than BM engaged current."
    #SetStatus "2) software limit should be less than the hardware limit but greater than BM/ID engaged current."
    SetStatus "2) MPS arming current should be greater than 0 (normally set to 0.5mA)"
    SetStatus "3) beam simulation current has to be equal or greater than BM/ID engaged current."
    SetStatus "checking hardware limit..."
    if [catch {exec cavget -list=APSU:MMPS2:Sim:BeamCurrent-SP,APSU:MMPS2:BM:Thold-SP,APSU:MMPS2:Sim:HWmaxBeam-SP,APSU:MMPS2:MaxSoftBeam-SP -pend=10} valList] {
	return -code error "Error reading sim current and current limit: $valList"
    }
    set simCurrent [lindex $valList 0]
    set BMcurrent [lindex $valList 1]
    set hwLimit [lindex $valList 2]
    set swLimit [lindex $valList 3]
    if {$hwLimit<[expr $BMcurrent+5]} {
	set limit [expr $BMcurrent + 20]
	SetStatus "Hardware limit is lower than BM engage current, please increase it to $limit."
	
	set hwLimit $limit
    }
    set limit 0
    if {$swLimit>$hwLimit} {
	SetStatus "software limit is higher than hardward limit, please reduce it..."
	set limit [expr $hwLimit -2]
    }
    if {$swLimit<$BMcurrent} {
	set limit [expr $BMCurrent + 1 ]
	puts "software limit is lower than BM engage current, increase it."
    }
    
    SetStatus "check beam current: it should be equal or greater than BM engaged current"
   
    if [catch {exec cavget -list=APSU:MMPS2:DCCT1:beamC-Calc -pend=10} current] {
	return -code error "Error reading beam current: $current"
    }
    set limit [expr $BMcurrent+1]
    if {$current<$BMcurrent} {
	APSInfoWindow .info -width 20 -infoMessage "The beam current is less than BM engage current, please increase the beam current to $limit mA." -modal 1
    }
    
    #SetStatus "Disable ID BPLD ..."
    set sectorList [GetSectorList]
    if {0} {
	if [catch {exec cavput -list=[join $sectorList ,] -list=-LMPS:BPLD: -list=ID1,ID2 \
		       -list=_Enable-SP=0 -pend=10 } result] {
	    return -code error "Error disable ID BPLD: $result"
	}
    }
    if [catch {exec cavput -list=[join $sectorList ,] -list=-LMPS:BPLD:BM_Enable-SP=1 } result] {
	return -code error "Error enabling BM BPLDs: $result"
    }
    
    SetStatus "Setting BM BPLD mask..."
    if [catch {SetBMMask} result] {
	return -code error "SetBMMask: $result"
    }
    SetStatus "Reset BPLD..."
    if [catch {APScavput -list=[join $sectorList ,]  -list=-LMPS:UsrReset-SP=1 -pend=30 } result] {
	return -code error "Error reset to clear faults: $result"
    }
    SetStatus "set allowed number of fault BPMs..."
    if  [catch {exec cavget -list=APSU:MMPS1:BM:FaultCnt-SP -pend=10} val] {
	return -code error "Esrror setting fault BPMs: $val"
    }
    set BPLD(origFaultBPMs) $val
    if [catch {exec cavput -list=APSU:MMPS1:BM:FaultCnt-SP=$BPLD(allowedFaultBPMs) -pend=10} result] {
	return -code error "Esrror setting fault BPMs: $result"
    }
    SetStatus "BPLD validation setup done."
}

set linkSetup 0
proc SetupPVLinks {args} {
    global BPLD linkSetup
    set sectorList [GetSectorList]
    if {$BPLD(lastSectors)==$sectorList} {
	return
    }
    if $linkSetup {
	pv unlinkw $BPLD(varList)
    }
    if [catch {SetBMMask} result] {
	return -code error "Error SetBMMask: $result"
    }
    
    foreach sector $sectorList {
	set BPLD($sector.ID1enablePV) ${sector}-LMPS:BPLD:ID1_Enable-SP
	set BPLD($sector.ID2enablePV) ${sector}-LMPS:BPLD:ID2_Enable-SP
	set BPLD($sector.BMEnablePV) ${sector}-LMPS:BPLD:BM_Enable-SP

	set sector0 [scan $sector S%ld]
	set fsector [expr ($sector0+1)/2-1] 
	set Bit [format %X $fsector]
	set BPLD($sector.main2fastPVBit) APSU:MMPS2:SMA:Data10-I.B$Bit
	set BPLD($sector.main1fastPVBit) APSU:MMPS1:LMPS:FastAbort-Sts.B$Bit
	set BPLD($sector.linkFaultPV) APSU:MMPS1:LMPS[expr ($sector0+1)/2]:Fault-I
	set BPLD($sector.localMPSPV) ${sector}-LMPS:MLinkTXpkt_FS-I
	
	set BPLD($sector.linkFaultPVBit) APSU:MMPS1:LMPS[expr ($sector0+1)/2]:Fault-I.B2
	set BPLD($sector.localMPSPVBit) ${sector}-LMPS:MLinkTXpkt_FS-I.B2
	
	set BPLD($sector.BMfaultPV) ${sector}-LMPS:BPLD:BM_IL_Status-I
 
	set BPLD($sector.BMmaskPV) ${sector}-LMPS:BPLD:BpmMask-SP
	set BPLD($sector.BMbpmEnablePV) ${sector}-LMPS:BPLD:BM_Enable-I

	foreach bpm $BPLD($sector.bpmList) index $BPLD($sector.bpmIndexList) {
	    set num [expr $index+3]
	    set Bit [format %X $num]
	    set BPLD($sector.$bpm.linkFaultPV) $BPLD($sector.linkFaultPV).B$Bit
	    set BPLD($sector.$bpm.localMPSPV) $BPLD($sector.localMPSPV).B$Bit
	}
    }
    
    
    set nmList [array names BPLD]
    set pvList ""
    set varList ""
    foreach name $nmList {
	if {[regexp "PV" $name] && ![string match  "*.var" $name]} {
	    lappend pvList $BPLD($name)
	    lappend varList BPLD($name.var)
	}
    }
    set BPLD(pvList) $pvList
    set BPLD(varList) $varList
    
    if [pv linkw $varList $pvList 50] {
	SetStatus "Error connecting some pvs: [join $pvList]"
	return -code error "Error connecting some pvs: $pvList"
    }
    set linkSetup 1
    set BPLD(lastSectors) $sectorList
}

proc WriteLogFileHeader {args} {
    set logFile ""
    APSParseArguments {logFile}
    global  BPLD
    set logDir $BPLD(archiveDir)
    if ![info exist BPLD(rootname)] {
	set timestr  [clock format [clock seconds] -format %Y-%m%d:%H%M%S]
	set BPLD(rootname) $timestr
	set BPLD(startTime) $timestr
    }
    #set logFile $logDir/$BPLD(rootname).sdds
    #set BPLD(logFile) $logFile
    if ![file exist $logFile] {
	set BPLD(logID) [open $logFile a+]
	puts $BPLD(logID) "SDDS1"
	puts $BPLD(logID) "&column name=StartTime, type=string, &end"
	puts $BPLD(logID) "&column name=EndTime, type=string, &end"
	puts $BPLD(logID) "&column name=Sector, type=long, &end"
	puts $BPLD(logID) "&column name=BPM, type=string &end"
	puts $BPLD(logID) "&column name=Plane, type=string, &end"
	puts $BPLD(logID) "&column name=Limit, type=string, &end"
	puts $BPLD(logID) "&column name=Result, type=string, &end"
	puts $BPLD(logID) "&column name=ValidationType, type=string,&end"
	puts $BPLD(logID) "&column name=FaultDesc, type=string, &end"
	puts $BPLD(logID) "&data mode=ascii, no_row_counts=1, &end"
	exec chmod 777 $logFile
	flush $BPLD(logID)
    }
}

proc WriteLogFile {args} {
    set logFile ""
    set bumpType Positive
    set sectorList ""
    APSParseArguments {bumpType sectorList logFile}
    if {$bumpType=="Positive"} {
	set otherType Negative
    } else {
	set otherType Positive
    }
    
    global BPLD
    if ![info exist BPLD(endTime)] {
	set BPLD(endTime) [clock format [clock seconds] -format %Y-%m%d:%H%M%S]
    }
    if ![llength $sectorList] {
	set sectorList [GetSectorList]
    }
    if ![string length $logFile] {
	set logFile $BPLD(archiveDir)/$BPLD(rootname).sdds
    }
    WriteLogFileHeader -logFile $logFile
    foreach sector $sectorList {
	set valList $BPLD(startTime)
	set sector0 [scan $sector S%ld]
	lappend valList $BPLD(endTime)
	lappend valList $sector0
	lappend valList \"[join $BPLD($sector.bpmList)]\"
	lappend valList $BPLD(plane)
	if {$sector0<20} {
	    lappend valList $bumpType
	} else {
	    lappend valList $otherType
	}
	lappend valList $BPLD($sector.result)
	if $BPLD(testFirmware) {
	    lappend valList BM-BPLD-Offset
	} else {
	    lappend valList BM-Orbit-Bump
	}
	lappend valList \"$BPLD($sector.faultDesc)\"
	puts $BPLD(logID) "[join $valList]"
    }
    flush $BPLD(logID)
}

proc CheckBMBPLDState {args} {
    set sectorList ""
    set bumpType Positive
    set checkOnly 0
    set tripPending 1
    APSParseArguments {sectorList bumpType checkOnly tripPending}
    global BPLD
    if $checkOnly {
	set logFile /tmp/[APSTmpString]
	APSAddToTmpFileList -ID bmbpld -fileList $logFile
    } else {
	if $tripPending {
	    set logFile $BPLD(archiveDir)/$BPLD(rootname).tripPending
	} else {
	    set logFile $BPLD(archiveDir)/$BPLD(rootname).fastAbort
	}
    }
    if ![llength $sectorList] {
	set sectorList [GetSectorList]
    }
    if {$BPLD(lastSectors)!=$sectorList} {
	if [info exist BPLD(varList)] {
	    pv unlink $BPLD(varList)
	}
	if [catch {SetupPVLinks} result] {
	    return -code error $result
	}
	set timestr  [clock format [clock seconds] -format %Y-%m%d:%H%M%S]
	set BPLD(rootname) $timestr
	set BPLD(startTime) $timestr
    }
    if [pv getw $BPLD(varList) 60] {
	return -code error "CheckBMBPLDState1: error reading PVs"
    }
    update
    if [pv getw $BPLD(varList) 60] {
	return -code error "CheckBMBPLDState1: error reading PVs"
    }
    update
    SetStatus "Check BPM enables ($sectorList)..."
    foreach sector $sectorList {
	set val $BPLD($sector.BMbpmEnablePV.var)
	set BPLD($sector.result) passed
	set BPLD($sector.faultDesc) ""
#	puts "$sector $val $BPLD($sector.mask)"
	if {$val!=$BPLD($sector.mask)} {
	    set BPLD($sector.result) failed
	    set msg "$sector failed: the enable BPMs are different from the setup."
	    set BPLD($sector.faultDesc) $msg
	} else {
	    set bitstr [format %b $val]
	    set len [string length $bitstr]
	    foreach index $BPLD($sector.bpmIndexList) bpm $BPLD($sector.bpmList) {
		set i0 [string index $bitstr [expr $len-$index]]
		if !$i0 {
		    append BPLD($sector.faultDesc) " $bpm not enabled."
		    set BPLD($sector.result) failed
		}
	    }
	}	
    }
    SetStatus "Check BM BPM faults..."
    foreach sector $sectorList {
	if {$BPLD($sector.result)=="failed"} {
	   SetStatus "$sector failed."
	    continue
	}
	set val $BPLD($sector.BMfaultPV.var)
	if {!$val} {
	    set BPLD($sector.result) failed
	    append BPLD($sector.faultDesc) "S$sector BM fault not detected."
	    continue
	}
	set enableValue $BPLD($sector.BMbpmEnablePV.var)
	if {$val!=$enableValue} {
	    set BPLD($sector.result) failed
	    append BPLD($sector.faultDesc) "S$sector BPM Faults are not equal to used BPMs."
	}
	if {0} { 
	    set bitstr [format %b $val]
	    foreach index $BPLD($sector.bpmIndexList) bpm $BPLD($sector.bpmList) {
		set i0 [string index $bitstr [expr $len-$index]]
		if !$i0 {
		    set BPLD($sector.result) failed
		    append BPLD($sector.result) "$bpm BM fault failed."
		}
	    }
	}
    }
    SetStatus "Check Local MPS status..."
    foreach sector $sectorList {
	if {$BPLD($sector.result)=="failed"} {
	    continue
	}
	set val $BPLD($sector.localMPSPV.var)
	if !$val {
	    set BPLD($sector.result) failed
	    append BPLD($sector.faultDesc) "S$sector local MPS fault not detected."
	    continue
	} else {
	    if {!$BPLD($sector.localMPSPVBit.var)} {
		set BPLD($sector.result) failed
		append BPLD($sector.faultDesc) "S$sector local MPS BM fault not detected."
	    } else {
		foreach bpm $BPLD($sector.bpmList) {
		    set val $BPLD($sector.$bpm.localMPSPV.var)
		    if !$val {
			set BPLD($sector.result) failed
			append BPLD($sector.faultDesc) "S$sector $bpm MPS fault not detected."
		    }
		}
	    }
	}
    }
    SetStatus "Check local link status..."
    foreach sector $sectorList {
	if {$BPLD($sector.result)=="failed"} {
	    continue
	}
	set val $BPLD($sector.linkFaultPV.var)
	if {!$val} {
	    set BPLD($sector.result) failed
	    append BPLD($sector.faultDesc) "S$sector link fault not detected."
	} else {
	    set val $BPLD($sector.linkFaultPVBit.var)
	    if {!$val} {
		set BPLD($sector.result) failed
		append BPLD($sector.faultDesc) "$sector BM link fault not detected."
	    } else {
		foreach bpm $BPLD($sector.bpmList) {
		    set val $BPLD($sector.$bpm.linkFaultPV.var)
		    if {!$val} {
			set BPLD($sector.result) failed
			append BPLD($sector.faultDesc) "$sector $bpm link fault not detected."
		    }
		}
	    }
	}
    }
    SetStatus "check main1 and main2 ..."
    foreach sector $sectorList {
	if {$BPLD($sector.result)=="failed"} {
	    continue
	}
	set val1 $BPLD($sector.main1fastPVBit.var)
	set val2 $BPLD($sector.main2fastPVBit.var)
	if !$val1 {
	    set BPLD($sector.result) failed
	    append BPLD($sector.faultDesc) "$sector main1 fast abort is wrong."
	}
	if !$val2 {
	    set BPLD($sector.result) failed
	    append BPLD($sector.faultDesc) "$sector main2 fast abort is wrong."
	}
    }
    if !$tripPending {
	if [catch {exec cavget -list=S-DCCT:currentM \
		   } current] {
	    return -code error "Error reading SR current: $current"
	}
	if {$current>0.5} {
	    SetStatus "Fast Abort Test failed."
	    foreach sector $sectorList {
		set BPLD($sector.result) failed
		append BPLD($sector.faultDesc) "Beam was not dumped."
	    }
	} else {
	    SetStatus "Fast Abort Test passed."
	    foreach sector $sectorList {
		if {$BPLD($sector.result)=="failed"} {
		    continue
		}
		set BPLD($sector.result) passed
	    }
	}
    }
    set BPLD(endTime) [clock format [clock seconds] -format %Y-%m%d:%H%M%S]
    SetStatus "Write to log file..."
    WriteLogFile -bumpType $bumpType -logFile $logFile -sectorList $sectorList -tripPending $tripPending
    DisplayResult -logFile $logFile
		   
}
proc DisplayResult {args} {
    set logFile ""
    APSStrictParseArguments {logFile}
    global BPLD
    if ![string length $logFile] {
	set logFile $BPLD(archiveDir)/$BPLD(rootname).tripPending
    }
    if ![file exist $logFile] {
	SetStatus "log file $logFile does not exist!"
	return
    }
       set printFile /tmp/[APSTmpString].print
    if [catch {exec sddsprintout $logFile $printFile \
		   -col=StartTime,format=%20s -col=Sector,format=%5d  \
		   -col=Plane,format=%5s  -col=Limit,format=%10s -col=ValidationType,format=%10s -col=Result,format=%6s \
		   -col=FaultDesc,format=%30s "-title=BM validation result" } result] {
	return -code error "Error printing result1: $result"
    }
    APSAddToTmpFileList -ID bmbpld -fileList $printFile
    APSFileDisplayWindow [APSUniqueName .] -fileName $printFile -deleteOnClose 1 -width 140
}

proc PlotArchive {args} {
    global BPLD selectFile
    cd $BPLD(archiveDir)
    set files0 [glob -nocomplain *.tripPending]
    set files1 [glob -nocomplain *.fastAbort]
    set files [lsort -decreasing [concat $files0 $files1]]
    if ![llength $files] {
	SetStatus "No data found."
	return
    }
    set selectFile ""
    APSScrolledListWindow .display -height 10 -name "Select File" -itemList $files  -selectionVar selectFile
    tkwait variable selectFile
    destroy .display
    if ![string length $selectFile] {
	SetStatus "No file is chosen."
	continue
    }
    if [file exist $selectFile] {
	DisplayResult -logFile $BPLD(archiveDir)/$selectFile
    }
	
}

proc ReduceTripLimits {args} {
    set factor 3
    APSParseArguments {factor}
 
    if [catch {exec sddsprocess /home/helios/oagData/SCR/snapshots/SRBPLD/SRBPLD-DefaultBetaLimits.gz -pipe=out \
		   -match=col,Category=BM_BPLD_Limit \
		   -scan=col,Value,ValueString,%lf \
		   | sddsprocess -pipe "-redefine=col,Value,Value $factor /" \
		   | sddsprocess -pipe -reprint=col,ValueString,%lf,Value \
		   | sddscasr -pipe=in -restore } result] {
	return -code error "Error reducing BM-BPLD trip limits: $result"
    }
}

proc Start {args} {
    set tripPending 0
    APSParseArguments {tripPending}
    global BPLD
    set plane $BPLD(plane)
    set amplitude $BPLD(${plane}Amp)
    SetStatus "Setup validation..."
    set timestr  [clock format [clock seconds] -format %Y-%m%d:%H%M%S]
    set BPLD(rootname) $timestr
    set BPLD(startTime) $timestr
    
    SetStatus "Setup validation...."
    if [catch {SetupValidation} result] {
	return -code error "Error setup validation: $result"
    }
    
    set plane $BPLD(plane)
    #SetStatus "Starting $plane orbit correction..."
    #APSInfoWindow .info -width 20 -infoMessage "Please start BPLD-BM orbit correction for $plane plane." -modal 1
    if {0} {
	if [catch {StartControllaw -plane $plane -regenerateFiles 1 } result] {
	    return -code error "Error starting $plane controllaw: $result"
	}
	after 5000
	SetStatus "Waiting for $plane orbit correction..."
	switch $plane {
	    h -
	    x {
		set runControlPV S:RC:OrbitControlLawXC 
	    }
	    v -
	    y {
		set runControlPV S:RC:OrbitControlLawXC
	    }
	}
	while {1} {
	    if [catch {APScavget -list=$runControlPV.RUN -pend=10 } running] {
		return -code errorr "Error checking orbit correction status: $running"
	    }
	    if $running {
		break
	    }  else {
		after 1000
		update
	    }
	}
    }
    if $tripPending {
	APSInfoWindow .info -width 20 -infoMessage "Please enable the trip inhibitor and continue ok to continue." -modal 1
    }
    set amp $BPLD(${plane}Amp)
    if !$BPLD(testFirmware) {
	if $BPLD(useGroup) {
	    SetStatus "Creating postive BM bump for $BPLD(posSectors) in $plane plane ..."
	    if [catch {CreateBump -sectorList "[split $BPLD(posSectors) -]" -plane $plane -amp $amp} result] {
	    return -code error "Error creating bump: $result"
	    }
	    SetStatus "Creating negative  BM bump for $BPLD(negSectors) in $plane plane ..."
	    if [catch {CreateBump -sectorList "[split $BPLD(negSectors) -]" -plane $plane -amp [expr -1.0*$amp]} result] {
		return -code error "Error creating bump: $result"
	    }
	    set sectorList [concat [split $BPLD(posSectors) -] [split $BPLD(negSectors) -]]
	} else {
	    SetStatus "Creating BM bump in $plane plane..."
	    set sectorList [GetSectorList]
	    if [catch {CreateBump -sectorList $sectorList -plane $plane -amp $amp} result] {
		return -code error "Error creating bump: $result"
	    }
	}
	SetStatus "waiting 20 seconds..."
	APSWaitWithUpdate -waitSeconds 20 -updateInterval 1
	SetStatus "waiting for orbit converge..."
    
	if [catch {CheckOrbit -plane $plane -sectorList $sectorList -timeout 200} result] {
	    SetStatus "$result"
	}
    } else {
	SetStatus " changing offsets of firmware..."
	set sectorList [GetSectorList]
	if [catch {exec /home/helios/oagData/sr/BPLD/Validation/BM/scripts/changeOffsets -sectorList $sectorList \
		       -plane $BPLD(plane) } result] {
	    return -code error "Error changing offset: $result"
	}
	after 10000
    }
    SetStatus "checking BM BPLD states."
    if [catch {CheckBMBPLDState -sectorList $sectorList -tripPending $tripPending} result] {
	if $BPLD(testFirmware) {
	    SetStatus "Clear faults..."
	    if [catch {ClearFaults} result] {
		return -code error "Error clear faults: $result"
	    }
	} else {
	    SetStatus "Zero bump..."
	    if [catch {CreateBump -plane $plane -amp 0} result] {
		return -code error "Error clear bump: $result"
	    }
	}
	return -code error "Error checking BPLD state: $result"
    }
    APSInfoWindow .info -width 20 -infoMessage "check the results." -modal 1
   
    if [catch {exec cavput -list=APSU:MMPS1:BM:FaultCnt-SP=$BPLD(origFaultBPMs) -pend=10} result] {
	if $BPLD(testFirmware) {
	    SetStatus "Clear faults..."
	    if [catch {ClearFaults} result] {
		return -code error "Error clear faults: $result"
	    }
	} else {
	    SetStatus "Zero bump..."
	    if [catch {CreateBump -plane $plane -amp 0} result] {
		return -code error "Error clear bump: $result"
	    }
	}
	return -code error "Error restoring fault BPMs: $result"
    }
    
    if $BPLD(testFirmware) {
	SetStatus "Clear faults..."
	if [catch {ClearFaults} result] {
	    return -code error "Error clear faults: $result"
	}
    } else {
	SetStatus "Zero bump..."
	if [catch {CreateBump -plane $plane -amp 0} result] {
	    return -code error "Error clear bump: $result"
	}
    }
    if {0} {
	if [catch {ClearFaults} result] {
	    return -code error "Error clear faults: $result"
	}
	SetStatus "Abort controllaw ..."
	if [catch { AbortControllaw -plane $BPLD(plane) } result] {
	    return -code error "Error abort $BPLD(plane) controllaw: $result"
	}
    }
    if $tripPending {
	APSInfoWindow .info -width 20 -infoMessage "Please disable the trip inhibitor and continue ok to continue." -modal 1
    }
    SetStatus "BPLD validation done."
}


proc GenerateControllawFiles {args} {
    set plane ""
    set regenerateFiles 0
    APSParseArguments {plane regenerateFiles}
    
    set rootname ${plane}OrbitBump
    global ${rootname}Readdir ${rootname}ReadDescription  BPLD
    set dataDir /home/helios/oagData/sr/orbitControllaw/lattices/default
    set directory [set ${rootname}Readdir]
    
    SetStatus "Generating orbit correction files ($regenerateFiles $directory) ..."
    if [catch {APSSRGenerateControllawFiles -dataDir $dataDir -config $directory \
		   -currLimitH $BPLD(currLimitH) -currLimitV $BPLD(currLimitV) \
                  -regenerateFiles $regenerateFiles} result] {
        SetStatus "$result"
        return
    }
    SetStatus "done"
}

set hOrbitBumpReaddir h.BPLD-BMs
set vOrbitBumpReaddir v.BPLD-BMs

set BPLD(currLimitH) 5
set BPLD(currLimitV) 5
set BPLD(ocInterval) 4
set BPLD(ocSteps) 10000
set BPLD(orbitGainH) 0.4
set BPLD(orbitGainV) 0.4

proc StartControllaw {args} {
    set plane ""
    set regenerateFiles 0
    APSParseArguments {plane regenerateFiles}
    if ![string length $plane] {
        return -code error "Plane for running orbit correction is not given"
    }
    set rootname ${plane}OrbitBump
    global ${rootname}Readdir BPLD
    set config [set ${rootname}Readdir]
    switch $plane {
        h {
            set runControlPV S:RC:OrbitControlLawXC
	    set widget .xcontrollaw
	    set config $hOrbitBumpReaddir
        }
        v {
            set runControlPV S:RC:OrbitControlLawYC
	    set widget .ycontrollaw
	    set config $vOrbitBumpReaddir
        }
        default {
            return -code error "plane should be h or v!"
        }
    }
    
    set dataDir /home/helios/oagData/sr/orbitControllaw/lattices/default
    if [catch {APSSRGenerateControllawFiles -dataDir $dataDir -config $config \
		   -regenerateFiles $regenerateFiles } result] {
        return -code error "$result"
    }
    if {0} {
	# check presence of beam
	if [catch {exec cavget -list=S-DCCT:currentM \
		   } current] {
        return -code error "StartControllaw: $current"
	}
	if [expr abs($current) < 12] {
	    return -code error "StartControllaw: not enough current in ring for BM-BPLD validation, inject beam to 12mA."
	}
    }
    set interval 4
    set steps 10000
    set Plane [string toupper $plane]
    if [catch {APSSRPrepareControllawOptions -config $config -steps $BPLD(ocSteps) -gain $BPLD(orbitGain$Plane) \
		   -interval $BPLD(ocInterval) -deltaLimit 0.5} options] {
	return -code error "Error prepare controllaw option: $options"
    }
  
    if [exec cavget -list=$runControlPV.RUN -pend=30] {
        if [catch {AbortControllaw -plane $plane } result] {
            return -code error "$result"
        }
    }
    
    if {0} {
    if [catch {exec logMessage -sourceId=offsetMeasurement \
                 -tag=Instance $runControlPV -tag=Action Start \
             } result ] {
        APSAlertBox .alert -errorMessage "error with logMessage: $result"
        return -code error "Error!"
    }
    }
    
    global controllawDone
    set controllawDone 0
    set abortComm "AbortControllaw -plane $plane"
    APSExecLog $widget -width 95 \
	-name "SR ${plane}-orbit correction for $plane BM-BPLD validation" \
	-unixCommand "sddscontrollaw  $options" \
	-abortCallback $abortComm \
	-cancelCallback $abortComm
    
}

proc MakeConfigWidget {args} {
    global BPLD
    set plane h
    set parent ""
    
    APSParseArguments {plane parent}
    
    set rootname ${plane}OrbitBump
    global ${rootname}MainDir ${rootname}Lattice 
    set ${rootname}MainDir /home/helios/oagData/sr/orbitControllaw/lattices
    set ${rootname}Lattice default
    global ${rootname}Plane ${rootname}Readdir ${rootname}ReadDescription
    global ${rootname}FilterEnd1 
    set ${rootname}Plane $plane
    set ${rootname}Readdir ${plane}.BPLD-BMs
    set ${rootname}ReadDescription ""
    set ${rootname}FilterEnd1 .*
    
    APSFileSelectWidget .file -parent $parent -variable ${rootname}Readdir -label "Config: " \
      -pathVariableList [list ${rootname}MainDir ${rootname}Lattice] \
      -mode directory -filterVariableList \
      [list ${rootname}Plane ${rootname}FilterEnd1] -width 60 \
      -incrementButtons 1 -contextHelp \
      "Enter the name of the configuration file to read."
	 
    APSLabeledEntry .descrip -parent $parent -label "Description:" -width 60 -packOption "-side top -anchor w" \
      -textVariable ${rootname}ReadDescription -contextHelp \
      "Shows the description of the last-read configuration file."
    
    APSButton .readDesc -parent $parent.descrip -text "Read" -packOption "-side right" \
      -command "ReadDescription  -plane $plane" \
      -contextHelp "Reads the description of the configuration."
    
}

proc ReadDescription {args} {
    global BPLD
    set plane ""
    APSParseArguments {plane}
    set rootname ${plane}OrbitBump
    global ${rootname}Readdir ${rootname}ReadDescription
    set config [subst \$${rootname}Readdir]
     set tmpfile /tmp/[APSTmpString]
    
    # read the configuration
    set baseDir /home/helios/oagData/sr/orbitControllaw
    
    set configDir $baseDir/lattices/default/$config
    if ![file exists $configDir/config] {
	SetStatus "Can't find config file for $configDir/config."
        return
    }
    set ${rootname}ReadDescription [lindex [exec sdds2stream $configDir/config -para=Description] 0]
    SetStatus  "Done."
    return
}

proc MakeBump {args} {
    set plane ""
    APSParseArguments {plane}
    
    global BPLD

    set amp $BPLD(${plane}Amp)
    if $BPLD(useGroup) {
	SetStatus "Creating postive BM bump for $BPLD(posSectors) in $plane plane ..."
	if [catch {CreateBump -sectorList "[split $BPLD(posSectors) -]" -plane $plane -amp $amp} result] {
	    return -code error "Error creating bump: $result"
	}
	SetStatus "Creating negative  BM bump for $BPLD(negSectors) in $plane plane ..."
	if [catch {CreateBump -sectorList "[split $BPLD(negSectors) -]" -plane $plane -amp [expr -1.0*$amp]} result] {
	    return -code error "Error creating bump: $result"
	}
    } else {
	set sectorList [GetSectorList]
	if [catch {CreateBump -sectorList $sectorList -amp $amp -plane $plane} result] {
	    return -code error "Error creating bump3: $result"
	}
    }
}

proc CreateBump {args} {
    set plane ""
    set amp ""
    set sectorList ""
    APSParseArguments {plane amp sectorList}
    global BPLD
    if ![string length $amp] {
	set amp $BPLD(${plane}Amp)
    }
   
    switch $plane {
	h -
	x {
	    set runControlPV S:RC:OrbitControlLawXC 
	    set coord x
	}
	v -
	y {
	    set runControlPV S:RC:OrbitControlLawYC
	    set coord y
	}
	default {
	    return -code error "plane should be h or v!"
	}
    }
    if [expr abs($amp)]>0 {
	SetStatus "check if controllaw runnin..."
	if [catch {exec cavget -list=${runControlPV}.RUN } running] {
	    return -code error "Error readding $plane runControlPV: $result"
	}
	if !$running {
	    return -code error "$plane controllaw is not running."
	}
    }
    if ![llength $sectorList] {
	set sectorList [GetSectorList]
    }
    SetStatus "Generating bump with amp=$amp for $plane plane..."
    foreach sector $sectorList {
	SetStatus "working on $sector..."
	set sector [scan $sector S%ld]
	if {$sector==1} {
	    set sector0 40
	} else {
	    set sector0 [expr $sector -1]
	}
	set sector1 [expr $sector+1]
	set putList ""
	set factor 0.7
	#S39B:P0 and S40A:P0 are being used for injection, their setpoint can not be changed.
	switch $coord {
	    x  {
		lappend putList S[format %02d $sector0]A:P3:x:SetpointC=[expr -1.0*$amp]
		lappend putList S[format %02d $sector0]B:P0:x:SetpointC=[expr -1.0*$amp*$factor]
		lappend putList S[format %02d $sector0]B:P3:x:SetpointC=[expr -1.0*$amp]
		lappend putList S[format %02d $sector0]B:P6:x:SetpointC=$amp
		if {$sector==1} {
		    #S01A:P0 does not exist use S01A:P1
		    lappend putList S01A:P1:x:SetpointC=[expr $amp*$factor]
		} else {
		    lappend putList S[format %02d $sector]A:P0:x:SetpointC=[expr $amp*$factor]
		}
		lappend putList S[format %02d $sector]A:P3:x:SetpointC=$amp
		if {$sector!=39} {   
		    lappend putList S[format %02d $sector]B:P0:x:SetpointC=[expr $factor*$amp]
		}
		lappend putList S[format %02d $sector]B:P3:x:SetpointC=$amp
		lappend putList S[format %02d $sector]B:P6:x:SetpointC=[expr -1.0*$amp]
		if {$sector!=39} {
		    lappend putList S[format %02d $sector1]A:P0:x:SetpointC=[expr -1.0*$amp*$factor]
		}
		lappend putList S[format %02d $sector1]A:P3:x:SetpointC=[expr -1.0*$amp]
		lappend putList S[format %02d $sector1]B:P3:x:SetpointC=[expr -1.0*$amp]
		lappend putList S[format %02d $sector1]B:P6:x:SetpointC=$amp
		if $BPLD(deltaBump) {
		     if [catch {exec cavput -delta -list=[join $putList ,] -pend=10 } result] {
			return -cde error "Error create x bump for sector $sector: $result"
		    }
		} else {
		    if [catch {exec cavput -list=[join $putList ,] -pend=10 } result] {
			return -cde error "Error create x bump for sector $sector: $result"
		    }
		}
	    }
	    y {
		if $BPLD(deltaBump) {
		    if [catch {exec cavput -delta  -list=S -list=[format %02d $sector0],[format %02d $sector],[format %02d $sector1] \
				   -list=B:P6=$amp,A:P3=$amp,A:P2=$amp,B:P0=[expr -1.0*$amp] -list=:y:SetpointC
			exec cavput  -delta -list=S[format %02d $sector]A:P1:y:SetpointC=[expr -1.0*$amp] } result] {
			return -code error "Error create y bump for sector $sector: $result"
		    }
		} else {
		     if [catch {exec cavput  -list=S -list=[format %02d $sector0],[format %02d $sector],[format %02d $sector1] \
				   -list=B:P6=$amp,A:P3=$amp,A:P2=$amp,B:P0=[expr -1.0*$amp] -list=:y:SetpointC
			exec cavput  -list=S[format %02d $sector]A:P1:y:SetpointC=[expr -1.0*$amp] } result] {
			return -code error "Error create y bump for sector $sector: $result"
		    }
		}
	    }
	}
    }
    SetStatus "done."
}

proc MakeOrbitBumpWidget {args} {
    set parent ""
    APSParseArguments {parent}
    
    #make sector widget
    global BPLD

    #make OC widget
    set wList [APSTabFrame .tab -parent $parent -labelList "Horizontal Vertical" -label "" -height 180 -width 700]
    set w1 [lindex $wList 0]
    set w2 [lindex $wList 1]
    MakeConfigWidget -plane h -parent $w1
    MakeConfigWidget -plane v -parent $w2

    APSLabeledEntry .currlimit -parent $w1 -label "DCCT current limit (mA):" -width 20 -textVariable BPLD(currLimitH)
    APSLabeledEntry .currlimit -parent $w2 -label "DCCT current limit (mA):" -width 20 -textVariable BPLD(currLimitV)
    APSLabeledEntry .gain -parent $w1 -label "Orbit Correction Gain:" -width 20 -textVariable BPLD(orbitGainH)
    APSLabeledEntry .gain -parent $w2 -label "Orbit Correction Gain:" -width 20 -textVariable BPLD(orbitGainV)
    
    APSLabeledEntry .interval -parent $w1 -label "Orbit Correction Interval(seconds):" -width 29 -textVariable BPLD(ocInterval)
    APSLabeledEntry .interval -parent $w2 -label "Orbit Correction Interval(seconds):" -width 29 -textVariable BPLD(ocInterval)
    APSLabeledEntry .steps -parent $w1 -label "Orbit Correction Steps:" -width 29 -textVariable BPLD(ocSteps)
    APSLabeledEntry .steps -parent $w2 -label "Orbit Correction Steps:" -width 29 -textVariable BPLD(ocSteps)
    
    
    
    APSButton .gen -parent $w1 -text "GENERATE" \
      -command "GenerateControllawFiles -plane h -regenerateFiles 1"\
      -contextHelp "Forces a regeneration of tests, bpm-in-use, and other files for response matrix selected. Necessary when bpm or corrector limits are changed.\n\nThis button does not start controllaw."

    APSButton .start -parent $w1 -text "RUN" \
	-command "StartControllaw -plane h" \
	-contextHelp "Press to start orbit correction using the above correction configuration in h plane."
    APSButton .abort -parent $w1 -text "ABORT" \
	-command "AbortControllaw -plane h" \
	-contextHelp "Press to orbit orbit correction in h plane."
    APSButton .bump -parent $w1 -text "Make Bump" -command "MakeBump -plane h"
    APSButton .restore -parent $w1 -text "Zero Bump" -command "CreateBump -plane h -amp 0"
    APSButton .check -parent $w1 -text "Check Orbit" -command "CheckOrbit -plane h"
    APSButton .info -parent $w1 -text "Info" -command "ControllawInfo -plane h"
    
    APSButton .gen -parent $w2 -text "GENERATE" \
	-command "GenerateControllawFiles -plane v -regenerateFiles 1"\
      -contextHelp "Forces a regeneration of tests, bpm-in-use, and other files for response matrix selected. Necessary when bpm or corrector limits are changed.\n\nThis button does not start controllaw."
    APSButton .start -parent $w2 -text "RUN" \
      -command "StartControllaw -plane v" \
      -contextHelp "Press to start orbit correction using the above correction configuration in v plane."
    APSButton .abort -parent $w2 -text "ABORT" \
      -command "AbortControllaw -plane v" \
      -contextHelp "Press to orbit orbit correction in v plane"
    APSButton .bump -parent $w2 -text "Make Bump" -command "MakeBump -plane v"
    APSButton .zero -parent $w2 -text "Zero Bump" -command "CreateBump -plane v -amp 0"
    APSButton .check -parent $w2 -text "Check Orbit" -command "CheckOrbit -plane v"
     APSButton .info -parent $w2 -text "Info" -command "ControllawInfo -plane v"
}

proc AbortControllaw {args} {
    set plane ""
    APSParseArguments {plane}
    SetStatus "aborting $plane controllaw..."
    switch $plane {
        h -
	x {
            set runControlPV S:RC:OrbitControlLawXC
        }
        v -
	y {
            set runControlPV S:RC:OrbitControlLawYC
        }
        default {
            return -code error "plane should be h or v!"
        }
    }
    
    if [catch {exec cavget -list=${runControlPV}.RUN } running] {
	return -code error "Error readding $plane runControlPV: $result"
    }
    if !$running {
	SetStatus "$plane controllaw is not running."
	return
    }
    SetStatus "Aborting $plane controllaw ($runControlPV)..."
    if [catch {exec cavput -list=${runControlPV}.ABRT=1 } result] {
	return -code error "Error abort $plane controllaw: $result"
    }
    exec cawait -waitFor=${runControlPV}.RUN,equalTo=0
    exec cavput -list=${runControlPV}.CLR=1
    SetStatus "$plane controllaw aborted."
    if {0} {
    if [catch {exec logMessage -sourceId=offsetMeasurement \
                 -tag=Instance $runControlPV -tag=Action Abort \
             } result ] {
        APSAlertBox .alert -errorMessage "error with logMessage: $result"
        return -code error "Error!"
    }
    }
}

proc GetSectorList {args} {
    global BPLD
    set sectorList ""
    if $BPLD(useGroup) {
	set sectorList  [concat [split $BPLD(posSectors) -] [split $BPLD(negSectors) -]]
    } else {
	foreach sector $BPLD(sectorList) {
	    if $BPLD($sector.checked) {
		lappend sectorList $sector
	    }
	}
    }
    return $sectorList
}

proc AbortControllaw {args} {
    set plane ""
    APSParseArguments {plane}
    SetStatus "aborting $plane controllaw..."
    switch $plane {
        h -
	x {
            set runControlPV S:RC:OrbitControlLawXC
        }
        v -
	y {
            set runControlPV S:RC:OrbitControlLawYC
        }
        default {
            return -code error "plane should be h or v!"
        }
    }
    
    if [catch {exec cavget -list=${runControlPV}.RUN } running] {
	return -code error "Error readding $plane runControlPV: $result"
    }
    if !$running {
	SetStatus "$plane controllaw is not running."
	return
    }
    SetStatus "Aborting $plane controllaw ($runControlPV)..."
    if [catch {exec cavput -list=${runControlPV}.ABRT=1 } result] {
	return -code error "Error abort $plane controllaw: $result"
    }
    exec cawait -waitFor=${runControlPV}.RUN,equalTo=0
    exec cavput -list=${runControlPV}.CLR=1
    SetStatus "$plane controllaw aborted."   
}


proc BringUpADT {args} {
    set type adjust
    APSParseArguments {type}
    set oldDir [pwd]
    set dir /home/helios/oagData/ADTFiles/srBpm
    switch $type {
	adjust {
	    set file sr.bpm.lowPass1s.adjusted.pv
	}
	setpoint {
	    set file sr.bpm.setpoint.pv
	}
	error {
	    set file sr.bpm.lowPass1s.error.pv
	}
    }
    if {$type=="adjust"} {
	exec adt -f  $dir/$file -a $dir -z 3 -d &
    } else {
	exec adt -f $dir/$file -a $dir &
    }
    cd $oldDir
}

proc CheckOrbit {args} {
    set plane ""
    set sectorList ""
    set timeout 50
    APSParseArguments {plane sectorList timeout}
    set rootname ${plane}OrbitBump
    global BPLD ${rootname}Readdir
    if ![llength $sectorList] {
	set sectorList [GetSectorList]
    }
    set dataDir /home/helios/oagData/sr/orbitControllaw/lattices/default
    set config [set ${rootname}Readdir]
    set tmpRoot /tmp/[APSTmpString]
    
    foreach sector $sectorList {
	if [catch {exec sddsprocess $dataDir/$config/definitions -pipe=out -match=col,ControlName=${sector}*ErrorM \
		       | sdds2stream -pipe=in -col=ControlName } bpmList] {
	    return -code error "Error getting bpm names: $bpmList"
	}
	set BPMList($sector) [join $bpmList]
	set BPLD($sector.done) 0
    }
    set timeout [expr [clock seconds]+$timeout]
    set first 1
    while {[clock seconds]<$timeout} {
	set done 1
	foreach sector $sectorList {
	    if $BPLD($sector.done) {
		continue
	    }
	    if $first {
		SetStatus "waiting for $sector orbit converging..."
	    }
	    if [catch {APScavget -list=[join $BPMList($sector) ,] -pend=10 } valList] {
		return -code error "Error reading BPM errors: $valList"
	    }
	    set good 1
	    foreach bpm $BPMList($sector) val $valList {
		if {[expr abs($val)]>$BPLD(tolerance)} {
		    if $first {
			SetStatus "$bpm not converged ($val)..."
		    }
		    set good 0
		    set done 0
		    break
		}
	    }
	    set BPLD($sector.done) $good
	}
	if $done {
	    break
	} else {
	    after 1000
	}
	set first 0
    }
    set badList ""
    foreach sector $sectorList {
	if !$BPLD($sector.done) {
	    SetStatus "Orbit at $sector not converged after $timeout seconds."
	    lappend badList $sector
	} else {
	    SetStatus "Orbit at $sector converged."
	}
    }
    if [llength $badList] {
	return -code error "orbit at [join $badList ,] not converged."
    }
    SetStatus "done."
}

proc UpdateSectorSelect1 {args} {
    global BPLD
    switch $BPLD(posSectors) {
	S01-S03 {
	    set BPLD(negSectors) S21-S23
	}
	S05-S07 {
	    set BPLD(negSectors) S25-S27
	}
	S09-S11 {
	   set  BPLD(negSectors) S29-S31
	}
	S13-S15 {
	   set   BPLD(negSectors) S33-S35
	}
	S17-S19 {
	    set  BPLD(negSectors) S37-S39
	}
    }
}
proc UpdateSectorSelect2 {args} {
    global BPLD
    switch $BPLD(negSectors) {
	S21-S23 {
	    set BPLD(posSectors) S01-S03
	}
	S25-S27 {
	    set BPLD(posSectors) S05-S07
	}
	S29-S31 {
	   set  BPLD(posSectors) S09-S11
	}
	S33-S35 {
	   set   BPLD(posSectors) S13-S15
	}
	S37-S39 {
	    set  BPLD(posSectors) S17-S19
	}
    }
}

for {set sector 1} {$sector<40} {incr sector 2} {
    lappend BPLD(sectorList) [format %02d $sector]
}
set archiveDir /home/helios/oagData/sr/BPLD/Validation/BM
set configDir /home/helios/oagData/sr/BPLD/BPLD_Config


set BPLD(configDir)  $configDir
set BPLD(archiveDir) $archiveDir
set BPLD(lastSectors) ""
APSApplication . -name "SRBMBPLDValidationWithOrbit" -version $CVSRevisionAuthor \
  -overview "SR BM BPLD validation with traveling orbit wave." \
  -contextHelp "SR BM BPLD validation."
set status ""

APSScrolledStatus .ss -parent .userFrame -textVariable status \
  -packOption "-side top -fill x" -height 4 -width 60 \
  -contextHelp "Provides execution status and operation hints."
SetStatus "Working..."
set dataDir [APSGoToDailyDirectory -subdirectory BMSteer]
set BPLD(dataDir) $dataDir
set BPLD(allowedFaultBPMs) 11
set BPLD(bpmConfig) Default
set BPLD(plane) h
set BPLD(hAmp) 400
set BPLD(vAmp) 400

set sectorList ""
set varList ""
for {set sector 1} {$sector<40} {incr sector 2} {
    set sectorf S[format %02d $sector]
    lappend sectorList $sectorf
    set BPLD($sectorf.checked) 0
    lappend varList BPLD($sectorf.checked)
}
set BPLD(sectorList) $sectorList
APSCheckButtonFrame .sector -parent .userFrame -label "Select BPLD Sector:" -orientation horizontal -buttonList $sectorList \
    -variableList $varList -allNone 1 -limitPerRow 10
set BPLD(posSectors) S01-S03
set BPLD(negSectors) S21-S23
APSDisableWidget .userFrame.sector

APSRadioButtonFrame .sec1 -parent .userFrame -label "Select Double-Sector Group:" \
    -buttonList {S01-S03 S05-S07 S09-S11 S13-S15 S17-S19}\
    -commandList {UpdateSectorSelect1 UpdateSectorSelect1 UpdateSectorSelect1  UpdateSectorSelect1 UpdateSectorSelect1} \
    -valueList {S01-S03 S05-S07 S09-S11 S13-S15 S17-S19} -variable BPLD(posSectors) -orientation horizontal
APSRadioButtonFrame .sec2 -parent .userFrame -label "Match  Double-Sector Group:" \
    -buttonList {S21-S23 S25-S27 S29-S31 S33-S35 S37-S39}  \
    -valueList {S21-S23 S25-S27 S29-S31 S33-S35 S37-S39} -variable BPLD(negSectors) -orientation horizontal \
    -commandList {UpdateSectorSelect2 UpdateSectorSelect2 UpdateSectorSelect2  UpdateSectorSelect2 UpdateSectorSelect2}


#APSDisableWidget .userFrame.sec2.frame
set BPLD(useGroup) 0
APSRadioButtonFrame .choice -parent .userFrame -label "Use Sector Group?   " -buttonList {Yes No} \
    -valueList {1 0} -variable BPLD(useGroup) -orientation horizontal -commandList "SelectGroup SelectGroup"
SelectGroup
set BPLD(testFirmware) 1
APSRadioButtonFrame .choice1 -parent .userFrame -label "Use BPLD Offsets?   " -buttonList {Yes No} \
    -valueList {1 0} -variable BPLD(testFirmware) -orientation horizontal -commandList "SelectGroup SelectGroup"

APSLabeledEntry .dir -parent .userFrame -width 70 -textVariable BPLD(archiveDir) -label "Data dir:"

APSFrameGrid .grid -parent .userFrame -xList {x1 x2}
set w1 .userFrame.grid.x1
set w2 .userFrame.grid.x2
APSLabeledEntry .bpms -parent $w1 -width 20 -textVariable BPLD(allowedFaultBPMs) -label "BM number of BPMs fault allowed:"
APSRadioButtonFrame .plane -parent $w2 -label "Plane:" -buttonList {x y} -valueList {h v} -variable plane -orientation horizontal \
    -variable BPLD(plane)
APSRadioButtonFrame .beam -parent $w2 -label "BPMs to use for BPLD:" -buttonList {Default_Config All} \
    -valueList {Default All} -variable BPLD(bpmConfig) -orientation horizontal \
    -contextHelp "if default is chosen then only BPMs that are selected in default config will be tested, otherwise all available BPMs will be tested."

APSLabeledEntry .xamp -parent $w1 -label "X plane bump amplitude (um):" -textVariable BPLD(hAmp) -width 20
APSLabeledEntry .yamp -parent $w1 -label "Y plane bump amplitude (um):" -textVariable BPLD(vAmp) -width 20
set BPLD(deltaBump) 0
APSRadioButtonFrame .delta -parent $w1 -label "Bump in delta mode?" -buttonList {yes no} \
    -valueList {1 0} -orientation horizontal -variable BPLD(deltaBump)
set BPLD(tolerance) 200
APSLabeledEntry .tol -parent $w2 -label "Orbit tolerance (um):" -textVariable BPLD(tolerance) -width 20
if $expert {
    APSFrame .f2 -parent .userFrame -label "Setup: Orbit Correction Config"
    MakeOrbitBumpWidget -parent .userFrame.f2.frame
    
}
    
APSFrame .f3 -parent .userFrame -label "Orbit Info"
set w1 .userFrame.f3.frame
#$w1 configure -bd 0
APSButton .adt -parent $w1 -text "BPM Adjusted ADT" -command "BringUpADT -type adjust"
APSButton .adt0 -parent $w1 -text "BPM Error ADT" -command "BringUpADT -type error"
APSButton .adt1 -parent $w1 -text "BPM Setpoint ADT" -command "BringUpADT -type setpoint"
APSButton .infox -parent $w1 -text "X Orbit Corr. Info" -command "ControllawInfo -plane h"
APSButton .infoy -parent $w1 -text "Y Orbit Corr. Info" -command "ControllawInfo -plane v"
APSFrame .f4 -parent .userFrame -label "LMPS Info"
set w1 .userFrame.f4.frame
APSButton .reset -parent $w1 -text "Reset All" -command "exec cavput -list=S-MPS:GlobalResetC=1"
APSButton .clear -parent $w1  -text "ClearFaults" -command "ClearFaults"
APSButton .setup -parent $w1 -text "Setup Validation" -command "SetupValidation"
APSButton .load -parent $w1 -text "Load Default Limits" -command LoadDefaultLimits
APSButton .check -parent $w1 -text "Check LMPS" -command "CheckBMBPLDState -checkOnly 1"

APSButton .trip -parent .userFrame -text "Trip Pending Test" -command "Start -tripPending 1"

APSButton .start -parent .userFrame -text "Fast Abort Test" -command "Start"
APSButton .display -parent .userFrame -text "Display Result" -command "PlotArchive"

APSButton .reduce -parent .userFrame -text "Reduce Limits by 3" -command "ReduceTripLimits -factor 3"
APSButton .restore -parent .userFrame -text "Restore Limits" -command "ReduceTripLimits -factor 1"
APSButton .medm -parent .userFrame -text "Global BM BPLD Pending States" -command BringUpGlobalMedm


if $expert {
    APSButton .check -parent .userFrame -text "Check Result" -command "SetupPVLinks;CheckBMBPLDState"
    SetStatus "Ready."
}
