#!/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 configFile /home/oxygen/DIAG/BPLD/BPLD_Config/config.sdds

proc GenerateGainWaveform {args} {
    set mainDir ""
    set filename ""
    set bpmList ""
    set gainType sine
    set sineAmp 2.0
    set sineOffset 1.0
    set sineCycles 1
    set sineDecay 0.0
    set step0 1
    set step1 0
    set step2 0
    set stepStart0 100
    set stepEnd0 200
    set stepStart1 300
    set stepEnd1 400
    set stepStart2 500
    set stepEnd2 600
    set stepAmp0 1.2
    set stepAmp1 1.2
    set stepAmp2 1.2
    set lab 0
    set statusCallback ""
    APSParseArguments {mainDir filename bpmList statusCallback gainType sineAmp sineOffset sineCycles sineDecay step0 step1 step2 \
		       stepStart0 stepEnd0 stepStart1 stepEnd1 stepStart2 stepEnd2 stepAmp0 stepAmp1 stepAmp2 lab}
    
   
    if $lab {
	set configFile /home/oxygen/DIAG/apsu/BPLD/BPLD_Config/config.sdds
	set prefix U:
    } else {
	set configFile /home/helios/oagData/sr/BPLD/BPLD_Config/config.sdds
	set prefix ""
    }
    
    set fileList ""
    set tmpFile /tmp/[APSTmpString]
    set outFile $mainDir/$filename
    if ![llength $bpmList] {
		return -code "Error: no bpms provided!"
    }
    if [file exist $outFile] {
		set bpmList0 [exec sdds2stream -par=BPMName $outFile]
    }
    set tmpRoot /tmp/[APSTmpString]
    foreach bpm $bpmList {
	set filename $tmpRoot.${bpm}GainWF.sdds
	if [catch {CreateGainWF -bpm $bpm -filename $filename -lab $lab \
		       -statusCallback $statusCallback \
		       -gainType $gainType -sineAmp $sineAmp -sineOffset $sineOffset -sineCycles $sineCycles -sineDecay $sineDecay \
		       -step0 $step0 -step1 $step1 -step2 $step2 -stepStart0 $stepStart0 -stepEnd0 $stepEnd0 \
		       -stepStart1 $stepStart1 -stepEnd1 $stepEnd1 -stepStart2 $stepStart2 -stepEnd2 $stepEnd2 \
		       -stepAmp0 $stepAmp0 -stepAmp1 $stepAmp1 -stepAmp2 $stepAmp2} result] {
		return -code error "Error creating WF for $bpm: $result"
	}
	lappend fileList $filename
    }
    if [llength $fileList]==1 {
		exec cp $fileList $outFile
    } else {
	if [catch {eval exec sddscombine $fileList $outFile -overwrite } result] {
	    return -code error "Error combing wf: $result"
	}
    }
    eval file delete -force $fileList
    if $lab {
	#only S44 libera is available for lab
	#need change the PV name to use S45 libera, only setup for sector 1, 3 and 5 (ony 3 sectors in lab)
	set liberaList [join [exec sdds2stream -col=LiberaBPM /home/oxygen/DIAG/apsu/BPLD/lab_libera.sdds]]
	set S01List [join [exec sdds2stream -col=S01BPM /home/oxygen/DIAG/apsu/BPLD/lab_libera.sdds]]
	set S03List [join [exec sdds2stream -col=S03BPM /home/oxygen/DIAG/apsu/BPLD/lab_libera.sdds]]
	set S05List [join [exec sdds2stream -col=S05BPM /home/oxygen/DIAG/apsu/BPLD/lab_libera.sdds]]
	#puts $S05List
	set pvList [join [exec sdds2stream -par=WaveformPV $outFile]]
	set opt -reedit=par,WaveformPV,
	foreach pv $pvList {
	    set pv0 [string range $pv 2 8]
	    set i1 [lsearch -exact $S01List $pv0]
	    set i2 [lsearch -exact $S03List $pv0]
	    set i3 [lsearch -exact $S05List $pv0]
		# puts "$pv0 $i1 $i2 $i3"
	    if {$i1>=0} {
		set index $i1
	    } elseif {$i2>=0} {
		set index $i2
	    } elseif {$i3>=0} {
		set index $i3
	    } else {
		return -code error "$pv0 not found in lab_libera.sdds"
	    }
	    append opt %/$pv0/[lindex $liberaList $index]/
	}
	#	puts $opt
	if [catch {exec sddsprocess $outFile -nowarn  $opt} result] {
	    return -code error "Error processing lab libera bpm: $result"
	}
    }
    if [string length $statusCallback] {
	eval $statusCallback {"done."}
    }
}


