#!/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 lab 0
set args $argv
APSStrictParseArguments {lab}

set sectorList ""
set varList ""
if $lab {
    set sectorList {01 03 05}
    set archiveDir /home/oxygen/DIAG/oagData/sr/BPLD/Validation/ID
    set BPLD(configDir) /home/oxygen/DIAG/apsu/BPLD/BPLD_Config
    set BPLD(beam) Sim
} else {
   # set sectors [exec sdds2stream -col=Sector /home/helios/oagData/sr/BPLD/doubleSectors.sdds]
    for {set sector 1} {$sector<=39} {incr sector 2} {
	lappend sectorList [format %02d $sector]
    }
    set archiveDir /home/helios/oagData/sr/BPLD/Validation/ID
    set BPLD(configDir) /home/helios/oagData/sr/BPLD/BPLD_Config
    set BPLD(beam) Real
}
set BPLD(lab) $lab

set BPLD(archiveDir) $archiveDir

foreach sector $sectorList {
    set BPLD(S$sector) 0
    lappend varList BPLD(S$sector)
}
set BPLD(sectorList) $sectorList
set BPLD(sectorVarList) $varList
set BPLD(xOffsetLimit) 1000
set BPLD(yOffsetLimit) 500
set BPLD(angleLimit) 250

proc ClearFaults {args} {
    set arm 1
    APSParseArguments {arm}
    
    global BPLD
    
    SetStatus "Clear faults..."
    set sectorList ""
    foreach sector $BPLD(sectorList) {
	if $BPLD(S$sector) {
	    lappend sectorList $sector
	}
    }
    if ![llength $sectorList] {
	set sectorList $BPLD(sectorList)
    }
    if {0} {
    SetStatus "set limits..."
    if [catch {exec cavput -list=S -list=[join $sectorList ,] -list=-LMPS:BPLD:ID -list=1,2 -list=:AIOL- -list=H1,H2,H3 \
		   -list=-SP=$BPLD(xOffsetLimit) -pend=10 } result] {
	return -code error "Error setting x  offset limits: $result"
    }
    
    if [catch {exec cavput -list=S -list=[join $sectorList ,] -list=-LMPS:BPLD:ID -list=1,2 -list=:AIOL- -list=V1,V2,V3 \
		   -list=-SP=$BPLD(yOffsetLimit) -pend=20 } result] {
	return -code error "Error setting y  offset limits: $result"
    }
    if [catch {exec cavput -list=S -list=[join $sectorList ,] -list=-LMPS:BPLD: -list=ID1,ID2 -list=:AIAL_ -list=H,V \
		   -list=-SP=$BPLD(angleLimit) } result] {
	return -code error "Error setting angle limits: $result"
    }
    }	   
	
    if [catch {APScavput -list=S -list=[join $sectorList ,] \
		   -list=-LMPS:BPLD:ID -list=1,2 -list=:AIOR- \
		   -list=H,V -list=1,2 -list=-SP=0 -pend=60} result] {
	return -code error "Error set ID bpm offsts to zero: $result"
    }
    if [catch {APScavput -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 "Error set BM bpm offsets to zero: $result"
    }
    #clear External inputs faults
    if [catch {APScavput -list=S -list=[join $sectorList ,] -list=-LMPS:CtrlReg0-Cmd=0 -pend=30 } result] {
	return -code error "Error clear ext inputs: $result"
    }
    after 5000
    if [catch {APScavput -list=S -list=[join $sectorList ,]  -list=-LMPS:UsrReset-SP=1 -pend=30 } result] {
	return -code error "Error reset to clear faults: $result"
    }
    
    
    SetStatus "done."
}

set status ""
proc SetStatus {text} {
    global status
    set status "$text"
    update
}
proc GetSelectedSectors {args} {
    global BPLD
    set sectorList ""
    foreach sector $BPLD(sectorList) {
	set sector0 [scan $sector %d]
	if {$BPLD(beam)=="Real" && $sector0>35} {
	    #no IDs in 37, 39 for operation
	    continue
	}
	if $BPLD(S$sector) {
	    lappend sectorList $sector
	}
    }
    return $sectorList
}

proc LoadDefaultLimits {args} {
    global BPLD lab  apsSCRSnapDir apsSCRRequestDir
    if $lab {
	set scrFile /home/oxygen/DIAG/oagData/SCR/snapshots/SRBPLD/SRBPLD-DefaultLimits.gz
	set apsSCRSnapDir /home/oxygen/DIAG/oagData/SCR/snapshots
	set apsSCRRequestDir /home/oxygen/DIAG/oagData/SCR/requestFiles
    } else {
	set scrFile /home/helios/oagData/SCR/snapshots/SRBPLD/SRBPLD-DefaultLimits.gz
	set apsSCRSnapDir /home/helios/oagData/SCR/snapshots
	set apsSCRRequestDir /home/helios/oagData/SCR/requestFiles
    }
    set tmpRoot /tmp/[APSTmpString]
    set opt ""
    set sectorList [GetSelectedSectors]
    if ![llength $sectorList] {
	SetStatus "No sectors selected."
	return
    }
    foreach sector $sectorList {
	if ![string length $opt] {
	    set opt -match=col,Beamline=S$sector
	} else {
	    append opt ",Beamline=S$sector,|"
	}
    }
    
    if [catch {eval exec sddsprocess $scrFile -pipe=out -match=col,Category=ID_BPLD_Limit $opt \
		   | sddscasr -pipe=in -restore } result] {
	return -code error "Error loading ID BPLD limits from SCR: $result"
    }
    SetStatus "Default SCR ID BPLD limits for double sector [join $sectorList] loaded."
    
}

proc SetArchiveLog {args} {
    global BPLD
    set BPLD(mainDir) $BPLD(archiveDir)
    set BPLD(rootname) [clock format [clock seconds] -format %Y-%m%d]
}
set BPLD(mainDir) [APSGoToDailyDirectory -subdirectory IDBPLDValidation]
set BPLD(rootname) IDValidation
set BPLD(BPM) P0
set BPLD(IDchoice) Both
set BPLD(window) Both
set BPLD(plane) x
set BPLD(IDL) 5.571
set L(P0) 2.756
set L(P1) 3.213

APSApplication . -name SRIDBPLDValidation  \
  -overview "SRIDBPLDValidation provides convenience controls for ID BPLD trip limit."
APSScrolledStatus .status -parent .userFrame -width 80 \
        -textVariable status
APSLabeledEntry .dir -parent .userFrame -textVariable BPLD(mainDir) -width 80 \
    -label "Log Dir:"
APSButton .archive -parent .userFrame.dir -packOption "-side right" -text "archive" -size small -command \
    "SetArchiveLog"
APSButton .daily -parent .userFrame.dir -packOption "-side right" -text "daily" -size small \
    -command "set BPLD(mainDir) [APSGoToDailyDirectory -subdirectory IDBPLDValidation]; set BPLD(rootname) IDValidation"

APSCheckButtonFrame .sector -label "LMPS:" -parent .userFrame  -limitPerRow 10 \
    -orientation horizontal -buttonList $sectorList -variableList $BPLD(sectorVarList) \
    -allNone 1

set BPLD(BPM) UpP0DownP0
set BPLD(BPM) default
APSRadioButtonFrame .bpm -parent .userFrame -label "BPMs:  " -buttonList {"Default Config" "All P0s" "All P1s" "UpP0 DownP1" "UpP1 DownP0"} \
    -orientation horizontal -variable BPLD(BPM) -valueList {default UpP0DownP0 UpP1DownP1 UpP0DownP1 UpP1DownP0}

APSFrameGrid .grid -parent .userFrame -xList {x1 x2}
set w1 .userFrame.grid.x1
set w2 .userFrame.grid.x2

APSRadioButtonFrame .id -parent $w1 -buttonList {ID1 ID2 Both} -valueList {ID1 ID2 Both} \
    -orientation horizontal -variable BPLD(IDchoice) -label "ID:    "
APSRadioButtonFrame .beam -parent $w2 -label "Beam:  " -buttonList {Simulation Real} \
    -orientation horizontal -valueList {Sim Real} -variable BPLD(beam) \
    -commandList {"set BPLD(testType) $BPLD(testType)" "set BPLD(testType) offset"}


APSRadioButtonFrame .plane -parent $w1 -label "Plane: " -buttonList {x y} -valueList {x y} \
    -orientation horizontal -variable BPLD(plane) -commandList {"set BPLD(window) Both" "set BPLD(window) Diamond"}

APSRadioButtonFrame .win -parent $w2 -buttonList {Diamond Rect Both} -valueList {Diamond Rect Both} \
    -orientation horizontal -variable BPLD(window) -label "Window type:"


set BPLD(testType) offset
APSRadioButtonFrame .type -parent $w1 -label "Validate with:" -buttonList {Setpoints Synthetic_data} \
    -valueList {offset synthetic} -orientation horizontal -variable BPLD(testType)


set BPLD(lab) $lab

#APSButton .start -parent .userFrame -text "START" -command StartValidation
APSFrame .f1 -parent .userFrame 
APSFrame .f2 -parent .userFrame
set w1 .userFrame.f1.frame
set w2 .userFrame.f2.frame
$w1 configure -bd 0
$w2 configure -bd 0


#APSButton .val2 -parent $w1 -text "BPLDArming Validation" -command "ValidateBPLDArming"
APSButton .val1 -parent $w1 -text "BPLDLimit Validation" -command BPLDLimitsValidation
APSButton .val3 -parent $w1 -text "FastAbort Test" -command "FastAbortTest"
APSButton .display -parent $w1 -text "Display Result" -command DisplayResult
APSButton .load -parent $w2 -text "Load Default Limits" -command LoadDefaultLimits
APSButton .kill -parent $w2 -text "Kill ExecWindows" -command KillExecWindows
APSButton .clear -parent $w2  -text "Clear Faults" -command ClearFaults

#APSButton .plot -parent .userFrame -text "Plot Archive" -command PlotArchive

proc PlotArchive {args} {
    global BPLD selectFile
    cd $BPLD(archiveDir)
    set files [glob -nocomplain *.sdds]
    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 LoadIDBPLDConfig {args} {
    global BPLD lab L
    if {$BPLD(BPM)=="default"} {
	#use default config
	set configFile  $BPLD(configDir)/config.sdds
    } else {
	set configFile $BPLD(configDir)/BPLDConfig-ID$BPLD(BPM).sdds
    }
  
    set tmpRoot /tmp/[APSTmpString]
    
    set pvList ""
    set valList ""
    APSAddToTmpFileList -ID bpld -fileList "$tmpRoot.1 $tmpRoot.load"
    foreach sectorf $BPLD(sectorList) {
	set sector [format $sectorf %d]
	if [catch {exec sddsprocess $configFile -filter=col,BPLDSector,$sector,$sector -filter=col,IDBPM,0.5,1.5 $tmpRoot.1 } result] {
	    return -code error "Error process data for sector $sector: $result"
	}
	set bpmList [exec sdds2stream -col=DeviceName $tmpRoot.1]
	set indexList [exec sdds2stream -col=BPLDIndex $tmpRoot.1]
	for {set i 1} {$i<=4} {incr i} {
	    set bpm$i [lindex $bpmList [expr $i-1]]
	    set index$i [lindex $indexList [expr $i-1]]
	}

	lappend pvList S${sectorf}-LMPS:BPLD:ID1:BPM-XY1_idx-SP
	lappend valList $index1
	lappend pvList S${sectorf}-LMPS:BPLD:ID1:BPM-XY2_idx-SP
	lappend valList $index2
	lappend pvList S${sectorf}-LMPS:BPLD:ID2:BPM-XY1_idx-SP
	lappend valList $index3
	lappend pvList S${sectorf}-LMPS:BPLD:ID2:BPM-XY2_idx-SP
	lappend valList $index4

	lappend pvList S${sectorf}-LMPS:BPLD:ID1:S1-SP
	if [regexp {P0} $bpm1] {
	    lappend valList -$L(P0)
	} elseif [regexp {P1} $bpm1] {
	    lappend valList -$L(P1)
	} else {
	    return -code error "invalid bpm - $bpm1 found!"
	}
	lappend pvList S${sectorf}-LMPS:BPLD:ID1:S2-SP
	if [regexp {P0} $bpm2] {
	    lappend valList $L(P0)
	} elseif [regexp {P1} $bpm2] {
	    lappend valList $L(P1)
	} else {
	    return -code error "invalid bpm - $bpm2 found!"
	}
	
	lappend pvList S${sectorf}-LMPS:BPLD:ID2:S1-SP
	if [regexp {P0} $bpm3] {
	    lappend valList -$L(P0)
	} elseif [regexp {P1} $bpm3] {
	    lappend valList -$L(P1)
	} else {
	    return -code error "invalid bpm - $bpm3 found!"
	}
	lappend pvList S${sectorf}-LMPS:BPLD:ID2:S2-SP
	if [regexp {P0} $bpm4] {
	    lappend valList $L(P0)
	} elseif [regexp {P1} $bpm4] {
	    lappend valList $L(P1)
	} else {
	    return -code error "invalid bpm - $bpm4 found!"
	}
    }
   # puts $tmpRoot.load
    if [catch {exec sddsmakedataset -col=ControlName,type=string -data=[join $pvList ,] \
		   -col=ValueString,type=string -data=[join $valList ,] $tmpRoot.load } result] {
	return -code error "Error creating load file: $result"
    }
    if [catch {exec sddscasr -restore $tmpRoot.load} result] {
	return -code error "Error writing config to firmware: $result"
    }
    SetStatus "Current BPM configuration $BPLD(BPM) is loaded to firmware."
}

proc MoveGapToBPLDTripLimits {args} {
    set moveTo ""
    set sectorList ""
    APSParseArguments {moveTo sectorList}
    global BPLD
    
    if ![llength $sectorList] {
	foreach sector $BPLD(sectorList) {
	    set sector0 [scan $sector %d]
	    if $BPLD(S$sector) {
		if $sector0>1 {
		    lappend sectorList [expr $sector0 -1]
		} else {
		    lappend sectorList 40
		}
		lappend sectorList $sector0
	    }
	}
    }
    set tmpRoot /tmp/[APSTmpString]
    if [catch {exec sddsmakedataset $tmpRoot.sector -col=LMPSsector,type=long -data=[join $sectorList ,] } result] {
        return -code error "Error moving gaps1: $result"
    }
    APSAddToTmpFileList -ID idbpld -fileList "$tmpRoot.sector $tmpRoot.move"
    
    if [catch {exec sddsselect /home/helios/oagData/sr/IDs/SetGapToBPLDTripLimits $tmpRoot.sector -reuse -equate=LMPSsector $tmpRoot.move } result] {
        return -code error "Error moving gaps2: $result"
    }
    set rows [exec sdds2stream -rows=bar $tmpRoot.move]
    if !$rows {
	SetStatus "No ID gaps to move."
        #no ID gap to move
        return
    }
    if [string length $moveTo] {
        if [catch {exec sddsprocess $tmpRoot.move -nowarnings -reprint=col,ValueString,$moveTo } result] {
            return -code error "Error moving gaps3: $result"
        }
    }
    SetStatus "Restore device values"
    set deviceList [exec sdds2stream -col=DeviceName $tmpRoot.move]
    
    if [catch {exec sddscasr -restore $tmpRoot.move } result] {
        APSMpReturn error "APSMpIDRestoreGapsFromSCR: $result"
    }
    
    after 1000
    if [catch {exec sddsprocess $tmpRoot.move -pipe=out -reedit=col,ControlName,%/:GapSetC/:StartC/ \
                 -reprint=col,ValueString,1 \
                 | sddscasr -pipe=in -restore -pend=30 } result] {
        return -code error "Error1: $result"
    }
    after 1000
    SetStatus "Waiting for ID gaps stop moving. (it may take several minutes, please be patient.)"
    if [catch {APSMpCheckAndWaitForIDs -deviceList $deviceList -timeout 500} results] {
        if {[APSPEMTKDialog .warningDialog -text "Problem1 occurred while waiting restoring ID gaps\n$results"] == 1} {
            return -code error "Error in checking ID gaps: $results"
        }
    }
    
}

proc WriteLogFileHeader {args} {
    set logFile ""
    APSStrictParseArguments {logFile}
    global BPLD
    
    if ![file exist $logFile] {
	#write header of 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=IDType, type=string, &end"
	puts $BPLD(logID) "&column name=BPM, type=string &end"
	puts $BPLD(logID) "&column name=WindowShape, type=string, &end"
	puts $BPLD(logID) "&column name=Plane, type=string, &end"
	puts $BPLD(logID) "&column name=ValidationType, type=string, &end"
	puts $BPLD(logID) "&column name=ValidationResult, type=string, &end"
	puts $BPLD(logID) "&column name=FaultDescription, type=string,&end"
	puts $BPLD(logID) "&data mode=ascii, no_row_counts=1, &end"
	exec chmod 777 $BPLD(logFile)
	flush $BPLD(logID)
    }
}

proc FastAbortTest {args} {
    #fast abort use only one sector and one limit point (instead of 12 points for x, 4 points for y)
    global BPLD lab
    set sectorList [GetSelectedSectors]
    if ![llength $sectorList] {
	SetStatus "Please select one sector for fast abort test!"
	return
    }
    set sector [lindex $sectorList 0]
    SetStatus "Test fast abort with sector $sector"
    set logRoot [CreateLogRoot]
    set logFile $logRoot.FastAbort
    set BPLD(logFile) $logFile
    WriteLogFileHeader -logFile $logFile
    #fastabort only run with offset
    if {$BPLD(window)=="Both" && $BPLD(plane)=="y"} {
	SetStatus "Either rectangular or diamond is valid window shape for y plane."
	return
    }
    SetStatus "Load BPM configuration..."
    if [catch {LoadIDBPLDConfig} result] {
	return -code error "Error loading current ID-BPLD configuration: $result"
    }
    if {$BPLD(beam)=="Real" && !$BPLD(lab)} {
	APSInfoWindow .info -name "Inject Beam" -infoMessage "Please inject the beam with single bunch to 1-2mA, press OK when it is done!" \
	    -modal 1
	SetStatus "check beam current..."
	if [catch {exec cavget -list=S-MPS:MPSM2:BeamCurrentAveM -pend=10} beam] {
	    return -code error "Error reading beam current: $beam"
	}
	if {$beam<2} {
	    return -code error "beam current ($beam) is less than 2mA, ID-BPLD validation is prevented."
	}
    }
    if {!$BPLD(lab) && $BPLD(beam)=="Real"} {
	SetStatus "Move ID gaps to BPLD trip limits..."
	if [catch {MoveGapToBPLDTripLimits -moveTo 48} result] {
	    return -code error "Error moving ID gaps: $result"
	}
    }
    global execList
    set command "/home/oxygen/SHANG/oag/apps/src/tcltkapp/oagapp/SRBPLD_ID_Validation -sector [scan $sector %d] -plane $BPLD(plane) -ID $BPLD(IDchoice) -bpmType $BPLD(BPM) -window $BPLD(window) -logFile $logFile -IDL $BPLD(IDL) -testType offset -lab $BPLD(lab) -beam $BPLD(beam) -fastAbort 1"
    if [catch {exec /home/oxygen/SHANG/oag/apps/src/tcltkapp/oagapp/SRBPLD_ID_Validation -sector [scan $sector %d] -plane $BPLD(plane) -ID $BPLD(IDchoice) -bpmType $BPLD(BPM) -window $BPLD(window) -logFile $logFile -IDL $BPLD(IDL) -testType offset -lab $BPLD(lab) -beam $BPLD(beam) -fastAbort 1} result] {
	return -code error "BPLD ID Validation for S$sector failed: $result"
    }
    
    if {!$BPLD(lab) && $BPLD(beam)=="Real"} {
	SetStatus "Move ID gaps to above BPLD trip limits..."
	if [catch {MoveGapToBPLDTripLimit} result] {
	    return -code error "Error moving ID gaps: $result"
	}
    }
    SetStatus "Fast abort test for sector $sector done."
    set BPLD(S$sector.done) 0
    APSExecLog .s$sector -width 80 -lineLimit 1048 -name "Test S$sector $BPLD(IDchoice) Fast Abort" \
	-unixCommand "$command" \
	-callback "set BPLD(S$sector.done) done;SetStatus \"Fast Abort for sector $sector done\"" \
	-abortCallback "set BPLD(S$sector.done) aborted;SetStatus \"Fast Abort for sector $sector aborted\"" \
	-cancelCallback "set BPLD(S$sector.done) canceled;SetStatus \"Fast Abort for sector $sector cancelled\""
    lappend execList .s$sector
    tkwait variable BPLD(S$sector.done)
    SetStatus "Fast Abort for sector $sector done."
}

set execList ""
proc BPLDLimitsValidation {args} {
    global BPLD execList lab

    set sectorList [GetSelectedSectors]
    if ![llength $sectorList] {
	SetStatus "No sectors chosen."
	return
    }
    set doList ""
    
    set logRoot [CreateLogRoot]
    set logFile $logRoot.BPLDLimits
    set BPLD(logFile) $logFile
    WriteLogFileHeader -logFile $logFile
    
    if {$BPLD(window)=="Both" && $BPLD(plane)=="y"} {
	SetStatus "Either rectangular or diamond is valid window shape for y plane."
	return
    }
    if {$BPLD(window)=="Both" && $BPLD(plane)=="both"} {
	SetStatus "window shape 'Both' is valid only for x plane, change the plane selection to x."
	set BPLD(plane) x
    }
    SetStatus "Load BPM configuration..."
    if [catch {LoadIDBPLDConfig} result] {
	return -code error "Error loading current ID-BPLD configuration: $result"
    }
    if {$BPLD(beam)=="Real" && !$lab} {
	APSInfoWindow .info -name "Inject Beam" -infoMessage "Please inject the beam with single bunch to 1-2mA, press OK when it is done!" \
	    -modal 1
	SetStatus "check beam current..."
	if [catch {exec cavget -list=S-MPS:MPSM2:BeamCurrentAveM -pend=10} beam] {
	    return -code error "Error reading beam current: $beam"
	}
	if {$beam<2} {
	    return -code error "beam current ($beam) is less than 2mA, ID-BPLD validation is prevented."
	}
	SetStatus "Open gaps..."
	if [catch {MoveGapToBPLDTripLimits -moveTo 100} result] {
	    return -code error "Error moving gaps: $result"
	}
	APSInfoWindow .info -name "Start Square Matrix OC" -infoMessage "Please start square matrix orbit controllaw, press OK when it is done!" \
	    -modal 1
    }
    
    foreach sector $BPLD(sectorList) {
	set BPLD(S$sector.done) 0
	set sector0 [scan $sector %d]
	if $BPLD(S$sector) {
	    if {$sector0>35 && $BPLD(beam)=="Real"} {
		SetStatus "No IDs in sector $sector for operation, skip"
		continue
	    }
	    lappend doList $sector
	    set BPLD(S$sector.done) 0
	set command "/home/oxygen/SHANG/oag/apps/src/tcltkapp/oagapp/SRBPLD_ID_Validation -sector [scan $sector %d] -plane $BPLD(plane) -ID $BPLD(IDchoice) -bpmType $BPLD(BPM) -window $BPLD(window) -logFile $logFile -IDL $BPLD(IDL) -testType $BPLD(testType) -lab $BPLD(lab) -beam $BPLD(beam) -fastAbort 0"
	    APSExecLog .s$sector -width 80 -lineLimit 1048 -name "Test S$sector $BPLD(IDchoice)" \
		-unixCommand "$command" \
		-callback "set BPLD(S$sector.done) done;SetStatus \"Limits validation for $sector done.\"" \
		-abortCallback "set BPLD(S$sector.done) aborted;SetStatus \"Limits validation for $sector aborted.\"" \
		-cancelCallback "set BPLD(S$sector.done) canceledSetStatus \"Limits validation for $sector cancelled.\";"
	    lappend execList .s$sector
	}
    }
    if [llength $doList] {
	SetStatus "validating [join $doList] ..."
	foreach sector $doList {
	    tkwait variable BPLD(S$sector.done)
	}
	if [catch {exec cavput \
		       -list=APSU:MMPS2:BeamSim-SP=0} result] {
	    return -code error "Error turn off simulation mode: $result"
	}
	SetStatus "done."
    } else {
	SetStatus "No sector chosen."
    }
}

proc ValidateBPLDArming {args} {
    global BPLD lab
    set sectorList [GetSelectedSectors]
    if ![llength $sectorList] {
	SetStatus "No sectors chosen!"
	return
    }
    if {$BPLD(beam)=="Real" && !$lab} {
	SetStatus "moving selected gaps to trip limit.."
	if [catch {MoveGapToBPLDTripLimits -sectorList $sectorList -moveTo 48 } result] {
	    return -code error "$result"
	}
    }
    
    SetStatus "clear arming..."
    if [catch { ClearFaults} result] {
	return -code error  "Error clear arming: $result"
    }
    
    switch $BPLD(beam) {
	Sim {
	    if [catch {exec cavput \
			   -list=APSU:MMPS2:BeamSim-SP=1,APSU:MMPS2:CtrlReg0-Cmd.B2=0,APSU:MMPS2:Sim:BeamCurrent-SP=2,APSU:MMPS2:ID:Thold-SP=2 } result] {
		return -code error "Error setting beam current: $result"
	    }
	    if [catch {exec cavput -list=S -list=[join $sectorList ,] \
			   -list=-LMPS:ID:GapSim-SP=1,-LMPS:ID:GapSimClose-SP=1 -pend=10 } result] {
		return -code error "Error enabling gap: $result"
	    }
	}
	Real {
	    if [catch {exec cavput \
			   -list=APSU:MMPS2:BeamSim-SP=0,APSU:MMPS2:CtrlReg0-Cmd.B2=1 } result] {
		return -code error "Error disabling simulation beam: $result"
	    }
	    if !$lab {
		APSInfoWindow .info -name "Inject Beam" -infoMessage "Please inject the beam with single bunch to 1-2mA, press OK when it is done!" \
		    -modal 1
	    }
	}
    }
    if [catch {exec cavget -list=APSU:MMPS2:Beam_ID_Th-Sts -num } beamArm] {
	return -code error "Error reading beam arming state: $beamArm"
    }
    if !$beamArm {
	SetStatus "Beam is not armed, arming test failed"
	return
    }
    if [catch {exec cavget -list=S -list=[join $sectorList ,] -list=-LMPS:SysStatus-I.B0 -num } valList] {
	return -code error "Error reading beam arm state of selected sectors: $valList"
    }
    set error ""
    foreach sector $sectorList val $valList {
	if !$val {
	    lappend error $sector
	}
    }
    if [llength $error] {
	return -code error "Error [join $error] sectors did not armed."
    }
    if [catch {exec cavput -list=S -list=[join $sectorList ,] \
		   -list=-LMPS:BPLD:ID1_Enable-SP=1,-LMPS:BPLD:ID2_Enable-SP=1  -pend=10} result] {
	return -code error "Error enabling ID1, ID2: $result"
    }
    if {$BPLD(beam)=="Sim" || $lab } {
	if [catch {exec cavput -list=S -list=[join $sectorList ,] \
		       -list=-LMPS:ID:GapSim-SP=1,-LMPS:ID:GapSimClose-SP=1 -pend=10 } result] {
	    return -code error "Error enabling gap: $result"
	}
    } else {
	SetStatus "Move gap to 48mm..."
	if [catch {MoveGapToBPLDTripLimits -moveTo 48} result] {
            return -code error "$result"
        }
	if [lsearch -exact $sectorList 29]>=0 {
	    if [catch {TurnOnOffIEX -turnOff 0} result] {
		return -code error "Error turn on IEX: $result"
	    }
	}
    }
    after 2000
    if [catch {exec cavget -list=S -list=[join $sectorList ,] -num \
		   -list=-LMPS:SysStatus-I.B2 -pend=10 } ID1valList] {
	return -code error "Error reading ID1 arming state: $ID1valList"
    }
    if [catch {exec cavget -list=S -list=[join $sectorList ,] -num \
		   -list=-LMPS:SysStatus-I.B3 -pend=10 } ID2valList] {
	return -code error "Error reading ID2 arming state: $ID2valList"
    }
    set passList ""
    set txtList ""
    set IDList ""
    foreach sector $sectorList val1 $ID1valList val2 $ID2valList {
	if {!$val1 && !$val2} {
	    SetStatus "$sector ID1 and ID2 arming test failed."
	    set text "$sector ID1 and ID2 arming test failed."
	    lappend passList 0
	} elseif {!$val1} {
	    SetStatus "$sector ID1 arming test failed."
	    set text  "$sector ID1 arming test failed."
	    lappend passList 0
	} elseif {!$val2} {
	    SetStatus "$sector ID2 arming test failed."
	    set text  "$sector ID2 arming test failed."
	    lappend passList 0
	} else {
	    lappend passList 1
	    set text "passed"
	}
	lappend txtList $text
	lappend IDList ID1/ID2
    }
    set logRoot [CreateLogRoot]
    if [catch {exec sddsmakedataset $logRoot.BPLDArming  -col=Sector,type=long -data=[join $sectorList ,] -col=IDType,type=string -data=[join $IDList ,] \
                 -col=ValidationResult,type=string "-data=[join $txtList ,]" -col=Passed,type=short -data=[join $passList ,] } result] {
        return -code error "Error creating arming test result file: $result"
    }
    set printFile /tmp/[APSTmpString]
    if [catch {exec sddsprintout $logRoot.BPLDArming $printFile "-title=Arming Test results" \
                 -col=Sector,format=%02d -col=ValidationResult } result] {
        return -code error "Error printing BPLD limit tests result: $result"
    }
    APSFileDisplayWindow [APSUniqueName .] -height 30  \
	-fileName $printFile  -width 160  -deleteOnClose 1 
    
    SetStatus "done."
    
}

proc CreateLogRoot {args} {
    global BPLD
    if {!$BPLD(lab) && $BPLD(beam)=="Sim"} {
	set logRoot $BPLD(mainDir)/TestCheckout/[clock format [clock seconds] -format %Y-%j-%m%d:%H%M%S]
    } else {
	set logRoot $BPLD(mainDir)/[clock format [clock seconds] -format %Y-%j-%m%d:%H%M%S]
    }
    set BPLD(logRoot) $logRoot
    return $logRoot
    set currDir [clock format [clock seconds] -format %Y-%j-%m%d]
    if ![file exist $BPLD(mainDir)/$currDir] {
        exec mkdir -p $BPLD(mainDir)/$currDir
	exec chmod 777 $BPLD(mainDir)/$currDir
    }
    set logRoot $BPLD(mainDir)/$currDir/[clock format [clock seconds] -format %Y-%j-%m%d:%H%M%S]
    set BPLD(logRoot) $logRoot
    return $logRoot
}

proc TurnOnOffIEX {args} {
    set turnOff 1
    APSParseArguments {turnOff}
    if [catch {exec cavget  -list=ID29:feedback.VAL -printErrors -pend=20 } msg] {
        return -code error "Error reading IEX status: $msg"
    }
    if {[string compare $msg "Ready"]!=0} {
        return -code error "Error: IEX is not Read!"
    }
    if [catch {exec cavget -list=ID29:Main_on_off.VAL -printErrors -pend=30} onoff] {
        return -code error "Error reading IEX state: $onoff"
    }
    if {$onoff=="Off"} {
	if $turnOff {
	    return
	}
        if [catch {exec cavput -list=ID29:EnergySet.VAL=3.8,ID29:BxSet.VAL=0,ID29:BySet.VAL=0 -pend=30 } result] {
            return -code error "Error seting IEX: $result"
        }
        after 1000
        SetStatus "Turning on IEX..."
        if [catch {exec cavput -list=ID29:Main_on_off.VAL=On -pend=30} result] {
            return -code error "Error turning on IEX: $result"
        }
        if [catch {exec cawait -waitFor=ID29:feedback.VAL,sameas=Ready -timeLimit=180 } result] {
            return -code error "Error waiting for IEX to turn on : $result"
        }
        if [catch {exec cavget -list=ID29:feedback.VAL -printErrors -pend=30} msg] {
            return -code error "Error reading ID29:feedback.VAL : $msg"
        }
        if {[string compare $msg "Ready"]!=0} {
            return -code error "IEX was not able to turn on!"
        }
    } else {
	if !$turnOff {
	    if [catch {exec cavput -list=ID29:EnergySet.VAL=3.8,ID29:BxSet.VAL=0,ID29:BySet.VAL=0 -pend=30 } result] {
		return -code error "Error seting IEX: $result"
	    }
	    if [catch {exec cawait -waitFor=ID29:Energy.VAL,lowerlimit=3.6,upperlimit=3.9 \
			   -waitFor=ID29:BxRdbk.VAL,lowerlimit=0,upperlimit=1 \
			   -waitFor=ID29:ByRdbk.VAL,lowerlimit=0,upperlimit=1 -and -and -timeLimit=180 } result] {
		return -code error "Error waiting for IEX energy to go down: $result"
	    }
	    after 1000
	    if [catch {exec cavput -list=ID29:Main_on_off.VAL=Off -pend=30} result] {
		return -code error "Error turning off IEX: $result"
	    }
	}
	return
    }
}

proc CheckIEXArming {args} {
    set turnOff 1
    APSParseArguments {turnOff}
    
    global BPLDArmingTripped logID
    
    if [catch {exec cavget  -list=ID29:feedback.VAL -printErrors -pend=20 } msg] {
        return -code error "Error reading IEX status: $msg"
    }
    if {[string compare $msg "Ready"]!=0} {
        return -code error "Error: IEX is not Read!"
    }
    if [catch {exec cavget -list=ID29:Main_on_off.VAL -printErrors -pend=30} onoff] {
        return -code error "Error reading IEX state: $onoff"
    }
    if {$onoff=="Off"} {
        if [catch {exec cavput -list=ID29:EnergySet.VAL=3.8,ID29:BxSet.VAL=0,ID29:BySet.VAL=0 -pend=30 } result] {
            return -code error "Error seting IEX: $result"
        }
        after 1000
        SetStatus "Turning on IEX..."
        if [catch {exec cavput -list=ID29:Main_on_off.VAL=On -pend=30} result] {
            return -code error "Error turning on IEX: $result"
        }
        if [catch {exec cawait -waitFor=ID29:feedback.VAL,sameas=Ready -timeLimit=180 } result] {
            return -code error "Error waiting for IEX to turn on : $result"
        }
        if [catch {exec cavget -list=ID29:feedback.VAL -printErrors -pend=30} msg] {
            return -code error "Error reading ID29:feedback.VAL : $msg"
        }
        if {[string compare $msg "Ready"]!=0} {
            return -code error "IEX was not able to turn on!"
        }
    }
    after 2000
    SetStatus "Checking IEX arming state..."
    #check arming status
    if [catch {exec cavget -list=S29BPLD: -list=CH1,CH2 -list=:IDgapBI.VAL -printErrors -num -pend=20 } valList] {
        return -code error "Error reading IEX arming state: $valList"
    }
    set v1 [lindex $valList 0]
    set v2 [lindex $valList 1]
    if {$v1==0 || $v2==0} {
        SetStatus "IEX arming validation failed."
        set BPLDArmingTripped(29) 0
        logData "29 0 \"Arming validation failed.\""
    } else {
        SetStatus "IEX arming validation success."
        set BPLDArmingTripped(29) 1
        logData "29 0 \"Arming validation passed.\""
    }
    if $turnOff {
        if [catch {exec cavput -list=ID29:EnergySet.VAL=3.8,ID29:BxSet.VAL=0,ID29:BySet.VAL=0 -pend=30 } result] {
            return -code error "Error seting IEX: $result"
        }
        if [catch {exec cawait -waitFor=ID29:Energy.VAL,lowerlimit=3.6,upperlimit=3.9 \
                     -waitFor=ID29:BxRdbk.VAL,lowerlimit=0,upperlimit=1 \
                     -waitFor=ID29:ByRdbk.VAL,lowerlimit=0,upperlimit=1 -and -and -timeLimit=180 } result] {
            return -code error "Error waiting for IEX energy to go down: $result"
        }
        after 1000
        if [catch {exec cavput -list=ID29:Main_on_off.VAL=Off -pend=30} result] {
            return -code error "Error turning off IEX: $result"
        }
    }
}

proc logData {text} {
    global logID logFile BPLD

    set mainDir $BPLD(archiveDir)
    set currDir [clock format [clock seconds] -format %Y-%j-%m%d]
    if ![file exist $mainDir/currDir] {
        exec mkdir -p $mainDir/currDir
	exec chmod 777 $mainDir/currDir
        set logFile $mainDir/currDir/[clock format [clock seconds] -format %Y-%j-%m%d:%H%M%S].log
        if [string length $logID] {
            close $logID
        }
        set logID [open $logFile a+]
    }
    if ![string length $logID] {
        set logFile $mainDir/currDir/[clock format [clock seconds] -format %Y-%j-%m%d:%H%M%S].log
        set logID [open $logFile a+]
    }
    puts $logID "[clock format [clock seconds] -format %H:%M%:S] $text"
    flush $logID
}


proc KillExecWindows {args} {
    global execList
    foreach win $execList {
	if [winfo exist $win] {
	    destroy $win
	}
    }
    set execList ""
}

proc DisplayResult {args} {
    set logFile ""
    APSStrictParseArguments {logFile}
    global BPLD selectFile
    
    cd $BPLD(archiveDir)
    #set files1 [glob -nocomplain ????-???-????/*.BPLDLimits]
    #set files2 [glob -nocomplain ????-???-????/*.BPLDArming]
    #set files3 [glob -nocomplain ????-???-????/*.FastAbort]
    set files1 [glob -nocomplain *.FastAbort]
    set files1a [glob -nocomplain *.BPLDLimits]
    set files2 [glob -nocomplain TestCheckout/*.FastAbort]
    set files2a [glob -nocomplain TestCheckout/*.BPLDLimits]
    set files [lsort -decreasing [concat $files1 $files1a $files2 $files2a]]
    if ![llength $files] {
        SetStatus "No validation results found."
        return
    }
    set selectFile ""
    APSScrolledListWindow .process -name "Select a file" \
      -label "Select a file" \
      -itemList $files -selectionVar selectFile
    tkwait variable selectFile
    set tmpRoot /tmp/[APSTmpString]
    if [regexp "Arming" $selectFile] {
	if [catch {exec sddsprintout $selectFile $tmpRoot.print \
		       "-title=[string range [file extension $selectFile] 1 end] validation result" \
		       -col=Sector,format=%25d -col=IDType,format=%8s -col=ValidationType,format=%10s \
		       -col=ValidationResult,format=%50s } result] {
	    return -code error "Error print result: $result"
	}
    } else {
	puts $selectFile
	if [catch {exec sddsprintout $selectFile $tmpRoot.print "-title=logFile:  $selectFile\n" \
		    -col=Sector,format=%05d -col=IDType,format=%6s \
		   -col=BPM,format=%35s -col=WindowShape,format=%15s \
		   -col=Plane,format=%8s   -col=ValidationType,format=%10s \
		   -col=ValidationResult,format=%15s  } result] {
	    return -code error "Error printing result: $result"
	}
	#puts $tmpRoot.print
    }
    APSFileDisplayWindow [APSUniqueName .] -height 30  \
	    -fileName $tmpRoot.print  -width 160  -deleteOnClose 1 
    
    return
    
}
SetArchiveLog
