#!/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 CVSRevisionAuthor "\$Revision: 1.0 $ \$Author: shang $"

source /home/oxygen/SHANG/oag/apps/src/tcltkapp/oagapp/SRBPLD.tcl

set BMBPLD(scriptTest) 0

set varList ""
set pvList ""
set sectorList ""
for {set sector 1} {$sector<40} {incr sector 2} {
    set sectorf [format %02d $sector]
    lappend BMBPLD(sectorList) $sectorf
    set BMBPLD(S$sectorf.Iarming) 0
    set BMBPLD(S$sectorf.arming) 0
    lappend varList BMBPLD(S$sectorf.Iarming)
   
    lappend pvList S${sectorf}-LMPS:SysStatus-I.B1
    lappend sectorList $sectorf
}
set BMBPLD(sectorList) $sectorList
set BMBPLD(armingVarList) $varList
if [pv linkw [join $varList] [join $pvList] 30] {
    puts stderr "Error link PVs: $errorCode"
    exit 1
}
pv getw $varList
update

#trip pending PVs
set pvList ""
set varList ""


proc SetStatus {text} {
    global status
    set status "$text"
    update
}

proc UpdateArmingState {args} {
    set sector ""
    APSParseArguments {sector}
    global BMBPLD

    if [string length $sector] {
	set sectorList $sector
    } else {
	set sectorList $BMBPLD(sectorList)
    }
    foreach sector $sectorList {
	if [catch {exec cavget -list=S${sector}-LMPS:BPLD:BpmMask-SP,S${sector}-LMPS:BPLD:BM_Enable-I -pend=5} valList] {
	    return -code error "Error reading BPM mask: $valList"
	}
	set bpmMask [lindex $valList 0]
	set enable [lindex $valList 1]
	if {$bpmMask!=$enable} {
	    set BMBPLD(S$sector.arming) 0
	} else {
	    set BMBPLD(S$sector.arming) 1
	}
	if $BMBPLD(S$sector.arming) {
	    set color red
	} else {
	    set color green
	}
	if [info exist BMBPLD(S$sector.armbutton)] {
	    $BMBPLD(S$sector.armbutton) configure -selectcolor $color
	}
    }
}

proc MakeArmingWidget {widget args} {
    set parent ""
    APSParseArguments {parent}

    global BMBPLD

    APSFrame $widget -parent $parent -label "BM arming states (red: armed; green: not armed)" -packOption "-side top"
    set parent0 $parent 
    set parent $parent0$widget.frame
    frame $parent.f1
    set f1 $parent.f1
    pack $f1 -side left 
    $f1 configure -width 20
    
    foreach sector $BMBPLD(sectorList) {
	
	frame $parent.f1.s$sector
	set fn $parent.f1.s$sector
	pack $fn -side left
	$fn configure -bd 0 -padx 0 -pady 0
	
	checkbutton $fn.item -text "" -width 0 -height 0 -relief flat -font smallFont 
	pack $fn.item -side bottom -pady 0 -padx 0
	if $BMBPLD(S$sector.arming) {
	    set color red
	} else {
	    set color green
	}
	$fn.item configure -selectcolor $color
	
	set BPLDarming(S$sector.armbutton)  $fn.item
	
	label $fn.label -text $sector  -borderwidth 0 -padx 0 -pady 0 -highlightthickness 0
	pack $fn.label  -side bottom
    }
    APSFrame .but -parent $parent0 -packOption "-side top"
    APSButton .check -parent $parent0.but.frame -text "Check Arming Status" -command UpdateArmingState
    APSButton .start -parent $parent0.but.frame -text "Start Arming Test" -command StartArmingTest
    APSButton .display -parent $parent0.but.frame -text "Display Result" -command "PrintArmingTestResult"
}

proc MakeTripPendingWidget {widget args} {
    set parent ""
    APSParseArguments {parent}

    global BMBPLD

    set BMBPLD(bpmConfig) default
    set BMBPLD(useLimit) high
    set BMBPLD(plane) x
    
    APSFrame $widget -parent $parent -label "" -packOption "-side top"
    set f0 $parent$widget.frame
    $f0 configure -bd 0
    APSRadioButtonFrame .bpm -parent $f0 -label "Use All/Default BPMs? " -buttonList {"All BPMs" "Default Config"} \
	-orientation horizonal -variable BMBPLD(bpmConfig) -contextHelp "use all BPMs or BPMs in the default configuration." \
	-valueList {all default}
    set varList ""
    foreach sector $BMBPLD(sectorList) {
	set BMBPLD(S$sector.pendingChoice) 0
	lappend varList BMBPLD(S$sector.pendingChoice)
    }
    APSCheckButtonFrame .sector -parent $f0 -label "Select BM-BPLD Sector:" -orientation horizontal -buttonList $BMBPLD(sectorList) \
	-variableList $varList -allNone 1 -limitPerRow 10
    APSRadioButtonFrame .limit -parent $f0 -label "Use high or low limit?" -orientation horizontal -buttonList {High Low} \
	-valueList {high low} -variable BMBPLD(useLimit)
    APSRadioButtonFrame .plane -parent $f0 -label "Plane:                " -orientation horizontal -buttonList {x y} \
	-valueList {x y} -variable BMBPLD(plane)

    APSButton .start -parent $f0 -text "Start Trip Pending Test" -command StartTripPendingTest
    APSButton .display -parent $f0 -text "Display Result" -command "DisplayTripPendingResult"
    APSButton .clea -parent $f0 -text "Clear Faults" -command "ClearFaults"
    APSButton .load -parent $f0 -text "Load Default Limits" -command LoadLimits
}

