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

# $Log: not supported by cvs2svn $
# Revision 1.48  2011/06/28 14:41:25  shang
# changed the save button to save current control bits into file instead of making a snapshot of SCR.
#
# Revision 1.47  2010/09/02 19:44:20  shang
# now the adjuster buttons in the RAM common bits widget work correctly.
#
# Revision 1.46  2010/06/15 20:29:19  shang
# fixed a bug in generating controlbits for all bpms that the parameters of individual bpm was not updated, so that
# the values were wrong after loading the parameters and waveforms.
#
# Revision 1.45  2010/02/01 17:53:46  shang
# fixed the turns per wrap problme when select presets for the common presets widget and fixed the problem that the bunch-pattern for
# indivual bpms were cleared when the "generate control bits" button is clicked for generating continuous beam.
#
# Revision 1.44  2010/01/28 17:03:36  shang
# corrected the calculation of turns per wrap based on the plane mode and commutation mode.
#
# Revision 1.43  2010/01/12 19:23:24  shang
# fixed a bug in loading parameters which complained that "TurnMarkerInterval" variable does not exist
#
# Revision 1.42  2010/01/08 22:43:58  shang
# made the default turn marker interval to be 324
#
# Revision 1.41  2010/01/08 22:02:08  shang
# made extensive changes so that user can select feasible turn marker interval and turns per wrap from provided list instead of fixed value of 324 for turn marker interval
#
# Revision 1.40  2009/12/14 23:06:34  shang
# modified to update the turns per wrap according to selected plane mode and commutation mode.
#
# Revision 1.39  2009/12/08 19:34:15  shang
# changed to set the global samples per bunch to be the same as the individual bpms if the samples per bunch for all bpms are the same.
#
# Revision 1.38  2009/12/02 22:06:15  shang
# changed the bpm naming convention so that it also works narrow band bpms.
#
# Revision 1.37  2009/09/30 06:47:16  lemery
# Made height of the data waveform display larger at the expense of the
# bit waveform display. This is ok because there is no vertical detail
# in bit wavforms.  Adjusted other heights. Made the zoom control
# buttons use up less vertical space with pack options. Added tab names
# as comments preceeding APSTabFrame commands.
#
# Revision 1.36  2009/09/30 02:49:00  lemery
# Fixed missing "transition dead time" widget in common "set common presets" tab.
# Removed large chunk of unused code in MakeCommonPresetWidget.
# Reduced the width of entries to 50 so that two columns of entries fit better.
#
# Revision 1.35  2009/08/21 19:27:30  shang
# added bpmList to the global variable list.
#
# Revision 1.34  2009/08/06 14:17:52  soliday
# Committed Hairong Shang's changes.
#
# Revision 1.33  2009/07/28 20:43:53  soliday
# Added the leftmargin option to specify the size of the margin in pixels to
# help line up graphs.
#
# Revision 1.32  2009/06/10 22:11:40  shang
# modified to use the scope address as the trigger offset for computing the scope control bits from RAM bits.
#
# Revision 1.31  2009/06/03 04:55:00  shang
# modified to not load turn marker offset from presets when preset button is clicked.
#
# Revision 1.30  2009/05/26 15:46:19  shang
# fixed a typo
#
# Revision 1.29  2009/05/26 15:38:30  shang
# added reading/setting the FPGA bpm waveform parameters when the waveform is being read/loaded.
#
# Revision 1.28  2008/12/03 21:15:08  soliday
# Updated to use dnsdomainname on Linux.
#
# Revision 1.27  2008/02/22 16:34:58  emery
# Changed the default PVprefix to S38D.
# Use APSStrictParseArguments now.
#
# Revision 1.26  2007/08/28 15:41:57  shang
# it now displays the bpm position.
#
# Revision 1.25  2007/07/05 22:01:46  emery
# Forgot to put BPMposition as argument to APSParseArguments.
#
# Revision 1.24  2007/03/29 21:17:51  emery
# Undid the work-around for ulong, now that sddsprocess handles ulong
# correctly.
# Added status labeled-output boxes for ram and scope tabs which reveal the
# "provenance" of the waveforms.
# Gave context help for plot describing what data file is being plotted.
#
# Revision 1.23  2007/03/29 15:48:59  emery
# Improved the comment in procedure SaveToFile, the procedure
# which takes the graphical waveforms and makes a control RAM file.
# Work around for ulong in sddsprocess, use the cast command to make
# a double column a ulong type.
# Removed the "P0offset" argument in procedure GenerateControlBit
# because there are none in the new version of the acquisition system.
# Improved status messages to claruify thatsome waveforms are
# simulated under some circumstances.
#
# Revision 1.22  2007/03/28 22:42:56  emery
# Define the Waveform column in *.RAMcontrolBits file a ulong instead of a long.
# (This may mean that sddswput needs updating to recognize the ulong data type.)
# Removed the option P0Offset of a sddsgencontrolbits command.
#
# Revision 1.21  2007/03/27 17:17:26  emery
# Enabled for all time the arm button.
#
# Revision 1.20  2007/03/27 16:13:14  emery
# Changed default prefix for oxygen to S42B.
# Aded BPMposition for the P? part of the prefix.
# Changed some control PVs to the new ones.
# Removed conditional for disabling the Load button.
# The load button is always enabled now.
#
# Revision 1.19  2007/02/21 18:41:00  emery
# Corrected the logic of disabling the Load button
#
# Revision 1.18  2007/01/18 16:15:26  soliday
# Updated to work with the new domain names.
#
# Revision 1.17  2006/12/20 23:33:58  emery
# Added RAMCommutationNegateFlag adjuster (tab added).
# Removed scopeTurnMarkerFlag scopeP0MarkerFlag scopeWrapMarkerFlag
# quantities. (Tabs removed)
# In GenerateControlBits added RAM content file argument of sddsgencontrolbits
# command.
# Changed units of transition dead timne to 88 MHz clock cycles.
# Made initial capture of waveform use the same initial
# /tmp directory that is generated for the directory entry box.
# Added extra adjuster buttons for half-width panning and
# making all adjuster the same width as the one viewed.
# Added plot button for plotting scope control bits overlayed with data.
# Commented out lists of button widget names which don't appear to be used anywhere.
# Renamed the procedure "pan" to adjustRange. Added argument factor to
# adjustRange.
#
# Revision 1.16  2006/08/10 20:57:13  emery
# Fixed bit 31 problem with signed long integer.
#
# Revision 1.15  2006/08/09 09:19:08  emery
# Shang added top level for two groups of control bits,
# a status text frame, and several SetStatus commands.
#
# Revision 1.14  2006/08/08 18:00:30  emery
# Updated scope bit flags. Use sddsbinarystring on control RAM file in
# SaveToFile. Changed the order of the tabs.
#
# Revision 1.13  2006/08/04 06:22:36  emery
# Fixed the SaveToFile procedure (Load button action)
# so that all receivers get the same plane accumulator and sample flags.
#
# Revision 1.12  2006/04/18 19:16:06  emery
# Fixed -buchPattern option for sddsgencontrolbits
#
# Revision 1.11  2006/04/18 17:13:41  emery
# Fixed RAM commutation switch flag and RAM wrap marker flag. Added -receiver avlue to sddsgencontrolbits. Fixed typos in column names in sdds commands.
#
# Revision 1.10  2006/04/17 22:22:16  emery
# When doing the match of PVprefix with the domainname, the program
# no longer exits. Just a warning is given. The prefix cf4 is
# now matched with domain name cntrl.ntw0rk
#
# Revision 1.9  2006/04/17 17:12:55  emery
# Addded some warning messages about EPICS environment variables
# if the domain name is aps.anl.gov or cntrl.ntw0rk.
#
# Revision 1.8  2006/04/17 16:59:21  emery
# Added aps.anl.gov as other domain name for which cf2 prefix is supposed
# to work.
#
# Revision 1.7  2006/04/17 16:52:40  emery
# Added verbose argument so that update messages for the creation of initial
# adjuster widgets can be printed to stderr. (This setup takes a few seconds).
# Do a check of domain name and the PV prefix. If prefix doesn't match
# then program exists.
#


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

set PVprefix S38A
set args $argv
APSStrictParseArguments {PVprefix}
APSStandardSetup
if {[info exists tcl_pkgPath]} {
    set rpnLib [file join [lindex $tcl_pkgPath 0] rpn libtclRPN.so]
    if {($tcl_platform(os) == "Linux") && [file exists $rpnLib]} {
        load $rpnLib
    } else {
        package require rpn
    }
} else {
    package require rpn
}
set RAMArrayLength 3888
set scopeArrayLength 4096
set archiveDir /home/helios/oagData/sr/BPMcontrolRAM/archive


set scopePrevIndex 0
set ramPrevIndex 0
proc SelectTabFrames {args} {
    global topIndex scopeFrameIndex ramFrameIndex scopePrevIndex ramPrevIndex
    global scopeBpmFrameIndex$scopePrevIndex scopeDataFrameIndex$scopePrevIndex
    global ramBpmFrameIndex$ramPrevIndex ramDataFrameIndex$ramPrevIndex
    global rampBpmFrameIndex$ramPrevIndex rampDataFrameIndex$ramPrevIndex
    
    
    if {$topIndex==0} {
        set type scope
    } elseif {$topIndex==1} {
        set type ram
    } else {
        return
    }
   
    if {[info exist ${type}FrameIndex]} {
        set index [set ${type}FrameIndex]
        global ${type}FrameParent$index
        if {[info exist ${type}FrameParent$index] && [winfo exist [set ${type}FrameParent$index]]} {
            set parent [set ${type}FrameParent$index]
            $parent.bpm.frame.tn select [set ${type}BpmFrameIndex[set ${type}PrevIndex]]
            $parent.data.frame.tn select [set ${type}DataFrameIndex[set ${type}PrevIndex]]
            set ${type}PrevIndex $index
        }
    }
}


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

set sampleModeList {continuous single bunchpattern}
proc ReadSetWaveformParameters {args} {
    set read 1
    APSParseArguments {read}
    global PVprefix bpmList bpmList sampleModeList
    
    
    foreach index {0 1 2 3} {
        global PlaneMode$index BunchPattern$index SampleMode$index SamplesPerBunch$index \
          TransitionDeadTime$index adcDelay$index AccumulatorMode$index
        set bpm [lindex $bpmList $index]
        if $read {
            if [catch {exec cavget -list=$bpm -list=:  -pend=30 \
                         -list=PlaneMode,SampleMode,TransitionLO,SamplesPerBunchLO,BunchPatternSO,adcDelay,AccumulatorMode } valList] {
                return -code error "ReadSetWaveformParameters1: $valList"
            }
            foreach val $valList name {PlaneMode SampleMode TransitionDeadTime SamplesPerBunch BunchPattern adcDelay AccumulatorMode} {
                set $name$index $val
            }
            set SampleMode$index [string tolower [set SampleMode$index]]
            set AccumulatorMode$index [set SampleMode$index]
        } else {
            set sampleMode [lsearch -exact $sampleModeList [set SampleMode$index]]
            if [catch {exec cavput -pend=30 -list=$bpm  -list=: \
                         "-list=PlaneMode=[set PlaneMode$index],SampleMode=$sampleMode,TransitionLO=[set TransitionDeadTime$index],SamplesPerBunchLO=[set SamplesPerBunch$index],BunchPatternSO=[set BunchPattern$index],AccumulatorMode=[set PlaneMode$index]" } result] {
                return -code error "ReadSetWaveformParameters3: $result"
            }
        }
        
    }
    
    global TurnsPerWrap CommutationMode TurnMarkerOffset SamplesPerBunch SampleMode PlaneMode BunchPattern TransitionDeadTime TurnMarkerInterval
    if $read {
        if [catch {exec cavget -list=${PVprefix}: -pend=30 -list=TurnsPerWrapLO,CommutationMode,TurnMarkerOffsetLO,TurnMarkerIntervalLO } valList] {
            return -code error "ReadSetWaveformParameters4: $valList"
        }
        set TurnsPerWrap [lindex $valList 0]
        set CommutationMode [lindex $valList 1]
        set TurnMarkerOffset [lindex $valList 2]
        set TurnMarkerInterval [lindex $valList 3]
    } else {
        
        if [catch {exec cavput -pend=30 -list=${PVprefix}: -list=TurnsPerWrapLO=$TurnsPerWrap,CommutationMode=$CommutationMode,TurnMarkerOffsetLO=$TurnMarkerOffset,TurnMarkerIntervalLO=$TurnMarkerInterval } valList] {
            return -code error "ReadSetWaveformParameters5: $valList"
        }
    }
    foreach name {SamplesPerBunch SampleMode PlaneMode TransitionDeadTime} {
        set a0 [set ${name}0]
        set a1 [set ${name}1]
        set a2 [set ${name}2]
        set a3 [set ${name}3]
        if {$a0==$a1 && $a1==$a2 && $a2==$a3} {
            set $name $a0
        }
    }
    return
    if {$SamplesPerBunch0==$SamplesPerBunch1 && $SamplesPerBunch1==$SamplesPerBunch2 && $SamplesPerBunch2==$SamplesPerBunch3} {
        set SamplesPerBunch $SamplesPerBunch0
    }
    if {$SampleMode0==$SampleMode1 && $SampleMode1==$SampleMode2 && $SampleMode2==$SampleMode3} {
        set SampleMode $SampleMode0
    }
    if {$PlaneMode0==$PlaneMode1 && $PlaneMode1==$PlaneMode2 && $PlaneMode2==$PlaneMode3} {
        set PlaneMode $PlaneMode0
    }
}
proc ReadBPMData {args} {
    set filename ""
    APSParseArguments {filename}
    
    global PVprefix bpmList  bpmType
    
    set index 0
    if ![string length $filename] {
        set filename /tmp/[APSTmpString]
    }
    
    foreach bpm $bpmList {
        global readbacks$index sums$index 
	switch $bpmType {
	    FPGA {
		set pv1 ${bpm}:scope:position
		set pv2 ${bpm}:scope:sum
	    }
	    Narrowband {
		set pv1 ${bpm}:scope:horizontal
		set pv2 ${bpm}:scope:vertical
               
	    }
            Xray {
              #  if [regexp BM $PVprefix] {
                    set pv1  ${bpm}:scope:A
                    set pv2 ${bpm}:scope:B
              #  }
            }
            Booster {
                set pv1 ${bpm}:scope:position
                set pv2 ${bpm}:scope:sum
            }
	}
        if [catch {exec sddswget -pv=$pv1 $filename.delta$index \
                 } result] {
            return -code error "ReadBPMData1: $result"
        }
        set readbacks$index  [join [exec sdds2stream -col=Waveform $filename.delta$index]]
        if [catch {exec sddswget -pv=$pv2 $filename.sum$index \
                 } result] {
            return -code error "ReadBPMData1: $result"
        }
	set sums$index [join [exec sdds2stream -col=Waveform $filename.sum$index]]
        
        incr index
    }
}

