#!/bin/sh
# \
exec tclsh "$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 bunchCounts 24
set bucketNo 0
set yPlane 0 
set system TFB
set keep 0
set gain 1.0
set rounding 0.5
set firList {0.862915 0.125275 1.0 0.86564 -0.140274 -0.987717 }
set inpList  {5797 5779 5780 5794 5779 5794 }
#keep files or not

#0 x plane, 1 y plane
set args $argv 
APSParseArguments {bunchCounts bucketNo  yPlane system keep }

proc sign { value args } { 
    return [expr $value / abs ($value)]
}

proc processDac { args } {
    global firLIst inpList rounding gain firLongList
    
    set inpLongList ""
    foreach inp $inpList {
	set inpLong [expr int ($inp * 16) ]
	lappend inpLongList $inpLong
    }
    puts "Input: $inpLongList"
    # now calculate FIR output
    set firOutLongList ""
    foreach firLong $firLongList inpLong $inpLongList  {
        #	puts "$firLong $inpLong"
	set firOutLong [expr int ($inpLong * $firLong / 2**15)]
	lappend firOutLongList $firOutLong
    }
    puts "FIROutLong: $firOutLongList"
    
    set add0List ""
    set i 0
    foreach firOut $firOutLongList  {
	if { [expr fmod ($i,2)] == 0} { 
            set sum [expr 1 * $firOut] 
            incr i 
            continue
	} else {
            set sum [expr $sum + $firOut]
            lappend add0List $sum
            incr i 
	}
    }
    if { [expr fmod ($i,2)] == 1} {
	lappend add0List $sum
    }
    puts "add0: $add0List" 
    
    set add0ListDec ""
    set add0ListHex ""
    foreach add0 $add0List {
	if { $add0 < 0 } {
            lappend add0ListDec [expr 2**21+$add0]
            lappend add0ListHex [format %x [expr 2**21 + $add0]]
	} else { 
            lappend add0ListDec $add0
            lappend add0ListHex [format %x $add0]
	}
    }
    
    puts "add0DEC: $add0ListDec"
    puts "add0Hex: $add0ListHex"
    

    
    set add1List ""
    set i 0
    foreach add0 $add0List  {
	if { [expr fmod ($i,2)] == 0} { 
            set sum $add0 
            incr i 
	continue
	} else {
            set sum [expr $sum + $add0]
            lappend add1List $sum
            incr i 
	}
    }
    if { [expr fmod ($i,2)] == 1} {
	lappend add1List $sum
	}
    puts "add1: $add1List" 
    
    set add1ListDec ""
    set add1ListHex ""
    foreach add1 $add1List {
	if { $add1 < 0 } {
            lappend add1ListDec [expr 2**22+$add1]
            lappend add1ListHex [format %x [expr 2**22+$add1]]
	} else { 
            lappend add1ListDec $add1
            lappend add1ListDec [format %x $add1]
	}
    }
    puts "add1Dec: $add1ListDec"
    puts "add1Hex: $add1ListHex"
    
    
    set add2List ""
    set i 0
    foreach add1 $add1List  {
	if { [expr fmod ($i,2)] == 0} { 
            set sum $add1 
            incr i 
            continue
	} else {
            set sum [expr $sum + $add1]
            lappend add2List $sum
            incr i 
	}
    }
    if { [expr fmod ($i,2)] == 1} {
	lappend add2List $sum
    }
    puts "add2: $add2List" 
    
    set add2ListDec ""
    set add2ListHex ""
    foreach add2 $add2List {
	if { $add2 < 0 } {
            lappend add2ListDec [expr 2**23+$add2]
            lappend add2ListHex [format %x [expr 2**23+$add2]]
	} else { 
            lappend add2ListDec $add2
            lappend add2ListHex [format %x $add2]
	}
    }
    puts "add2Dec: $add2ListDec"
    puts "add2Hex: $add2ListHex"
    
    set add3List ""
    set i 0
    foreach add2 $add2List  {
	if { [expr fmod ($i,2)] == 0} { 
            set sum $add2 
            incr i 
            continue
	} else {
            set sum [expr $sum + $add2]
            lappend add3List $sum
            incr i 
	}
    }
    if { [expr fmod ($i,2)] == 1} {
	lappend add3List $sum
    }
    puts "add3: $add3List" 
    
    set add3ListDec ""
    set add3ListHex ""
    foreach add3 $add3List {
	if { $add3 < 0 } {
            lappend add3ListDec [expr 2**24+$add3]
            lappend add3ListHex [format %x [expr 2**24+$add3]]
	} else { 
            lappend add3ListDec $add3
            lappend add3ListHex [format %x $add3]
	}
    }
    puts "add3Dec: $add3ListDec"
    puts "add3Hex: $add3ListHex"
    
    set add4List ""
    set i 0
    foreach add3 $add3List  {
	if { [expr fmod ($i,2)] == 0} { 
            set sum $add3 
            incr i 
            continue
	} else {
            set sum [expr $sum + $add3]
            lappend add4List $sum
            incr i 
	}
    }
    if { [expr fmod ($i,2)] == 1} {
	lappend add4List $sum
    }
    puts "add4: $add4List" 
    
    set add4ListDec ""
    set add4ListHex ""
    foreach add4 $add4List {
	if { $add4 < 0 } {
            lappend add4ListDec [expr 2**25+$add4]
            lappend add4ListHex [format %x [expr 2**25+$add4]]
	} else { 
            lappend add4ListDec $add4
            lappend add4ListHex [format %x $add4]
	}
    }
    puts "add4Dec: $add4ListDec"
    puts "add4Hex: $add4ListHex"
    
    puts "gain: $gain"
    set gainLong [expr int ($gain * 2**9)]
    set add4 [lindex $add4List 0]
    set gainCtlOut [expr $add4 * $gainLong]
    if { $gainCtlOut < 0 } {
	set gainCtlOut [expr 2**42 + $gainCtlOut]
    }
    puts "gainCtl: $gainCtlOut gainCtlHex: [format %x $gainCtlOut]" 
    
    if {$gainCtlOut > 2**41} {
	set gainClamp [ expr 2**14 - int ((2**42-$gainCtlOut)/2**14 + 1)] 
    } else {
        set gainClamp [expr int($gainCtlOut/2**14 + 1)]
    }
    puts "gainClamp: $gainClamp gainClamp: [format %x $gainClamp]"
    if {$gainClamp > 2 ** 13} {
        set dacOut [expr int (fmod ($gainClamp,2**13))]
    } else {
        set dacOut [expr $gainClamp + 2**13]
    }
    puts "DacOut: $dacOut DacOutHex: [format %x $dacOut]"
    
    return $dacOut
}