proc DisplayTripPendingResult {args} {
    global BMBPLD SelectFile
    cd $BMBPLD(archiveDir)/TripPending
    set files [glob -nocomplain *.tripPending ]
    if ![llength $files] {
	SetStatus "No trip pending files found."
	return
    }
    set files [lsort -decreasing $files]
    set SelectFile ""
    APSScrolledListWindow .process -name "Select a file" \
      -label "Select a file" \
      -itemList $files -selectionVar SelectFile
    tkwait variable SelectFile
    set tmpRoot /tmp/[APSTmpString]
    if [catch {exec sddsprintout $SelectFile $tmpRoot.print \
		   "-title=[string range [file root [file tail $SelectFile]] 0 7]  result" \
		   -col=StartTime,format=%20s \
		   -col=EndTime,format=%20s \
		   -col=Sector,format=%6s \
		   -col=Plane,format=%5s \
		   -col=Limit,format=%6s \
		   -col=ValidationType,format=%10s \
		   -col=Result,format=%7s -col=FaultDesc,format=%30s  } result] {
	return -code error "Error print result: $result"
    }
    APSFileDisplayWindow [APSUniqueName .] -height 30  \
	-fileName $tmpRoot.print  -width 140  -deleteOnClose 1 
}

proc DisplayFastAbortResult {args} {
    global BMBPLD
    set logFile $BMBPLD(archiveDir)/FastAbort/FastAbort.sdds
    set tmpRoot /tmp/[APSTmpString]
    if [catch {exec  sddstimeconvert $logFile -pipe=out \
		   "-dateToTime=col,Time,StartTime,format=%a %b %d %H:%M:%S %Z %Y" \
		   |  sddsprintout -pipe=in $tmpRoot.print \
		   "-title=Fast Abort Test results" \
		   -col=StartTime,format=%20s \
		   -col=EndTime,format=%20s \
		   -col=Sector,format=%6s \
		   -col=Plane,format=%5s \
		   -col=Limit,format=%6s \
		   -col=ValidationType,format=%10s \
		   -col=Result,format=%7s -col=FaultDesc,format=%30s  } result] {
	return -code error "Error print result: $result"
    }
    APSFileDisplayWindow [APSUniqueName .] -height 30  \
	-fileName $tmpRoot.print  -width 140  -deleteOnClose 1	   
    
}

proc MakeFastAbortWidget {widget args} {
    set parent ""
    APSParseArguments {parent}

    global BMBPLD
    set BMBPLD(fastAbortSector) 01
    APSFrame $widget -parent $parent -label "" -packOption "-side top"
    set f0 $parent$widget.frame
    $f0 configure -bd 0
    APSRadioButtonFrame .sector -parent $f0 -label "Select BM-BPLD Sector:" -orientation horizontal -buttonList $BMBPLD(sectorList) \
	-valueList $BMBPLD(sectorList) \
	-variable BMBPLD(fastAbortSector) -limitPerRow 10
    set BMBPLD(useLimit) high
    set BMBPLD(plane) x
    APSRadioButtonFrame .limit -parent $f0 -label "Use high or low limit?" -orientation horizontal -buttonList {High Low} \
	-valueList {high low} -variable BMBPLD(useLimit)
    APSRadioButtonFrame .plane -parent $f0 -label "Plane:                " -orientation horizontal -buttonList {x y} \
	-valueList {x y} -variable BMBPLD(plane)

    APSButton .start -parent $f0 -text "Start Fast Abort Test" -command StartFastAbortTest
    APSButton .display -parent $f0 -text "Display Result" -command "DisplayFastAbortResult"
    APSButton .clea -parent $f0 -text "Clear Faults" -command "ClearFaults"
    APSButton .load -parent $f0 -text "Load Default Limits" -command LoadLimits
    
}

