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

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

set env(EPICS_CA_AUTO_ADDR_LIST) YES
set env(EPICS_CA_ADDR_LIST) ""
wm geometry . +10+10

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

set bmBPMConfigStatus "Note: 1) there must be 4 ID bpms in each sector\n       2) BM BPMs can not use ID BPMs.\n      3)  S39B:P1 is actually S39B:P0, and S39B:P0 is actually S39C:P0"

proc SaveConfig {args} {
    set configFile ""
    APSParseArguments {configFile}
    global sectorList itemList description IDitemList configDir lab
    
    set dir $configDir
    if ![string length $configFile] {
	set filename IDBPLDConfig-[clock format [clock seconds] -format %Y-%j-%m%d:%H%M%S]
    } else {
	set filename $configFile
    }
   
    set bpmList ""
    set IDvalList ""
    set deviceList ""
    set error 0
    set msg ""
    foreach sector $sectorList {
	set IDcount 0
	set Sector [scan $sector S%d]
	set n1BPcount 0
	set n1APcount 0
	set n2BPcount 0
	set n2APcount 0

	foreach item $itemList {
	    set idname idBPM$sector$item
	    global $idname
	    lappend IDvalList [set $idname]
	    if [set $idname] {
		incr IDcount
	    }
	    set n $Sector
	    if {$sector=="S01"} {
		set n1 40
	    } else {
		set n1 [expr $Sector-1]
	    }
	    set n2 [expr $Sector+1]
	    set str [string range $item 0 2]
	    switch $str {
		"n-1" {
		    set item [string replace $item 0 2 [format %02d $n1]]
		    if [set $idname] {
			incr n1BPcount
		    }
		}
		"n+1" {
		    set item [string replace $item 0 2 [format %02d $n2]]
		    if [set $idname] {
			incr n2APcount
		    }
		}
		default {
		    set item [regsub "n" $item [format %02d $n]]
		  
		    if  [set $idname] {
			if [regexp {AP} $item] {
			    incr n1APcount
			} elseif [regexp {BP} $item] {
			    incr n2BPcount
			}
		    }
		    if {$Sector==39 && !$lab} {
			#S39B:P1 -> S39B:P0; S39B:P0 -> S39C:P0
			set item [regsub "BP0" $item "CP0"]
			set item [regsub "BP1" $item "BP0"]
		    }
		}
	    }
	    lappend bpmList S$item
	    set item [regsub "AP" $item A:P]
	    set item [regsub "BP" $item B:P]
	    set item [regsub "CP" $item C:P]
	    lappend deviceList S$item
	}
	if {$IDcount!=4} {
	    append msg "Error: $sector ID bpms !=4, you must select 4 bpms for each ID sector!\n"
	    SetStatus $msg
	    return
	}
	if {$n1BPcount==2 || $n1APcount==2} {
	    SetStatus "Error: both bpms for $sector ID1 are on same side!"
	    return
	}

	if {$n2BPcount==2 || $n2APcount==2} {
	    SetStatus "Error: both bpms for $sector ID2 are on same side!"
	    return
	}
    }
    if $error {
	SetStatus $msg
	return
    }
    set tmpRoot /tmp/[APSTmpString]
    if [catch {exec sddsmakedataset $tmpRoot.1 -col=DeviceName,type=string -data=[join $deviceList ,] \
		   -col=IDBPM,type=short -data=-data=[join $IDvalList ,] } result] {
	return -code error "Error creating IDBPM column1: $result"
    }
    if [catch {exec sddsconvert $dir/IDconfig.sdds -pipe=out -del=col,IDBPM \
		   | sddsprocess -pipe "-reprint=par,Description,[APSMakeSafeQualifierString $description]" \
		   | sddsxref -pipe=in $tmpRoot.1 -match=DeviceName -take=IDBPM $dir/$filename -fill -nowarn} result] {
	return -code error "Error creating IDBPM column2: $result"
    }
    
    APSAddToTmpFileList -ID idbpld -fileList $tmpRoot.1
    set oldDir [pwd]
    catch {exec rm $dir/IDconfig.sdds}
    cd $dir
    exec ln -s $filename IDconfig.sdds
    cd $oldDir
    SetStatus "config saved to $filename"
    if ![APSYesNoPopUp "Write saved configuration into LMPS?"] {
	return
    }
    if [catch { WriteIDBPLDConfig -statusCallback SetStatus -lab $lab} result] {
	return -code error "Error writing ID config into LMPS: $result"
    }
}