proc CreateGainWF {args} {
    set bpm ""
    set filename ""
    set gainType sine
    set sineAmp 2.0
    set sineOffset 1.0
    set sineCycles 1
    set sineDecay 0.0
    set step0 1
    set step1 0
    set step2 0
    set stepStart0 100
    set stepEnd0 200
    set stepStart1 300
    set stepEnd1 400
    set stepStart2 500
    set stepEnd2 600
    set stepAmp0 1.2
    set stepAmp1 1.2
    set stepAmp2 1.2
    set statusCallback ""
    set lab 0
    APSParseArguments {statusCallback bpm filename gainType sineAmp sineOffset sineCycles sineDecay step0 step1 step2 \
		       stepStart0 stepEnd0 stepStart1 stepEnd1 stepStart2 stepEnd2 stepAmp0 stepAmp1 stepAmp2 lab}

    if $lab  {
	set prefix U:
    } else {
	set prefix ""
    }
    
    switch $gainType {
	sine {
	    if [string length $statusCallback] {
		eval $statusCallback { "Create sine gain waveform for $bpm..."}
	    }
	    if [catch {exec sddssequence -pipe=out -define=Waveform,type=double -sequence=beg=1,num=4096,end=1 \
			   | sddsprocess -pipe=in $filename -define=col,Index,i_row,type=long \
			   "-redefine=col,Waveform,2 pi * Index * $sineCycles * 4096 / sin $sineAmp * $sineDecay Index * 4096 / exp / $sineOffset +" \
			   -print=par,GainType,sine \
			   -print=par,BPMName,$bpm \
			   -define=par,SineCycles,$sineCycles,type=long \
			   -define=par,SineAmp,$sineAmp \
			   -define=par,SineOffset,$sineOffset \
			   -define=par,SineDecay,$sineDecay \
			   -print=par,WaveformPV,$prefix${bpm}:lsg:wfm_gain_coeff_sp } result] {
		return -code error "Error: Error creating sine gain waveform for $bpm: $result"
	    }
	}
	step {
	    set option ""
	    if $step0 {
		append option " \"-redefine=col,Waveform,Index $stepStart0 1 - > Index $stepEnd0 1 +  < && ? $stepAmp0 : Waveform $ \""
	    }
	    if $step1 {
		append option " \"-redefine=col,Waveform,Index $stepStart1 1 -  > Index $stepEnd1 1 + < && ? $stepAmp1 : Waveform $ \""
	    }
	    if $step2 {
		append option " \"-redefine=col,Waveform,Index $stepStart2 1 - > Index $stepEnd2 1 + < && ? $stepAmp2 : Waveform $ \""
	    }
	    if ![string length $option] {
		return -code error "Error: no step function is chosen!"
	    }
	    if [catch {eval exec sddssequence -pipe=out -define=Waveform,type=double -sequence=beg=1,num=4096,end=1 \
			   | sddsprocess -pipe=in $filename  -define=col,Index,i_row,type=long \
			   -print=par,GainType,step \
			   -print=par,BPMName,$bpm \
			   -print=par,WaveformPV,$prefix${bpm}:lsg:wfm_gain_coeff_sp \
			   $option } result] {
		return -code error "Error define step functions: $result"
	    }
	}
    }
}