proc StartFastAbortTest {args} {
    global BMBPLD
    set timestr  [clock format [clock seconds] -format %Y-%m%d:%H%M%S]
    set BMBPLD(startTime) $timestr
    set BMBPLD(fastAbortLogFile) $BMBPLD(archiveDir)/FastAbort/FastAbort.sdds
     #change the MPS Access Mode to "MPS testing" so that users can write to offset PVs
    if [catch {exec cavput -list=S-MPS:AccessType=0 -pend=5} result] {
	return -code error "Error changing MPS access mode: $result"
    }
    if [catch {PrepareValidation -type FastAbort -sectorList $BMBPLD(fastAbortSector) -tripInhibit 0 } result] {
	SetStatus "Error prepare validation for fast abort test: $result"
	return
    }
    #fast abort use default config  number of allowed fault BPMs is 3
    if [catch {exec cavput -list=APSU:MMPS1:BM:FaultCnt-SP=3 -pend=5} result] {
	return -code error "Error change number of allowed fault BPMs: $result"
    }
    set sector $BMBPLD(fastAbortSector)
    set BMBPLD(S$sector.pendingMsg) ""
    SetStatus "Change BM-BPLD offsets for S$sector..."
    if [catch {ChangeBPMOffsets -sectorList $sector } result] {
	return -code error "Error change bpms offsets: $result"
    }
    after 5000
    SetStatus "check beam current..."
    set tries 1
    while {$tries<3} {
	if [catch {exec cavget -list=S-DCCT:CurrentM  } current] {
	    return -code error "Error reading SR current: $current"
	}
	if {$current<0.5} {
	    break
	}
	after 3000
	incr tries
    }
    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 for S$sector passed."
	set BMBPLD(S$sector.fastAbortResult) passed
    } else {
	SetStatus "Fast Abort test for S$sector failed."
	set BMBPLD(S$sector.fastAbortResult) failed
	if [catch {CheckBMPendingTrips -sectorList $sector} result] {
	    return -code error "Error checking BM faults: $result
	}
    }
    set timestr  [clock format [clock seconds] -format %Y-%m%d:%H%M%S]
    set BMBPLD(endTime) $timestr
    
    #write log file
    WriteFastAbortTestLogFile
    #set offset to 0
    if [catch {exec cavput -list=S${sector}-LMPS:BM_ -list=X,Y -range=begin=1,end=28 -list=_Offset-SP=0 } result] {
	return -code error "Error clear offsets(ChangeBPMOffsets1): $result"
    }
     # change the MPS access mode back to operation mode		
    if [catch {exec cavput -list=S-MPS:AccessType=1 -pend=5} result] {	
	return  -code error "Error changing MPS access mode to operation after trip pending test: $result"
    }
    SetStatus "Fast abort for $sector done."
}

proc ClearFaults {args} {
    global BMBPLD
    if [catch {ClearBPLDFaults -type BM -sectorList $BMBPLD(sectorList) -statusCallback SetStatus} result] {
	return -code error "Error clear faults: $result"
    }
}

proc LoadLimits {args} {
    if [catch {LoadDefaultBPLDLimits -type BM -statusCallback SetStatus } result] {
	return -code error "Error loading limits: $result"
    }
}
proc WriteArmingLogFileHeader {args} {
    global  BMBPLD
    set logDir $BMBPLD(archiveDir)/Arming
    if ![file exist $logDir] {
	exec mkdir $logDir
	exec chmod 777 $logDir
    }
    set logFile $logDir/$BMBPLD(armingRootname).sdds
    set BMBPLD(armingLogFile) $logFile
    if ![file exist $logFile] {
	set BMBPLD(arminglogID) [open $BMBPLD(armingLogFile) a+]
	puts $BMBPLD(arminglogID) "SDDS1"
	puts $BMBPLD(arminglogID) "&column name=StartTime, type=string, &end"
	puts $BMBPLD(arminglogID) "&column name=EndTime, type=string, &end"
	puts $BMBPLD(arminglogID) "&column name=Sector, type=string, &end"
	puts $BMBPLD(arminglogID) "&column name=Result, type=string, &end"
	puts $BMBPLD(arminglogID) "&column name=FaultDesc, type=string, &end"
	puts $BMBPLD(arminglogID) "&data mode=ascii, no_row_counts=1, &end"
	exec chmod 777 $BMBPLD(armingLogFile)
	flush $BMBPLD(arminglogID)
    }
}

proc WriteArmingLogFile {args} {
    global BMBPLD
    set sectorList $BMBPLD(sectorList)
    foreach sector $sectorList {
	set valList ""
	lappend valList $BMBPLD(startTime)
	lappend valList $BMBPLD(endTime)
	lappend valList S$sector
	lappend valList $BMBPLD(S$sector.armResult)
	lappend valList \"$BMBPLD(S$sector.armDesc)\"
	puts $BMBPLD(arminglogID) "[join $valList]"
    }
    flush $BMBPLD(arminglogID)
}

proc SetBMMask {args} {
    global BMBPLD
    set type Arming
    set sectorList ""
    APSParseArguments {type sectorList}
    
    SetStatus "Get BPMs..."
    if ![llength $sectorList] {
	set sectorList $BMBPLD(sectorList)
    }
    set gui 0
    set all 0
    switch $type {
	Arming {
	    set all 1
	}
	TripPending {
	    if {$BMBPLD(bpmConfig)=="all"} {
		set all 1
	    }
	}
	FastAbort {
	    set all 0
	}
    }
    if [catch {GetBMBPMs  -gui $gui -all $all} result] {
	return -code error "Error getting BM BPLD BPMs: $result"
    }
    set putList ""
    foreach sector $sectorList {
	lappend putList  S${sector}-LMPS:BPLD:BpmMask-SP=$BMBPLD(S$sector.mask)
    }
    SetStatus "Set BM masks for $sectorList..."
    if [catch {exec cavput -list=[join $putList ,] -pend=10} result] {
	return -code error "Error setting mask: $result"
    }
    SetStatus "done."
}