proc ReadOCConfig {args} {
    global BPLD itemList bmBPMCBWidget idBPMCBWidget sectorList configDir
    #the [hv].BPLD-IDs has to be the same
    set dir /home/helios/oagData/sr/orbitControllaw/lattices/default/h.BPLD-IDs
    set configFile $configDir/IDconfig.sdds
    APSSetSRSectorButtons -mode all-off -rootname idBPM  -itemList $itemList -sectorList $sectorList
    set tmpRoot /tmp/[APSTmpString]
    APSAddToTmpFileList -ID bpld -fileList $tmpRoot.0
    if [catch {exec sddsprocess $dir/config -pipe=out \
		   -match=par,NameType=MonitorNames \
		   "-match=col,Name=*:P0,Name=*:P1,|" \
		   | sddsxref -pipe $configFile  \
		   -match=Name=DeviceName -take=BPLDSector,BPLDIndex \
		   | sddssort -pipe=in $tmpRoot.0 -col=BPLDSector } result] {
	return -code error "Error reading h.BPLD-IDs/config: $result"
    }
    set bpmList [exec sdds2stream -col=Name $tmpRoot.0]
    set sectorList0 [exec sdds2stream -col=BPLDSector $tmpRoot.0]
    set indexList [exec sdds2stream -col=BPLDIndex $tmpRoot.0]
    foreach bpm $bpmList sector $sectorList0 index $indexList {
	#if {$sector>35} {
	#    break
	#}
	set item [lindex $itemList [expr $index -1]]
	set sector [format %02d $sector]
	set name idBPMS$sector$item
	global $name
	if [info exist idBPMCBWidget(S$sector$item)] {
	    $idBPMCBWidget(S$sector$item) invoke
	}
    }
}

proc ReadConfig {args} {
    
    global BPLD itemList bmBPMCBWidget idBPMCBWidget sectorList configDir lab

    set tmpFile /tmp/[APSTmpString]
    APSAddToTmpFileList -ID bmbpld -fileList "$tmpFile.id"
    set configFile $configDir/IDconfig.sdds
    
    
    APSSetSRSectorButtons -mode all-off -rootname idBPM  -itemList $itemList -sectorList $sectorList

    foreach sector $sectorList {
	set sector0 [scan $sector S%d]
	if [catch {exec sddsprocess $configFile $tmpFile.id -filter=col,IDBPM,0.5,1.5 -filter=col,BPLDSector,$sector0,$sector0 -nowarnings} result] {
	    continue
	}
	set idList [exec sdds2stream -col=BPLDIndex $tmpFile.id]
	foreach index $idList {
	    set item [lindex $itemList [expr $index -1]]
	    set name idBPM$sector$item
	   # puts "$name"
	    global $name
	    $idBPMCBWidget($sector$item) invoke
	}
    }
    
}

proc CreateSpecialConfig {args} {
    set up P0
    set down P0
    APSParseArguments {up down}

    global sectorList idBPMCBWidget itemList configDir
    set configFile BPLDConfig-IDUp${up}Down${down}.sdds
   
    APSSetSRSectorButtons -mode all-off -rootname idBPM  -itemList $itemList -sectorList $sectorList
    
    switch $up {
	P0 {
	    set item1 {n-1BP0 nBP0}
	}
	P1 {
	    set item1 {n-1BP1 nBP1}
	}
    }
    switch $down {
	P0 {
	    set item2 {nAP0 n+1AP0}
	}
	P1 {
	    set item2 {nAP1 n+1AP1}
	}
    }
    set itemList1 [concat $item1 $item2]
    foreach sector $sectorList {
	foreach item $itemList1 {
	    if {$sector=="S01" && [regexp "nAP0" $item]} {
		set item [regsub "AP0" $item "AP1"]
	    }
	    set name idBPM$sector$item
	    global $name
	   # set $name 1
	    $idBPMCBWidget($sector$item) invoke
	}
    }
    set save 1
    if [file exist $configDir/$configFile] {
	if ![APSYesNoPopUp "$configFile already exist, overwrite it?"] {
	    SetStatus "$configFile already exist!"
	    set save 0
	}
    }
    if $save {
#	puts $configFile
	SaveConfig -configFile $configFile
	catch {exec chmod 777 $configFile}
    }
    cd $configDir
    catch {exec rm IDconfig.sdds}
    exec ln -s $configFile IDconfig.sdds
    SetStatus "IDconfig.sdds is switched to $configFile."
    
}

#following are for limits