set SetAll 0
set PlaneMode x
set AccumulatorMode $PlaneMode
set SampleMode single
set TransitionDeadTime 70
set BunchPattern ""
set TurnMarkerOffset 200
set SamplesPerBunch 6
set TurnsPerWrap 2
set secondSampleDelay 141
set secondSamplesPerBunch 30
set includeSecondSample 0
proc SetConfiguration {args} {
    set bpmIndex ""
    set index ""
    APSParseArguments {bpmIndex index}

    global presetConfigurationData label configuration
    if {$index == ""} {
        return -code error "SetConfiguration: No index value passed."
    }
    if [string length $bpmIndex] {
        global  PlaneMode$bpmIndex BunchPattern$bpmIndex SampleMode$bpmIndex SamplesPerBunch$bpmIndex \
	    TransitionDeadTime$bpmIndex  AccumulatorMode$bpmIndex CommutationMode
        set PlaneMode$bpmIndex        [lindex [lindex $presetConfigurationData(Column.PlaneMode) 0] $index]
        set SampleMode$bpmIndex       [string tolower [lindex [lindex $presetConfigurationData(Column.SampleMode) 0] $index]]
        
        set BunchPattern$bpmIndex     [lindex [lindex $presetConfigurationData(Column.BunchPattern) 0] $index]
        set SamplesPerBunch$bpmIndex  [lindex [lindex $presetConfigurationData(Column.SamplesPerBunch) 0] $index]
        
        set TransitionDeadTime$bpmIndex [lindex [lindex $presetConfigurationData(Column.TransitionDeadTime) 0] $index]
	set CommutationMode  [lindex [lindex $presetConfigurationData(Column.CommutationMode) 0] $index]
	GenerateControlBits -setAll 0
    } else {
        global Label PlaneMode CommutationMode SampleMode BunchPattern SamplesPerBunch
        global TurnMarkerOffset TransitionDeadTime TurnsPerWrap TurnMarkerInterval
        set BunchPatternLabel [lindex [lindex $presetConfigurationData(Column.Label) 0] $index]
        SetStatus "$BunchPatternLabel was selected."
        
        set PlaneMode        [lindex [lindex $presetConfigurationData(Column.PlaneMode) 0] $index]
        set CommutationMode  [lindex [lindex $presetConfigurationData(Column.CommutationMode) 0] $index]
        set SampleMode       [string tolower [lindex [lindex $presetConfigurationData(Column.SampleMode) 0] $index]]
        
        set BunchPattern     [lindex [lindex $presetConfigurationData(Column.BunchPattern) 0] $index]
        set SamplesPerBunch  [lindex [lindex $presetConfigurationData(Column.SamplesPerBunch) 0] $index]
        set TurnMarkerInterval [lindex [lindex $presetConfigurationData(Column.TurnMarkerInterval) 0] $index]
       # set TurnMarkerOffset [lindex [lindex $presetConfigurationData(Column.TurnMarkerOffset) 0] $index]
        
        set TransitionDeadTime [lindex [lindex $presetConfigurationData(Column.TransitionDeadTime) 0] $index]
        set TurnsPerWrap [GetTurns]
        set AccumulatorMode $PlaneMode
        
       
	foreach bpmIndex {0  1 2 3} {
	    global  PlaneMode$bpmIndex BunchPattern$bpmIndex SampleMode$bpmIndex SamplesPerBunch$bpmIndex \
		TransitionDeadTime$bpmIndex  AccumulatorMode$bpmIndex  configuration$bpmIndex
	    set PlaneMode$bpmIndex $PlaneMode
	    set BunchPattern$bpmIndex $BunchPattern
	    set SampleMode$bpmIndex $SampleMode
	    set SamplesPerBunch$bpmIndex $SamplesPerBunch
	    set TransitionDeadTime$bpmIndex $TransitionDeadTime
	    set AccumulatorMode$bpmIndex $AccumulatorMode
	    set configuration$bpmIndex $configuration
	    
	}
	GenerateControlBits -setAll 1
    }
    update
    
}


# Called for each of the BPMs
proc MakePresetWidget {args} {
    set bpmIndex 0
    set parent ""
    APSParseArguments {bpmIndex parent}
    
    global configuration$bpmIndex PlaneMode$bpmIndex BunchPattern$bpmIndex SampleMode$bpmIndex SamplesPerBunch$bpmIndex \
      TransitionDeadTime$bpmIndex adcDelay$bpmIndex AccumulatorMode$bpmIndex
    global presetConfigurationLabelList presetConfigurationData presetFile
    global secondSampleDelay  secondSamplesPerBunch  includeSecondSample
    
    set w $parent
    set configuration$bpmIndex ""
    APSFrameGrid .entries -parent $w -xList {x1 x2}
    # Note that all the variable names end with $bpmIndex
    APSComboboxFrame .preset -parent $w.entries.x1 -label Presets \
      -packOption "-fill x" \
      -textVariable configuration$bpmIndex \
      -itemList $presetConfigurationLabelList \
      -width 58 \
      -editable 0 \
      -callback "SetConfiguration -bpmIndex $bpmIndex -index" \
      -contextHelp "Select a preset RAM configuration which defines the control bit pattern for each of the possible 3888 88-Mhz time slots. Tcl variables in this tab frame will be updated and the bit generated (as though the \"GenerateControl Bits\" button is pressed)."
    APSFrame .button -parent $w.entries.x1
    APSButton .edit -parent $w.entries.x1.button.frame -packOption "-side left -anchor w" \
      -text "Edit presets ..." \
      -command "exec sddsedit $presetFile &" \
      -contextHelp "Brings up sddsedit for the preset controlRAM configuration file. You need to restart 
application for new or updated presets to appear in combobox."
    
    APSButton .generate -parent $w.entries.x1.button.frame -packOption "-side left -anchor w" \
      -text "Generate control bits" \
      -command "GenerateControlBits -setAll 0" \
      -contextHelp "Generates or regenerate control bits for individual bpm."
    
    
    APSRadioButtonFrame .planeMode -parent $w.entries.x1\
      -label "Plane Mode" -variable PlaneMode$bpmIndex \
      -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 [list "UpdateTurnsPerWrap -index $bpmIndex" "UpdateTurnsPerWrap -index $bpmIndex" "UpdateTurnsPerWrap -index $bpmIndex" "UpdateTurnsPerWrap -index $bpmIndex"]
    
    APSRadioButtonFrame .sampleMode -parent $w.entries.x1 \
      -label "Sample Mode" -variable SampleMode$bpmIndex \
      -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." 
    
    APSLabeledEntry .bunchPattern -parent $w.entries.x1 \
      -label "Bunch Pattern:" -textVariable BunchPattern$bpmIndex \
      -contextHelp "Enter a name for the bunch pattern. Must be one of the presets of SRBunchTrain." -width 50
    
    
    APSLabeledEntry .samples -parent $w.entries.x1 \
      -label "Samples per Bunch" -textVariable SamplesPerBunch$bpmIndex \
      -contextHelp "Enter an integer value for samples per bunch, e.q. 5." -width 50
    
    APSLabeledEntry .transitionDeadTime -parent $w.entries.x1 \
      -label "Transition Dead time (clock cycles)" -textVariable TransitionDeadTime$bpmIndex \
      -contextHelp "Enter a value for transition dead time cycles, the time the state of the ADC output is unknown." -width 50

    APSLabeledEntry .adcDelay -parent $w.entries.x1 \
      -label "ADC delay" -textVariable adcDelay$bpmIndex \
      -contextHelp "adc delay, press enter the new value will be set." -width 50
    

    APSLabel .label -parent $w.entries.x2 -text "Following are common for all channels:"
    global CommutationMode TurnMarkerOffset TurnsPerWrap
    APSRadioButtonFrame .commutationMode -parent $w.entries.x2 \
	-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." 
    APSLabeledEntry .turnMarkerOffset -parent $w.entries.x2 \
	-label "Turn Marker Offset" -textVariable TurnMarkerOffset \
	-contextHelp "Enter an integer value for the P0 offset." -width 50
   
    APSLabeledEntry .turns -parent $w.entries.x2 \
	-label "Turns Per Wrap" -textVariable TurnsPerWrap \
	-contextHelp "Enter an integer value for samples per bunch, e.q. 5." -width 50
    APSLabeledEntry .sec1 -parent $w.entries.x2 \
      -label "Second sample delay" -textVariable secondSampleDelay -width 50
    APSLabeledEntry .sec2 -parent $w.entries.x2 \
      -label "Seconds sample samples per bunch" -textVariable secondSamplesPerBunch -width 50
    APSRadioButtonFrame .sec3 -parent $w.entries.x2  \
      -label "Include second sample?" -buttonList {Yes No} -valueList {1 0}  -variable includeSecondSample \
      -orientation horizontal
    
}

