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

set CVSRevisionAuthor "\$Revision: 1.2 $ \$Author: shang $"

set archiveDir /home/helios/oagData/sr/tuneArchive/FPGAdata

set env(EPICS_CA_MAX_ARRAY_BYTES) "3000000"


proc SetupNASATuneDrive {args} {
    set plane x
    set drive on
    APSParseArguments {plane drive}
    global centerFreq  xPowerLevel xPoints xCenterFreq  yPowerLevel yPoints yCenterFreq \
	defaultSpan xySpan origSpan srRevFreq
    
    #disable the chirper
    if [catch {exec cavput -list=S:tune:chirp:dacGainA=0,S:tune:chirp:dacGainB=0 } result] {
	return -code error "SetupNASATuneDrive: unable to disable chirper."
    }
    
    if {$drive=="off"} {
	set plane x/y
    }
    set harmonic 1390
    switch $plane {
	x {
	    set  pointsVal [expr int ( log (($xPoints  )/50)/ log (2.0)) ]
	    set c0p0 1
	    set c0p1 1
	    set c2p0 1
	    set mux 0
	    set centerF [expr ($harmonic - $xCenterFreq) * $srRevFreq]
	    set startF [expr ($harmonic - $xCenterFreq) * $srRevFreq - 0.5 * $xySpan]
	    set trig 1
	    set rfon 1
	    set rfpower $xPowerLevel
	    set sweep 1
	    set if 2
	    set sweeptime 0
	}
	y {
	    set pointsVal [expr int ( log (($yPoints  )/50)/ log (2.0)) ]
	    set c0p0 1
	    set c0p1 2
	    set c2p0 4
	    set mux 1
	    set centerF [expr ($harmonic - $yCenterFreq) * $srRevFreq]
	    set startF [expr ($harmonic - $yCenterFreq) * $srRevFreq - 0.5 * $xySpan]
	    set trig 1
	    set rfon 1
	    set rfpower $yPowerLevel
	    set sweep 1
	    set if 2
	    set sweeptime 0
	}
	default {
	    if [catch {exec cavput -list=SR:TUNE:HP_1366A_C0P1_MBBO=0,SR:TUNE:NASA:freqSpanAO=$origSpan,SR:TUNE:NASA:trigModeBO=0,SR:TUNE:NASA:rfPowerAO=13,SR:TUNE:NA:setNumPointsMO=3,SR:TUNE:NASA:ifBwMO=2,SR:TUNE:NASA:sweepTimeAO=0,SR:TUNE:Mux4Sw2BO=0 -pend=30 
	    } result] {
                return -code error "unable to setup NASA for x/y plane: $result"
            }
	    after 1000
	    if [catch {exec cavput -list=SR:TUNE:NASA:sweepSelectMBBO=0,SR:TUNE:NASA:rfPowerBO=0 -pend=30} result] {
		return -code error "unable to setup NASA for x/y plane2: $result"
	    }
	    return
	}
    }
    lappend opt SR:TUNE:Mux4Sw2BO=$mux
    lappend opt SR:TUNE:HP_1366A_C0P0_MBBO=$c0p0
    lappend opt SR:TUNE:HP_1366A_C0P1_MBBO=$c0p1
    lappend opt SR:TUNE:HP_1366A_C2P0_MBBO=$c2p0
    lappend opt SR:TUNE:NASA:centerFreqAO=$centerF
    lappend opt SR:TUNE:NASA:freqSpanAO=$xySpan
    lappend opt SR:TUNE:NASA:startFreqAO=$startF
    if [catch {exec cavput -list=[join $opt ,] -pend=30} result] {
	return -code error "Error in setup NASA drive1: $result"
    }
    after 2000
    set opt ""
    lappend opt SR:TUNE:NASA:freqSpanAO=$xySpan
    lappend opt SR:TUNE:NASA:trigModeBO=$trig
    lappend opt SR:TUNE:NASA:rfPowerBO=$rfon
    lappend opt SR:TUNE:NASA:rfPowerAO=$rfpower
    lappend opt SR:TUNE:NA:setNumPointsMO=$pointsVal
    lappend opt SR:TUNE:NA:setNumPointsMO=$pointsVal
    lappend opt SR:TUNE:NASA:sweepSelectMBBO=$sweep
    lappend opt SR:TUNE:NASA:ifBwMO=$if
    lappend opt SR:TUNE:NASA:sweepTimeAO=$sweeptime
    if [catch {exec cavput -list=[join $opt ,] -pend=30} result] {
	return -code error "Error in setup NASA drive2: $result"
    }
}

