#!/bin/sh
# \
exec oagtclsh "$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/LiberaSyntheticDataSetup.tcl
set liberaList {ioc2sn1bpm1 ioc2sn1bpm2 ioc2sn1bpm3 ioc2sn1bpm4 ioc2snbpm5 ioc2snbpm6 ioc2snbpm7}

set args $argv
set sector 1
set bpmList {25 26 27 28}
set logFile ""
set P0Limit 1.25
set BPMLimit 1.25
set hiLimit 1
set plane x
set lab 1
set validateType offset 
APSParseArguments {sector bpmList logFile plane P0Limit BPMLimit hiLimit lab validateType}

set BPLD(sector) $sector
set BPLD(sectorf) [format %02d $sector]

if $lab {
    set configFile /home/oxygen/DIAG/apsu/BPLD/BPLD_Config/config.sdds
    #only S44 libera exist in the lab, need match bpm with S44 libera bpm
    set liberaList [join [exec sdds2stream -col=LiberaBPM /home/oxygen/DIAG/apsu/BPLD/lab_libera.sdds]]
    set sbpmList [join [exec sdds2stream -col=S$BPLD(sectorf)BPM /home/oxygen/DIAG/apsu/BPLD/lab_libera.sdds]] 
} else {
    set configFile /home/helios/oagData/sr/BPLD/BPLD_Config/config.sdds
}
set BPLD(validateType) $validateType
set BPLD(lab) $lab
set BPLD(P0Limit) $P0Limit
set BPLD(BPMLimit) $BPMLimit
#obtain the BM bpm from config file
set tmpFile /tmp/[APSTmpString]
APSAddToTmpFileList -ID bmBPLD -fileList $tmpFile

if ![llength $bpmList] {
    if [catch {exec sddsprocess $configFile -filter=col,BPLDSector,$sector,$sector \
		   -filter=col,BMBPM,0.5,1.5 $tmpFile} result] {
	puts stderr "Error reading data from config file: $result"
	exit 1
    }
    set indexList [exec sdds2stream -col=BPLDIndex $tmpFile]
    set bpmList [exec sdds2stream -col=DeviceName $tmpFile]
    set BPLD(indexList) [join $indexList]
    set BPLD(bpmList) [join $bpmList]
    #set all bpms InUse
    
} else {
    set indexList $bpmList
    set opt ""
    foreach index $indexList {
	if ![string length $opt] {
	    set opt -filter=col,BPLDIndex,$index,$index
	} else {
	    append opt ,BPLDIndex,$index,$index,|
	}
    }
    if [catch {exec sddsprocess $configFile -filter=col,BPLDSector,$sector,$sector \
		  $opt $tmpFile} result] {
	puts stderr "Error reading data from config file: $result"
	exit 1
    }
    set bpmList [exec sdds2stream -col=DeviceName $tmpFile]
    set BPLD(indexList) $indexList
    set BPLD(bpmList) $bpmList
}

#set inuse BPMs
puts $tmpFile

puts "Setting inuse PVs..."
if [catch {exec sddsmakedataset -pipe=out -col=DeviceName,type=string -data=[join $BPLD(bpmList) ,] \
	       | sddsprocess -pipe=in $tmpFile.inuse -edit=col,ControlName,DeviceName,ei/:MPS:bmBPLD:InUse.RVAL/ \
	       -print=col,ValueString,1 } result] {
    puts stderr "Error creating inuse file: $result"
    exit 1
}
if [catch {exec sddsprocess $configFile -pipe=out -filter=col,BPLDSector,$sector,$sector \
	       | sddsselect -pipe $tmpFile.inuse -match=DeviceName  -invert  \
	       | sddsprocess -pipe=in $tmpFile.notuse -edit=col,ControlName,DeviceName,ei/:MPS:bmBPLD:InUse.RVAL/ -nowarn \
	       -print=col,ValueString,0 } result] {
    puts stderr "Error creating notuse file: $result"
    exit 1
}
if [catch {exec sddscombine $tmpFile.inuse $tmpFile.notuse -merge -pipe=out \
	       | sddscasr -restore -pipe=in } result] {
    puts stderr "Error setting inuse PVs: $result"
    exit 1
}