# This isn't used anywhere
proc SetBPMModes {args} {
    global SetAll  PlaneMode BunchPattern SampleMode SamplesPerBunch \
	TransitionDeadTime adcDelay AccumulatorMode CommunicatioMode TurnsPerWrap TurnMarkerOffset
    global commonPresetWidget
    set nameList {PlaneMode BunchPattern SampleMode SamplesPerBunch TransitionDeadTime AccumulatorMode}
    if $SetAll {
        for {set index 0} {$index<4} {incr index} {
            foreach name $nameList {
                global ${name}$index ${name}${index}Old
                set ${name}${index}Old [set ${name}$index]
                set ${name}$index [set $name]
            }
        }
        APSEnableWidget $commonPresetWidget
    } else {
        for {set index 0} {$index<4} {incr index} {
            foreach name $nameList {
                global ${name}$index ${name}${index}Old
                set ${name}$index [set ${name}${index}Old]
            }
        }
        APSDisableWidget $commonPresetWidget
    }
}
set SetAll 0
proc MakeCommonPresetWidget {args} {
    set parent ""
    APSParseArguments {parent}
    
    global configuration PlaneMode BunchPattern SampleMode SamplesPerBunch \
      TransitionDeadTime adcDelay AccumulatorMode CommunicatioMode TurnsPerWrap TurnMarkerOffset
    global presetConfigurationLabelList presetConfigurationData presetFile SetAll commonPresetWidget TurnMarkerInterval
    
    set w $parent
    set configuration ""
    
   
    APSFrameGrid .entries -parent $w -xList {x1 x2} -yList {y1 y2}
    set commonPresetWidget $w.entries
    APSComboboxFrame .preset -parent $w.entries.x1.y1 -label Presets \
      -packOption "-fill x" \
      -textVariable configuration \
      -itemList $presetConfigurationLabelList \
      -width 58 \
      -editable 0 \
      -callback "SetConfiguration -index" \
      -contextHelp "Select a preset RAM configuration which defines the control bit pattern for each of the possible 3888 88-Mhz time slots. Tcl variables in this tab frame will be updated and the bit generated (as though the \"GenerateControl Bits\" button is pressed)."
    
    APSButton .edit -parent $w.entries.x2.y1 -packOption "-side left -anchor w" \
      -text "Edit presets ..."  \
      -command "exec sddsedit $presetFile &" \
      -contextHelp "Brings up sddsedit for the preset controlRAM configuration file. You need to restart 
application for new or updated presets to appear in combobox."
    
    APSButton .generate -parent $w.entries.x2.y1 -packOption "-side left -anchor w" \
      -text "Generate control bits" \
      -command "GenerateControlBits -setAll 1" \
      -contextHelp "Generates or regenerate control bits with the same modes for all bpms."
    
    APSRadioButtonFrame .planeMode -parent $w.entries.x1.y2 \
	-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 {"UpdateTurnsPerWrap" "UpdateTurnsPerWrap" "UpdateTurnsPerWrap" "UpdateTurnsPerWrap"}
    APSRadioButtonFrame .sampleMode -parent $w.entries.x1.y2 \
	-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.entries.x1.y2 \
	-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 {"UpdateTurnsPerWrap" "UpdateTurnsPerWrap" "UpdateTurnsPerWrap" "UpdateTurnsPerWrap"}
     APSLabeledEntry .transitionDeadTime -parent $w.entries.x1.y2 \
      -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 50
    
    APSLabeledEntry .bunchPattern -parent $w.entries.x2.y2 \
	-label "Bunch Pattern:" -textVariable BunchPattern \
	-contextHelp "Enter a name for the bunch pattern. Must be one of the presets of SRBunchTrain." -width 50
    APSLabeledEntry .samples -parent $w.entries.x2.y2 \
	-label "Samples per Bunch" -textVariable SamplesPerBunch \
	-contextHelp "Enter an integer value for samples per bunch, e.q. 5." -width 50
    
    APSLabeledEntry .turnMarkerOffset -parent $w.entries.x2.y2 \
      -label "Turn Marker Offset" -textVariable TurnMarkerOffset \
      -contextHelp "Enter an integer value for the P0 offset." -width 50
   # APSLabeledEntry .per -parent $w.entries.x2.y2 \
   #   -label "Pattern (wrap) length " -textVariable PatternLength \
    #  -contextHelp "TurnMarkerInterval of one turn, e.q. 324." -width 50
    global turnParent
    set turnParent $w.entries.x2.y2
   
    GenerateTurnsWidget 
    return
   
}

set leftmargin 70
proc MakeBPMDataWidget {args} {
    set bpmIndex 0
    set widgetList ""
    APSParseArguments {bpmIndex widgetList}

    global readbacks$bpmIndex sums$bpmIndex adjuster scopeAdjusterList dataHeight \
      outputDir root fileIndex leftmargin
    if ![info exist sums$bpmIndex] {
        ReadBPMData
    }
    
    set index 0
    foreach quantity [list readbacks$bpmIndex sums$bpmIndex] {
        set x${quantity} 0
        set y${quantity} [lindex [set $quantity] [set x${quantity}]]
        set w  [lindex $widgetList $index]
        
        APSFrame .adjuster -parent $w \
          -packOption "-side top -fill both -expand true" -relief flat
        APSFrame .controls -parent $w \
          -packOption "-side top" -relief flat
        APSWaveformAdjuster .widget${quantity} \
          -parent $w.adjuster.frame \
          -static 0 \
          -height $dataHeight \
          -showPrevious 1 \
          -waveformVariable $quantity \
          -handleSpacing 1 \
          -selectedXCoordVar x${quantity} \
          -selectedYCoordVar y${quantity} \
          -packOption "-side top -fill x -expand true"  \
          -leftmargin $leftmargin \
          -contextHelp "$quantity control"
        
        APSButton .panLeft -parent  $w.controls.frame -text "<-"  \
          -command "adjustRange -quantity $quantity -direction left -doAllScopeAdjusters \$doAllScopeAdjusters" \
          -packOption "-side left" \
          -contextHelp "This button pans the zoom window left" \
          -fastClick 1
        
        APSButton .panLeftHalf -parent  $w.controls.frame -text "<-1/2"  \
          -command "adjustRange -quantity $quantity -direction left -factor 0.5 -doAllScopeAdjusters \$doAllScopeAdjusters" \
          -packOption "-side left" \
          -contextHelp "This button pans the zoom window left one-half screen" \
          -fastClick 1
        
        APSButton .adjustRange -parent  $w.controls.frame -text "="  \
          -command "adjustRange -quantity $quantity -doAllScopeAdjusters \$doAllScopeAdjusters" \
          -packOption "-side left" \
          -contextHelp "Make all adjuster the same range as this one" \
          -fastClick 1
        
        APSButton .panRightHalf -parent  $w.controls.frame -text "1/2->"  \
          -command "adjustRange -quantity $quantity -direction right -factor 0.5 -doAllScopeAdjusters \$doAllScopeAdjusters" \
          -packOption "-side left" \
          -contextHelp "This button pans the zoom window right one-half screen" \
          -fastClick 1
        
        APSButton .panRight -parent  $w.controls.frame -text "->"  \
          -command "adjustRange -quantity $quantity -direction right -doAllScopeAdjusters \$doAllScopeAdjusters" \
          -packOption "-side left" \
          -contextHelp "This button pans the zoom window right" \
          -fastClick 1

        
        APSButton .center0 -parent  $w.controls.frame -text "Center +/- 2 turn"  \
          -command "center -quantity $quantity -width 1296  -turns 4 -doAllScopeAdjusters \$doAllScopeAdjusters" \
          -packOption "-side left" \
          -contextHelp "This button centers on 2048, which is the trigger position." \
          -fastClick 1
        
        APSButton .center1 -parent  $w.controls.frame -text "Center +/- 1 turn"  \
          -command "center -quantity $quantity -width 648 -turns 2 -doAllScopeAdjusters \$doAllScopeAdjusters" \
          -packOption "-side left" \
          -contextHelp "This button centers on 2048, which is the trigger position." \
          -fastClick 1
        
        APSButton .center2 -parent  $w.controls.frame -text "Center +/- 1/2 turn"  \
          -command "center -quantity $quantity -width 324 -turns 1 -doAllScopeAdjusters \$doAllScopeAdjusters" \
          -packOption "-side left" \
          -contextHelp "This button centers on 2048, which is the trigger position." \
          -fastClick 1
        
        APSButton .center3 -parent  $w.controls.frame -text "Center +/- 1/4 turn"  \
          -command "center -quantity $quantity -width 162 -turns 0.5 -doAllScopeAdjusters \$doAllScopeAdjusters" \
          -packOption "-side left" \
          -contextHelp "This button centers on 2048, which is the trigger position." \
          -fastClick 1
        
        APSButton .center4 -parent  $w.controls.frame -text "Center +/- 1/8 turn"  \
          -command "center -quantity $quantity -width 81 -turns 0.25  -doAllScopeAdjusters \$doAllScopeAdjusters" \
          -packOption "-side left" \
          -contextHelp "This button centers on 2048, which is the trigger position." \
          -fastClick 1
        
        APSButton .plot0 -parent  $w.controls.frame -text "Plot"  \
          -command "plotScopeData -quantity $quantity -bpmIndex $bpmIndex" \
          -packOption "-side left" \
          -contextHelp "Plots overlayed scope data of file $outputDir/$root-[format %03ld $fileIndex] for the range displayed." \
          -fastClick 1
        
        set adjuster($quantity) $w.adjuster.frame.widget${quantity}.graph
        lappend scopeAdjusterList $w.adjuster.frame.widget${quantity}.graph

        incr index
    }
    
}


proc MakeReadWaveformWidget {args} {
    set parent ""
    APSParseArguments {parent}
    
    global PVprefix outputDir root fileIndex Comment TimeStamp bpmType
    
    set w $parent
    APSFrame .entries -parent $w
    APSFrame .actions -parent $w
    APSButton .update -parent  $w.actions.frame -text "Arm"  \
      -command "exec cavput -list=${PVprefix}:scope:gtr:arm=1 -pend=20" \
      -packOption "-side left" \
      -contextHelp "Causes a trigger to update the scope PVs for scope control RAM readback and the delta and sum readbacks." \
      -fastClick 1
    
    APSButton .readRAM -parent  $w.actions.frame -text "Get Waveforms"  \
      -command "incr fileIndex; GetWaveforms -mode RAM" \
      -packOption "-side left" \
      -contextHelp "Reads scope PVs for scope control RAM readback and the delta and sum readbacks. The data is written to files with names created by rootname and index, e.g.\n<rootname>-<index>.delta,\n<rootname>-<index>.sum,\n<rootname>-<index>.controlBits. A file of control bits has separate colums for the control RAM bits. The index shown in widget is incremented just before reading." \
      -fastClick 1
    
    APSButton .readFile -parent  $w.actions.frame -text "Read Waveforms from File"  \
      -command "GetWaveforms -mode file -outputDir \$outputDir -root \$root -index \$fileIndex" \
      -packOption "-side left" \
      -contextHelp "Reads control bit and data from files with names with rootname and index, e.g.\n<rootname>-<index>.deltaData,\n<rootname>-<index>.sumData,\n<rootname>-<index>.controlRAM. A file is created with control bits in separate colums: <rootname>-<index>.controlBits. The index shown in widget is not changed." \
      -fastClick 1
    APSButton .readfile1 -parent $w.actions.frame -text "Read Waveforms From SCR" \
      -command "ReadWaveformsFromSCR" \
      -contextHelp "Reads control bit and data from SBPMWaveform SCR snapshots." \
      -fastClick 1
    
    APSButton .stop -parent $w.actions.frame -text "Booster Timing Setup" \
      -command "StopResumeStartBoosterBPMAverage -action stop" \
      -contextHelp "setup triiger and scope event for view booster bpm timing." \
      -fastClick 1
     APSButton .resume -parent $w.actions.frame -text "Restore Booster Operation Timing" \
      -command "StopResumeStartBoosterBPMAverage -action resume" \
      -contextHelp "resume booster bpm average and restore trigger setting for operation." \
      -fastClick 1
    APSLabeledEntry .outputDir -parent $w.entries.frame \
      -label "Output directory:" -textVariable outputDir \
      -contextHelp "Enter a name for the output file directory." -width 50
    
    APSButton .daily -parent $w.entries.frame.outputDir -packOption "-anchor e" \
      -text "daily" -size small \
      -command {set outputDir [APSGoToDailyDirectory -subdirectory monopulseBPM]}
    
    APSLabeledEntry .root -parent $w.entries.frame -label "Root name of file: " \
      -textVariable root \
      -contextHelp "Enter the root name of the ouput files."
    
    APSLabeledEntry .index -parent $w.entries.frame -label "Index (incremented just before reading): " -textVariable fileIndex \
      -contextHelp "Enter the index (minus 1) to be part of the name of the output file. The index is incremented by 1 before execution."
    
    APSLabeledEntry .comment -parent $w.entries.frame -label "Comment: " -textVariable Comment \
      -width 50 \
      -contextHelp "Enter a Comment."
    
    APSButton .update -parent $w.entries.frame.comment -packOption "-anchor e" \
      -text "update from SR:bunchPatternSO" -size small \
      -command "UpdateComment"
    APSLabeledEntry .time -parent $w.entries.frame -label "Read waveform time:" -textVariable TimeStamp \
	-width 50 -contextHelp "display the time when the waveform is being read."
}

proc SaveSnapshot {args} {
    global Description
    if [catch {APSSaveMachine -machine SBPMWaveform -routine 0 -description "$Description" \
                 -pendIOTime 60 -statusCallback SetStatus} result] {
        APSAlertBox [APSUniqueName .] -errorMessage "Error doing save for SBPMWaveform: $result"
        return
    }
}

proc MakeSaveWidget {args} {
    set parent ""
    APSParseArguments {parent}
    set w $parent

    global Description
    APSLabeledEntry .comment -parent $parent -label "Description:" -textVariable Description -width 120 \
      -contextHelp "enter the descript for SCR."
    APSButton .save -parent $parent -text "Save" -command "SaveToFile -archive 0 -Comment $Description" \
      -contextHelp "this button is the same as the save button in SCR -- SCR save for SBPMWaveform."
    return
   
}

proc MakeLoadWidget {args} {
    set parent ""
    APSParseArguments {parent}
    global scrComment
    APSFrame .actions -parent $parent
    APSButton .load -parent  $parent.actions.frame -text "Load"  \
      -command "LoadRAM -Comment \$Comment" \
      -packOption "-side left" \
      -contextHelp "Loads RAM from file <rootname>-<index>.controlRAM to control RAM array PV." \
      -fastClick 1
}