proc PrepareValidation {args} {
    set type Arming
    set tripInhibit 1
    set statusCallback SetStatus
    set sectorList ""
    APSParseArguments {type tripInhibit statusCallback sectorList}
    global BMBPLD
    
    if [catch {SetupValidation -type BM -tripInhibit $tripInhibit -statusCallback $statusCallback -SimBeam 0} result] {
	return -code error "Error setup BPLD: $result"
    }
    if [catch {APScavget -list=APSU:MMPS2:BM:Thold-SP -pend=10} BMarming] {
	   return -code error "Error reading BM arming current: $BMarming"
    }
    APSInfoWindow .info -width 20 -infoMessage "Please inject beam to greater than $BMarming mA." -modal 1
    if [catch {exec cavget -list=S-DCCT:CurrentM  } current] {
	return -code error "Error reading SR current: $current"
    }
    if {$current<$BMarming && !$BMBPLD(scriptTest)} {
	return -code error "The SR current is $current, less than the BM arming current. can not arm BM-BPLD."
    }
    if [catch {APScavget -num -list=APSU:MMPS2:Beam_BM_Th-Sts -pend=10} armed] {
	return -code error "Error reading BM arming state: $armed"
    }
    if {!$armed && !$BMBPLD(scriptTest) } {
	return -code error "The BM current is not armed!"
    }
    
    if [catch {SetBMMask -type $type -sectorList $sectorList} result] {
	return -code error "$result"
    }
    if [catch {APScavput -list=S -list=[join $sectorList ,] -list=-LMPS:BPLD:BM_Enable-SP=1 -pend=10} result] {
	return -code error "Error enabling BM BPLD: $result"
    }
    if {$type!="Arming"} {
	#change the MPS Access Mode to "MPS testing" so that users can write to offset PVs
	if [catch {exec cavput -list=S-MPS:AccessType=0 -pend=5} result] {
	    return -code error "Error changing MPS access mode: $result"
	}
	if [catch {exec cavput -list=S -list=[join $sectorList ,] -list=-LMPS:BM_ -list=X,Y -range=begin=1,end=28 -list=_Offset-SP=0 } result] {
	    APSInfoWindow .info -width 20 -infoMessage "$result.\nPlease change the write permission of BM-BPLD BPM offsets." -modal 1
	}
    }
}
    

proc StartArmingTest {args} {
    global BMBPLD
    set sectorList $BMBPLD(sectorList)
    set timestr  [clock format [clock seconds] -format %Y-%m%d:%H%M%S]
    set BMBPLD(armingRootname) BMArming-$timestr
    set BMBPLD(startTime) $timestr
    #change the MPS access mode back to testing  mode
    if [catch {exec cavput -list=S-MPS:AccessType=0 -pend=5} result] {
	return -code error "Error changing MPS access mode to MPS testing: $result"
    }
    if [catch {PrepareValidation -type Arming -sectorList $BMBPLD(sectorList) } result] {
	SetStatus "Error prepare validation for arming test: $result"
	return
    }
    after 3000
    
    #check arming state
    if [catch { CheckBMArming } result] {
	return -code error "BM arming test failed: $result"
    }
    #change the MPS access mode back to operation mode
    if [catch {exec cavput -list=S-MPS:AccessType=1 -pend=5} result] {
	return -code error "Error changing MPS access mode to operation after arming test: $result"
    }
    set timestr  [clock format [clock seconds] -format %Y-%m%d:%H%M%S]
    set BMBPLD(endTime) $timestr
    WriteArmingLogFileHeader
    WriteArmingLogFile
    APSInfoWindow .info -width 20 -infoMessage "Please disable the trip inhibitor after arming test." -modal 1
    SetStatus "BM arming test done."
    set tmpRoot  /tmp/[APSTmpString]
    if [catch {exec sddsprintout $BMBPLD(armingLogFile) $tmpRoot.print -col=StartTime,format=%20s -col=EndTime,format=%20s \
		   -col=Sector,format=%6s -col=Result,format=%10s -col=FaultDesc,format=%30s } result] {
	return -code error "Error printing result: $result"
    }
    APSFileDisplayWindow [APSUniqueName .] -fileName $tmpRoot.print -height 30 -width 150 -deleteOnClose 1
}