proc CalculateTune {args} {
    set filename ""
    set plot 0
    APSParseArguments {filename plot}
    global xTuneLow xTuneHigh yTuneLow yTuneHigh xCenterFreq yCenterFreq 
    global srRevFreq xStartA xStartB xStopA xStopB 
    
    if [catch {exec sdds2stream -par=SR:TUNE:NASA:centerFreqAI $filename} centerFreqHz] {
	return -code error "CalculateTune1: centerFreqHz parameter not found: $centerFreqHz"
    }
    set plane [exec sdds2stream -par=plane $filename]
    switch $plane {
	x {
	    set low $xTuneLow
            set high $xTuneHigh
	    set xStart $xStartA
	    set xStop $xStopA
	}
	y {
	    set low $yTuneLow
            set high $yTuneHigh
	    set xStart $xStartB
	    set xStop $xStopB
	}
    }
    
    set centerFreqTune [expr fmod ($centerFreqHz / $srRevFreq, 1)]
    if { $centerFreqTune > 0.5 } {
	set centerFreqTune [expr 1.0 - $centerFreqTune]
    }
    if [catch {exec sddsprocess $filename \
		   "-redefine=col,tune,Index 1024 mod 2048 /" -pipe=out \
		   | sddssort -col=tune -pipe \
		   | sddsbreak -change=tune -pipe \
		   | sddsprocess -process=SrTune,max,SrTune \
		   -process=tune,first,tune -pipe \
		   | sddscollapse  -pipe \
		   | sddsprocess -filter=col,SrTune,100,1e9 -pipe \
		   | sddssmooth -col=SrTune -pipe \
		   | sddsxref -pipe=in $filename -leave=* -transfer=par,* $filename.tune.1 } result] {
	return -code error "Error in processing tune: $result"
    }
    if [catch {exec sddsprocess $filename.tune.1 -pipe=out \
		   -process=SrTune,max,tune,functionOf=tune,position,lowerLimit=$low,upperLimit=$high \
		   | sdds2stream -pipe -par=tune} tune] {
        return -code error $tune
    }
    
    if [catch {exec sddsprocess $filename $filename.1 -redefine=par,nu,$tune} result] {
        return -code error $result
    }
    
    if [catch {exec sddsprocess $filename.tune.1 $filename.tune -redefine=par,nu,$tune \
		   -redefine=par,tune,$tune \
		   "-reprint=par,tuneString,${plane} tune=[format %.4f $tune]"} result] {
        return -code error $result
    }
    exec mv $filename.1 $filename
    exec rm $filename.tune.1 
    if $plot {
        exec sddsplot -col=tune,SrTune -graph=line $filename.tune \
	    "-title=$filename" "-topline=@tuneString" \
	    -filter=col,tune,$low,$high &
    }
    puts "$plane tune is $tune."
    return $tune
}