#set liberaList {Sn1:LB1 Sn1:LB2 Sn1:LB3 Sn1:LB4 Sn:LB5 Sn:LB6 Sn:LB7}
set liberaList {ioc2sn1bpm1 ioc2sn1bpm2 ioc2sn1bpm3 ioc2sn1bpm4 ioc2snbpm5 ioc2snbpm6 ioc2snbpm7}
#set liberaList {Sn1LB1 Sn1LB2 Sn1LB3 Sn1LB4 SnLB5 SnLP6 SnLB7}
set iocLiberaList {LBP1 LBP2 LBP3 LBP4 LBP5 LBP6 LBP7}
proc SetupSyntheticData {args} {
    set doubleSector ""
    set hostList {S44LBP1 S44LBP2 S44LBP3 S44LBP4 S45LBP5 S45LBP6 S45LBP7}
    set eventList {119 119 119 119 119 119 119}
    set eventList {62 62 62 62 62 62 62}
    set bpmList ""
    set statusCallback ""
    set xstatic 1000
    set ystatic 2000
    set loadGain 0
    set gainFile ""
    set plane x
    set repetition 1
    set samples 4095
    set trigger event
    set lab 0
    set sector 17
    APSParseArguments {doubleSector hostList eventList bpmList statusCallback loadGain gainFile plane repetition samples trigger lab xstatic ystatic sector}
    
    global liberaList
    if {$doubleSector==1} {
	set sector1 40
    } else {
	set sector1 [expr $doubleSector -1]
    }
    if $lab {
	set configFile /home/oxygen/DIAG/apsu/BPLD/BPLD_Config/config.sdds
	set hostList {S44LBP1 S44LBP2 S44LBP3 S44LBP4 S45LBP5 S45LBP6 S45LBP7}
    } else {
	set configFile /home/helios/oagData/sr/BPLD/BPLD_Config/config.sdds
#	puts $liberaList
	set hostList [regsub -all "n1" $liberaList [format %02d $sector1]]
	set hostList [regsub -all "n" $hostList [format %02d $doubleSector]]
#	puts $hostList
    }
    
    if ![llength $eventList] {
	set eventList [APSReplicateItem -item 255  -number $[llength $hostList]] 
    }
    if $lab { 
	#only one libera available in lab
	set liberaList0 {S44LBP1 S44LBP2 S44LBP3 S44LBP4 S45LBP5 S45LBP6 S45LBP7}
	#bpm list needs to be updated also
	set liberaList [join [exec sdds2stream -col=LiberaBPM /home/oxygen/DIAG/apsu/BPLD/lab_libera.sdds]]
	set S01List [join [exec sdds2stream -col=S01BPM /home/oxygen/DIAG/apsu/BPLD/lab_libera.sdds]]
	set S03List [join [exec sdds2stream -col=S03BPM /home/oxygen/DIAG/apsu/BPLD/lab_libera.sdds]]
	set S05List [join [exec sdds2stream -col=S05BPM /home/oxygen/DIAG/apsu/BPLD/lab_libera.sdds]]
	set newList ""
	foreach bpm $bpmList {
	    set i1 [lsearch -exact $S01List $bpm]
	    set i2 [lsearch -exact $S03List $bpm]
	    set i3 [lsearch -exact $S05List $bpm]
	    if {$i1>=0} {
		set index $i1
	    } elseif {$i2>=0} {
				set index $i2
	    } elseif {$i3>=0} {
		set index $i3
	    } else {
		return -code error "$bpm not found in lab_libera.sdds"
	    }
	    lappend newList [lindex $liberaList $index]
	}
	set bpmList $newList
	#	puts $bpmList
    } 
    if [string length $statusCallback] {
	eval $statusCallback {"1, set static values for sector $doubleSector BPMs."}
    }
    if $lab {
	if [catch {exec cavput -list=U:  -list=[join $bpmList ,] \
		       -list=:lsg:k_ -list=X_sp=$xstatic,Y_sp=$ystatic -pend=10} result] {
	    return -code error "Error setting static values: $result"
	}
    } else {
	if [catch {exec cavput -list=[join $bpmList ,] \
		       -list=:lsg:k_ -list=X_sp=$xstatic,Y_sp=$ystatic -pend=20} result] {
	    return -code error "Error setting static values: $result"
	}
    }
    if [string length $statusCallback] {
	eval $statusCallback {"2, enable static synthetic data..."}
    }
    if $lab {
	if [catch {exec cavput -list=U: -list=[join $bpmList ,] -list=:lsg:enable_sp=true -pend=10} result] {
	    return -code error "Error enabling static synthetic data: $result"
	}
    } else {
	if [catch {exec cavput -list=[join $bpmList ,] -list=:lsg:enable_sp=true -pend=10} result] {
	    return -code error "Error enabling static synthetic data: $result"
	}
    }
    if $loadGain {
	if [string length $statusCallback] {
	    eval $statusCallback {"30, load gain waveform..."}
	}
	if [catch {exec sddswput $gainFile } result] {
	    return -code error "Error loading gain WF: $result"
	}
    }
    if [string length $statusCallback] {
	eval $statusCallback {"3, choose field (X/Y) to apply gain waveform..."}
    }
    switch $plane {
	x -
	X {
	    set mask 64
	}
	y -
	Y {
	    set mask 128
	}
    }
    if $lab {
	if [string length $statusCallback] {
	    eval $statusCallback {"cavput -list=U: -list=[join $bpmList ,] -list=:lsg:data_mask_sp=$mask"}
	}
	if [catch {exec cavput -list=U: -list=[join $bpmList ,] -list=:lsg:data_mask_sp=$mask -pend=10} result] {
	    return -code error "Error setting data mask for $plane plane: $result"
	}
	if [string length $statusCallback] {
	    eval $statusCallback {"4, define number of repetitions and samples used.."}
	}
	if [catch {exec cavput -list=U: -list=[join $bpmList ,] -list=:lsg:repetitions_sp=$repetition -pend=10} result] {
	    return -code error "Error setting repetition number: $result"
	}
	if [catch {exec cavput -list=U: -list=[join $bpmList ,] -list=:lsg:wfm_gain_coeff_size_sp=$samples -pend=10} result] {
	    return -code error "Error setting samples: $result"
	}
    } else {
	if [string length $statusCallback] {
	    eval $statusCallback {"cavput -list=[join $bpmList ,] -list=:lsg:data_mask_sp=$mask"}
	}
	if [catch {exec cavput -list=[join $bpmList ,] -list=:lsg:data_mask_sp=$mask -pend=10} result] {
	    return -code error "Error setting data mask for $plane plane: $result"
	}
	if [string length $statusCallback] {
	    eval $statusCallback {"4, define number of repetitions and samples used.."}
	}
	if [catch {exec cavput -list=[join $bpmList ,] -list=:lsg:repetitions_sp=$repetition -pend=10} result] {
	    return -code error "Error setting repetition number: $result"
	}
	if [catch {exec cavput  -list=[join $bpmList ,] -list=:lsg:wfm_gain_coeff_size_sp=$samples -pend=10} result] {
	    return -code error "Error setting samples: $result"
	}
    }
    if [string length $statusCallback] {
	eval $statusCallback {"5, set libera IOC trigger event number..."}
    }
    foreach host $hostList event $eventList {
	#puts " caput ${host}:evrx:rtc:t2:in_mask_sp $event"
	if [catch {exec caput ${host}:evrx:rtc:t2:in_mask_sp 255 } result] {
	    return -code error "Error set event trigger for $host: $result"
	}
	#puts "  caput ${host}:evrx:rtc:t2:in_function_sp $event"
	if [catch {exec caput ${host}:evrx:rtc:t2:in_function_sp $event } result] {
	    return -code error "Error set event trigger for $host: $result"
	}
	if {0} {
	    #use alias for helio
	    puts "caput ${host}:EVRX:Pll_RtcT2InFunctionC $event "
	    if [catch {exec caput ${host}:EVRX:Pll_RtcT2InFunctionC $event } result] {
			return -code error "Error set event trigger for $host: $result"
	    }
	    puts "caput ${host}:EVRX:Pll_RtcT2InMaskC $event"
	    if [catch {exec caput ${host}:EVRX:Pll_RtcT2InMaskC $event} result] {
			return -code error "Error set event trigger1 for $host: $result"
	    }
	}
	
    }
    if [string length $statusCallback] {
	eval $statusCallback {"6, Enable gain waveform..."}
    }
   # puts $trigger
    switch $trigger {
	event {
	    #SetStatus "cavput -list=U: -list=[join $bpmList ,] -list=:lsg:enable_waveform_sp=1"
	    if $lab {
		if [catch {exec cavput -list=U: -list=[join $bpmList ,] -list=:lsg:enable_waveform_sp=1 -pend=10} result] {
		    return -code error "Error enabling gain waveform: $result"
		}
	    } else {
	#	puts "cavput  -list=[join $bpmList ,] -list=:lsg:enable_waveform_sp=1"
		if [catch {exec cavput  -list=[join $bpmList ,] -list=:lsg:enable_waveform_sp=1 -pend=10} result] {
		    return -code error "Error enabling gain waveform: $result"
		}
	    }
	} 
	immediate {
	    if $lab  {
		if [catch {exec cavput  -list=U: -list=[join $bpmList ,] -list=:lsg:waveform_start_sp=1 -pend=10} result] {
		    return -code error "Error enabling gain waveform: $result"
		}
	    } else {
	#	puts "cavput -list=[join $bpmList ,] -list=:lsg:waveform_start_sp=1"
		if [catch {exec cavput -list=[join $bpmList ,] -list=:lsg:waveform_start_sp='1' -pend=10} result] {
		    return -code error "Error enabling gain waveform: $result"
		}
	    }
	}
    }
    if [string length $statusCallback] {
	eval $statusCallback {"Synthetic data setup done."}
    }
}