proc CheckBMArming {args} {
    global BMBPLD
    set sectorList $BMBPLD(sectorList)
    SetStatus "check BM amring..."
    
    if [catch {APScavget -num -list=APSU:MMPS2:Beam_BM_Th-Sts -pend=10} armed] {
	return -code error "Error reading BM arming state: $armed"
    }
    
    if {!$armed && !$BMBPLD(scriptTest)} {
	SetStatus "BM current is not armed."
	return -code error "BM current is not armed."
    }
    pv getw $BMBPLD(armingVarList)
    update
    foreach sector $sectorList {
	#UpdateArmingState -sector $sectorf -type BM
	if !$BMBPLD(S$sector.Iarming) {
	    SetStatus "S$sector BM is not armed."
	    set BMBPLD(S$sector.armResult) failed
	    set BMBPLD(S$sector.armDesc) "not armed"
	} else {
	    set BMBPLD(S$sector.armResult) passed
	    set BMBPLD(S$sector.armDesc) ""
	}
    }
    foreach sector $sectorList {
	if {$BMBPLD(S$sector.armResult)=="failed"} {
	    continue
	}
	set msg ""
	if [catch {APScavget -list=S${sector}-LMPS:BPLD:BM_Enable-I -pend=10} val] {
	    return -code error "Error reading BM arming of S$sector: $val"
	}
	if [catch {APScavget -list=S${sector}-LMPS:BPLD:BpmMask-SP -pend=5} mask] {
	    return -code error "Error reading BM bpm mask: $mask"
	}
	if {$val!=$mask} {
	    set BMBPLD(S$sector.arming) 0
	    SetStatus "S$sector BM is not armed correctly..."
	    set bitstring [format %b $val]
	    set len [string length $bitstring]
	    if {$len<[lindex $BMBPLD(S$sector.bpmIndexList) end]} {
		append msg "S$sector BM arming failed."
		continue
	    }
	    set badBPMList ""
	    foreach index $BMBPLD(S$sector.bpmIndexList) bpm $BMBPLD(S$sector.bpmList) {
		set i [expr $len-$index]
		puts "$i $index"
		set i0 [string index $bitstring $i]
		if !$i0 {
		    lappend badBPMList $bpm
		}
	    }
	    set msg "S$sector [join $badBPMList ,] arming test failed."
	} else {
	    set BMBPLD(S$sector.arming) 1
	}
	if [string length $msg] {
	    SetStatus "S$sector BM arming test failed: $msg."
	    set BMBPLD(S$sector.result) failed
	    set BMBPLD(S$sector.desc) $msg
	} else {
	    set BMBPLD(S$sector.result) passed
	    set BMBPLD(S$sector.desc) ""
	    SetStatus "S$sector BM arming test passed."
	}
    }
}

proc PrintArmingTestResult {args} {
    global BMBPLD SelectFile
    cd $BMBPLD(archiveDir)/Arming
    set files [glob -nocomplain *Arming*.sdds]
    if ![llength $files] {
	SetStatus "No arming test files found."
	return
    }
    set files [lsort -decreasing $files]
    set SelectFile ""
    APSScrolledListWindow .process -name "Select a file" \
      -label "Select a file" \
      -itemList $files -selectionVar SelectFile
    tkwait variable SelectFile
    set tmpRoot /tmp/[APSTmpString]
    if [catch {exec sddsprintout $SelectFile $tmpRoot.print \
		   "-title=[string range [file root [file tail $SelectFile]] 0 7]  result" \
		   -col=StartTime,format=%20s \
		   -col=EndTime,format=%20s \
		   -col=Sector,format=%6s -col=Result,format=%10s -col=FaultDesc,format=%30s  } result] {
	return -code error "Error print result: $result"
    }
    APSFileDisplayWindow [APSUniqueName .] -height 30  \
	-fileName $tmpRoot.print  -width 140  -deleteOnClose 1
}

proc GetSectorList {args} {
    global BMBPLD
    set sectorList ""
    foreach sector $BMBPLD(sectorList) {
	if $BMBPLD(S$sector.pendingChoice) {
	    lappend sectorList $sector
	}
    }
    return $sectorList
}

proc ChangeBPMOffsets {args} {
    set sectorList ""
    APSParseArguments {sectorList}

    global BMBPLD
    set coord [string toupper $BMBPLD(plane)]
    
    #set offset to 0
    if [catch {exec cavput -list=S -list=[join $sectorList ,] -list=-LMPS:BM_ -list=X,Y -range=begin=1,end=28 -list=_Offset-SP=0 } result] {
	return -code error "Error clear offsets(ChangeBPMOffsets1): $result"
    }
    set type $BMBPLD(useLimit)
    foreach sector $sectorList {
	SetStatus "Changing S$sector $coord BPM offsets..."
	if [catch {exec cavget -list=S${sector}-LMPS:BM_TBT_${coord} -range=begin=1,end=28 -list=-I -pend=5 -printErrors} rawList] {
	    return -code error "Error reading BPM raw readings(ChangeBPMOffset2): $rawList"
	}
	if [catch {exec cavget -list=S${sector}-LMPS:BM_${coord} -range=begin=1,end=28 -list=_TH-SP -pend=5 -printErrors} limitList] {
	    return -code error "Error reading BPM limits(ChangeBPMOffset2): $limitList"
	}
	set putList ""
	set index 1
	foreach raw $rawList limit $limitList {
	    switch $type {
		high {
		    set s0 [expr $limit - $raw]
		}
		low {
		    set s0 [expr -1.0*$limit - $raw]
		}
	    }
	    set offset [expr -1.10*$s0]
	    lappend putList S${sector}-LMPS:BM_${coord}${index}_Offset-SP=$offset
	    incr index
	}
	if [catch {exec cavput -list=[join $putList ,] -pend=10 } result] {
	    return -code "Error changing BPM offsets (ChangeBPMOffset3): $result"
	}
    }
}