proc MakeBPMBitWidget {args} {
    set widgetList ""
    set bpmIndex ""
    set type ""
    APSParseArguments {widgetList bpmIndex type}

    global ${type}PlaneSwitch$bpmIndex ${type}Accumulator$bpmIndex ${type}Sample$bpmIndex
    global adjuster scopeAdjusterList  adjusterHeight leftmargin

    set index 0
    foreach quantity [list ${type}Sample$bpmIndex ${type}PlaneSwitch$bpmIndex ${type}Accumulator$bpmIndex] {
        set x${quantity} 0
        set y${quantity} [lindex [set $quantity] [set x${quantity}]]
        set w  [lindex $widgetList $index]
        
        APSFrame .adjuster -parent $w \
          -packOption "-side top -fill both -expand true" -relief flat
        APSFrame .controls -parent $w \
          -packOption "-side top" -relief flat
        APSWaveformAdjuster .widget${quantity} \
          -parent $w.adjuster.frame \
          -static 0 \
          -height $adjusterHeight \
          -showPrevious 1 \
          -waveformVariable $quantity \
          -handleSpacing 1 \
          -selectedXCoordVar x${quantity} \
          -selectedYCoordVar y${quantity} \
          -leftmargin $leftmargin \
          -packOption "-side top -fill both -expand true"  \
          -contextHelp "$quantity control"
        
        APSButton .panLeft -parent  $w.controls.frame -text "<-"  \
          -command "adjustRange -quantity $quantity -direction left -doAllScopeAdjusters \$doAllScopeAdjusters" \
          -packOption "-side left" \
          -contextHelp "This button pans the zoom window left" \
          -fastClick 1
        
        APSButton .panLeftHalf -parent  $w.controls.frame -text "<-1/2"  \
          -command "adjustRange -quantity $quantity -direction left -factor 0.5 -doAllScopeAdjusters \$doAllScopeAdjusters" \
          -packOption "-side left" \
          -contextHelp "This button pans the zoom window left one-half screen" \
          -fastClick 1
        
        APSButton .adjustRange -parent  $w.controls.frame -text "="  \
          -command "adjustRange -quantity $quantity -doAllScopeAdjusters \$doAllScopeAdjusters" \
          -packOption "-side left" \
          -contextHelp "Make all adjuster the same range as this one" \
          -fastClick 1
        
        APSButton .panRightHalf -parent  $w.controls.frame -text "1/2->"  \
          -command "adjustRange -quantity $quantity -direction right -factor 0.5 -doAllScopeAdjusters \$doAllScopeAdjusters" \
          -packOption "-side left" \
          -contextHelp "This button pans the zoom window right one-half screen" \
          -fastClick 1
        
        APSButton .panRight -parent  $w.controls.frame -text "->"  \
          -command "adjustRange -quantity $quantity -direction right -doAllScopeAdjusters \$doAllScopeAdjusters" \
          -packOption "-side left" \
          -contextHelp "This button pans the zoom window right" \
          -fastClick 1
        
        APSButton .center0 -parent  $w.controls.frame -text "Center +/- 2 turn"  \
          -command "center -quantity $quantity -width 1296 -turns 4 -doAllScopeAdjusters \$doAllScopeAdjusters" \
          -packOption "-side left" \
          -contextHelp "This button centers on 2048, which is the trigger position." \
          -fastClick 1

        APSButton .center1 -parent  $w.controls.frame -text "Center +/- 1 turn"  \
          -command "center -quantity $quantity -width 648 -turns 2 -doAllScopeAdjusters \$doAllScopeAdjusters" \
          -packOption "-side left" \
          -contextHelp "This button centers on 2048, which is the trigger position." \
          -fastClick 1
        
        APSButton .center2 -parent  $w.controls.frame -text "Center +/- 1/2 turn"  \
          -command "center -quantity $quantity -width 324  -turns 1 -doAllScopeAdjusters \$doAllScopeAdjusters" \
          -packOption "-side left" \
          -contextHelp "This button centers on 2048, which is the trigger position." \
          -fastClick 1
        
        APSButton .center3 -parent  $w.controls.frame -text "Center +/- 1/4 turn"  \
          -command "center -quantity $quantity -width 162 -turns 0.5  -doAllScopeAdjusters \$doAllScopeAdjusters" \
          -packOption "-side left" \
          -contextHelp "This button centers on 2048, which is the trigger position." \
          -fastClick 1
        
        APSButton .center4 -parent  $w.controls.frame -text "Center +/- 1/8 turn"  \
          -command "center -quantity $quantity -width 81 -turns 0.25  -doAllScopeAdjusters \$doAllScopeAdjusters" \
          -packOption "-side left" \
          -contextHelp "This button centers on 2048, which is the trigger position." \
          -fastClick 1
        
        APSButton .plot0 -parent  $w.controls.frame -text "Plot"  \
          -command "plotScopeData -quantity $quantity -bpmIndex $bpmIndex" \
          -packOption "-side left" \
          -contextHelp "Plots overlayed scope data for the range displayed." \
          -fastClick 1
        
        APSLabeledOutput .status -parent  $w.controls.frame -label "Updated from" \
          -textVariable scopeWaveformStatus -backgroundcolor white \
          -width 22 \
          -packOption "-side right" \
          -contextHelp "Reveals whether the data shown on the graph is freshly obtained from the scope waveform PV or simulated from a calculation"
        
        set adjuster($quantity) $w.adjuster.frame.widget${quantity}.graph
        lappend scopeAdjusterList $w.adjuster.frame.widget${quantity}.graph
        
        incr index
    }
}

proc MakeScopeCommonBitsWidget {args} {
    set widgetList ""
    APSParseArguments {widgetList}
    
    global scopeCommutationNegate scopeCommutationSwitch adjuster scopeAdjusterList adjusterHeight
    
    set commParent [lindex $widgetList 0]
    set negParent [lindex $widgetList 1]
    
    foreach quantity {scopeCommutationNegate scopeCommutationSwitch} w [list $commParent $negParent] {
        set x${quantity} 0
        set y${quantity} [lindex [set $quantity] [set x${quantity}]]
        APSFrame .adjuster -parent $w \
          -packOption "-side top -fill both -expand true"  -relief flat
        APSFrame .controls -parent $w \
          -packOption "-side top"  -relief flat
        APSWaveformAdjuster .widget${quantity} \
          -parent $w.adjuster.frame \
          -static 0 \
          -height $adjusterHeight \
          -showPrevious 1 \
          -waveformVariable $quantity \
          -handleSpacing 1 \
          -selectedXCoordVar x${quantity} \
          -selectedYCoordVar y${quantity} \
          -packOption "-side top -fill both -expand true"  \
          -contextHelp "$quantity control"
        
        APSButton .panLeft -parent  $w.controls.frame -text "<-"  \
          -command "adjustRange -quantity $quantity -direction left -doAllScopeAdjusters \$doAllScopeAdjusters" \
          -packOption "-side left" \
          -contextHelp "This button pans the zoom window left" \
          -fastClick 1
        
        APSButton .panLeftHalf -parent  $w.controls.frame -text "<-1/2"  \
          -command "adjustRange -quantity $quantity -direction left -factor 0.5 -doAllScopeAdjusters \$doAllScopeAdjusters" \
          -packOption "-side left" \
          -contextHelp "This button pans the zoom window left one-half screen" \
          -fastClick 1
        
        APSButton .adjustRange -parent  $w.controls.frame -text "="  \
          -command "adjustRange -quantity $quantity -doAllScopeAdjusters \$doAllScopeAdjusters" \
          -packOption "-side left" \
          -contextHelp "Make all adjuster the same range as this one" \
          -fastClick 1

        APSButton .panRightHalf -parent  $w.controls.frame -text "1/2->"  \
          -command "adjustRange -quantity $quantity -direction right -factor 0.5 -doAllScopeAdjusters \$doAllScopeAdjusters" \
          -packOption "-side left" \
          -contextHelp "This button pans the zoom window right one-half screen" \
          -fastClick 1
        
        APSButton .panRight -parent  $w.controls.frame -text "->"  \
          -command "adjustRange -quantity $quantity -direction right -doAllScopeAdjusters \$doAllScopeAdjusters" \
          -packOption "-side left" \
          -contextHelp "This button pans the zoom window right" \
          -fastClick 1
        
        APSButton .center0 -parent  $w.controls.frame -text "Center +/- 2 turn"  \
          -command "center -quantity $quantity -width 1296 -doAllScopeAdjusters \$doAllScopeAdjusters" \
          -packOption "-side left" \
          -contextHelp "This button centers on 2048, which is the trigger position." \
          -fastClick 1
        
        APSButton .center1 -parent  $w.controls.frame -text "Center +/- 1 turn"  \
          -command "center -quantity $quantity -width 648 -doAllScopeAdjusters \$doAllScopeAdjusters" \
          -packOption "-side left" \
          -contextHelp "This button centers on 2048, which is the trigger position." \
          -fastClick 1
        
        APSButton .center2 -parent  $w.controls.frame -text "Center +/- 1/2 turn"  \
          -command "center -quantity $quantity -width 324 -doAllScopeAdjusters \$doAllScopeAdjusters" \
          -packOption "-side left" \
          -contextHelp "This button centers on 2048, which is the trigger position." \
          -fastClick 1
        
        APSButton .center3 -parent  $w.controls.frame -text "Center +/- 1/4 turn"  \
          -command "center -quantity $quantity -width 162 -doAllScopeAdjusters \$doAllScopeAdjusters" \
          -packOption "-side left" \
          -contextHelp "This button centers on 2048, which is the trigger position." \
          -fastClick 1
        
        APSButton .center4 -parent  $w.controls.frame -text "Center +/- 1/8 turn"  \
          -command "center -quantity $quantity -width 81 -doAllScopeAdjusters \$doAllScopeAdjusters" \
          -packOption "-side left" \
          -contextHelp "This button centers on 2048, which is the trigger position." \
          -fastClick 1
       
        
        APSLabeledOutput .status -parent  $w.controls.frame -label "Updated from" \
          -textVariable scopeWaveformStatus -backgroundcolor white \
          -width 22 \
          -packOption "-side right" \
          -contextHelp "Reveals whether the data shown on the graph is freshly obtained from the scope waveform PV or simulated from a calculation"
        
        set adjuster($quantity) $w.adjuster.frame.widget${quantity}.graph
        lappend scopeAdjusterList $w.adjuster.frame.widget${quantity}.graph

    }
    
}

proc MakeRAMCommonBitsWidget {args} {
    set widgetList ""
    APSParseArguments {widgetList}

    global RAMCommutationNegate RAMCommutationSwitch RAMSaveSample RAMSelfTest RAMTurnMarker RAMWrapMarker
    global adjuster  adjusterHeight scopeAdjusterList
    
    SetStatus "Creating control RAM bits widgets..."
    set index 0
    foreach quantity {RAMCommutationSwitch RAMCommutationNegate RAMSaveSample RAMSelfTest RAMTurnMarker RAMWrapMarker} {
        set x${quantity} 0
        set y${quantity} [lindex [set $quantity] [set x${quantity}]]
        set w  [lindex $widgetList $index]
        APSFrame .adjuster -parent $w \
          -packOption "-side top -fill both -expand true"  -relief flat
        APSFrame .controls -parent $w \
          -packOption "-side top"  -relief flat
        APSWaveformAdjuster .widget${quantity} \
          -parent $w.adjuster.frame \
          -static 0 \
          -height $adjusterHeight \
          -showPrevious 1 \
          -waveformVariable $quantity \
          -handleSpacing 1 \
          -selectedXCoordVar x${quantity} \
          -selectedYCoordVar y${quantity} \
          -packOption "-side top -fill both -expand true"  \
          -contextHelp "$quantity control"
        APSButton .panLeft -parent  $w.controls.frame -text "<-"  \
          -command "adjustRange -quantity $quantity -direction left -doAllScopeAdjusters \$doAllScopeAdjusters" \
          -packOption "-side left" \
          -contextHelp "This button pans the zoom window left" \
          -fastClick 1
        
        APSButton .panLeftHalf -parent  $w.controls.frame -text "<-1/2"  \
          -command "adjustRange -quantity $quantity -direction left -factor 0.5 -doAllScopeAdjusters \$doAllScopeAdjusters" \
          -packOption "-side left" \
          -contextHelp "This button pans the zoom window left one-half screen" \
          -fastClick 1
        
        APSButton .adjustRange -parent  $w.controls.frame -text "="  \
          -command "adjustRange -quantity $quantity -doAllScopeAdjusters \$doAllScopeAdjusters" \
          -packOption "-side left" \
          -contextHelp "Make all adjuster the same range as this one" \
          -fastClick 1
        
        APSButton .panRightHalf -parent  $w.controls.frame -text "1/2->"  \
          -command "adjustRange -quantity $quantity -direction right -factor 0.5 -doAllScopeAdjusters \$doAllScopeAdjusters" \
          -packOption "-side left" \
          -contextHelp "This button pans the zoom window right one-half screen" \
          -fastClick 1
        
        APSButton .panRight -parent  $w.controls.frame -text "->"  \
          -command "adjustRange -quantity $quantity -direction right -doAllScopeAdjusters \$doAllScopeAdjusters" \
          -packOption "-side left" \
          -contextHelp "This button pans the zoom window right" \
          -fastClick 1
        
        APSButton .center0 -parent  $w.controls.frame -text "Center +/- 2 turn"  \
          -command "center -quantity $quantity -width 1296 -doAllScopeAdjusters \$doAllScopeAdjusters" \
          -packOption "-side left" \
          -contextHelp "This button centers on 2048, which is the trigger position." \
          -fastClick 1

        APSButton .center1 -parent  $w.controls.frame -text "Center +/- 1 turn"  \
          -command "center -quantity $quantity -width 648 -doAllScopeAdjusters \$doAllScopeAdjusters" \
          -packOption "-side left" \
          -contextHelp "This button centers on 2048, which is the trigger position." \
          -fastClick 1
        
        APSButton .center2 -parent  $w.controls.frame -text "Center +/- 1/2 turn"  \
          -command "center -quantity $quantity -width 324 -doAllScopeAdjusters \$doAllScopeAdjusters" \
          -packOption "-side left" \
          -contextHelp "This button centers on 2048, which is the trigger position." \
          -fastClick 1
        
        APSButton .center3 -parent  $w.controls.frame -text "Center +/- 1/4 turn"  \
          -command "center -quantity $quantity -width 162 -doAllScopeAdjusters \$doAllScopeAdjusters" \
          -packOption "-side left" \
          -contextHelp "This button centers on 2048, which is the trigger position." \
          -fastClick 1
        
        APSButton .center4 -parent  $w.controls.frame -text "Center +/- 1/8 turn"  \
          -command "center -quantity $quantity -width 81 -doAllScopeAdjusters \$doAllScopeAdjusters" \
          -packOption "-side left" \
          -contextHelp "This button centers on 2048, which is the trigger position." \
          -fastClick 1
       
        
        APSLabeledOutput .status -parent  $w.controls.frame -label "Updated from" \
          -textVariable scopeWaveformStatus -backgroundcolor white \
          -width 22 \
          -packOption "-side right" \
          -contextHelp "Reveals whether the data shown on the graph is freshly obtained from the scope waveform PV or simulated from a calculation"
        
        set adjuster($quantity) $w.adjuster.frame.widget${quantity}.graph
        lappend scopeAdjusterList $w.adjuster.frame.widget${quantity}.graph
        incr index
    }
}


