#!/bin/sh  
# \
exec oagtclsh "$0" "$@"

set auto_path [linsert $auto_path 0  /usr/local/oag/apps/lib/$env(HOST_ARCH)]
set auto_path [linsert $auto_path 0 /usr/local/oag/lib_patch/$env(HOST_ARCH)]

APSStandardSetup
set args $argv

set command0 ":WAVEFORM:DATA?"
set instName ""
set filename ""
set ring PAR
set verbose 0
set readMux 0
set lastSegment -1
set overwrite 0
set timeColumn 0
set comment "None provided"
APSParseArguments {filename ring verbose readMux lastSegment overwrite comment instName timeColumn}

set errorMessage "Usage: $argv0 -filename <filename> \[-ring <PAR|SR> || -instName <IP address>] \[-verbose 1] \[-readMux 1] \[-lastSegment <num>] \[-overwrite 1] \[-comment <string>]"
if {[string length $filename] == 0 } {
    puts stderr $errorMessage
    exit
}
if {[file exists $filename] && !$overwrite} { 
    puts stderr "In use: $filename"
    exit
}

if ![string length $instName] {
    switch $ring {
        SR {
            set instName "164.54.2.169"
            set instName "10.6.56.45"
           # set instName "164.54.0.253"
            if $readMux {
                set muxList [exec cavget -list=srscope -list=chan1,chan2,chan3,chan4]
            }
        }
        PAR {
            set instName "164.54.2.252"
            #par scope ID address changed to 10.6.56.31 10/5/2023 HS
	    set instName "10.6.56.31"
            if $readMux {
                set muxList [exec cavget -list=parscope -list=chan1,chan2,chan3,chan4,trig]
            }
            
        }
        default {
            puts stderr "getHP9000ScopeData: invalid ring ($ring) provided."
            exit 1
        }
    }
} else {
    set ring ""
}

set instrumentName $instName
set PeerPort 5025

if {[catch {socket $instrumentName $PeerPort} sid]} {
    puts "Error: Socket Could not be created: $sid"
    exit
}

#set the waveform data transfer mode to ASCII, this is important to read the channel waveform data.
puts $sid ":WAVEFORM:FORM ASC"

if $verbose { puts stderr "opened socket" }

fconfigure $sid -buffering line

# this is important for the scope to finish and not to delete the waveforms of an incomplete set of segments!
puts $sid ":Stop"

# parameters
if {$ring=="SR" || $ring=="PAR"} {
    set parameterList { {:TIMebase:POSition TimebasePosition SDDS_DOUBLE}
        {:TIMebase:RANGe TimebaseRange  SDDS_DOUBLE}
        {:TIM:DELAY TimeDelay SDDS_DOUBLE}
        {:TIMebase:SCALe TimebaseScale  SDDS_DOUBLE}
        {:ACQuire:SRATe:ANALog SampleRateAnalog SDDS_DOUBLE}
        {:ACQuire:SRATe SampleRate SDDS_DOUBLE}
        {:ACQuire:POINts Points SDDS_LONG}
        {:ACQuire:MODE AcquisitionMode SDDS_STRING}
        {:CHANnel1:INPut Channel1Input SDDS_STRING}}
} else {
    set parameterList { {:TIMebase:POSition TimebasePosition SDDS_DOUBLE}
        {:TIMebase:RANGe TimebaseRange  SDDS_DOUBLE}
        {:TIM:DELAY TimeDelay SDDS_DOUBLE}
        {:TIMebase:SCALe TimebaseScale  SDDS_DOUBLE}
        {:ACQuire:SRATe SampleRate SDDS_DOUBLE}
        {:ACQuire:POINts Points SDDS_LONG}
        {:ACQuire:MODE AcquisitionMode SDDS_STRING}
        {:CHANnel1:INPut Channel1Input SDDS_STRING}}
}
set peakDetect 0
set segmented 0
set segments 1
foreach parameter $parameterList {
    set command "[lindex $parameter 0]?"
    set parameterName [lindex $parameter 1]
    puts $sid "$command"
    gets $sid response 
    lappend data(ParameterNames) $parameterName
    set data(ParameterInfo.$parameterName) "type [lindex $parameter 2]"
    lappend data(ParameterTypes) [lindex $parameter 2]
    lappend data(ParameterUnits) ""
    lappend data(Parameter.$parameterName) $response
    if [string match $parameterName "AcquisitionMode"] {
        if {[string match $response "PDET"] || [string match $response "SEGP"]} {
            set peakDetect 1
        }
        if {[string match $response "SEGM"] || [string match $response "SEGP"]} {
            set segmented 1
            puts $sid ":WAVeform:SEGMented:COUNt?"
            gets $sid segments
        }
    }
    if [string match $parameterName "Points"] {
        set points $response
    }
}