proc SaveIDBPLDLimit {args} {
    global BPLD
    
    set IDLimitConfig $BPLD(IDLimitConfig)
    set filename BPID_ID_Limits-[clock format [clock seconds] -format %Y-%j-%m%d:%H%M%S]
    set sectorList [join [exec sdds2stream -col=ID $IDLimitConfig]]
    set BPLDsectorList [join [exec sdds2stream -col=BPLDSector $IDLimitConfig]]
   
    foreach sector $sectorList {
	set sectorf [format %02d $sector]
	foreach name {x y xp yp} {
	    lappend ${name}Limit $BPLD(S$sectorf.${name}Limit)
	}
    }
    set tmpRoot /tmp/[APSTmpString]
    if [catch {exec sddsmakedataset $tmpRoot.1 -col=ID,type=long -data=[join $sectorList ,] \
		   -col=XLimit,type=double -data=[join $xLimit ,] \
		   -col=YLimit,type=double -data=[join $yLimit ,] \
		   -col=XpLimit,type=double -data=[join $xpLimit ,] \
		   -col=YpLimit,type=double -data=[join $ypLimit ,] } result] {
	return -code error "Error creating limit file: $result"
    }
    APSAddToTmpFileList -ID idbpld -fileList $tmpRoot.1
    set dir [file dirname $IDLimitConfig]
    if [catch {exec sddsconvert $IDLimitConfig -pipe=out -del=col,*Limit \
		   | sddsxref -pipe=in $tmpRoot.1 $dir/$filename  -take=*Limit -equate=ID } result] {
	return -code error "Error creating new limit config: $result"
    }
    set oldDir [pwd]
    cd $dir
    exec rm BPLD_ID_Limits.sdds
    exec ln -s $filename BPLD_ID_Limits.sdds
    cd $oldDir
    SetStatus "new limits saved to config."
}