proc CheckBMPendingTrips {args} {
    set sectorList ""
    APSParseArguments {sectorList}
    global BMBPLD
    SetStatus "Checking arming states..."
    if [catch {exec cavget -list=S -list=[join $sectorList ,] -list=-LMPS:SysStatus-I.B1 -pend=5 -printErrors} armList] {
	return -code error "Error in checking BM-BPLD trips: $armList"
    }
    foreach sector $sectorList  arm $armList {
	if !$arm {
	    set BMBPLD(S$sector.pendingResult) failed
	    SetStatus "$sector BM-BPLD not armed"
	    set BMBPLD(S$sector.pendingMsg) "BM-BPLD not armed;"
	} else {
	    set BMBPLD(S$sector.pendingResult) passed
	    set BMBPLD(S$sector.pendingMsg) ""
	}
    }
    SetStatus "Checking BM-BPM Faults..."
    if [catch {exec cavget -list=S -list=[join $sectorList ,] -list=-LMPS:BPLD:BM_IL_Status-I -printErrors -pend=5} bpmList] {
	return -code error "Error checking BPM faults: $bpmList"
    }
    foreach sector $sectorList bpm $bpmList {
	if {$BMBPLD(S$sector.pendingResult)=="failed" && !$BMBPLD(scriptTest) } {
	    continue
	}
	if {$bpm!=$BMBPLD(S$sector.mask)} {
	    set BMBPLD(S$sector.pendingResult) failed
	    SetStatus "$sector some BPMs not faulted."
	    append BMBPLD(S$sector.pendingMsg) "some BPMs not faulted;"
	}
    }
    SetStatus "check BM-BPLD faults..."
    if [catch {exec cavget  -list=S -list=[join $sectorList ,] -list=-LMPS:MLinkTXpkt_FS-I.B2 -printErrors -pend=5} bmList] {
	return -code error "Error checking BM-faults: $bmList"
    }
    foreach sector $sectorList bm $bmList {
	if {$BMBPLD(S$sector.pendingResult)=="failed" && !$BMBPLD(scriptTest) } {
	    continue
	}
	if !$bm {
	    set BMBPLD(S$sector.pendingResult) failed
	    SetStatus "$sector BM-BPLD not faulted."
	    append BMBPLD(S$sector.pendingMsg) "BM-BPLD not faulted;"
	}
    }
    SetStatus "Check BM-BPLD local link faults..."
    set fList ""
    set bit0List ""
    foreach sector $sectorList {
	set sector0 [scan $sector %d]
	set f [expr ($sector0 + 1)/2]
	set f0 [expr ($sector0-1)/2]
	lappend fList $f
	lappend bit0List [format %X $f0]
    }
    if [catch {exec cavget -list=APSU:MMPS1:LMPS -list=[join $fList ,] -list=:Fault-I.B2 -printErrors -pend=5} localList] {
	return -code error "Error reading local MPS faults: $localList"
    }
    foreach sector $sectorList local $localList {
	if {$BMBPLD(S$sector.pendingResult)=="failed" && !$BMBPLD(scriptTest) } {
	    continue
	}
	if !$local {
	    set BMBPLD(S$sector.pendingResult) failed
	    SetStatus "$sector BM-BPLD local MPS link not faulted."
	    append BMBPLD(S$sector.pendingMsg) "BM-BPLD local MPS link not faulted;"
	}
    }
    SetStatus "Check BM-BPLD local BPM MPS fault..."
    foreach sector $sectorList f $fList {
	if {$BMBPLD(S$sector.pendingResult)=="failed" && !$BMBPLD(scriptTest) } {
	    continue
	}
	set bitList ""
	foreach index $BMBPLD(S$sector.bpmIndexList) bpm $BMBPLD(S$sector.bpmList) {
	    set i [expr $index + 3]
	    set b [format %X $i]
	    lappend bitList $b
	}
	if [catch {exec cavget -list=APSU:MMPS1:LMPS${f}:Fault-I.B -list=[join $bitList ,] -printErrors -pend=5} faultList] {
	    return -code error "Error reading local BPM fault: $faultList"
	}
	foreach bpm $BMBPLD(S$sector.bpmList) fault $faultList index $BMBPLD(S$sector.bpmIndexList) bit $bitList {
	    if !$fault {
		set BMBPLD(S$sector.pendingResut) failed
		SetStatus "$sector $bpm not faulted."
		append BMBPLD(S$sector.pendingMsg) "$bpm not faulted;"
	    }
	}
    }
    SetStatus "Check local sector fast abort..."
    if [catch {exec cavget -list=APSU:MMPS1:LMPS:FastAbort-Sts.B -list=[join $bit0List ,] -pend=5 -printErrors} l1List] {
	return -code error "Error reading local sector fast abort: $l1List"
    }
    foreach sector $sectorList l1 $l1List {
	if {$BMBPLD(S$sector.pendingResult)=="failed" && !$BMBPLD(scriptTest)} {
	    continue
	}
	if !$l1 {
	    set BMBPLD(S$sector.pendingResult) failed
	    SetStatus "$sector local fast abort not faulted."
	    append BMBPLD(S$sector.pendingMsg) "local fast abort not faulted;"
	}
    }
   
    SetStatus "Check local sector fast abort with mask..."
    if [catch {exec cavget -list=APSU:MMPS1:LocalFAStatusMaskO-Sts.B -list=[join $bit0List ,] -pend=5 -printErrors} l2List] {
	return -code error "Error reading local mast status: $l2List"
    }
    foreach sector $sectorList l2 $l2List {
	if {$BMBPLD(S$sector.pendingResult)=="failed" && !$BMBPLD(scriptTest)} {
	    continue
	}
	if !$l2 {
	    set BMBPLD(S$sector.pendingResult) failed
	    SetStatus "$sector local fast abort mask not faulted."
	    append BMBPLD(S$sector.pendingMsg) "local fast abort mask not faulted;"
	}
    }
    SetStatus "check main2 fault..."
    if [catch {exec cavget -list=APSU:MMPS2:SMA:Data10-I.B -list=[join $bit0List ,] -pend=5 -printErrors} mainList] {
	return -code error "Error reading main2 status: $mainList"
    }
    foreach sector $sectorList main $mainList {
	if {$BMBPLD(S$sector.pendingResult)=="failed" && !$BMBPLD(scriptTest)} {
	    continue
	}
	if !$main {
	    set BMBPLD(S$sector.pendingResult) failed
	    SetStatus "$sector main2 not faulted."
	    append BMBPLD(S$sector.pendingMsg) "S$sector main2 not faulted;"
	} else {
	    SetStatus "S$sector trip pending test passed."
	}
    }
}