if {$ring=="PAR" || $ring=="SR"} {
    for {set chan 1} {$chan<5} {incr chan} {
        set command ":CHAN${chan}:DISP:OFFS?"
        puts $sid "$command"
        gets $sid response
    #    puts "$command $response AAA"
        lappend data(ParameterNames) chan${chan}offset
        lappend data(ParameterTypes) "SDDS_DOUBLE"
        lappend data(Parameter.chan${chan}offset) $response
        lappend parameterList ":CHAN${chan}:DISP:OFFS chan${chan}offset"
        
        set command ":CHAN${chan}:DISP:RANG?"
        puts $sid "$command"
        gets $sid response
        lappend data(ParameterNames) chan${chan}range
        lappend data(ParameterTypes) "SDDS_DOUBLE"
        lappend data(Parameter.chan${chan}range) $response
        lappend parameterList ":CHAN${chan}:DISP:RANG chan${chan}range"
    }
}

if {[expr $lastSegment>0] && [expr $segments>$lastSegment]} {
    set segments $lastSegment
}

if $verbose { puts stderr "segments = $segments"}

if $segmented {
    # make parameters repeat for each page
    foreach parameter $parameterList {
        set parameterName [lindex $parameter 1]
        set parameterValue $data(Parameter.$parameterName)
        # start at 1 since we already have one element
        for {set i 1} {$i<$segments} {incr i} {
            lappend data(Parameter.$parameterName) $parameterValue
        }
    }
    puts $sid ":WAVeform:SEGMented:XLISt? TTAG"
    gets $sid response 
    if {[llength $response] == 0} {
        puts stderr "Weird. No data segments appears to have been acquired. Exiting."
        exit
    }
    lappend data(ParameterNames) "SegmentTime"
    set data(ParameterInfo.SegmentTime) "type SDDS_DOUBLE"
    lappend data(ParameterTypes) SDDS_DOUBLE
    lappend data(ParameterUnits) s
    set segment 0
    foreach item [lrange [split $response ","] 0 end-1] {
        lappend data(Parameter.SegmentTime) $item
        incr segment
        if [expr $segment>=$segments] break
    }
    puts $sid ":WAVEFORM:SEGMENTED:ALL ON"
}

if $readMux {
    switch $ring {
        SR {
            set index 0
            foreach channel [list Channel1 Channel2 Channel3 Channel4] {
                lappend data(ParameterNames) $channel
                lappend data(ParameterUnits) ""
                lappend data(ParameterTypes) SDDS_STRING
                set data(ParameterInfo.$channel) "type SDDS_STRING"
                for {set i 0} {$i<$segments} {incr i} {
                    lappend data(Parameter.$channel) [lindex $muxList $index]
                }
                incr index
            }
        }
        PAR {
            set index 0
            foreach channel [list Channel1 Channel2 Channel3 Channel4 ExternalTrigger] {
                lappend data(ParameterNames) $channel
                lappend data(ParameterUnits) ""
                lappend data(ParameterTypes) SDDS_STRING
                set data(ParameterInfo.$channel) "type SDDS_STRING"
                for {set i 0} {$i<$segments} {incr i} {
                    lappend data(Parameter.$channel) [lindex $muxList $index]
                }
                incr index
            }
        }
    }                
}

lappend data(ParameterNames) Comment
lappend data(ParameterTypes) SDDS_STRING
lappend data(ParameterUnits) ""
set data(ParameterInfo.Comment) "type SDDS_STRING"
for {set i 0} {$i<$segments} {incr i} {
    lappend data(Parameter.Comment) "$comment"
}

if $verbose {
    foreach parameter $data(ParameterNames) {
        puts stderr "$parameter: [llength $data(Parameter.$parameter)] items"
    }
}

set fid [sdds open $filename w SDDS_BINARY]
foreach parameter $data(ParameterNames) type $data(ParameterTypes) units $data(ParameterUnits) {
    if $verbose { puts stderr "sdds defineParameter $fid $parameter -type $type -units $units" }
    sdds defineParameter $fid $parameter -type $type -units "$units"
}
for {set chan 1 } { $chan < 5 } {incr chan } {
    if $verbose { puts stderr "Checking for data on channel $chan"}
    set command ":CHANNEL$chan:DISPLAY?"
    puts $sid "$command"
    gets $sid response 
    if {$response == 0} {
        set chanData($chan) 0
        continue
    }
    set chanData($chan) 1
    if {!$peakDetect} {
        lappend data(ColumnNames) Channel$chan
        set data(ColumnInfo.Channel$chan) "type SDDS_FLOAT"
    } else {
        lappend data(ColumnNames) Channel${chan}Min
        set data(ColumnInfo.Channel${chan}Min) "type SDDS_FLOAT"
        lappend data(ColumnNames) Channel${chan}Max
        set data(ColumnInfo.Channel${chan}Max) "type SDDS_FLOAT"
    }
}
foreach column $data(ColumnNames) {
    sdds defineColumn $fid $column -type SDDS_FLOAT -units V
}
sdds writeLayout $fid

if {!$segmented && [string length $ring]} {
    sdds startPage $fid $points
    foreach parameter $data(ParameterNames) {
        if $verbose {
            puts stderr "Setting data for parameter $parameter"
        }
        sdds setParameter $fid $parameter [lindex $data(Parameter.$parameter) 0]
    }
}