proc LoadIDBPLDLimit {args} {
    set load 0
    set read 0
    set save 0
    set loadSCR 0
    APSParseArguments {load read loadSCR save}
    global BPLD lab SCRdesc
    
    if {$save && ![string length $SCRdesc]} {
	SetStatus "Error: SCR description has to be provided for saving SCR."
	return
    }
    
    set IDLimitConfig $BPLD(IDLimitConfig)
    set sectorList [join [exec sdds2stream -col=ID $IDLimitConfig]]
    set BPLDsectorList [join [exec sdds2stream -col=BPLDSector $IDLimitConfig]]
    set xLimit [join [exec sdds2stream -col=XLimit $IDLimitConfig]]
    set yLimit [join [exec sdds2stream -col=YLimit $IDLimitConfig]]
    set xpLimit [join [exec sdds2stream -col=XpLimit $IDLimitConfig]]
    set ypLimit [join [exec sdds2stream -col=YpLimit $IDLimitConfig]]
    set IDexist [join [exec sdds2stream -col=IDExist $IDLimitConfig]]
    set BPLD(sectorList) ""
    
    set putList ""
    set pvList ""
    set valList ""
    set labelList ""
    set BPLD(IDsectorList) ""
    set BPLD(bpldSectorList) ""
    set anglePVList ""
    set angleValList ""
    set angleLabelList ""
    foreach sector $sectorList bpld $BPLDsectorList x $xLimit y $yLimit exist $IDexist xp $xpLimit yp $ypLimit  {
	set sectorf [format %02d $sector]
	if !$save {
	    set BPLD(S$sectorf.xLimit) [format %.3f $x]
	    set BPLD(S$sectorf.yLimit) [format %.3f $y]
	    set BPLD(S$sectorf.xpLimit) [format %.3f $xp]
	    set BPLD(S$sectorf.ypLimit) [format %.3f $yp]
	} else {
	    set x $BPLD(S$sectorf.xLimit)
	    set y $BPLD(S$sectorf.yLimit)
	    set xp $BPLD(S$sectorf.xpLimit)
	    set yp $BPLD(S$sectorf.ypLimit) 
	}
	if $exist {
	    lappend BPLD(IDsectorList) $sectorf
	    set BPLD(S$sectorf.BPLDsector) [format %02d $bpld]
	    lappend BPLD(bpldSectorList) [format %02d $bpld]
	   
	    if {$sector==40 && $bpld==1} {
		set ID ID1
	    } elseif {[expr $sector%2]==0} {
		set ID ID1
	    } else {
		set ID ID2
	    }
	    
	    lappend putList S[format %02d $bpld]-LMPS:BPLD:${ID}:AIOL-H1-SP=[expr $x*1000]
	    lappend putList S[format %02d $bpld]-LMPS:BPLD:${ID}:AIOL-H2-SP=[expr $x*1000]
	    lappend putList S[format %02d $bpld]-LMPS:BPLD:${ID}:AIOL-H3-SP=[expr $x*1000]
	    lappend putList S[format %02d $bpld]-LMPS:BPLD:${ID}:AIOL-V1-SP=[expr $y*1000]
	    lappend putList S[format %02d $bpld]-LMPS:BPLD:${ID}:AIOL-V2-SP=[expr $y*1000]
	    lappend putList S[format %02d $bpld]-LMPS:BPLD:${ID}:AIOL-V3-SP=[expr $y*1000]
	    lappend putList S[format %02d $bpld]-LMPS:BPLD:${ID}:AIAL_H-SP=[expr $xp * 1000]
	    lappend putList S[format %02d $bpld]-LMPS:BPLD:${ID}:AIAL_V-SP=[expr $yp * 1000]

	    lappend labelList S${sectorf}-${ID}:H1DimondLimit
	    lappend pvList S[format %02d $bpld]-LMPS:BPLD:${ID}:AIOL-H1-SP
	    lappend valList [expr $x*1000]
	    
	    lappend labelList S${sectorf}-${ID}:H2DimondLimit
	    lappend pvList S[format %02d $bpld]-LMPS:BPLD:${ID}:AIOL-H2-SP 
	    lappend valList [expr $x*1000]

	    lappend labelList S${sectorf}-${ID}:HRectOffsetLimit
	    lappend pvList S[format %02d $bpld]-LMPS:BPLD:${ID}:AIOL-H3-SP
	    lappend valList [expr $x*1000]

	    lappend labelList S${sectorf}-${ID}:V1DimondLimit
	    lappend pvList S[format %02d $bpld]-LMPS:BPLD:${ID}:AIOL-V1-SP
	    lappend valList  [expr $y*1000]

	    lappend labelList S${sectorf}-${ID}:V2DimondLimit
	    lappend pvList S[format %02d $bpld]-LMPS:BPLD:${ID}:AIOL-V2-SP
	    lappend valList  [expr $y*1000]

	    lappend labelList S${sectorf}-${ID}:VRectOffsetLimit
	    lappend pvList S[format %02d $bpld]-LMPS:BPLD:${ID}:AIOL-V3-SP
	    lappend valList  [expr $y*1000]
	    if {0} {
	    lappend labelList S${sectorf}-${ID}-HRectAngleLimit
	    lappend pvList  S[format %02d $bpld]-LMPS:BPLD:${ID}:AIAL_H-SP
	    lappend valList [expr $xp * 1000]
	    
	    lappend labelList S${sectorf}-${ID}-VRectAngleLimit
	    lappend pvList  S[format %02d $bpld]-LMPS:BPLD:${ID}:AIAL_V-SP
	    lappend valList [expr $yp * 1000]
	    }
	    lappend angleLabelList S${sectorf}-${ID}-HRectAngleLimit
	    lappend anglePVList S[format %02d $bpld]-LMPS:BPLD:${ID}:AIAL_H-SP
	    lappend angleValList [expr $xp * 1000]

	    lappend angleLabelList S${sectorf}-${ID}-VRectAngleLimit
	    lappend anglePVList S[format %02d $bpld]-LMPS:BPLD:${ID}:AIAL_V-SP
	    lappend angleValList [expr $yp * 1000]
	    
	    if $read {
	
		if [catch {exec cavget -list=S[format %02d $bpld]-LMPS:BPLD:${ID}:AIOL-H3-SP,S[format %02d $bpld]-LMPS:BPLD:${ID}:AIOL-V3-SP,S[format %02d $bpld]-LMPS:BPLD:${ID}:AIAL_H-SP,S[format %02d $bpld]-LMPS:BPLD:${ID}:AIAL_V-SP -pend=10 } valList] {
		    return -code error "Error reading ID-BPLD limits: $valList"
		}
		set  BPLD(S$sectorf.xLimit) [format %0.3f [expr [lindex $valList 0]/1000.0]]
		set  BPLD(S$sectorf.yLimit) [format %0.3f [expr [lindex $valList 1]/1000.0]]
		set  BPLD(S$sectorf.xpLimit) [format %0.3f [expr [lindex $valList 2]/1000.0]]
		set  BPLD(S$sectorf.ypLimit) [format %0.3f [expr [lindex $valList 3]/1000.0]]
	    }
	}
    }
    if $read {
	SetStatus "read limits done."
	return
    }
    SetStatus "ID BPLD limits are loaded from config."
    
    if $load {
	SetStatus "Checking if ID BPLD limits before loading..."
	set tmpRoot /tmp/[APSTmpString]
	if [catch {exec sddsmakedataset -pipe=out \
		       -col=Label,type=string -data=[join $labelList ,] \
		       -col=ControlName,type=string -data=[join $pvList ,] \
		       -col=SetValue,type=double -data=[join $valList ,] \
		       | sddscasr -save -pipe \
		       | sddsprocess -pipe -scan=col,CurrentValue,ValueString,%lf \
		       | sddsprocess -pipe "-define=col,Diff,CurrentValue SetValue - abs" \
		       | sddsprocess -pipe=in "-test=col,Diff $BPLD(offsetDiff) >" $tmpRoot.offset -nowarnings } result] {
	    return -code error "Error checking Limits loading1:$result"
	}
	if [catch {exec sddsmakedataset -pipe=out \
		       -col=Label,type=string -data=[join $angleLabelList ,] \
		       -col=ControlName,type=string -data=[join $anglePVList ,] \
		       -col=SetValue,type=double -data=[join $angleValList ,] \
		       | sddscasr -save -pipe \
		       | sddsprocess -pipe -scan=col,CurrentValue,ValueString,%lf \
		       | sddsprocess -pipe "-define=col,Diff,CurrentValue SetValue - abs" \
		       | sddsprocess -pipe=in "-test=col,Diff $BPLD(angleDiff) >" $tmpRoot.angle -nowarnings } result] {
	    return -code error "Error checking Limits loading2:$result"
	}
	if [catch {exec sddscombine -merge $tmpRoot.offset $tmpRoot.angle $tmpRoot.test -over } result] {
	    return -code error "Error checking limits loading3: $result"
	}
	set rows [exec sdds2stream -rows=bar $tmpRoot.test]
	if $rows>0 {
	    if  [catch {exec sddsprintout $tmpRoot.test $tmpRoot.print \
			    -col=Label,format=%25s -col=SetValue,format=%10.0f -col=CurrentValue,format=%10.0f -col=Diff,format=%.0f  \
			    "-title=following ID limit difference are greater than $BPLD(offsetDiff) um/$BPLD(angleDiff)mrad." } result] {
		return -code error "Error printing result: $result"
	    }
	    APSFileDisplayWindow [APSUniqueName .fileDisp] -fileName $tmpRoot.print  \
		-comment "ID-BPLD Limits loading failed" -deleteOnClose 1 \
		-printCommand "enscript -r"
	    set answer [APSMultipleChoice .limitcheck -question "The differences of some limit loadings and current limits are greater than the loading limit difference, do you still want to continue load the limits?" -labelList {Continue-Loading Abort} \
			    -returnList {continue abort}]
	    if {$answer=="abort"} {
		SetStatus "The  differences of some limit loadings and current limits are greater than 100um/urad, limits loading is aborted."
		return
	    }
	}
	SetStatus "writing ID BPLD limits to hardware..."
	if [catch {exec cavput -list=[join $putList ,] -pend=30} result] {
	    return -code error "Error loading limits to hardware: $result"
	}
	SetStatus "done."
    }
    if $save {
	#save SCR
	global SCRDesc lab apsSCRSnapDir apsSCRRequestDir
	APSSCRDefineVariables
	if $lab {
	    set apsSCRSnapDir /home/oxygen/DIAG/oagData/SCR/snapshots
	    set apsSCRRequestDir /home/oxygen/DIAG/oagData/SCR/requestFiles
	} else {
	    set apsSCRSnapDir /home/helios/oagData/SCR/snapshots
	    set apsSCRRequestDir /home/helios/oagData/SCR/requestFiles
	}
	if [catch {APSSaveMachine -machine SRBPLD -description "$SCRdesc" \
		       -routine 0 -statusCallback SetStatus} result] {
	    return -code error "Saving SCR: $result"
	}
	SetStatus "[lindex $result 0] snapshot saved."
    }
}