proc ProcessData {args} {
    set rootname ""
    set plot 1
    set plane ""
    APSParseArguments {rootname plot plane}
    global xDim xDimMax yDim totalTimeMs fftLength xTuneLow xTuneHigh yTuneLow yTuneHigh
    global adcAcqDelay xStartA xStopA zRangeA  xStartB xStopB zRangeB 

    switch $plane {
	x {
	    set index 0
            set low $xTuneLow
            set high $xTuneHigh
	}
	y {
	    set index 1
            set low $yTuneLow
            set high $yTuneHigh
	}
    }
    set fftFormatLog [exec sdds2stream -par=S:tune:crosspointControl.B3 $rootname.$plane]
    set cutoff [expr $xDim * $yDim - 1]
    if {$fftFormatLog == 0 } { 
	if [catch {eval exec sddsprocess $rootname.$plane -pipe=out -filter=col,Index,0,$cutoff \
		       | sddsprocess -pipe=in $rootname.$plane.1 -nowarnings \
		       \"-redefine=col,SrTune,S:tune:fftAvg:gtr:waveform$index \" \
		       "-reprint=par,plane,$plane" \
		       "-reprint=par,source,NASA" \
		       -redefine=para,xDimension,$xDim,type=long \
		       -redefine=para,yDimension,$yDim,type=long } result] {
	    return -code error "Error in processing tune1: $result"
	}
    } else {
        if [catch {eval exec sddsprocess $rootname.$plane -pipe=out -filter=col,Index,0,$cutoff \
		       | sddsprocess -pipe=in $rootname.$plane.1 -nowarnings \
		       \"-redefine=col,SrTune,2 S:tune:fftAvg:gtr:waveform$index 1024.0 / pow \" \
		       "-reprint=par,plane,$plane" \
		       "-reprint=par,source,NASA" \
		       -redefine=para,xDimension,$xDim,type=long \
		       -redefine=para,yDimension,$yDim,type=long } result] {
            return -code error "Error in processing tune2: $result"
        }
    }
    exec mv $rootname.$plane.1 $rootname.$plane
    if [catch {CalculateTune -filename $rootname.$plane -plot $plot } tune] {
        return -code error "Error in computing tune: $tune"
    }
    
    
}

proc MeasureTuneNASA {args} {
    set rootname ""
    set plane x
    set plot 0
    set drive on
    APSParseArguments {rootname plane plot drive}
    
    set tuneInterval [expr 1.0 / 2048.0]
    global xDim yDim

    set scalars /home/helios/oagData/sr/tuneArchive/inputFiles/tuneScalars.mon 
    
    switch $plane {
	x {
	    set index 0
	    set waveformPV S:tune:fftAvg:gtr:waveform0
	}
	y {
	    set index 1
	    set waveformPV S:tune:fftAvg:gtr:waveform1
	}
    }
    if [catch {SetupNASATuneDrive -plane $plane -drive $drive} result] {
	return -code error "$result"
    }
    if [catch {exec cavput -list=S:tune:fftAvg:gtr:arm=0} result] {
	return -code error "Error in disable fft arm: $result"
    }
    after 500
    if [catch {exec cavput -list=S:tune:fftAvg:gtr:autoRestart=0} result] {
	return -code error "Error in turn off auto start: $result"
    }
    after 500
    if [catch {exec cavput -list=S:tune:fftAvg:gtr:arm=1} result] {
	return -code error "Error in arm fft: $result"
    }
    if [catch {exec sddswmonitor -erase -pvnames=$waveformPV  \
		   -xparameter=name=x,dimension=$xDim,interval=1,minimum=0 \
		   -yparameter=name=y,dimension=$yDim,interval=$tuneInterval,minimum=0 \
		   -scalars=$scalars \
		   $rootname.$plane } result] {
	return -code error "Error in reading SR tune waveform: $result"
    }
    if [catch {ProcessData -plot $plot -rootname $rootname -plane $plane } result] {
	return -code error "Error in processing tune: $result"
    }
    #turn off NASA drive
    if [catch {SetupNASATuneDrive -plane x/y } result] {
	return -code error "Error in turn off NASA drive: $result"
    }
}

proc UpdateXYFreqFilter {args} {
    global xCenterFreq yCenterFreq xTuneLow xTuneHigh yTuneLow yTuneHigh
    set xTuneLow [format %.2f [expr $xCenterFreq - 0.05]]
    set xTuneHigh [format %.2f [expr $xCenterFreq + 0.05]]
    set yTuneLow [format %.2f [expr $yCenterFreq - 0.05]]
    set yTuneHigh [format %.2f [expr $yCenterFreq + 0.05]]
}

set usage "getxytuneFPGA -rootname <filename> -plot <0|1> -drive <on|off> -plane <x|y>"
set rootname ""
set plot 0
set drive on
set plane x
set args $argv
APSParseArguments {rootname plot drive plane}

if ![string length $rootname] {
    puts stderr $usage
    puts stderr "output file rootname not provided."
    exit 1
}
if {$plane!="x" && $plane!="y"} {
    puts stderr $usage
    puts stderr "invalid plane provided."
    exit 1
}

set xDim 128 
set yDim 1024 
set xDimMax 128

set centerFreq 357317200
if [catch {exec cavget -list=SR:TUNE:NASA:freqSpanAO -printErrors} origSpan] {
    return -code error $origSpan
}

set fftLength [exec caget S:tune:pinger:FFTsampleCount -t]
set configFile /home/helios/oagData/sr/tuneArchive/inputFiles/tuneconfig.sdds

set varList [exec sdds2stream -col=VariableName $configFile]
set valList [exec sdds2stream -col=DefaultValue $configFile]
foreach var $varList val $valList {
    set $var $val
}

UpdateXYFreqFilter 
set srRevFreq [expr [exec /home/helios/PAR/bin/getSrRevFreq] * 1e6]

if [catch {MeasureTuneNASA -rootname $rootname -plane $plane -plot $plot -drive $drive} result] {
    puts stderr "Error in measure SR tunes: $result"
    exit 1
}
puts "tune data is generated in $rootname.$plane.tune"
exit 0