proc ReadWaveformsFromSCR {args}  {
    global ReadWaveformsFromSCR PVprefix dialogBoxResponse bpmList bpmType
    global TurnsPerWrap CommutationMode TurnMarkerOffset SamplesPerBunch SampleMode PlaneMode BunchPattern TransitionDeadTime TurnMarkerInterval
    
    set ReadWaveformsFromSCR(ShortFilename) ""
    SetStatus "Reading waveforms from SCR ..."
    if {$bpmType=="Booster"} {
        set snapDir /home/helios/oagData/SCR/snapshots/BBPMWaveform
        set system BBPMWaveform
    } else {
        set snapDir /home/helios/oagData/SCR/snapshots/SBPMWaveform
        set system SBPMWaveform
    }
    APSDialogBox .diag  -cancelCommand "set dialogBoxResponse cancel" \
      -okCommand "set dialogBoxResponse ok"  -name "Select SCR"
    APSAddSCRDialog .scr -parent .diag.userFrame -system $system \
      -label "Choose SCR file for viewing" \
      -arrayName ReadWaveformsFromSCR \
      -defaultFile $ReadWaveformsFromSCR(ShortFilename)
    tkwait window .diag

    if {$dialogBoxResponse=="cancel"} {
        SetStatus "Review SCR waveforms was cancelled."
        return
    }
    if ![string length $ReadWaveformsFromSCR(ShortFilename)] {
        SetStatus "No SCR file chosen."
        return
    }
    #update the parameters
    foreach name {TurnsPerWrap CommutationMode TurnMarkerOffset TurnMarkerInterval} {
        if [catch {exec sddsprocess $snapDir/$ReadWaveformsFromSCR(ShortFilename) -match=col,ControlName=${PVprefix}:${name}* -pipe=out \
                     | sdds2stream -pipe -col=ValueString} result] {
            return -code error "Error in getting value for ${PVprefix}:${name} from SCR: $result"
        }
        set $name $result
    }
    
    foreach name {SamplesPerBunch SampleMode PlaneMode TransitionDeadTime BunchPattern AccumulatorMode} {
        if {$name=="TransitionDeadTime"} {
            set match Transition
        } else {
            set match $name
        }
        for {set i 0} {$i<[llength $bpmList]} {incr i} {
            set bpm [lindex $bpmList $i]
            if [catch {exec sddsprocess  $snapDir/$ReadWaveformsFromSCR(ShortFilename) -match=col,ControlName=${bpm}:${match}* -pipe=out \
                         |  sdds2stream -pipe -col=ValueString} result] {
                return -code error "Error in getting value for ${bpm}:${match} from SCR: $result"
            }
            global ${name}$i
            set ${name}$i $result
            
        }              
    }

    set pvname ${PVprefix}:AcqControlGetWF
    set tmpFile /tmp/[APSTmpString]
    
    if [catch {exec sddsprocess $snapDir/[file root $ReadWaveformsFromSCR(ShortFilename)].waveform.gz \
                 -match=par,WaveformPV=$pvname $tmpFile.input } result] {
        return -code error "Error get $pvname from SCR: $result"
    }
   
    if [catch {exec sddswget -pv=${PVprefix}:Px:scope:acqAddress $tmpFile.a } result] {
        return -code error "Error reading ${PVprefix}:Px:scope:acqAddress : $result"
    }
    if [catch {exec sddsprocess $tmpFile.a -clip=1,0,invert -pipe=out \
                 | sdds2stream -pipe -col=Waveform } offset] {
        return -code error "Error getting the offset: $offset"
    }
   # puts "sddsgencontrolbits -turnMarkerOffset=$TurnMarkerOffset -turnsPerWrap=$TurnsPerWrap -turnMarkerInterval=$TurnMarkerInterval  \
    #             $tmpFile.input $tmpFile.controlbits -scopeTriggerIndexOffset=$offset"
    set len [expr $TurnsPerWrap*$TurnMarkerInterval]
    if $len>=2048 {
        set offset [expr $len-2048]
    } else {
        for {set i 2} {$i<=36} {incr i} {
            set len0 [expr $i*$len]
            if $len0>=2048 {
                break
            }
        }
        set offset [expr $len0 - 2048]
    }
    
    if [catch {exec sddsgencontrolbits -turnMarkerOffset=$TurnMarkerOffset -turnsPerWrap=$TurnsPerWrap -turnMarkerInterval=$TurnMarkerInterval  \
                 $tmpFile.input $tmpFile.controlbits -scopeTriggerIndexOffset=$offset } result] {
        return -code error "Error generating controlbits from SCR: $result"
    }
    loadControlBitsFromFile -filename $tmpFile.controlbits -read 1
    
    #updating the scalar variables
    if [catch {exec sddsprocess $snapDir/$ReadWaveformsFromSCR(ShortFilename) -match=col,ControlName=${PVprefix}:* \
                 -filter=col,Count,1,1 $tmpFile } result] {
        return -code error "Error get scalar pvs from SCR: $result"
    }
    global CommutationMode TurnsPerWrap TurnMarkerOffset bpmList TurnMarkerInterval
    if [catch {exec sddsprocess $tmpFile -match=col,ControlName=${PVprefix}:CommutationMode -pipe=out \
                 | sdds2stream -pipe -col=ValueString} CommutationMode] {
        return -code error "Error obtaining commutation mode: $CommutationMode"
    }
    if [catch {exec sddsprocess $tmpFile -match=col,ControlName=${PVprefix}:TurnsPerWrapLO -pipe=out \
                 | sdds2stream -pipe -col=ValueString} TurnsPerWrap] {
        return -code error "Error obtaining turns per wrap from SCR: $TurnsPerWrap"
    }
    if [catch {exec sddsprocess $tmpFile -match=col,ControlName=${PVprefix}:TurnMarkerOffsetLO -pipe=out \
                 | sdds2stream -pipe -col=ValueString} TurnMarkerOffset] {
        return -code error "Error obtaining turn marker offset from SCR: $TurnsPerWrap"
    }
    if [catch {exec sddsprocess $tmpFile -match=col,ControlName=${PVprefix}:TurnMarkerIntervalLO $tmpFile.interval } result] {
        #default value is 324
        set TurnMarkerInterval 324
    } else {
        set TurnMarkerInterval [exec sdds2stream $tmpFile.interval -col=ValueString]
    }
    set index 0
    foreach bpm $bpmList {
        global AccumulatorMode$index PlaneMode$index BunchPattern$index SampleMode$index SamplesPerBunch$index TransitionDeadTime$index
        if [catch {exec sddsprocess $tmpFile -match=col,ControlName=$bpm:* $tmpFile.$index} result] {
            #no info was obtained
            return
            return -code error "Error get bpm $bpm info from SCR:  $result"
        }
        set nameList [exec sdds2stream -col=ControlName $tmpFile.$index]
        set valList [exec sdds2stream -col=ValueString $tmpFile.$index]
        foreach name $nameList val $valList {
            if [regexp {AccumulatorMode} $name] {
                set AccumulatorMode$index $val
            } elseif [regexp {PlaneMod} $name] {
                set PlaneMode$index $val
            } elseif [regexp {BunchPatter} $name] {
                set BunchPattern$index $val
            } elseif [regexp {SampleMode} $name] {
                set SampleMode$index $val
            } elseif [regexp {SamplesPerBunch} $name] {
                set SamplesPerBunch$index $val
            } elseif [regexp {Transition} $name] {
                set TransitionDeadTime$index $val
            }
        }
        incr index
    }
    SetStatus "done"
}
proc GetWaveforms {args} {
    set mode RAM
    set filename ""
    APSParseArguments {mode filename}

    global PVprefix TimeStamp
    global outputDir root fileIndex
    
    if ![string length $filename] {
        if ![file exists $outputDir] {
            exec mkdir -p $outputDir
        }
        set filename $outputDir/$root-[format %03ld $fileIndex]
    }
    if {$mode=="RAM"} {
        SetStatus "Reading control RAM PV, scope waveform PV of control RAM, delta and sum readbacks..."
        if [catch {exec cavput -list=${PVprefix}:AcqControlGetWF.PROC=1 -pend=20} result] {
            return -code error "GetWaveforms1: Something wrong with PV ${PVprefix}:AcqControlGetWF: $result"
        }
        if [catch {exec cavput -list=${PVprefix}:scope:gtr:arm=1 -pend=20} result] {
            return -code error "GetWaveforms2: $result"
        }
        ReadSetWaveformParameters
        ReadBPMData -filename $filename
        
        if [catch {exec sddsgencontrolbits $filename \
                     -RAMWaveform=${PVprefix}:AcqControlGetWF \
                     -scopeWaveform=${PVprefix}:Px:scope:acqControl } result] {
            return -code error $result
        }
    } else {
        SetStatus "Reading control bits and data from file $filename (saved earlier)..."
    }
    set TimeStamp [clock format [clock seconds]]
    global RAMArrayLength
    loadControlBitsFromFile -filename $filename -read 1
}

proc loadControlBitsFromFile {args} {
    set filename ""
    set updateParam 0
    set read 0
    APSParseArguments {filename updateParam read}
    
    global RAMArrayLength scopeArrayLength
    if [catch {sdds load $filename data} result] {
        return -code error $result
    }
    if $updateParam {
        eval global $data(ParameterNames)
        foreach par $data(ParameterNames) {
            set $par [lindex $data(Parameter.$par) 0]
        }
       
    }
    if $read {
        set RAMArrayLength [lindex $data(Parameter.ArrayLength) 0]
        set scopeArrayLength [lindex $data(Parameter.ArrayLength) 1]
    }
    for {set i 0} {$i<2} {incr i} {
        set type [lindex $data(Parameter.RecordType) $i]
        foreach col $data(ColumnNames) {
            global ${type}${col}
           # set ${type}${col} [lrange [lindex $data(Column.$col) $i] 0 [expr [set ${type}ArrayLength] -1]]
             set ${type}${col} [lindex $data(Column.$col) $i]
        }
    }
}

proc UpdateComment {} {
    global Comment
    catch {exec cavget -list=SR:bunchPatternSO -pend=30} initialBunchPattern
    set Comment "Test with $initialBunchPattern. LEm"
    return
}

proc LoadRAM {args} {
    global PVprefix BPMposition
    set Comment ""
    APSParseArguments {Comment}
    
    SetStatus "Loading preset or edited RAM waveforms to EPICS ..."
    if [catch {SaveToFile -archive 0 -Comment $Comment} filename] {
        return -code error "LoadRAM1: $filename"
    }
    if [catch {exec sddswput $filename} result] {
        return -code error "LoadRAM2: sddswput: $result"
    }
    # do a caput ${PVprefix}:AcqControlGetWF.PROC 1
    if [catch {exec cavput -list=${PVprefix}:AcqControlGetWF.PROC=1 -pend=30} result] {
        return -code error "LoadRAM3: $result"
    }
    after 2000
    # update scope PV waveforms
    if [catch {exec cavput -list=${PVprefix}:scope:gtr:arm=1 -pend=30} result] {
        return -code error "LoadRAM4: $result"
    }
    if [catch {ReadSetWaveformParameters -PVprefix $PVprefix -read 0} result] {
        return -code error "LoadRAM5: $result"
    }
    SetStatus "Done."
}