set indexList ""
for {set chan 1 } { $chan < 5 } {incr chan } {
    if {$chanData($chan) == 0} {
        continue
    }
    if $verbose { puts stderr "Acquiring data on channel $chan (1)"}
    set command ":WAVEFORM:SOURCE CHANNEL$chan"
    puts $sid "$command"
    set command $command0
    #puts "Sending query: ${command}"
    puts $sid "$command" 
    gets $sid response
    if $verbose { puts stderr "Acquiring data on channel $chan (2)"}
    set response [string trim $response]
    if ![string length $response] {
        puts stderr "no data for channel $chan."
        continue
    }
    set astring [string trim [split $response ,]]
    unset response

    if $verbose { puts stderr "Acquiring data on channel $chan (3)"}
    if {!$peakDetect && !$segmented} {
        if {!$segmented && [string length $ring]} {
            eval sdds setColumn $fid Channel$chan [lrange $astring 0 end-1]
        } else {
            lappend data(Column.Channel${chan})  [lrange $astring 0 end-1]
        }
    } elseif {$peakDetect && !$segmented} {
        if {!$segmented && [string length $ring]} {
            eval sdds setColumn $fid Channel${chan}Min [lrange $astring 0 [expr $points-1]]
            eval sdds setColumn $fid Channel${chan}Max [lrange $astring $points end-1]
        } else {
            lappend data(Column.Channel${chan})  [lrange $astring 0 end-1]
        }
    } elseif {!$peakDetect && $segmented} {
        for {set i 0} {$i < $segments} {incr i} {
            set begin [expr $i * $points]
            set end   [expr ($i+1) * $points - 1]
            if $verbose { puts stderr "channel $chan, segment $i: [llength [lrange $astring $begin $end]] points" }
            lappend data(Column.Channel${chan}) [lrange $astring $begin $end]
        }
    } elseif {$peakDetect && $segmented} {
        for {set i 0} {$i<$segments} {incr i} {
            set begin1 [expr 2 * $i * $points]
            set end1   [expr (2 * $i + 1) * $points - 1]
            set begin2 [expr (2 * $i + 1) * $points]
            set end2   [expr (2 * $i + 2) * $points - 1]
            if $verbose { puts stderr "channel $chan, segment $i, Min: [llength [lrange $astring $begin1 $end1]] points" }
            if $verbose { puts stderr "channel $chan, segment $i, Max: [llength [lrange $astring $begin2 $end2]] points" }
            lappend data(Column.Channel${chan}Min) [lrange $astring $begin1 $end1]
            lappend data(Column.Channel${chan}Max) [lrange $astring $begin2 $end2]
        }
    }
    unset astring
    if {!$segments} {
        set pages 1
    } else {
        set pages $segments
    }
    for {set n 0} {$n < $pages} {incr n} {
        # Bob, is something supposed to happen here?
    }
    if $verbose { puts stderr "Done acquiring data on channel $chan"}
}
#  set arraynames [array names data]
#  foreach name $arraynames {
#      puts stderr "$name [llength $data($name)]"
# }

puts $sid ":RUN"
#puts $sid ":RUN"
catch {close $sid}
if $verbose { puts stderr "Writing data to file" }
set data(Layout.DataMode.Mode) binary
if {0} {
    if [catch {sdds save $filename data} result] {
        puts stderr "getHP9000ScopeData: Error saving file: $result"
        exit 1
    }
} else {
    if {!$segmented && [string length $ring]} {
        sdds writePage $fid
        sdds close $fid
    } else {
        set column1 [lindex $data(ColumnNames) 0]
        set pages [llength $data(Column.$column1)]
        for {set n 0} {$n < $pages} {incr n} {
            if $verbose { puts stderr "** Page $n" }
            set rows [llength [lindex $data(Column.$column1) $n]]
            sdds startPage $fid $rows
            foreach parameter $data(ParameterNames) {
                if $verbose {
                    puts stderr "Setting data for parameter $parameter"
                }
                if [catch {sdds setParameter $fid $parameter [lindex $data(Parameter.$parameter) $n]} results] {
                    puts stderr "problem with sdds setParameter:  $parameter \"[lindex $data(Parameter.$parameter) $n]\"\n$results"
                    exit
                }
            }
            foreach column $data(ColumnNames) {
                if $verbose {
                    puts stderr "Setting data for column $column"
                }
                eval sdds setColumn $fid $column [lindex $data(Column.$column) $n]
            }
            sdds writePage $fid
        }
        sdds close $fid
    }
}

if $timeColumn {
    if [catch {exec sddsprocess $filename -redefine=col,Index,i_row,type=long -pipe=out \
                 | sddsprocess -pipe=in $filename.1 "-redefine=col,time,Index SampleRate / 1.0e9 *,units=ns" } result] {
        puts stderr "Error processing time column: $result"
        exit 1
    }
    exec mv $filename.1 $filename
}


exit


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