proc LoadSCRLimits {args} {
    global lab BPLD 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]
    if [catch {exec sddsprocess $scrFile -pipe=out -match=col,Category=ID_BPLD_Limit \
		   | tee $tmpRoot.0 \
		   | sddscasr -pipe=in -restore } result] {
	return -code error "Error loading ID BPLD limits from SCR: $result"
    }
    set pvList [exec sdds2stream -col=ControlName $tmpRoot.0]
    set valList [exec sdds2stream -col=ValueString $tmpRoot.0]
    set beamlineList [exec sdds2stream -col=Beamline $tmpRoot.0]
    
    foreach pv $pvList val $valList beamline $beamlineList {
	set sector [scan $beamline S%ld]
	if [regexp {ID1} $pv] {
	    set ID ID1
	    if {$sector==1} {
		set sector 40
	    } else {
		set sector [expr $sector-1]
	    }
	} elseif [regexp {ID2} $pv] {
	    set ID ID2
	    set sector $sector
	} else {
	    SetStatus "Invalid pv name $pv"
	    continue
	}
	set sectorf [format %02d $sector]
	if [regexp {AIOL-H3} $pv] {
	    set BPLD(S$sectorf.xLimit) [format %0.3f [expr $val/1000.0]]
	} elseif [regexp {AIOL-V3} $pv] {
	    set BPLD(S$sectorf.yLimit) [format %0.3f [expr $val/1000.0]]
	} elseif [regexp {AIAL_H} $pv] {
	    set BPLD(S$sectorf.xpLimit) [format %0.3f [expr $val/1000.0]]
	} elseif [regexp {AIAL_V} $pv] {
	    set BPLD(S$sectorf.ypLimit) [format %0.3f [expr $val/1000.0]]
	}
    }
    SetStatus "Default SCR ID BPLD limits loaded."
}