proc SaveToRAMarchive {args} {
    set Comment ""
    APSParseArguments {Comment}
    SetStatus "Save preset or edited RAM waveforms to RAM archive .."
    SaveToFile -archive 1 -Comment $Comment
    UpdateArchiveListFile
    SetStatus "Done."
}

set globalVariables {PVprefix RAMArrayLength scopeArrayLength archiveDir bpmList \
			 RAMAccumulator RAMSaveSample RAMSelfTest RAMCommutationNegate RAMCommutationSwitch \
			 RAMTurnMarker RAMWrapMarker \
			 scopeCommutationNegate scopeCommutationSwitch \
			 RAMPlaneSwitch0 RAMPlaneSwitch1 RAMPlaneSwitch2 RAMPlaneSwitch3 \
			 RAMAccumulator0 RAMAccumulator1 RAMAccumulator2 RAMAccumulator3 \
                       RAMSample0 RAMSample1 RAMSample2 RAMSample3 \
                       scopePlaneSwitch0 scopePlaneSwitch1 scopePlaneSwitch2 scopePlaneSwitch3 \
                       scopeAccumulator0 scopeAccumulator1 scopeAccumulator2 scopeAccumulator3 \
                       scopeSample0 scopeSample1 scopeSample2 scopeSample3 \
                       PlaneMode0 PlaneMode1 PlaneMode2 PlaneMode3 \
                       AccumulatorMode0 AccumulatorMode1 AccumulatorMode2 AccumulatorMode3 \
                       SampleMode0 SampleMode1 SampleMode2 SampleMode3 \
                       BunchPattern0 BunchPattern1 BunchPattern2 BunchPattern3 \
                       SamplesPerBunch0 SamplesPerBunch1 SamplesPerBunch2 SamplesPerBunch3 \
                       TransitionDeadTime0 TransitionDeadTime1 TransitionDeadTime2 TransitionDeadTime3 \
                       adcDelay0 adcDelay1 adcDelay2 adcDelay3 \
                       TurnsPerWrap CommutationMode TurnMarkerOffset TransitionDeadTime \
                       PlaneMode SampleMode SamplesPerBunch AccumulatorMode BunchPattern TurnMarkerInterval}

proc SaveToFile {args} {
    # This procedure converts the user-edited RAM data from the widgets into
    # a RAM contents file that is either archived or loaded to the waveform RAM PVs
    # This procedure allows arbitrary bits to be loaded into the FPGA RAM
    # from the tcl waveform widgets of the GUI. So this allows completely 
    # arbitrary control of acquisition RAM.
    # This procedure cannot make use of sddsgencontrolbits because
    # sddsgencontrolbits is used only for preset bunch trains.
    set archive 1
    set Comment ""
    APSParseArguments {archive Comment}
    global globalVariables
    eval global $globalVariables
    
    set tmpfile /tmp/[APSTmpString]
    set PVname ${PVprefix}:AcqControlSetWF
    
    catch {exec timeconvert -now} timeList 
    set dt \
      [format %4ld-%03ld-%02ld%02ld-%02ld%02ld%02ld \
         [lindex $timeList 0] [lindex $timeList 1] \
         [lindex $timeList 2] [lindex $timeList 3] \
         [lindex $timeList 5] [lindex $timeList 6] \
         [lindex $timeList 7] ]
    set time [rpn expr "[lindex $timeList 8] int"]
    set timeStamp [clock format $time]
    set archiveFile $archiveDir/RAMControlRAM${dt}
    set archiveFile1 $archiveDir/scopeControlRAM${dt}
    if [catch {exec sddsmakedataset -pipe=out \
                 -para=Time,type=double  -data=$time \
                 -para=TimeStamp,type=string  -data=$timeStamp \
                 -para=WaveformPV,type=string -data=$PVname \
                 -para=Comment,type=string -data=[APSMakeSafeQualifierString $Comment] \
                 -para=PlaneMode0,type=string -data=$PlaneMode0 \
                 -para=PlaneMode1,type=string -data=$PlaneMode1 \
                 -para=PlaneMode2,type=string -data=$PlaneMode2 \
                 -para=PlaneMode3,type=string -data=$PlaneMode3 \
                 -para=AccumulatorMode0,type=string -data=$AccumulatorMode0 \
                 -para=AccumulatorMode1,type=string -data=$AccumulatorMode1 \
                 -para=AccumulatorMode2,type=string -data=$AccumulatorMode2 \
                 -para=AccumulatorMode3,type=string -data=$AccumulatorMode3 \
                 -para=SampleMode0,type=string -data=$SampleMode0 \
                 -para=SampleMode1,type=string -data=$SampleMode1 \
                 -para=SampleMode2,type=string -data=$SampleMode2 \
                 -para=SampleMode3,type=string -data=$SampleMode3 \
                 -para=BunchPattern0,type=string  -data=[APSMakeSafeQualifierString $BunchPattern0] \
                 -para=BunchPattern1,type=string  -data=[APSMakeSafeQualifierString $BunchPattern1] \
                 -para=BunchPattern2,type=string  -data=[APSMakeSafeQualifierString $BunchPattern2] \
                 -para=BunchPattern3,type=string  -data=[APSMakeSafeQualifierString $BunchPattern3] \
                 -para=SamplesPerBunch0,type=long -data=$SamplesPerBunch0 \
                 -para=SamplesPerBunch1,type=long -data=$SamplesPerBunch1 \
                 -para=SamplesPerBunch2,type=long -data=$SamplesPerBunch2 \
                 -para=SamplesPerBunch3,type=long -data=$SamplesPerBunch3 \
                 -para=TransitionDeadTime0,type=long -data=$TransitionDeadTime0 \
                 -para=TransitionDeadTime1,type=long -data=$TransitionDeadTime1 \
                 -para=TransitionDeadTime2,type=long -data=$TransitionDeadTime2 \
                 -para=TransitionDeadTime3,type=long -data=$TransitionDeadTime3 \
                 -para=TurnMarkerOffset,type=long -data=$TurnMarkerOffset \
                 -para=CommutationMode,type=string  -data=$CommutationMode \
                 -para=TurnsPerWrap,type=long -data=$TurnsPerWrap \
                 -col=PlaneSwitch0,type=long -data=[join $RAMPlaneSwitch0 ,] \
                 -col=PlaneSwitch1,type=long  -data=[join $RAMPlaneSwitch1 ,] \
                 -col=PlaneSwitch2,type=long  -data=[join $RAMPlaneSwitch2 ,] \
                 -col=PlaneSwitch3,type=long  -data=[join $RAMPlaneSwitch3 ,] \
                 -col=CommutationNegate,type=long -data=[join $RAMCommutationNegate ,] \
                 -col=CommutationSwitch,type=long -data=[join $RAMCommutationSwitch ,] \
                 -col=Sample0,type=long  -data=[join $RAMSample0 ,] \
                 -col=Sample1,type=long -data=[join $RAMSample1 ,] \
                 -col=Sample2,type=long -data=[join $RAMSample2 ,] \
                 -col=Sample3,type=long -data=[join $RAMSample3 ,] \
                 -col=TurnMarker,type=long -data=[join $RAMTurnMarker ,] \
                 -col=WrapMarker,type=long  -data=[join $RAMWrapMarker ,] \
                 -col=Accumulator0,type=long -data=[join $RAMAccumulator0 ,] \
                 -col=Accumulator1,type=long -data=[join $RAMAccumulator1 ,] \
                 -col=Accumulator2,type=long  -data=[join $RAMAccumulator2 ,] \
                 -col=Accumulator3,type=long  -data=[join $RAMAccumulator3 ,] \
                 -col=SaveSample,type=long -data=[join $RAMSaveSample ,] \
                 -col=SelfTest,type=long -data=[join $RAMSelfTest ,] \
                 | sddsprocess -pipe=in  $tmpfile.RAMcontrolBits \
                 -def=col,Index,i_row,type=long } result] {
        return -code error "SaveToFile: $result"
    }
    
    # to set bit 31 in a signed long, we have to add (-1)*2^31
    if [catch {exec sddsprocess $tmpfile.RAMcontrolBits -pipe=out \
                 -filter=col,Index,0,[expr $RAMArrayLength -1] \
                 "-def=col,Waveform,PlaneSwitch0 Accumulator0 2 * + Sample0 4 * + PlaneSwitch1 8 * + Accumulator1 16 * + Sample1 32 * + PlaneSwitch2 64 * + Accumulator2 128 * + Sample2 256 * + PlaneSwitch3 512 * + Accumulator3 1024 * + Sample3 2048 * + CommutationNegate 2 14 pow * + CommutationSwitch 2 15 pow * +  SaveSample 2 28 pow * + SelfTest 2 29 pow * + TurnMarker 2 30 pow * + WrapMarker 2 31 pow * +,type=ulong" \
                 | sddsconvert -pipe  \
                 -retain=col,Index,Waveform \
                 | sddsbinarystring -pipe=in $tmpfile.controlRAM \
                 -col=Waveform} result] {
        return -code error "SaveToFile: $result"
    }
    if $archive {
        exec cp $tmpfile.controlRAM $archiveFile
    }
    APSAddToTmpFileList -ID controlRAM -fileList "$tmpfile.RAMcontrolBits $tmpfile.controlRAM"
    return $tmpfile.controlRAM
}

