#!/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.5 $ \$Author: shang $"

proc SetStatus {text} {
    global status
    set status "[clock format [clock seconds] -format %H:%M:%S]  $text"
    update
}

proc SetupAcquistionControl {args} {
    set subsector ""
    APSParseArguments {subsector}
    global  PlaneMode SampleMode CommutationMode TurnMarkerOffset TurnsPerWrap TransitionDeadTime \
	TurnMarkerInterval SamplesPerBunch
    set tmpRoot /tmp/[APSTmpString]
    
    if {$SampleMode=="bunchpattern"} {   
        set sampleMode bunchPattern=$BunchPattern
    } else {
        set sampleMode $SampleMode
    }
    set len [expr $TurnsPerWrap*$TurnMarkerInterval]
    if $len>=2048 {
        set offset [expr $len-2048]
    } else {
        for {set i 2} {$i<=12} {incr i} {
            set len0 [expr $i*$len]
            if $len0>=2048 {
                break
            }
        }
        set offset [expr $len0 - 2048]
    }
    SetStatus "Generating and setting control RAMs for $subsector..."
    
    if [catch {exec sddsgencontrolbits $tmpRoot.$subsector.wave -scopeArrayLength=4096 -RAMArrayLength=3888 \
		   -setRAMWaveformPV=${subSector}:AcqControlSetWF \
		   -turnsPerWrap=$TurnsPerWrap -controlRAMFile=$tmpRoot.$subsector.RAM \
		   -planeMode=$PlaneMode -commutationMode=$CommutationMode \
		   "-sampleMode=$sampleMode" -samplesPerBunch=$SamplesPerBunch \
		   -turnMarkerOffset=$TurnMarkerOffset -transitionDeadTime=$TransitionDeadTime \
		   -scopeTriggerIndexOffset=$offset -turnMarkerInterval=$TurnMarkerInterval} result] {
	return -code error "Error in generating controlbits for $subsector: $result"
    }
    APSAddToTmpFileList -ID fpgaSelfTest -fileList "$tmpRoot.$ioc.wave $tmpRoot.$subsector.ram"
}

proc GetTurnsPerWrap {args} {
    global PlaneMode CommutationMode TurnsPerWrap
    
    set turns [expr ([regexp {[12]} $PlaneMode] + 1) * ([regexp {[12]} $CommutationMode] + 1)]
    if {$PlaneMode=="xy2"} {
        set turns 4
    }
    if {$PlaneMode=="xy1" && $CommutationMode=="ab1"} {
        set turns 2
    }
    set TurnsPerWrap $turns
    return $turns
}

proc GetTurnMarkerOffset {args} {
    global subsector TurnMarkerOffset
    if [catch {exec cavget -list=${subsector} -list=:TurnMarkerOffsetLO -pend=10} offset] {
	SetStatus "Error in reading turn marker offset of $subsector: $offset."
    } else {
	set TurnMarkerOffset $offset
    }

}

proc StartScan {args} {
    global iocList outputDir rootname inputFileDir outputFile sectorList
    eval global $iocList
    
    #check if there is beam, can only run when there is no beam
    if [catch {exec cavget -list=S-DCCT:CurrentM -printErrors -pend=20} current] {
	SetStatus "Error in reading SR beam current: $current"
	return
    }
    if {$current>0.5}  {
	SetStatus "Can not run FPGA bpm selft with beam."
	return
    }
    set tmpRoot /tmp/[APSTmpString]
    set sectorList ""
    foreach subsector $iocList {
	if [set $subsector] {
	    if [regexp {A} $subsector] {
		set monFile $inputFileDir/selfTestA_msAve.mon
	    } else {
		set monFile $inputFileDir/selfTestB_msAve.mon
	    }
	    if [catch {exec replaceText $monFile ${tmpRoot}.${subsector}.mon -orig=<subsector> -repl=$subsector} result] {
		SetStatus "StartScan1: Error in making monitor file: $result"
		return
	    }
	    if [catch {exec replaceText $inputFileDir/selfTestTemplate1.exp $tmpRoot.$subsector.exp \
			   -orig=<subsector> -repl=$subsector   } result] {
		SetStatus "StartScan1: Error in making exp and monitor file: $result"
		return
	    }
	    lappend expFileList  ${tmpRoot}.${subsector}.exp
	    lappend monFileList ${tmpRoot}.${subsector}.mon
	    lappend sectorList $subsector
	}
    }
    if ![llength $expFileList] {
	SetStatus "No sector selected."
	return
    }
    if {[llength $monFileList]>1} {
	if [catch {eval exec sddscombine $monFileList $tmpRoot.mon -merge} result] {
	    SetStatus "StartScan2: error in combining monitor files; $result"
	    return
	}
	set monFile1 $tmpRoot.mon
    } else {
	set monFile1 $monFileList
    }
    if [catch {exec replaceText $inputFileDir/selfTestTemplate2.exp $tmpRoot.exp1 \
		   -orig=<sectorList>,<monFile> -repl=[APSMakeSafeQualifierString [join $sectorList ,]],$monFile1} result] {
	SetStatus "StartScan3: Unable to generate exp file: $result"
	return
    }
    lappend expFileList $tmpRoot.exp1
    if [catch {eval exec  cat $expFileList > $tmpRoot.exp} result] {
        return -code error $result
    }
    
    set outputFile [APSNextGenerationedName -directory $outputDir -name ${rootname}.sdds-0001 -separator - -newFile 1]
    APSAddToTmpFileList -ID 1 -fileList $expFileList
    APSAddToTmpFileList -ID 1 -fileList $monFileList
    #catch {eval file delete $expFileList}
    #catch {eval file delete $monFileList}
    SetStatus "start scan ..."
    global scanStatus
    set scanStatus 0
    if [catch {exec cavget -list=S-DCCT:CurrentM -printErrors -pend=20} current] {
	SetStatus "Error in reading SR beam current: $current"
	return
    }
    if {$current>0.5}  {
	SetStatus "Can not run FPGA bpm selft with beam."
	return
    }
    APSExecLog .scan -width 80 -lineLimit 2048 -width 95 -height 30 -name "Scan" -unixCommand \
	"sddsexperiment $tmpRoot.exp $outputDir/$outputFile -verbose" \
	-callback "ProcessFile -file $outputDir/$outputFile -sectorList \"$sectorList\"" -cancelCallback "set scanstatus cancelled" \
	-abortCallback "set scanStatus aborted"
}
proc ProcessFile {args} {
    set file ""
    set sectorList ""
    APSParseArguments {file sectorList}
    if [catch {exec sddsprocess $file -nowarnings $file.1 \
		   "-reprint=par,Sectors,[join $sectorList]"} result] {
	return -code error $result
    }
    exec mv $file.1 $file
}