APSAddToTmpFileList -ID bmbpld -fileList "$tmpFile.inuse $tmpFile.notuse"
set BPLD(sector) $sector
set BPLD(BPLDNumber) [format %02d $sector]
set BPLD(plane) [string toupper $plane]
if ![llength $bpmList] {
    puts stderr "Error no bpms provided"
    exit 1
}

set BPLD(bpmList) [join $bpmList]
set BPLD(indexList) [join $indexList]

if ![string length $logFile] {
    set mainDir [APSGoToDailyDirectory -subdirectory APSUBPLDValidation]
    set logDir $mainDir
    set BPLD(logDir) $logDir
    
    set stamp [clock format [clock seconds] -format %Y%m%d]
    set BPLD(logFile) $logDir/BM[format %02d ${sector}]-${stamp}.log
} else {
    set BPLD(logFile) $logFile
}
set maxBeamS [exec cavget -list=APSU:MMPS2:MaxSoftBeam-SP -pend=10]
set maxBeamH [exec cavget -list=APSU:MMPS2:Sim:HWmaxBeam-SP -pend=10]
if {$maxBeamS<$maxBeamH} {
    set BPLD(allowedBeam) $maxBeamS
} else {
    set BPLD(alloedBeam) $maxBeamS
}

#userReset S${BPLDNumber}-LMPS:UsrReset-SP
set BPLD(userResetPV) S$BPLD(BPLDNumber)-LMPS:UsrReset-SP
set BPLD(simBeamCurrentPV) APSU:MMPS2:Sim:BeamCurrent-SP
set BPLD(hwBeamLimitPV) APSU:MMPS2:Sim:HWmaxBeam-SP
set BPLD(IDcurrentLimitPV) APSU:MMPS2:ID:Thold-SP
set BPLD(swBeamLimitPV) APSU:MMPS2:MaxSoftBeam-SP
set BPLD(simEnablePV) APSU:MMPS2:BeamSim-SP
set BPLD(DCCTPV) APSU:MMPS2:CtrlReg0-Cmd.B2

set BPLD(ID1.enablePV) S$BPLD(BPLDNumber)-LMPS:BPLD:ID1_Enable-SP
set BPLD(ID2.enablePV) S$BPLD(BPLDNumber)-LMPS:BPLD:ID2_Enable-SP
set BPLD(BMEnablePV) S$BPLD(BPLDNumber)-LMPS:BPLD:BM_Enable-SP


#BM is fast fault
#set BPLD(main1fastPV) APSU:MMPS1:LMPS:FastAbort-Sts
#set BPLD(main2fastPV) APSU:MMPS2:SMA:Data10-I
#use bit for main2fault pv
set fsector [expr ($sector+1)/2-1] 
set Bit [format %X $fsector]
set BPLD(main2fastPVBit) APSU:MMPS2:SMA:Data10-I.B$Bit
set BPLD(main1fastPVBit) APSU:MMPS1:LMPS:FastAbort-Sts.B$Bit

#puts $BPLD(main2fastPV)
set BPLD(linkFaultPV) APSU:MMPS1:LMPS[expr ($sector+1)/2]:Fault-I
set BPLD(localMPSPV) S$BPLD(BPLDNumber)-LMPS:MLinkTXpkt_FS-I
set BPLD(linkFaultPVBit) APSU:MMPS1:LMPS[expr ($sector+1)/2]:Fault-I.B2
set BPLD(localMPSPVBit) S$BPLD(BPLDNumber)-LMPS:MLinkTXpkt_FS-I.B2

set BPLD(BMfaultPV) S$BPLD(BPLDNumber)-LMPS:BPLD:BM_IL_Status-I

set BPLD(BMmaskPV) S$BPLD(BPLDNumber)-LMPS:BPLD:BpmMask-SP
set BPLD(BMbpmEnablePV) S$BPLD(BPLDNumber)-LMPS:BPLD:BM_Enable-I