proc GenerateControlBits {args} {
    global globalVariables  
    eval global $globalVariables secondSampleDelay  secondSamplesPerBunch  includeSecondSample
    set setAll 0
    APSParseArguments {setAll} 
    set tmpFile /tmp/[APSTmpString]

    if ![string length $TurnMarkerInterval] {
        return -code error "Turn marker interval not provided.!"
    }
    if ![string length $TurnsPerWrap] {
        return -code error "Turns per wrap not provided."
    }
    
    #2048 is the post-trigger, len is the pattern length
    if {$TurnMarkerOffset>$TurnMarkerInterval} {
        set answer [APSMultipleChoice .warning -name "Incompatible turn marker offset/interval provided."  \
                      -returnList {Continue Abort} -labelList {Continue-Any-Way Abort} \
                      -question "The turn marker offset should be less than the turn marker interval. Otherwise, you will miss the sample points before the turn marker. Click continue if you want to continue anyway or abort."]
        if {$answer=="Abort"} {
            SetStatus "Generate control bits was aborted because of incompatible turn marker offset/interval."
            return
        }
    }
    set len [expr $TurnsPerWrap*$TurnMarkerInterval]
    if $len>=2048 {
        set offset [expr $len-2048]
    } else {
        for {set i 2} {$i<=36} {incr i} {
            set len0 [expr $i*$len]
            if $len0>=2048 {
                break
            }
        }
        set offset [expr $len0 - 2048]
        if {$offset<0} {
            SetStatus "The offset for scope RAM is <0, the control bits of scope might not be valid. Please check the turns per wrap or turn marker interval, they might be too small."
        }
    }
   
   # puts "offset: $offset"
   # set offset 220
   # set offset [expr $offset + $TurnMarkerInterval - 324]
   
    if $setAll {
        if {$SampleMode=="bunchpattern"} {
            SetStatus "Generating control bits for (possibly) modified preset configuration ..."
            # variable BunchPattern is data from BunchPattern column of preset RMS configuration file
            # $presetFile
            set sampleMode bunchPattern=$BunchPattern
            # puts $BunchPattern
        } else {
            SetStatus "Generating control bits for (possibly) modified configuration ..."
            set sampleMode $SampleMode
        }
        # wait for waveforms to update
       
        if [catch {exec sddsgencontrolbits $tmpFile -controlRAMFile=$tmpFile.RAM \
                     -RAMArrayLength=$RAMArrayLength -scopeArrayLength=$scopeArrayLength -turnsPerWrap=$TurnsPerWrap \
                     -planeMode=$PlaneMode -commutationMode=$CommutationMode \
                     "-sampleMode=$sampleMode" -samplesPerBunch=$SamplesPerBunch \
                     -turnMarkerOffset=$TurnMarkerOffset -transitionDeadTime=$TransitionDeadTime \
                     -scopeTriggerIndexOffset=$offset -turnMarkerInterval=$TurnMarkerInterval} result] {
            return -code error "GenerateControlBits: $result"
        }
        #update all bpms' parameters
        	foreach bpmIndex {0  1 2 3} {
	    global  PlaneMode$bpmIndex BunchPattern$bpmIndex SampleMode$bpmIndex SamplesPerBunch$bpmIndex \
		TransitionDeadTime$bpmIndex  AccumulatorMode$bpmIndex 
	    set PlaneMode$bpmIndex $PlaneMode
	    set BunchPattern$bpmIndex $BunchPattern
	    set SampleMode$bpmIndex $SampleMode
	    set SamplesPerBunch$bpmIndex $SamplesPerBunch
	    set TransitionDeadTime$bpmIndex $TransitionDeadTime
	    set AccumulatorMode$bpmIndex $AccumulatorMode
	}
    } else {
        set sampleOpt -sampleMode=
        set samplesOpt -samplesPerBunch=
        set planeOpt -planeMode=
        set transOpt -transitionDeadTime=$TransitionDeadTime0
        set tranDeadTime $TransitionDeadTime0
        if $includeSecondSample {
             set secondSampleOpt "-secondSampleBunch=delay=$secondSampleDelay,samplesPerBunch=$secondSamplesPerBunch"
        } else {
            set secondSampleOpt ""
        }
        
        for {set index 0} {$index<4} {incr index} {
            if {[set SampleMode$index]=="bunchpattern"} {
                append sampleOpt "bunchPattern=[set BunchPattern$index]"
            } else {
                append sampleOpt [set SampleMode$index]
            }
            append samplesOpt [set SamplesPerBunch$index]
            append planeOpt [set PlaneMode$index]
            if {$index<3} {
                append sampleOpt ,
                append samplesOpt ,
                append planeOpt ,
            }
            if {[set TransitionDeadTime$index]!=$tranDeadTime} {
                SetStatus "Warning: [lindex $bpmList $index] transition dead time is different from first bpm, set it to be the same."
                set TransitionDeadTime$index $tranDeadTime
            }
        }
        if [catch {eval exec  sddsgencontrolbits \
                     $tmpFile \
                     -RAMArrayLength=$RAMArrayLength -scopeArrayLength=$scopeArrayLength \
                     $secondSampleOpt \
                     $planeOpt -commutationMode=$CommutationMode -turnsPerWrap=$TurnsPerWrap \
                     \"$sampleOpt\" \"$samplesOpt\" \"$transOpt\" \
                     -turnMarkerOffset=$TurnMarkerOffset \
                     -scopeTriggerIndexOffset=$offset -turnMarkerInterval=$TurnMarkerInterval} result] {
            return -code error "GenerateControlBits: $result"
        }
    }
    
    # This will update global variables for immediate viewing
    # The scope readback will be a simulated one
    # The RAM contents displayed will be one that can be loaded
    # into the FPGA RAM.
    SetStatus "Generating RAM contents waveforms from parameters. Note that updated scope readbacks waveforms are *simulated* from the RAM contents shown..."
    loadControlBitsFromFile -filename $tmpFile -updateParam 0 -read 0
   
    global scopeWaveformStatus ramWaveformStatus
    set scopeWaveformStatus "Presets [clock format [clock seconds] -format "%H:%M:%S"]"
    set ramWaveformStatus "Presets [clock format [clock seconds] -format "%H:%M:%S"]"

    APSAddToTmpFileList -ID bpmViewer -fileList $tmpFile
    SetStatus "Done."
}

proc MakeArchiveFileList {args} {
    global status archiveDir
    
    set returnList 0
    APSParseArguments {returnList}
    
    SetStatus "Searching for archives..."; update
    if ![file exist $archiveDir/archiveList.sdds] {
        set oldDir [pwd]
        cd $archiveDir
        set fileList [glob -nocomplain RAMControlRAM*]
        if [catch {eval exec sddscombine $fileList -pipe=out \
                     | sddscollapse -pipe \
                     | sddssort -pipe=in -col=Time,decreasing archiveList.sdds } result] {
            return -code error "MakeArchiveFileList: $result"
        }
        cd $oldDir
    }
    set fileList [exec sdds2stream -col=Filename $archiveDir/archiveList.sdds]
    set commList [exec sdds2stream -col=Comment $archiveDir/archiveList.sdds]
    set itemList ""
    foreach file $fileList Comment $commList {
        lappend itemList [list $file $Comment]
    }
    return $itemList
}

proc UpdateArchiveListFile {} {
    global archiveDir
    if [file exists $archiveDir/archiveList.sdds] {
        file rename -force $archiveDir/archiveList.sdds $archiveDir/archiveList.sdds~
    }
    MakeArchiveFileList
}

proc adjustRange {args} {
    global adjuster scopeAdjusterList 
    set direction "none"
    set quantity ""
    set doAllScopeAdjusters 0
    set doAllRAMAdjusters 0
    set factor 1
    APSParseArguments {quantity direction factor doAllScopeAdjusters doAllRAMAdjusters}
    if {$quantity==""} {
        return -code error "adjustRange: quantity not specified."
    }
    if {$direction==""} {
        return -code error "adjustRange: direction not specified."
    }
    
    set w $adjuster($quantity)
    set xmin [expr {round([$w xaxis cget -min])}]
    set xmax [expr {round([$w xaxis cget -max])}]
    set width [expr $xmax - $xmin]
    set xLoLimit 0
    set xHiLimit 4096
    set padding 1
    switch $direction {
        right  {
            set newMin [expr $xmin + $factor * $width]
            set newMax [expr $xmax + $factor * $width]
            if {$newMax > $xHiLimit} {
                set newMax $xHiLimit
                set newMin [expr $xHiLimit - $width]
            }
        }
        left {
            set newMin [expr $xmin - $factor * $width]
            set newMax [expr $xmax - $factor * $width]
            if {$newMin < $xLoLimit} {
                set newMin $xLoLimit
                set newMax [expr $xLoLimit + $width]
            }
        }
        default {
            # do nothing
            set newMin $xmin
            set newMax $xmax
        }
    }
    if {!$doAllScopeAdjusters && !$doAllRAMAdjusters} {
        $w xaxis configure -min [expr $newMin - $padding] -max [expr $newMax - $padding]
    } else {
        # determine whether the widget $w is a scope adjuster or an RAM adjuster
        if {-1 < [lsearch $scopeAdjusterList $w]} {
            foreach item $scopeAdjusterList {
                $item xaxis configure -min [expr $newMin - $padding] -max [expr $newMax - $padding]
            }
        }
    }
}

proc center {args} {
    global adjuster scopeAdjusterList TurnMarkerInterval
    set width 648
    set quantity ""
    set doAllScopeAdjusters 0
    set doAllRAMAdjusters 0
    set centerReference 2048
    set turns 1
    APSParseArguments {quantity width doAllScopeAdjusters doAllRAMAdjusters turns}
    if {$quantity==""} {
        return -code error "center: quantity not specified."
    }
    
    set w $adjuster($quantity)
    set xLoLimit 0
    set xHiLimit 4096
    set padding 1
    set width [expr $turns * $TurnMarkerInterval]
    set newMin [expr $centerReference - $width/2]
    set newMax [expr $centerReference + $width/2]
    if {$newMax > $xHiLimit} {
        set newMax $xHiLimit
    }
    if {$newMin < $xLoLimit} {
        set newMin $xLoLimit
    }
    if {!$doAllScopeAdjusters} {
        $w xaxis configure -min [expr $newMin - $padding] -max [expr $newMax - $padding]
    } else {
        # determine whether the widget $w is a scope adjuster or an RAM adjuster
        if {-1 < [lsearch $scopeAdjusterList $w]} {
            foreach item $scopeAdjusterList {
                $item xaxis configure -min [expr $newMin - $padding] -max [expr $newMax - $padding]
            }
        }
    }
}

proc plotScopeData {args} {
    global adjuster
    global outputDir root fileIndex
    
    APSParseArguments {quantity bpmIndex}

    set file $outputDir/$root-[format %03ld $fileIndex]

    # determine range of adjuster
    set w $adjuster($quantity)
    set xmin [expr {round([$w xaxis cget -min])}]
    set xmax [expr {round([$w xaxis cget -max])}]
    global scopePlaneSwitch$bpmIndex scopeAccumulator$bpmIndex scopeSample$bpmIndex scopeCommutationSwitch scopeCommutationNegate
    global readbacks$bpmIndex sums$bpmIndex
    eval global $quantity
    set tmpFile /tmp/[APSTmpString]
    if [catch {exec sddsmakedataset -pipe=out \
		   -col=readbacks,type=double -data=[join [set readbacks$bpmIndex] ,] \
		   -col=sums,type=double -data=[join [set sums$bpmIndex] ,] \
		   -col=scopePlaneSwitch$bpmIndex,type=long -data=[join [set scopePlaneSwitch$bpmIndex] ,] \
		   -col=scopeAccumulator$bpmIndex,type=long -data=[join [set scopeAccumulator$bpmIndex] ,] \
		   -col=scopeSample$bpmIndex,type=long -data=[join [set scopeSample$bpmIndex] ,] \
		   -col=scopeCommutationSwitch,type=long -data=[join $scopeCommutationSwitch ,] \
		   -col=scopeCommutationNegate,type=long -data=[join $scopeCommutationNegate ,] \
		   | sddsprocess -pipe=in "-define=col,Index,i_row,type=long" $tmpFile } result] {
	return -code error $result
    }
    exec sddsplot $tmpFile -scale=$xmin,$xmax,0,0 -col=Index,sums -col=Index,readbacks \
	-col=Index,scope* -leg -yscale=namestring -grap=line,vary,thick=2 -stagger=yincr=0.01,data $tmpFile &
    return
    exec sddsplot \
      -scale=$xmin,$xmax,0,0 \
      -col=Index,Waveform -leg=spec=Delta \
      $file.delta \
      -yscale=id=delta \
      -col=Index,(PlaneSwitch,Accumulator,Sample,CommutationSwitch,CommutationNegate) \
      $file -match=para,RecordType=scope \
      -grap=line,vary,thick=2 -leg -stagger=yincr=0.01,data \
      -ylabel=Flags \
      -yscale=id=aflags \
      -end \
      \
      -col=Index,Waveform -leg=spec=Sum \
      $file.sum \
      -yscale=id=sum \
      -col=Index,(PlaneSwitch,Accumulator,Sample,CommutationSwitch,CommutationNegate) \
      $file -match=para,RecordType=scope \
      -grap=line,vary,thick=2 -leg -stagger=yincr=0.01,data \
      -ylabel=Flags \
      -yscale=id=aflags \
      -end \
      \
      -col=Index,Waveform -leg=spec=Sum \
      $file.delta \
      -yscale=id=sum \
      -col=Index,(PlaneSwitch,CommutationSwitch) \
      $file -match=para,RecordType=scope \
      -grap=line,vary,thick=2 -leg -stagger=yincr=0.01,data \
      -ylabel=Flags \
      -yscale=id=aflags \
      &
}

proc UpdateTurnsPerWrap {args} {
    set index ""
    APSParseArguments {index}
    global PlaneMode  CommutationMode TurnsPerWrap  PlaneMode0  PlaneMode1 PlaneMode2 PlaneMode3 TurnMarkerInterval
    global turnMarkerList turns
    
    set turns0 $turns
    GetTurns -index $index
    
    if {$turns!=$turns0} {
        # set TurnsPerWrap $turns
       # set TurnMarkerInterval ""
        GenerateTurnsWidget -turns $turns
    }
    #  if [string length $TurnMarkerInterval] {
    #      
    #  }
}

proc GetTurns {args} {
    set index ""
    APSParseArguments {index}
    global turns PlaneMode CommutationMode PlaneMode0 PlaneMode1 PlaneMode2 PlaneMode3
    if ![string length $index] {
        set planeMode $PlaneMode
    } else {
        set planeMode [set PlaneMode$index]
    }
    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
    }
    return $turns
}

proc GenerateTurnsWidget {args} {
    global turnParent turnMarkerList turns
    GetTurns
    
    switch $turns {
        1 {
            set turnMarkerList {27 28 30 32 33  36 40 42 44 45 48 54 60 63 66 72 \
                                  81 84 90 96 99 108 120 126 132 135 144 162 180 189 198 \
                                  216 243 252 270 288 297 324 360 378 396 405 432 486 540 \
                                  567 594 648 729 756 810 864 891 972 1080 1134 1188 1296 \
                                  1458 1620 1782 1944 2268 2592 2916 3240 3564 3888} 
        }
        2 {
            set turnMarkerList {30 33 36 42 45\
                                  54 63 66 72 81 90 99 108 126 135 144 162 \
                                  180 189 198 216 243 270 297 324 378 405 432 486 540 567 594 \
                                  648 729 810 891 972 1134 1296 1458 1620 1782 \
                                  1944}
            
        }
        4 {
            set turnMarkerList {30 33 36 45 \
                                   54   63   72  81 90 108  135 162  189  216 \
                                  243 270  297 324 405  486  567 648 729 810 891 972}
        }
    }
    if [winfo exist $turnParent] {
        destroy $turnParent.period
        destroy $turnParent.wrap
    }
    global TurnMarkerInterval
    set index [lsearch -exact $turnMarkerList $TurnMarkerInterval]
    APSComboboxFrame .period -parent $turnParent -label "Turn marker interval" \
      -packOption "-fill x" \
      -textVariable TurnMarkerInterval \
      -itemList $turnMarkerList \
      -width 58 \
      -editable 1 \
      -callback "GenerateWrapWidget -index"
    GenerateWrapWidget -index $index
}