proc ToggleBPMPermission {args} {
    SetSRBPLDLoadingStatus "reset the access mode ..."
    if [catch {exec cavget -list=S:bpm:accessControlMBBO.VAL -pend=10 -numerical -printErrors} orig] {
	return -code error "Unable to toggle the access mode(1): $orig"
    }
    if {$orig==1} {
	set value 0
    } else {
	set value 1
    }
    if [catch {exec cavput -list=S:bpm:accessControlMBBO.VAL=$value -pend=10} result] {
	return -code error "Unable to toggle the access mode(2): $result"
    }
    after 1000
    if [catch {exec cavput -list=S:bpm:accessControlMBBO.VAL=$orig -pend=10} result] {
	return -code error "Unable to toggle the access mode(3): $result"
    }
    
    SetSRBPLDLoadingStatus "done."
}

set xIDGUI ""
set yIDGUI ""
proc IDBPLDdisplay {args} {
    global xIDGUI yIDGUI lab
    KillIDBPLDdisplay
    catch {exec SRIDBPLDPositionDisplay -lab $lab &} xIDGUI
    after 5000
    catch {exec SRIDBPLDPositionDisplay -plane y -lab $lab &} yIDGUI
}

proc KillIDBPLDdisplay {args} {
    global xIDGUI yIDGUI
    puts $xIDGUI 
    puts $yIDGUI
    if [string length $xIDGUI] {
	catch {exec kill -9 $xIDGUI}
	set xIDGUI ""
    }
    if [string length $yIDGUI] {
	catch {exec kill -9 $yIDGUI}
	set yIDGUI ""
    }
}

proc GetBadList {args} {
    global configDir
    set statusFile /home/helios/oagData/sr/BPMStatus/config.sdds
    set tmpRoot /tmp/[APSTmpString]
    if [catch {exec sddsxref $configDir/IDconfig.sdds $statusFile -match=DeviceName -take=Nonexist*,OkForIDBPLD* -pipe=out \
		   | tee $tmpRoot.0 \
		   | sddsprocess  -pipe=in $tmpRoot.1 -nowarn  \
		   "-filter=col,NonexistentH,1,1,NonexistentV,1,1,|" }  result] {
	return -code error "Error obtaining nonExistList: $result"
    }
    
    if [catch {exec sddsprocess $tmpRoot.0 $tmpRoot.2 \
		   "-filter=col,OkForIDBPLDH,0,0,OkForIDBPLDV,0,0,|" } result] {
	return -code error "Error obtaining notOkList: $result"
    }
    
    if [catch {exec sddscombine $tmpRoot.1 $tmpRoot.2 $tmpRoot.3 -merge -over } result] {
	return -code error "Error combining bad list: $result"
    }
    
    APSAddToTmpFileList -ID bpld -fileList "$tmpRoot.0 $tmpRoot.1 $tmpRoot.2 $tmpRoot.3"
    global itemList sectorList
    set badList [exec sdds2stream -col=DeviceName $tmpRoot.3]
    set badSectors [exec sdds2stream -col=BPLDSector $tmpRoot.3]
    set indexList [exec sdds2stream -col=BPLDIndex $tmpRoot.3]
    
    set missingList ""
    foreach device $badList sector $badSectors index $indexList {
	if {$sector>35} {
	    if {[regexp "P0" $device] || [regexp "P1" $device]} {
		#it is needed for setup LMPS in S37 and S38 even though there is no IDs there.
		continue
	    }
	}
	set item [lindex $itemList [expr $index -1]]
	lappend missingList S[format %02d $sector]$item
    }
    return $missingList
}