proc StartTripPendingTest {args} {
    global BMBPLD
    set timestr  [clock format [clock seconds] -format %Y-%m%d:%H%M%S]
    set BMBPLD(startTime) $timestr
    set BMBPLD(tripPendingLogFile) $BMBPLD(archiveDir)/TripPending/${timestr}.tripPending
    set sectorList [GetSectorList]
    if ![llength $sectorList] {
	SetStatus "No sectors chosen for trip pending test."
	return
    }
    #change the MPS Access Mode to "MPS testing" so that users can write to offset PVs
    if [catch {exec cavput -list=S-MPS:AccessType=0 -pend=5} result] {
	return -code error "Error changing MPS access mode: $result"
    }
    if [catch {PrepareValidation -type TripPending -sectorList $sectorList -tripInhibit 1 } result] {
	SetStatus "Error prepare validation for trip pending: $result"
	return
    }
    
    foreach nbpms $BMBPLD(nbpmsList) {
	set sectorList0 ""
	foreach sector $sectorList {
	    set bpms [llength $BMBPLD(S$sector.bpmList)]
	    if {$bpms==$nbpms} {
		lappend sectorList0 $sector
	    }
	}
	if ![llength $sectorList0] {
	    continue
	}
	set bpms [expr $nbpms-1]
	SetStatus "Change BM-BPLD number of allowed fault BPMs to $bpms."
	if [catch {exec cavput -list=APSU:MMPS1:BM:FaultCnt-SP=$bpms \
		       -pend=5} result] {
	    return -code error "Error change number of allowed fault BPMs: $result"
	}
	SetStatus "Change BM-BPLD offsets for [join $sectorList0]..."
	if [catch {ChangeBPMOffsets -sectorList $sectorList0 } result] {
	    return -code error "Error change bpms offsets: $result"
	}
	after 6000
	SetStatus "checking pending trip states..."
	if [catch {CheckBMPendingTrips -sectorList $sectorList0 } result] {
	    return -code error "Error check BM pending trips: $result"
	}
	after 1000
    }
    set BMBPLD(endTime) [clock format [clock seconds] -format %Y-%m%d:%H%M%S]
    #log data
    WritePendingTripTestLogFile

    #zero offsets
    if [APSYesNoPopUp "reset everything now?"] {
	if [catch {exec cavput -list=S -list=[join $sectorList ,] \
		       -list=-LMPS:BM_ -list=X,Y -range=begin=1,end=28 \
		       -list=_Offset-SP=0 -pend=60} result] {
	    return -code error "ClearBPLDFaults1: Error set BM bpm offsets to zero: $result"
	}
	after 1000
	if [catch {exec cavput -list=S -list=[join $sectorList ,] -list=-LMPS:UsrReset-SP=1 -pend=5} result] {
	    return -code error "Error reset BM-BPLDs: $result"
	}
	#change the MPS access mode back to operation mode
	if [catch {exec cavput -list=S-MPS:AccessType=1 -pend=5} result] {
	    return -code error "Error changing MPS access mode to operation after trip pending test: $result"
	}
	#change the number of fault BPMs back to 3
	if [catch {exec cavput -list=APSU:MMPS1:BM:FaultCnt-SP=3 -pend=5} result] {
	    return -code error "Error change number of allowed fault BPMs: $result"
	}
    }
    SetStatus "trip pending test done."
    set tmpRoot /tmp/[APSTmpString]
    if [catch {exec sddsprintout  $BMBPLD(tripPendingLogFile) $tmpRoot.print \
		   "-title=Trip Pending Test results" \
		   -col=StartTime,format=%20s \
		   -col=EndTime,format=%20s \
		   -col=Sector,format=%6s \
		   -col=Plane,format=%5s \
		   -col=Limit,format=%6s \
		   -col=ValidationType,format=%10s \
		   -col=Result,format=%7s -col=FaultDesc,format=%30s  } result] {
	return -code error "Error print result: $result"
    }
    APSFileDisplayWindow [APSUniqueName .] -height 30  \
	-fileName $tmpRoot.print  -width 140  -deleteOnClose 1
}