proc Install {args} {
    global outputDir rootname selectFile
    set oldDir [pwd]
    
    set fileList [glob -nocomplain $outputDir/${rootname}.sdds*]
     if ![string length $fileList] {
	SetStatus "No data found."
	return
    }
    APSScrolledListWindow .select -name "Select file" \
	-label "Select File" \
	-itemList $fileList  -selectionVar selectFile
    tkwait variable selectFile
    if ![string length $selectFile] {
	SetStatus "No file chosen."
	return
    }
    if ![APSYesNoPopUp "Are you sure to install $selectFile as reference?"] {
	return
    }
    set refDir /home/helios/oagData/sr/FPGAbpm/selfTest
    set newFile [APSNextGenerationedName -directory $refDir -name fpgaSelfTest.sdds-0001 -separator - -newFile 1]
    exec cp $selectFile $refDir/$newFile
    cd $refDir
    catch {exec rm default.sdds}
    exec ln -s $newFile default.sdds
    cd $oldDir
}
proc PlotData {args} {
    set compare 0
    APSParseArguments {compare}
    
    global outputDir rootname selectedFiles
    
    set fileList [glob -nocomplain $outputDir/${rootname}.sdds*]
    
    if ![llength $fileList] {
	SetStatus "No data found."
	return
    }
    APSScrolledListWindow .select -name "Select files" \
	-label "Select Files" \
	-itemList $fileList  -selectionVar selectedFiles
    tkwait variable selectedFiles
    set refFile /home/helios/oagData/sr/FPGAbpm/selfTest/default.sdds
    if $compare {
	if ![file exist $refFile] {
	    SetStatus "Reference file does not exist!"
	    return	    
	}
	set refSectorList [exec sdds2stream -par=Sectors $refFile]
	set refSectorList [regsub -all {\"} $refSectorList ""]
    }
    foreach file $selectedFiles {
	set sectorList [join [exec sdds2stream -par=Sectors $file]]
	set sectorList [regsub -all {\"} $sectorList ""]
	if $compare {
	    foreach sector  [split $sectorList " "] {
		if [lsearch -exact $refSectorList $sector]>=0 {
		    exec sddsplot -sep=2 -graphic=line,vary -legend=file,edit=20Z/ -layout=2,2 $file $refFile -groupby=nameString \
			-col=${sector}:SelfTestAttenLO,${sector}:P*  &
		}
	    }
	} else {
	    foreach sector [split $sectorList " "] {
		exec sddsplot -sep=2 -graphic=line,vary -legend -layout=2,2 -yscalesgroup=namestring \
		    -col=${sector}:SelfTestAttenLO,${sector}:P* $file &
	    }
	}
    }
}

set outputDir .
set rootname fpgaBPMtest
proc CreateWidgets {args} {
    global iocList  outputDir rootname PlaneMode SampleMode CommutationMode TurnMarkerOffset TurnsPerWrap TransitionDeadTime \
	TurnMarkerInterval SamplesPerBunch subsector
    
    eval global $iocList
    set parent ""
    APSParseArguments {parent}
    
    set width 70
    set PlaneMode xy1
    set SampleMode Single
    set CommutationMode ab2
    set TransitionDeadTime 100
    set TurnMarkerInterval 324
    set SamplesPerBunch 6
    set subsector S33A
    GetTurnsPerWrap
    GetTurnMarkerOffset
    if {0} {
    APSFrame .control -parent $parent -label "Control Parameters"
    set w $parent.control.frame
    APSRadioButtonFrame .plane -parent $w \
	-label "Plane Mode      " -variable PlaneMode \
	-orientation horizontal \
	-buttonList [list x y "x/y every turn" "x/y every two turns"] \
	-valueList "x y xy1 xy2" \
	-contextHelp "Select how the plane switch should vary."  \
	-commandList {"GetTurnsPerWrap" "GetTurnsPerWrap" "GetTurnsPerWrap" "GetTurnsPerWrap"}
    APSRadioButtonFrame .sampleMode -parent $w \
	-label "Sample Mode     " -variable SampleMode \
	-orientation horizontal \
	-buttonList [list Continuous Single "Bunch Pattern"] \
	-valueList [list continuous Single bunchpattern] \
	-contextHelp "Select the sample mode. \"Bunch pattern\" refers to the bunch pattern (also known as fill pattern) in the bunch pattern entry box." 
    
    APSRadioButtonFrame .commutationMode -parent $w \
	-label "Commutation Mode" -variable CommutationMode \
	-orientation horizontal \
	-buttonList [list 0 180 "0/180 every turn" "0/180 every two turns"] \
	-valueList "a b ab1 ab2" \
	-contextHelp "Select how the 0/180 phase shifter commutation switch should vary." \
	-commandList {"GetTurnsPerWrap" "GetTurnsPerWrap" "GetTurnsPerWrap" "GetTurnsPerWrap"}
    
    APSLabeledEntry .transitionDeadTime -parent $w \
	-label "Transition Dead time (clock cycles)" -textVariable TransitionDeadTime \
	-contextHelp "Enter a value for transition dead time cycles, the time the state of the ADC output is unknown." -width $width
    
    APSLabeledEntry .bunchPattern -parent $w \
	-label "Bunch Pattern:" -textVariable BunchPattern \
	-contextHelp "Enter a name for the bunch pattern. Must be one of the presets of SRBunchTrain." -width $width
    APSLabeledEntry .samples -parent $w \
	-label "Samples per Bunch" -textVariable SamplesPerBunch \
	-contextHelp "Enter an integer value for samples per bunch, e.q. 5." -width $width
    
    APSLabeledEntry .wrap -parent $w \
	-label "Turns per wrap:" -textVariable TurnsPerWrap -width $width \
	-contextHelp "the number of turns of the repetition period."
    
    APSLabeledEntry .interval -parent $w \
	-label "Turn marker interval:" -textVariable TurnMarkerInterval -width $width \
	-contextHelp "TurnMarkerInterval of one turn, e.q. 324."
    
    APSLabeledEntry .offset -parent $w \
	-label "Turn marker offset:" -textVariable TurnMarkerOffset -width $width \
	-contextHelp "TurnMarker offset."
    }
    set commList [APSReplicateItem -item GetTurnMarkerOffset -number [llength $iocList]]
    APSCheckButtonFrame .ioc -parent $parent -buttonList "$iocList"  -variableList $iocList \
	-limitPerRow 4 -label "Select Subsector" -allNone 1
    
    APSLabeledEntry .dir -parent $parent -label "Output dir:" -textVariable outputDir \
	-width 70 -contextHelp \
      "Enter a directory in which the output files will be written."
    APSButton .dialy -parent $parent.dir -text "daily" -size small \
	-command {set outputDir [APSGoToDailyDirectory -subdirectory fpgaBPMtest]} \
	-packOption "-side right" \
	-contextHelp "Set the output dir to APS daily directory"
    
    APSLabeledEntry .root -parent $parent -label "Output rootname:" -textVariable rootname \
	-width 70
    
    APSButton .scan -parent $parent -text "Start Scan" -command "StartScan"
    APSButton .plot -parent $parent -text "Plot" -command "PlotData"
    APSButton .install -parent $parent -text "Install" -command Install
    APSButton .compare -parent $parent -text "Compare" -command "PlotData -compare 1"
    
}

set status ""
set inputFileDir /home/helios/oagData/sr/FPGAbpm/inputFiles
APSApplication . -name "FPGABpmSelfTest" \
  -version $CVSRevisionAuthor \
  -overview "Perform FPGA bpm self test."

APSScrolledStatus .status -parent .userFrame -textVariable status -width 70 \
    -height 8 -packOption "-fill both -expand true"

if [catch {exec sddsprocess /home/helios/oagData/SCR/requestFiles/SBPMWaveform.config -match=par,Location=Accel,BPMType=FPGA,& -pipe=out \
	       | sdds2stream -pipe -par=IOCName} iocList] {
    puts stderr "Unable to obtain the FPGA ioc list: $iocList"
    exit 1
}
set iocList [join $iocList]
foreach ioc $iocList {
    set $ioc 0
}
CreateWidgets -parent .userFrame