switch $system {
    TFB {
        set prefix S:TFB:M:
    }
    P0 {
        set prefix S:P0FB:
    }
    default {
        puts stderr "Invalid system - $system provided (has to be TFB or P0"
        exit 1
    }
}

if {$yPlane==0} {
    set inputPV ${prefix}scope:gtr:waveform0
    set outputPV ${prefix}scope:gtr:waveform2
    set gainPV ${prefix}AcqGainX_GetWF
    set filterPV  ${prefix}Coef_X_GetWF
} else {
    set inputPV ${prefix}scope:gtr:waveform1
    set outputPV ${prefix}scope:gtr:waveform2
    set gainPV ${prefix}AcqGainY_GetWF
    set filterPV ${prefix}Coef_Y_GetWF

}

set tmpRoot /tmp/[APSTmpString]
set filename $tmpRoot.raw
set filterFile $tmpRoot.filter
exec sddswget -pv=$inputPV $tmpRoot.input
exec sddswget -pv=$outputPV $tmpRoot.output
#input and output waveform are short values
#filter and gain are double values
if [catch {exec sddswget -pv=$filterPV $filterFile} result] {
    puts stderr "Error reading filter: $result"
    exit 1
}
if [catch {exec sddswget -pv=$gainPV -pipe=out \
             | sddsprocess -pipe -process=Waveform,first,Gain \
             | sdds2stream -pipe=in -par=Gain} gain] {
    puts stderr "Error reading gain: $gain"
    exit 1
}

if [catch {exec sddsprocess $filterFile -filter=col,Waveform,0,0,! -pipe=out \
             | sdds2stream -pipe -col=Waveform } filterList] {
    puts stderr "Error getting filter: $filterList"
    exit 1
}
puts $filterList

exec sddsprocess -redefine=para,bunchCounts,$bunchCounts \
	$tmpRoot.input -redefine=col,Index,i_row,type=long \
	"-redefine=col,IndexM,Index $bunchCounts mod,type=long" \
	-pipe=out \
	| sddssort -col=IndexM -pipe \
	| sddsbreak -changeOf=IndexM -pipe  \
	| sddsprocess -process=IndexM,first,bucketNo -pipe \
	| sddsprocess -filter=para,bucketNo,$bucketNo,$bucketNo \
	-redefine=col,Index,i_row \
	-pipe=in \
    $tmpRoot.break

exec sddsprocess -redefine=para,bunchCounts,$bunchCounts \
	$tmpRoot.output -redefine=col,Index,i_row,type=long \
	"-redefine=col,IndexM,Index $bunchCounts mod,type=long" \
	-pipe=out \
	| sddssort -col=IndexM -pipe \
	| sddsbreak -changeOf=IndexM -pipe  \
	| sddsprocess -process=IndexM,first,bucketNo -pipe \
	| sddsprocess -filter=para,bucketNo,$bucketNo,$bucketNo \
	-redefine=col,Index,i_row \
	-pipe=in \
    $tmpRoot.break.out

set fLen [llength $filterList]
set firList $filterList
set firLongList ""
foreach fir $firList {
    if { $fir > 0 } {
        set firLong [expr int ( $fir * 2**16 + $rounding )]
    } else {
        set firLong [expr int ( -$rounding + $fir * 2**16 )]
    }
    
    #	puts "$fir $firLong"
    lappend firLongList $firLong
}
puts "FIR: [join $firLongList]"

puts "gain: $gain"
set dacList ""
set inDataList [exec sdds2stream -col=Waveform $tmpRoot.break]
set dataLen [llength $inDataList]
set i 0
while {$i<[expr $dataLen-$fLen]} {
    set inpList [lrange $inDataList $i [expr $i+$fLen-1]]
    puts "step $i: $inpList"
    set dacOut [processDac]
    lappend dacList $dacOut
    incr i
}
if [catch {exec sddsmakedataset -col=WaveformProc,type=double -data=[join $dacList ,] -pipe=out \
             | sddsprocess -pipe=in -define=col,Index,i_row,type=long $tmpRoot.sum "-redefine=col,WaveformProc,WaveformProc 8192 -" } result] {
    puts stderr "Error creating dac output: $result"
    exit 1
}



exec sddsplot -col=Index,WaveformProc $tmpRoot.sum -gra=symbol,vary=sub \
  -leg    \
  -col=Index,Waveform  $tmpRoot.break.out -grap=symbol,vary=sub \
  -leg &
exec sddsxref $tmpRoot.sum $tmpRoot.break.out -equate=Index -take=Waveform $tmpRoot.xref
exec sddsplot -col=WaveformProc,Waveform $tmpRoot.xref -grap=symbol &

after 3000
set files [glob $tmpRoot.*]
if !$keep {
  # eval file delete -force $files
}