#number of fault bpms should be greater than this number to enable Main1 and Main2 fault
set BPLD(BMFaultBPMcount) APSU:MMPS1:BM:FaultCnt-SP
if [catch {APScavget -list=$BPLD(BMFaultBPMcount) -pend=30 -printErrors} bpmCount] {
    puts stderr "Error reading BPM fault count: $bpmCount"
    exit 1
}
set bpms [llength $bpmList]
if {$bpms<=$bpmCount} {
    #there should be no error passing to main1 and main2 when number of fault BM bpms is less than this count
    set BPLD(mainFault) 0
} else {
    set BPLD(mainFault) 1
}


set nmList [array names BPLD]
set pvList ""
set varList ""
foreach name $nmList {
    if [regexp "PV" $name] {
	lappend pvList $BPLD($name)
	lappend varList BPLD($name.var)
    }
}
if [pv linkw $varList $pvList 50] {
    puts stderr "Error connecting some pvs"
    exit 1
}

set BPLD(pvList) $pvList
set BPLD(varList) $varList

set pvList1 ""
set pvList2 ""
set pvList3 ""
set pvList4 ""
set bpmValue 0
foreach bpm $BPLD(indexList) {
    set num [expr $bpm+3]
    set Bit [format %X $num]
    lappend pvList1 $BPLD(linkFaultPV).B$Bit
    lappend pvList2 $BPLD(localMPSPV).B$Bit
    set bpmValue [expr $bpmValue + pow(2, $bpm-1)]
}
set bpmValue [expr int($bpmValue)]
set BPLD(BMmaskValue) $bpmValue
set BPLD(linkFaultBPMPVList) $pvList1
set BPLD(localMPSBPMPVList) $pvList2

if $BPLD(lab) {
    puts "set ID and BPM offsets to 0..."
    if [catch {APScavput -list=S$BPLD(BPLDNumber) \
		   -list=-LMPS:BPLD:ID -list=1,2 -list=:AIOR- \
		   -list=H,V -list=1,2 -list=-SP=0 -pend=60} result] {
	puts stderr "Error set ID bpm offsts to zero: $result"
	exit 1
    }
    if [catch {APScavput -list=S$BPLD(BPLDNumber) \
		   -list=-LMPS:BM_ -list=X,Y -range=begin=1,end=28 -list=_Offset-SP=0 -pend=60} result] {
	puts stderr "Error set BM bpm offsets to zero: $result"
	exit 1
    }
}

#read original offsets
if [catch {exec cavget -list=S$BPLD(BPLDNumber) \
		       -list=-LMPS:BM_ -list=X,Y -range=begin=1,end=28 -list=_Offset-SP -cavputForm } initList] {
    puts stderr "Error reading initial offsets: $initList"
    exit 1
}
puts $initList
set BPLD(initOffsetList) $initList

proc SetBMMask {args} {
    global BPLD
    #set inuse PVs
    
   # puts "cavput -list=$BPLD(BMmaskPV)=$BPLD(BMmaskValue),$BPLD(BMEnablePV)=1"
    if [catch {APScavput -list=$BPLD(BMmaskPV)=$BPLD(BMmaskValue),$BPLD(BMEnablePV)=1 -pend=30} result] {
	return -code error "Error setting BM mask: $result"
    }
    after 3000
    #read the BPM mask
   # puts "$BPLD(BMbpmEnablePV)"
    if [catch {APScavget -list=$BPLD(BMbpmEnablePV) -printErrors -pend=30} bpmMask] {
	return -code error "Error reading enabled BM: $bpmMask"
    }
   # puts "$BPLD(BMmaskPV) $BPLD(BMbpmEnablePV)"
   # puts "$bpmMask $BPLD(BMmaskValue)"
    if {$bpmMask!=$BPLD(BMmaskValue)}  {
	return -code error "Error: BM bpm mask is not correctly set!"
    }
}