#note that ID positions are 40, 1, 2, 3, 4...., 30 ; ID 40 and ID1 are belong to Secotr 01; ID2 and ID3 belong to Sector 02
proc MakeLimitsWidget {widget args} {
    set parent ""
    APSParseArguments {parent}
    
    global BPLD
    set BPLD(offsetDiff) 100
    set BPLD(angleDiff) 50
    
    APSFrame $widget -parent $parent -label "" \
      -contextHelp "Frame to specify options for automatically downloading adjusted BPLD trip limits."
    $parent$widget.frame  configure -relief flat -bd 0
    
    set w $parent$widget.frame
    APSLabeledEntry .limit1 -parent $w -width 15 -label "Position limit difference (um) for loading:" \
	-textVariable BPLD(offsetDiff)
    APSLabeledEntry .limit2 -parent $w -width 15 -label "Angle limit difference (urad) for loading:" \
	-textVariable BPLD(angleDiff)
    label $w.label  -text "     ID        x (mm)          xp(mrad)         y (mm)          yp(mrad)               "
    pack $w.label  -side top
    set wscroll [APSScroll .scroll -parent $w \
                   -contextHelp "ID BPLD limits for each sector"]
    set width 15
    foreach sector $BPLD(IDsectorList) {
        set sectorWidget $wscroll.s$sector.frame
        APSFrame .s$sector -parent $wscroll -height 20 \
          -packOption "-side top -fill x"
        APSLabel .label -parent $sectorWidget -text "   [format %3d [scan $sector %ld]]   " -packOption {-padx 0 -pady 0 -side left} -width $width
        APSLabeledEntry .xLimit -parent $sectorWidget \
          -label ""  -width $width \
          -packOption {-padx 0 -pady 0 -side left} \
          -textVariable BPLD(S$sector.xLimit)
	APSLabeledEntry .xpLimit -parent $sectorWidget \
          -label ""  -width $width \
          -packOption {-padx 0 -pady 0 -side left} \
          -textVariable BPLD(S$sector.xpLimit)
        APSLabeledEntry .yLimit -parent $sectorWidget \
          -label ""  -width $width \
          -packOption {-padx 0 -pady 0 -side left} \
          -textVariable BPLD(S$sector.yLimit)
	
	 APSLabeledEntry .ypLimit -parent $sectorWidget \
          -label ""  -width $width \
          -packOption {-padx 0 -pady 0 -side left} \
          -textVariable BPLD(S$sector.ypLimit)
        set lastWidget $sectorWidget
    }
    tkwait visibility $lastWidget 
    APSScrollAdjust $w.scroll -numVisible 6
    
    global SCRdesc
    set SCRdesc ""
    APSLabeledEntry .scr -parent $w -label "SCR Save Description:" \
	-textVariable SCRdesc -width 70
    APSFrame .f1 -parent $w
    set w1 $w.f1.frame
    APSFrame .f2 -parent $w
    set w2 $w.f2.frame
    $w1 configure -relief flat -bd 0
    $w2 configure -relief flat -bd 0
    
   
    APSButton .limits -parent $w1 -text "Load Generic Limits" \
	-command {LoadIDBPLDLimit -load 1} -contextHelp \
	"Reads the BPLD limits for ID and load into BPLD hardware."
   
    APSButton .limits0 -parent $w1 -text "Load Default Limits from SCR" \
	-command {LoadSCRLimits} -contextHelp "load SCR default limits."
    
    APSButton .limits1 -parent $w1 -text "Save BPLD Limits" \
	-command {LoadIDBPLDLimit -load 1 -save 1} -contextHelp \
	"Save the ID BPLD limits into database"
    
    #APSButton .changeperm -parent $w2 -text "Toggle BPM Permission" \
#	-command "ToggleBPMPermission" \
#	-contextHelp "This button resets the access mode so that the pvs can be written."
    APSButton .display -parent $w2 -text "ID-BPLD Display" -command "IDBPLDdisplay"
    APSButton .kill -parent $w2 -text "Kill ID-BPLD Display" -command "KillIDBPLDdisplay"
}

set lab 0
set args $argv
APSParseArguments {lab}
#########################following are GUI code#####################
set name SRIDBPLDConfigAndLimits
if $lab {
    set name ${name}-Lab
}
APSApplication . -name $name -version 1 \
  -overview {.}


APSScrolledStatus .scrolled -parent .userFrame \
    -textVariable bmBPMConfigStatus \
    -width 85 -height 10 -lineLimit 1000 -label ""