proc WritePendingTripTestLogFile {args} {
    global BMBPLD
    if [catch {WriteBMValidationLogFileHeader -logFile $BMBPLD(tripPendingLogFile) } logID] {
	return -code error "Error writing log file for trip pending test: $logID"
    }
    foreach sector $BMBPLD(sectorList) {
	if !$BMBPLD(S$sector.pendingChoice) {
	    continue
	}
	set valList ""
	lappend valList $BMBPLD(startTime)
	lappend valList $BMBPLD(endTime)
	lappend valList S$sector
	lappend valList \"[join $BMBPLD(S$sector.bpmList)]\"
	lappend valList $BMBPLD(plane)
	lappend valList $BMBPLD(useLimit)
	lappend valList $BMBPLD(S$sector.pendingResult)
	lappend valList offset
	lappend valList \"$BMBPLD(S$sector.pendingMsg)\"
	puts $logID "[join $valList]"
    }
    flush $logID
    close $logID
}

proc WriteFastAbortTestLogFile {args} {
    global BMBPLD
    set logFile $BMBPLD(archiveDir)/FastAbort/FastAbort.sdds
    if [catch {WriteBMValidationLogFileHeader -logFile $BMBPLD(fastAbortLogFile) } logID] {
	return -code error "Error writing log file header for BM fast abort: $logID"
    }
    set sector $BMBPLD(fastAbortSector)
    
    set valList ""
    lappend valList $BMBPLD(startTime)
    lappend valList $BMBPLD(endTime)
    lappend valList S$sector
    lappend valList \"[join $BMBPLD(S$sector.bpmList)]\"
    lappend valList $BMBPLD(plane)
    lappend valList $BMBPLD(useLimit)
    lappend valList $BMBPLD(S$sector.fastAbortResult)
    lappend valList offset
    lappend valList \"$BMBPLD(S$sector.pendingMsg)\"
    puts $logID "[join $valList]"
    flush $logID
    close $logID
}

set BMBPLD(configDir) /home/helios/oagData/BPLD/BPLD_Config
set BMBPLD(archiveDir) /home/helios/oagData/sr/BPLD/Validation/BM


APSApplication . -name "SRBMBPLDValidationNew" -version $CVSRevisionAuthor \
  -overview "SR BM BPLD arming, trip-pending and fast abort test" \
  -contextHelp "SR BM BPLD arming, trip pending and fast abort test ."
set status ""
set BMBPLD(SimBeam) 0

APSScrolledStatus .ss -parent .userFrame -textVariable status \
  -packOption "-side top -fill x" -height 10 -width 60 \
  -contextHelp "Provides execution status and operation hints."
SetStatus "Working..."
set dataDir [APSGoToDailyDirectory -subdirectory BMBPLD]
APSLabeledEntry .dir -parent .userFrame -width 70 -textVariable BMBPLD(archiveDir) -label "Data directory:"
APSRadioButtonFrame .test -parent .userFrame -label "Test Script Only?" -buttonList {Yes No} \
    -valueList {1 0} -orientation horizontal -variable BMBPLD(scriptTest)

set wList [APSTabFrame .tab -parent .userFrame -labelList "Arming TripPending FastAbort" -width 700 -height 300]
set w0 [lindex $wList 0]
set w1 [lindex $wList 1]
set w2 [lindex $wList 2]


#monitor arming state
for {set sector 1} {$sector<40} {incr sector 2} {
    set sectorf [format %02d $sector]
    pv umon BMBPLD(S$sectorf.arming) "UpdateArmingState -sector $sectorf -type BM"
}

UpdateArmingState

MakeArmingWidget .arming -parent $w0
MakeTripPendingWidget .pending -parent $w1
MakeFastAbortWidget .abort -parent $w2