proc ClearFaults {args} {
    global BPLD
  
    puts "set ID  to 0..."
    if [catch {APScavput -list=S$BPLD(BPLDNumber) \
		   -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"
    }
   
    puts "set BM offsets to its initial values..."
    if [catch {APScavput -list=$BPLD(initOffsetList) -pend=60 } result] {
	return -code error "Error set BM BPLD offsets to its initial values: $result"
    }
    #p0 has different limits
    if {0} {
	foreach index $BPLD(indexList) bpm $BPLD(bpmList) {
	    if [regexp {P0} $bpm] {
		set limit [expr $BPLD(P0Limit)*1000.0]
	    } else {
		set limit [expr $BPLD(BPMLimit)*1000.0]
	}
	    if [catch {exec cavput -list=S$BPLD(BPLDNumber)-LMPS:BM_ -list=X,Y -list=$index \
			   -list=_TH-SP=$limit -pend=20} result] {
		return -code error "Error setting BM P0 BPLD limit: $result"
	    }
	}
    }
    #clear External inputs faults
    if [catch {APScavput -list=S$BPLD(BPLDNumber) -list=-LMPS:CtrlReg0-Cmd=0 -pend=30 } result] {
	return -code error "Error clear ext inputs: $result"
    }
    after 5000
    if [catch {APScavput -list=$BPLD(userResetPV)=1 -pend=30 } result] {
	return -code error "Error reset to clear faults: $result"
    }
    after 2000
    puts "check if faults are cleared..."
    if [catch {APScavget -list=$BPLD(localMPSPV) -printErrors -pend=30} fault] {
	return -code error "Error reading local MPS fault: $fault"
    }
    return $fault
}

puts "start BM validation for sector $sector plane=$plane..."
proc SetupValidation {args} {
    global BPLD
    
    puts "Step 0: before start validation, check the local MPS fault, make sure it is zero. if not, fix it first!"
    if [catch {ClearFaults} fault] {
	return -code error "Error clearing faults: $fault"
    }
    if $fault {
	puts "Trying to clear the faults for second time..."
	if [catch {ClearFaults} fault] {
	    return -code error "Error clearing faults for second time: $fault"
	}
    }
    set BPLDNumber $BPLD(BPLDNumber)
    set BPLD(userResetPV.var) 1
    set BPLD(simBeamCurrentPV.var) 25
    set BPLD(IDcurrentLimitPV.var) 2
    set BPLD(simEnablePV.var) 0
    set BPLD(DCCTPV.var) 0
    set BPLD(P0CountLimitPV.var) 100
    set varList {BPLD(simBeamCurrentPV.var) BPLD(IDcurrentLimitPV.var) BPLD(simEnablePV.var) BPLD(DCCTPV.var)}
    pv putw $varList 30
    set BPLD(userResetPV.var) 1
    pv putw BPLD(userResetPV.var) 30
    after 2000
    puts "Step 0: before start validation, check the local MPS fault, make sure it is zero. if not, fix it first!"
    pv getw BPLD(localMPSPV.var) 30
    update
    set fault $BPLD(localMPSPV.var)
    
    if $fault {
	puts "The local MPS fault for S$BPLD(BPLDNumber) has to be cleared before starting validation!"
	exit 1
    }
    
    
    puts "To enable BM/ID validation, it needs following conditions"
    puts "1)the simulated hardware limit should be equal or greater than BM engaged current."
    #puts "2) software limit should be less than the hardware limit but greater than BM/ID engaged current."
    puts "2) MPS arming current should be greater than 0 (normally set to 0.5mA)"
    puts "3) beam simulation current has to be equal or greater than BM/ID engaged current."
    puts "checking hardware limit..."
    
    pv getw BPLD(IDcurrentLimitPV.var) 30
    pv getw BPLD(hwBeamCurrentPV.var) 30
    pv getw BPLD(swBeamLimitPV.var) 30
    update
    
    set hwLimit $BPLD(hwBeamLimitPV.var)
    set IDengageCurrent $BPLD(IDcurrentLimitPV.var)
    set limit 0
    if { $hwLimit<[expr $IDengageCurrent+5]} {
	set limit [expr $IDengageCurrent+20]
    }
    if $limit>0 {
	puts "Hardware limit is lower than ID engage current, increase it to $limit"
#	set BPLD(simBeamCurrentPV.var) $limit
#	set hwLimit $limit
#	pv putw BPLD(simBeamLimitPV.var) 30
	
    }
    puts "checking software current limit..."
    set swLimit $BPLD(swBeamLimitPV.var)
    
    set limit 0
    if {$swLimit>$hwLimit} {
	puts "software limit is higher than hardward limit, reduce it."
	set limit [expr $hwLimit - 2]
    }
    
    if {$swLimit<$IDengageCurrent} {
	set limit [expr $IDengageCurrent + 1 ]
	puts "software limit is lower than ID engage current, increase it."
    }
    if {$limit>0} {
	   #	set BPLD(swBeamLimitPV.var) $limit
	#pv putw BPLD(swBeamLimitPV.var) 30
    }
    puts "checking beam simulation current: it should be equal or greater than BM/ID engaged current"
    pv getw BPLD(simBeamCurrentPV.var) 30
    update
    set beamCurrent $BPLD(simBeamCurrentPV.var)
 
    puts "enable beam simulator"
    
    set BPLD(simEnablePV.var) 1
    pv putw BPLD(simEnablePV.var) 30
    
    #disable BM, ID1, ID2, enable gap sim, and close gap
    set BPLD(BMEnablePV.var) 0
    set BPLD(ID1.enablePV.var) 0
    set BPLD(ID2.enablePV.var) 0
    set BPLD(userResetPV.var) 1
    set varList {BPLD(BMEnablePV.var) BPLD(ID1.enablePV.var) BPLD(ID2.enablePV.var)}
    pv putw $varList 30
    pv putw BPLD(userResetPV.var) 30
    puts "reset and enable BM"
    #set S1 and S2 distance
    if [catch {APScavput -list=$BPLD(BMEnablePV)=1 -pend=30} result] {
	return -code error "Error enable BM: $result"
    }
    puts "Set BM BPM Mask..."
    if [catch {SetBMMask} result] {
	return -code error $result
    }
}

proc SetDPBPLDStatus {text} {
    puts $text
    flush stdout
}

#validate BM BPMs with offset

proc ValidateBMBPMs {args} {
    global BPLD
    
    set BPLDNumber $BPLD(BPLDNumber)
    SetDPBPLDStatus "Start BM bpm validation with offset..."
    
    if [catch {SetupValidation} result] {
	return -code error "Error setup BM validation: $result"
    }
    
    set result0 passed
    set BPLD(X.faultDesc) ""
    set BPLD(Y.faultDesc) ""
    if {$BPLD(plane)=="BOTH"} {
	set planeList {X Y}
    } else {
	set planeList $BPLD(plane)
    }
    set result0 passed
    set BPLD(startTime) [clock format [clock  seconds] -format %Y%m%d-%H:%M:%S]
    foreach plane $planeList {
	SetDPBPLDStatus "Validating $plane plane..."
	switch $BPLD(validateType) {
	    offset {
		if [catch {ValidateBMBPMWithOffset -plane $plane} result] {
		    return -code error "Error validating BM $plane bpm: $result"
		}
	    }
	    synthetic {
		if [catch {ValidateBMBPMWithSyntheticData -plane $plane} result] {
		    return -code error "Error validating BM $plane bpm: $result"
		}
	    }
	}
	if {$result=="failed"} {
	    set result0 failed
	}
	ResetBMBPMOffsets
    }
    set BPLD(faultDesc) [concat $BPLD(X.faultDesc) $BPLD(Y.faultDesc)]
    set BPLD(result) $result0
    set BPLD(endTime)  [clock format [clock  seconds] -format %Y%m%d-%H:%M:%S]
   
    SetDPBPLDStatus "log result..."
    LogValidationResult 
    #SetDPBPLDStatus "Reset offsets and clear faults..."
    #ResetBMBPMOffsets
    SetDPBPLDStatus "Done."
}

proc ValidateBMBPMWithOffset {args} {
    set plane X
    APSParseArguments {plane}

    global BPLD hiLimit
    
    if [catch {APScavget -list=S$BPLD(BPLDNumber)-LMPS:BM_$plane -list=[join $BPLD(indexList) ,] -list=_TH-SP -pend=30 -printError} limitList] {
	return -code error "Error reading bpmLimits: $limitList"
    }
    if [catch {APScavget -list=S$BPLD(BPLDNumber)-LMPS:BM_TBT_$plane -list=[join $BPLD(indexList) ,] -list=-I -pend=30 -printErrors} rawList] {
	return -code error "Error reading raw values: $rawList"
    }
    if [catch {APScavget -list=S$BPLD(BPLDNumber)-LMPS:BM_$plane -list=[join $BPLD(indexList) ,] -list=_Offset-SP -pend=30 -printErrors} offsetList] {
	return -code error "Error reading raw values: $offsetList"
    }
    
    set putList ""
    foreach bpm $BPLD(indexList) limit $limitList raw $rawList offset $offsetList {
	if $hiLimit {
	    set offset0 [expr -1.0*$limit + ($offset+$raw)-10]
	} else {
	    set offset0 [expr $limit+($offset+$raw)+10]
	}
	lappend putList S$BPLD(BPLDNumber)-LMPS:BM_${plane}${bpm}_Offset-SP=$offset0
    }
    SetDPBPLDStatus "change S$BPLD(BPLDNumber) [join $BPLD(indexList)] offsets..."
    if [catch {APScavput -list=[join $putList ,] -pend=30 -printErrors} result] {
	return -code "Error change BPM offsets: $result"
    }
    SetDPBPLDStatus "waiting 5 seconds..."
    after 5000
    SetDPBPLDStatus "checking result..."
    set result [CheckBMFaultStatus -plane $plane]
    set BPLD($plane.result) $result
    puts "S$BPLD(BPLDNumber) BM test $result"
    
    SetDPBPLDStatus "reset offsets..."
    if [catch {APScavput -list=$BPLD(initOffsetList) -pend=30 } result] {
	return -code error "Error reset offset to 0: $result"
    }
    after 3000
    SetDPBPLDStatus "reset..."
    if [catch {APScavput -list=$BPLD(userResetPV)=1 -pend=30} result] {
	return -code error "Error reset: $result"
    }
    
    return $BPLD($plane.result)
}



set BPLD(faultPVNameList1) {BPLD(main2fastPVBit) BPLD(main1fastPVBit) BPLD(linkFaultPV) BPLD(linkFaultPVBit) BPLD(localMPSPVBit) \
				BPLD(BMfaultPV)}


proc CheckBMFaultStatus {args} {
    global BPLD
    set plane X
    APSParseArguments {plane}
    
    set BPLDNumber $BPLD(BPLDNumber)
    SetDPBPLDStatus "checking BM bpm fault status..."
    after 2000
    pv getw $BPLD(varList) 30
    update
    set desc ""
    if !$BPLD(localMPSPVBit.var) {
	append desc "local BM MPS fault PV status is wrong."
    }
    if {$BPLD(BMfaultPV.var)!=$BPLD(BMmaskValue)} {
	append desc "local BM BPM fault status is wrong."
    }
    #check each bit
    if [catch {APScavget -list=[join $BPLD(localMPSBPMPVList) ,] -printErrors -pend=30} valList] {
	return -code error "Error reading local MPS bpm status: $valList"
    }
    foreach bpm $BPLD(indexList) val $valList {
	if !$val {
	    append desc "The $bpm bpm in local MPS fault is wrong"
	}
    }
    
    if [catch {APScavget -list=[join $BPLD(linkFaultBPMPVList) ,] -printErrors -pend=30} valList] {
	return -code error "Error reading link bpm status: $valList"
    }
    foreach bpm $BPLD(indexList) val $valList {
	if !$val {
	    append desc "The $bpm bpm in local link fault is wrong"
	}
    }
    
    #check main1 and main2
    if {$BPLD(main1fastPVBit.var)!=$BPLD(mainFault)} {
	append desc "main1 fast fault status is wrong."
    }
    if {$BPLD(main2fastPVBit.var)!=$BPLD(mainFault)} {
	append desc "main2 fast fault status is wrong."
    }
    set BPLD($plane.faultDesc) $desc
    if [string length $desc] {
	return failed
    } else {
	return passed
    }
    return
    if [catch {APScavget -list=$BPLD(main2fastPVBit),$BPLD(main1fastPVBit),$BPLD(linkFaultPV),$BPLD(linkFaultPVBit),$BPLD(main2fastPV) -printErrors -pend=30} valList] {
	return -code error "Error reading fault pvs: $valList"
    }
    set BPLD(faultDesc) ""
    set BPLD(IDfaultPV.var) [lindex $valList 0]
    set BPLD(localMPSPV.var) [lindex $valList 1]
    set BPLD(linkFaultPV.var) [lindex $valList 2]
    set BPLD(main1fastPV.var) [lindex $valList 3]
    set BPLD(main2fastPV.var) [lindex $valList 4]
    
    if {$BPLD(IDfaultPV.var)==0} {
	append BPLD(faultDesc) "ID fault not detected!"
	return failed
    }
    #local MPS, ID fault=2
    if {$BPLD(localMPSPV.var)!=2} {
	append BPLD(faultDesc) "Local MPS ID fault not detected!"
	return failed
    }
    #link fault
    if {$BPLD(linkFaultPV.var)!=2} {
	append BPLD(faultDesc) "Local MPS ID link fault not detected!"
	return failed
    }
    
    if {!$BPLD(main1fastPV.var)} {
	append BPLD(faultDesc) "Main1 fast fault failed"
	return failed
    }
    if {!$BPLD(main2fastPV.var)} {
	append BPLD(faultDesc) "Main2 fast fault failed"
	return failed
    }
    return passed
}


proc ResetBMBPMOffsets {args} {
    global BPLD 

    if {0} {
    if [catch {APScavput -list=S$BPLD(BPLDNumber) -list=-LMPS:BM_ -list=X,Y -range=begin=1,end=28  -list=_Offset-SP=0 -pend=30 } result] {
	return -code error "Error reset BM bpm offsets: $result"
    }
    }
    if [catch {APScavput -list=[join $BPLD(initOffsetList) ,] -pend=10} result] {
	return -code error "Error restoring initial offsets: $result"
    }   
    after 3000
    set BPLD(userResetPV.var) 1
    pv putw BPLD(userResetPV.var) 30
}



proc LogValidationResult {args} {
    global BPLD hiLimit
    
    if ![file exist $BPLD(logFile)] {
	set BPLD(logID) [open $BPLD(logFile) a+]
	puts $BPLD(logID) "SDDS1"
	puts $BPLD(logID) "&column name=StartTime, type=string, &end"
	puts $BPLD(logID) "&column name=EndTime, type=string, &end"
	puts $BPLD(logID) "&column name=DoubleSector, type=long, &end"
	puts $BPLD(logID) "&column name=BPM, type=string &end"
	puts $BPLD(logID) "&column name=Plane, type=string, &end"
	puts $BPLD(logID) "&column name=Limit, type=string, &end"
	puts $BPLD(logID) "&column name=Result, type=string, &end"
	puts $BPLD(logID) "&column name=ValidationType, type=string, &end"
	puts $BPLD(logID) "&column name=FaultDesc, type=string, &end"
	puts $BPLD(logID) "&data mode=ascii, no_row_counts=1, &end"
	exec chmod 777 $BPLD(logFile)
    } else {
	set BPLD(logID) [open $BPLD(logFile) a+]
    }
    
    set valList $BPLD(startTime)
    lappend valList $BPLD(endTime)
    lappend valList $BPLD(sector)
    lappend valList \"[join $BPLD(bpmList)]\"
    lappend valList $BPLD(plane)
    if $hiLimit {
	lappend valList High
    } else {
	lappend valList Low
    }
    switch $BPLD(plane) {
	X {
	    lappend valList $BPLD(X.result)
	}
	Y {
	    lappend valList $BPLD(Y.result)
	}
	BOTH {
	    if {$BPLD(X.result)=="passed" && $BPLD(Y.result)=="passed"} {
		lappend valList passed
	    } elseif {$BPLD(X.result)=="failled" && $BPLD(Y.result)=="failled"} {
		lappend valList both_failed
	    } elseif {$BPLD(X.result)=="failled"} {
		lappend valList x_failed
	    } elseif {$BPLD(Y.result)=="failled"} {
		lappend valList y_failed
	    }
	}
    }
    
    # lappend valList $BPLD(result)
    lappend valList $BPLD(validateType)
    lappend valList \"$BPLD(faultDesc)\"
    puts "[join $valList]"
    puts $BPLD(logID) "[join $valList] "
    flush $BPLD(logID)
   # close $BPLD(logID)
}
proc ValidateBMBPMWithSyntheticData {args} {
    set plane X
    APSParseArguments {plane}

    global BPLD hiLimit liberaList

     if [catch {APScavget -list=S$BPLD(BPLDNumber)-LMPS:BM_$plane -list=[join $BPLD(indexList) ,] -list=_TH-SP -pend=30 -printError} limitList] {
	return -code error "Error reading bpmLimits: $limitList"
    }
    if [catch {APScavget -list=S$BPLD(BPLDNumber)-LMPS:BM_TBT_$plane -list=[join $BPLD(indexList) ,] -list=-I -pend=30 -printErrors} rawList] {
	return -code error "Error reading raw values: $rawList"
    }
    if [catch {APScavget -list=S$BPLD(BPLDNumber)-LMPS:BM_$plane -list=[join $BPLD(indexList) ,] -list=_Offset-SP -pend=30 -printErrors} offsetList] {
	return -code error "Error reading raw values: $offsetList"
    }
    set sector $BPLD(sector)
    if {$sector==1} {
	set liberaList0 [regsub -all "n1" $liberaList 40]
    } else {
	set liberaList0 [regsub  -all "n1" $liberaList [format %02d [expr $sector-1]]]
    }
    set liberaList0 [regsub -all  "n2" $liberaList0 [format %02d [expr $sector+1]]]
   
    set liberaList0 [regsub -all "n" $liberaList0 [format %02d $sector]]
    set hostList ""
    set eventList ""
     if !$BPLD(lab) {
	foreach libera $liberaList0 {
	    lappend hostList $libera
	    lappend eventList 119
	}
    } else {
	set hostList {S44LBP1 S44LBP2 S44LBP3 S44LBP4 S45LBP5 S45LBP6 S45LBP7}
	set eventList {119 119 119 119 119 119 119}
    }
    switch $plane {
	X {
	    set plane0 H
	}
	Y {
	    set plane0 V
	}
    }
    set fileList ""
    set tmpRoot [APSTmpString]
    set static 5000
    foreach bpm $BPLD(bpmList) limit $limitList raw $rawList offset $offsetList {
	if $hiLimit {
	    set offset0 [expr -1.0*$limit - ($offset+$raw)-10]
	} else {
	    set offset0 [expr $limit+($offset+$raw)+10]
	}
	set offset0 [expr $offset0/($static/1000.0)]
	if [catch {GenerateGainWaveform -mainDir /tmp -filename $tmpRoot.$bpm.gain.sdds \
			   -bpmList $bpm \
			   -gainType step -step0 1 \
			   -stepStart0 0 -stepEnd0 4095 -stepAmp0 $offset0 } result] {
	    return -code error "Error generate gain wf: $result"
	}
	lappend fileList /tmp/$tmpRoot.$bpm.gain.sdds
    }
    if [catch {eval exec sddscombine $fileList /tmp/$tmpRoot.gain } result] {
	return -code error "Error combining files: $result"
    }
    puts "Loading gain waveform..."
    if [catch {exec sddswput /tmp/$tmpRoot.gain } result] {
	return -code error "Error loading gain waveform: $result"
    }
    puts "setup  synthetic data..."
    if [catch {SetupSyntheticData -lab $BPLD(lab) -hostList $hostList -eventList $eventList -plane [string tolower $plane] \
		   -statusCallback puts  \
		   -bpmList $BPLD(bpmList) -doubleSector [scan $BPLD(sector) %d] -repetition 100 \
		   -xstatic $static -ystatic $static } result] {
	return -code error "Error setup synthetic data: $result"
    }
    puts "start event trigger...."
    if $BPLD(lab) {
	if [catch {exec caput DIA:EVG-SoftEvt:EvtCode-SP 119} result] {
	    return -code error "Error set libera the trigger: $result"
	}
    } else {
	if [catch {exec caput S$BPLD(BPLDNumber)-MT:EVM1-SoftEvt:EvtCode-SP  119} result] {
	    return -code error "Error set libera the trigger: $result"
	}
    }
    after 10000
    SetDPBPLDStatus "checking result..."
    set result [CheckBMFaultStatus -plane $plane]
    set BPLD($plane.result) $result
    puts "S$BPLD(BPLDNumber) BM test $result"
}


pv linkw $varList $pvList

SetupValidation

ValidateBMBPMs

puts $BPLD(logFile)
exit 0