if $lab {
    set configDir /home/oxygen/DIAG/apsu/BPLD/BPLD_Config
    set BPLD(sectors) {1 3 5}
    set IDLimitConfig /home/oxygen/DIAG/apsu/BPLD/BPLD_Config/BPLD_ID_Limits.sdds
    set BPLD(IDLimitConfig)   /home/oxygen/DIAG/apsu/BPLD/BPLD_Config/BPLD_ID_Limits.sdds
    set BPLD(IDLimitTestConfig)  /home/oxygen/DIAG/apsu/BPLD/BPLD_Config/BPLD_ID_Limits.sdds.test
} else {
    set configDir /home/helios/oagData/sr/BPLD/BPLD_Config
    set IDLimitConfig $configDir/BPLD_ID_Limits.sdds
    set BPLD(IDLimitConfig) $IDLimitConfig
    set BPLD(IDLimitTestConfig) $IDLimitConfig.test
    #set BPLD(sectors) [exec sdds2stream -col=Sector /home/helios/oagData/sr/BPLD/doubleSectors.sdds]
    for {set sector 1} {$sector<=40} {incr sector 2} {
	lappend BPLD(sectors) $sector
    }
}
set BPLD(configDir) $configDir
LoadIDBPLDLimit -read 1

#there is no IDs in S37 and S39
for {set i 1} {$i<36} {incr i 2} {
    lappend sectorList S[format %02d $i]
}

set itemLabelList ""
set indexList ""
for {set i 1} {$i<=28} {incr i} {
    lappend indexList $i
}

set itemLabelList {n-1AP5 n-1AP6 n-1BP6 n-1BP5 n-1BP4 n-1BP3 n-1BP2 n-1BP1 n-1BP0 \
		       nAP0 nAP1 nAP2 nAP3 nAP4 nAP5 nAP6 nBP6 nBP5 nBP4 nBP3 nBP2 nBP1 nBP0 \
		       n+1AP0 n+1AP1 n+1AP2 n+1AP3 n+1AP4}

set itemList $itemLabelList
set IDMissingList ""
if {0} {
foreach sector $sectorList {
    foreach item $itemList {
	set idBPM$sector$item 0
	if { [regexp {P0} $item] || [regexp {P1} $item]} {
	    
	    continue
	} else {
	    lappend IDMissingList $sector$item
	}
    }
}
}

set IDMissingList [GetBadList]

set wList [APSTabFrame .tab -parent .userFrame -labelList "Configuration Limits" -width 700 -height 650]
set w1 [lindex $wList 0]
set w2 [lindex $wList 1]
APSSRSectorButtons .bpm -parent $w1 -rootname idBPM -allButtons 0 \
    -label "BPLD ID BPM Configuration"  -sectorList $sectorList -orientation horizontal \
    -itemList $itemList -itemLabelList $itemLabelList -description "BPLD ID BPM Config" \
    -sectorControl 0 -packOption "-side top" -globalButtons 0 -allButtons 1 -missingList $IDMissingList -colorDesc 0

APSSetSRSectorButtons -mode all-off -rootname IDBPM  -itemList $itemList -sectorList $sectorList 

set description ""
APSLabeledEntry .desc -parent $w1 -label "Description: " -width 70 -textVariable description

APSFrame .fn -parent $w1 
set w $w1.fn.frame
$w configure -bd 0  -relief flat
APSButton .read0 -parent $w -text "Read OC Config" -command ReadOCConfig -contextHelp \
    "read \[hv\].BPLD-IDs OC config, the ID BPLD config has to be consistent with \[hv\].BPLD-IDs OC config."
APSButton .read -parent $w -text "Read Config" -command ReadConfig
APSButton .save -parent $w -text "Save Config" -command SaveConfig
APSButton .write -parent $w -text "Write Config to LMPS" -command "WriteIDBPLDConfig -lab $lab -statusCallback SetStatus"
APSFrame .f1 -parent $w1
set w $w1.f1.frame
$w configure -bd 0  -relief flat
APSButton .p0 -parent $w -text "All P0s" -command "CreateSpecialConfig -up P0 -down P0"
APSButton .p1 -parent $w -text "All P1s" -command "CreateSpecialConfig -up P1 -down P1"
APSButton .p01 -parent $w -text "UpP0 DownP1" -command "CreateSpecialConfig -up P0 -down P1"
APSButton .p11 -parent $w -text "UpP1 DownP0" -command "CreateSpecialConfig -up P1 -down P0"

ReadConfig

MakeLimitsWidget .limit -parent $w2