proc GenerateWrapWidget {args} {
    global turnParent TurnMarkerInterval TurnsPerWrap PlaneMode CommutationMode turns turnMarkerList bpmType
    set index ""
    APSParseArguments {index}
    set TurnsPerWrap ""
    if [winfo exist $turnParent.wrap] {
        destroy $turnParent.wrap
    }
    GetTurns
    if {![string length $index] || $index<0} {
        if ![string length $TurnMarkerInterval] {
            puts stderr "The turn marker interval not provided."
            return
        }
    } else {
        set TurnMarkerInterval [lindex $turnMarkerList $index]
    }
    set itemList ""
    
    for {set i 1} {$i<150} {incr i} {
        set len [expr $turns*$i*$TurnMarkerInterval]
        if {$len>3888} {
            break
        }
        if {[expr $len%324]==0} {
            if {$bpmType=="Booster"} {
                lappend itemList [expr $i*$turns/3]
            } else {
                lappend itemList [expr $i*$turns]
            }
        }
    }
   
    if ![llength $itemList] {
        APSInfoWindow .info -name "Wrong turn marker interval" -infoMessage "Wrong turn marker interval provided." -modal 1
        return
    }
    set TurnsPerWrap [lindex $itemList 0]
    APSComboboxFrame .wrap -parent $turnParent -label "Turns Per Wrap" \
      -packOption "-fill x" \
      -textVariable TurnsPerWrap \
      -itemList $itemList \
      -width 58 \
      -editable 1
   
}

proc StopResumeStartBoosterBPMAverage {args} {
    set action ""
    APSParseArguments {action}

    global PVprefix
    
    switch $action {
        stop {
            set event 25
            set state 0
            set scopetrigger event
        }
        resume {
         #   set event 4
            set event 28
            set state 1
            set scopetriiger wrap
        }
        default {
            return -code error "Invalid action - $action given."
        }
    }
    if [catch {exec cavput -list=${PVprefix}:startRamp_er.ENM=$event,${PVprefix}:intervalAvg:AutoRestart=$state,${PVprefix}:scope:gtr:trigger=$scopetrigger \
                 -pend=20 } result] {
        return -code error "Error setting startRamp_er.ENM and intervalAvg:AutoRestart : $result"
    }
    if {$action=="resume"} {
        if [catch {exec cavput -list=${PVprefix}:turn:gtr:arm=1 -pend=20} result] {
            return -code error "Unable to arm $PVprefix : $result"
        }
    }
}

proc SetADCDelay {args} {
    set bpmIndex ""
    APSParseArguments {bpmIndex}
    global adcDelay$bpmIndex bpmList bpmType
    set bpm [lindex $bpmList $bpmIndex]
    if {$bpmType!="Booster"} {
        #only set it booster bpms
        return
    }
    set delay [set adcDelay$bpmIndex]
    if {$delay<0 || $delay} {
        return -code error "Error: invalid adcDelay entered ($delay), the ADC delay has to be 0-10"
    }
    if [catch {exec cavput -list=${bpm}:adcDelay=$delay -pend=20} result] {
        return -code error "Error setting adc delay: $result"
    }
    if [catch {exec cavget -list=${bpm}:adcDelay -pend=20} delay1] {
        return -code error "Error reading adc delay: $delay1"
    }
    if {$delay1!=$delay} {
        SetStatus "The adc delay of $bpm was not changed to $delay."
        set adcDelay$bpmIndex $delay1
        return
    }
}
#GUI starts from here

APSApplication . -name "BPM Waveform Viewer and Control Bits Editor" \
  -version $CVSRevisionAuthor \
  -overview "BPM Waveform Viewer and Control Bits Editor."
if {$tcl_platform(os) == "Linux"} {
    if [catch {exec dnsdomainname} domain] {
        set domain [exec domainname]
    }
} else {
   set domain [exec domainname]
}
switch $domain {
    aps4.anl.gov -
    accel.ntw0rk {
        if [regexp S42 $PVprefix] {
            puts stderr "In domain $domain the PVs are of type S38B:P*. The PVprefix $PVprefix selection may not exist. If the program hangs up try a different type."
        }
    }
    (none) -
    aps.anl.gov -
    cntrl.ntw0rk {
        if [regexp S38 $PVprefix] {
            puts stderr "In domain $domain the PVs are of type S42B:P*. The PVprefix $PVprefix selection may not exist. If the program hangs up try a different type."
        }
        # check environment variables
        global env
        if {-1 < [lsearch [array names env] EPICS_CA_ADDR_LIST]} {
            puts stderr "The environment variable EPICS_CA_ADDR_LIST is defined. It may be necessary to change its value or unset it if some channel access error occurs in starting this GUI."
        }
        if {-1 < [lsearch [array names env] EPICS_CA_AUTO_ADDR_LIST]} {
            puts stderr "The environment variable EPICS_CA_AUTO_ADDR_LIST is defined. It may be necessary to change its value or unset it if some channel access error occurs in starting this GUI."
        }
    }
}

set bpmList [exec sddsprocess /home/helios/oagData/SCR/requestFiles/SBPMWaveform.config \
		 -match=par,IOCName=$PVprefix -pipe=out | sdds2stream -pipe -col=BPM]
set bpmType [exec sddsprocess /home/helios/oagData/SCR/requestFiles/SBPMWaveform.config \
                 -match=par,IOCName=$PVprefix -pipe=out | sdds2stream -pipe -par=BPMType]
if {$bpmType=="Booster"} {
    set presetFile /home/helios/oagData/sr/BPMcontrolRAM/boosterPresetConfigurations
    set TurnMarkerInterval 108
} else {
    set presetFile /home/helios/oagData/sr/BPMcontrolRAM/presetConfigurations
    set TurnMarkerInterval 324
}
if [catch {sdds load $presetFile presetConfigurationData} result] {
    puts stderr $result
    exit 1
}
set presetConfigurationLabelList [lindex $presetConfigurationData(Column.Label) 0]
#set pvList ""
#set scopeList ""
#set ramList ""
#foreach bpm $bpmList {
#    lappend pvList ${PVprefix}:$bpm
#    lappend scopeList ${PVprefix}:$bpm
#    lappend ramList ${PVprefix}:$bpm
#}
set pvList $bpmList
set scopeList $bpmList
set ramList $bpmList
set tabList {Scope RAM CommonBits Status}
set scopeCommList {"scope Commutation" "scope Commutation Negate"}
set ramCommList {"RAM Commutation" "RAM Commutation Negate" "RAM Save Sample" "RAM Self Test" "RAM Turn Marker" "RAM Wrap Marker"}


set parent .userFrame
APSFrame .generalControls -parent $parent
set doAllScopeAdjusters 1
set doAllRAMAdjusters 1
APSCheckButtonFrame  .checkScope -parent $parent.generalControls.frame  -label "" \
  -packOption "-side left" \
  -buttonList {"Couple all scope waveform adjusters"} \
  -variableList "doAllScopeAdjusters" \
  -contextHelp "If selected then all scope-related adjusters are redrawn with the range of the adjuster selected."
APSCheckButtonFrame  .checkRAM -parent $parent.generalControls.frame  -label "" \
  -packOption "-side left" \
  -buttonList {"Couple all RAM waveform adjusters"} \
  -variableList "doAllRAMAdjusters" \
  -contextHelp "If selected then all RAM-related adjusters are redrawn with the range of the adjuster selected."


set width 1500
set height 780
set height 670
set topIndex -1
set adjusterHeight 100
# this is critical if too high, then the contol buttons below the waveform widget disappear
set dataHeight 280
set outputDir /tmp/[APSTmpString]
set root monopulseBPM
set fileIndex -1

set widgetList [APSTabFrame .top -parent .userFrame -label "" -frameIndexVariable topIndex\
                  -labelList $tabList -width $width -height $height ]


set scopeWidget [lindex $widgetList 0]
set ramWidget [lindex $widgetList 1]
set commWidget [lindex $widgetList 2]
set statusWidget [lindex $widgetList 3]
GetWaveforms
set scopeFrameIndex -1
set ramFrameIndex -1

# scope->bpm1
# scope->bpm2
# scope->bpm3
# scope->bpm4
set scopeWidgetList [APSTabFrame .scope -parent $scopeWidget -label "" -frameIndexVariable scopeFrameIndex \
                       -commandList [APSReplicateItem -item SelectTabFrames -number [llength $scopeList]] \
                        -labelList $scopeList -width $width -height $height ]

# ram->bpm1
# ram->bpm2
# ram->bpm3
# ram->bpm4
set ramWidgetList [APSTabFrame .ram -parent $ramWidget -label "" -frameIndexVariable ramFrameIndex \
                     -commandList [APSReplicateItem -item SelectTabFrames -number [llength $scopeList]] \
                     -labelList $ramList -width $width -height $height]

# commonBits->"scope Commutation"
# commonBits->"scope Commutation negate"
set scopeCommWidgetList [APSTabFrame .scope -parent $commWidget -label "" \
                            -labelList $scopeCommList -width $width -height 280]

# commonBits->"RAM commutation"
# commonBits->"RAM commutation Negate"
# etc.
set ramCommWidgetList [APSTabFrame .ram -parent $commWidget -label "" \
                            -labelList $ramCommList -width $width -height 280]

MakeScopeCommonBitsWidget -widgetList $scopeCommWidgetList
MakeRAMCommonBitsWidget -widgetList $ramCommWidgetList

set index 0
set labelList {Sample Plane Accumulator}

foreach pv $pvList {
    set scopeBpmFrameIndex$index -1
    set scopeDataFrameIndex$index -1
    set ramDataFrameIndex$index -1
    set ramBpmFrameIndex$index -1
    set w0 [lindex $scopeWidgetList $index]
    set w1 [lindex $ramWidgetList $index]
    set scopeFrameParent$index $w0
    set ramFrameParent$index $w1

# Scope->bpm1->Sample
# Scope->bpm1->Plane
# Scope->bpm1->Accumulator
   set scopeTop${index}WidgetList [APSTabFrame .bpm -parent $w0 -label "" \
                                     -frameIndexVariable scopeBpmFrameIndex$index \
                                     -labelList $labelList -width $width -height 200 ]
    MakeBPMBitWidget -bpmIndex $index -type scope -widgetList [set scopeTop${index}WidgetList] -type scope
    
# RAM->bpm1->Sample
# RAM->bpm1->Plane
# RAM->bpm1->Accumulator
    set ramTop${index}WidgetList [APSTabFrame .bpm -parent $w1 -label "" \
                                    -frameIndexVariable ramBpmFrameIndex$index \
                                    -labelList $labelList -width $width -height 200]
    MakeBPMBitWidget -bpmIndex $index -type RAM -widgetList [set ramTop${index}WidgetList] -type RAM

# Scope->bpm1->Data
# Scope->bpm1->Sum
# Scope->bpm1->Preset
    set data${index}WidgetList [APSTabFrame .data -parent $w0 -label "" \
				    -frameIndexVariable scopeDataFrameIndex$index \
				    -labelList "Data Sum Presets" -width $width -height 350 ]
    MakeBPMDataWidget -bpmIndex $index -widgetList [set data${index}WidgetList]

# RAM->bpm1->Data
# RAM->bpm1->Sum
# RAM->bpm1->Preset
    set data${index}WidgetList1 [APSTabFrame .data -parent $w1 -label "" \
				     -frameIndexVariable ramDataFrameIndex$index\
				     -labelList "Data Sum Presets" -width $width -height 350 ]
    MakeBPMDataWidget -bpmIndex $index -widgetList [set data${index}WidgetList1] 

# These two widgets are the same. They use the same variables.
    MakePresetWidget -bpmIndex $index -parent [lindex [set data${index}WidgetList] 2]
    MakePresetWidget -bpmIndex $index -parent [lindex [set data${index}WidgetList1] 2]
    incr index
}
set widgetList2 [APSTabFrame .bottom -parent .userFrame -label "" \
                   -labelList {"Get Waveforms" "Read/Set common presets"  "Save" "Load RAM"} \
                   -width $width \
                   -height 220]
set waveWidget [lindex $widgetList2 0]
set presetWidget [lindex $widgetList2 1]
set saveWidget [lindex $widgetList2 2]
set loadWidget [lindex $widgetList2 3]

APSScrolledStatus .status -parent $statusWidget -textVariable status -width 150 \
    -height 5 -packOption "-fill both -expand true" 

MakeReadWaveformWidget -parent $waveWidget
MakeCommonPresetWidget -parent $presetWidget
MakeSaveWidget -parent $saveWidget
MakeLoadWidget -parent $loadWidget

# Local Variables:
# mode: tcl
# indent-tabs-mode: nil
# End:
