Index: trunk/MultiChannelUSB/UserInterface.tcl
===================================================================
--- trunk/MultiChannelUSB/UserInterface.tcl	(revision 73)
+++ trunk/MultiChannelUSB/UserInterface.tcl	(revision 73)
@@ -0,0 +1,678 @@
+package require XOTcl
+
+package require BLT
+package require swt
+package require usb
+
+wm minsize . 900 720
+
+namespace eval ::mca {
+    namespace import ::xotcl::*
+
+    namespace import ::blt::vector
+    namespace import ::blt::graph
+    namespace import ::blt::tabnotebook
+
+    proc validate {value} {
+        if {![regexp {^[1-9][0-9]*$} $value]} {
+            return 0
+        } elseif {$value > 4095} {
+            return 0
+        } elseif {[string length $value] > 4} {
+            return 0
+        } else {
+            return 1
+        }
+    }
+
+# -------------------------------------------------------------------------
+
+    Class OscDisplay -parameter {
+        {number}
+        {master}
+    }
+
+# -------------------------------------------------------------------------
+
+    OscDisplay instproc init {} {
+        my instvar data xvec yvec
+
+        set xvec [vector #auto]
+        set yvec [vector #auto]
+        # fill one vector for the x axis with 1025 points
+        $xvec seq 0 1024
+
+        my reset
+
+        my setup
+
+        next
+    }
+
+# -------------------------------------------------------------------------
+
+    OscDisplay instproc destroy {} {
+        next
+    }
+
+# -------------------------------------------------------------------------
+
+    OscDisplay instproc reset {} {
+        my instvar data xvec yvec
+
+        dict set data none {}
+        dict set data uwt1 {}
+        dict set data uwt2 {}
+        dict set data uwt3 {}
+#        dict set data sum8 {}
+
+        $yvec set {}
+    }
+
+# -------------------------------------------------------------------------
+
+    OscDisplay instproc start {} {
+        my instvar config
+        
+        trace add variable [myvar auto] write [myproc auto_update]
+        trace add variable [myvar thrs] write [myproc thrs_update]
+        trace add variable [myvar fltr_val] write [myproc fltr_val_update]
+
+        ${config}.thrs_check deselect
+        ${config}.thrs_field set 10
+        ${config}.none select
+    }
+
+# -------------------------------------------------------------------------
+
+    OscDisplay instproc setup {} {
+        my instvar number master
+        my instvar data xvec yvec
+        my instvar config auto thrs thrs_val fltr_val
+
+        my set restart_command [usb::convert 0001000${number}00000000]
+        my set acquire_command [usb::convert 0002000${number}00000000]
+
+        # create a graph widget and show a grid
+        set graph [graph ${master}.graph -height 250 -leftmargin 80]
+        $graph crosshairs configure -hide no -linewidth 2 -dashes { 1 1 }
+        $graph grid configure -hide no
+        $graph legend configure -hide yes
+        $graph axis configure x -min 0 -max 1024
+
+        set config [frame ${master}.config]
+
+        checkbutton ${config}.auto_check -text {auto update} -variable [myvar auto]
+
+        frame ${config}.spc1 -width 10 -height 10
+
+        checkbutton ${config}.thrs_check -text threshold -variable [myvar thrs]
+        spinbox ${config}.thrs_field -from 1 -to 4095 \
+            -increment 5 -width 10 -textvariable [myvar thrs_val] \
+            -validate all -vcmd {::mca::validate %P}
+
+        frame ${config}.spc2 -width 10 -height 10
+
+        label ${config}.fltr -text {low-pass filter}
+        radiobutton ${config}.none -text none -variable [myvar fltr_val] -value none
+        radiobutton ${config}.uwt1 -text uwt1 -variable [myvar fltr_val] -value uwt1
+        radiobutton ${config}.uwt2 -text uwt2 -variable [myvar fltr_val] -value uwt2
+        radiobutton ${config}.uwt3 -text uwt3 -variable [myvar fltr_val] -value uwt3
+#        radiobutton ${config}.sum8 -text sum8 -variable [myvar fltr_val] -value sum8
+
+        frame ${config}.spc3 -width 10 -height 10
+
+        button ${config}.acquire -text Acquire \
+            -bg green -activebackground green -command [myproc acquire]
+        button ${config}.restart -text Restart \
+            -bg yellow -activebackground yellow -command [myproc restart]
+        button ${config}.register -text Register \
+            -bg lightblue -activebackground lightblue -command [myproc register]
+
+        grid ${config}.auto_check -sticky w
+        grid ${config}.spc1
+        grid ${config}.thrs_check -sticky w
+        grid ${config}.thrs_field -sticky ew -pady 1 -padx 5
+        grid ${config}.spc2
+        grid ${config}.fltr -sticky w -pady 1 -padx 3
+        grid ${config}.none -sticky w
+        grid ${config}.uwt1 -sticky w
+        grid ${config}.uwt2 -sticky w
+        grid ${config}.uwt3 -sticky w
+#        grid ${config}.sum8 -sticky w
+        grid ${config}.spc3
+        grid ${config}.acquire -sticky ew -pady 3 -padx 5
+        grid ${config}.restart -sticky ew -pady 3 -padx 5
+        grid ${config}.register -sticky ew -pady 3 -padx 5
+
+        grid ${graph} -row 0 -column 0 -sticky news
+        grid ${config} -row 0 -column 1
+
+        # enable zooming
+        Blt_ZoomStack $graph
+
+        #bind .graph <Motion> {%W crosshairs configure -position @%x,%y}
+
+        # create one element with data for the x and y axis, no dots
+        $graph element create Spectrum1 -symbol none -xdata $xvec -ydata $yvec
+    }
+
+# -------------------------------------------------------------------------
+
+    OscDisplay instproc auto_update args {
+        my instvar auto after_handle
+
+        if {$auto} {
+            ${config}.acquire configure -state disabled
+            ${config}.restart configure -state disabled
+            ${config}.register configure -state disabled
+
+            my acquire_restart_loop
+        } else {
+            if {[my exists after_handle]} {
+                after cancel $after_handle
+            }
+            ${config}.acquire configure -state active
+            ${config}.restart configure -state active
+            ${config}.register configure -state active
+        }
+    }
+
+# -------------------------------------------------------------------------
+
+    OscDisplay instproc thrs_update args {
+        my instvar config thrs
+        if {$thrs} {
+            ${config}.thrs_field configure -state normal
+        } else {
+            ${config}.thrs_field configure -state disabled
+        }
+    }
+
+# -------------------------------------------------------------------------
+
+    OscDisplay instproc fltr_val_update args {
+        my instvar yvec data fltr_val
+        $yvec set [dict get $data $fltr_val]
+    }
+
+# -------------------------------------------------------------------------
+
+    OscDisplay instproc save_data {data} {
+        set file [tk_getSaveFile]
+        if {[string equal $file {}]} {
+            return
+        }
+
+        set x [catch {set fid [open $file w+]}]
+        set y [catch {puts $fid $data}]
+        set z [catch {close $fid}]
+
+        if { $x || $y || $z || ![file exists $file] || ![file isfile $file] || ![file readable $file] } {
+            tk_messageBox -icon error \
+                -message "An error occurred while writing to \"$file\""
+        } else {
+            tk_messageBox -icon info \
+                -message "File \"$file\" written successfully"
+        }
+    }
+
+# -------------------------------------------------------------------------
+
+    OscDisplay instproc register {} {
+        my save_data [my set data]
+    }
+
+# -------------------------------------------------------------------------
+
+    OscDisplay instproc send_data {data} {
+        global usb_handle
+
+        if {[catch {$usb_handle writeRaw $data} result]} {
+            puts {Error during write}
+            puts $result
+        }
+    }
+
+# -------------------------------------------------------------------------
+
+    OscDisplay instproc restart {} {
+        my instvar restart_command
+        my send_data $restart_command
+    }
+
+# -------------------------------------------------------------------------
+
+    OscDisplay instproc acquire {} {
+        global usb_handle
+        my instvar xvec yvec data fltr_val
+        my instvar acquire_command
+
+        my send_data $acquire_command
+
+        set usb_data {}
+        if {[catch {$usb_handle readHex 2 1024} usb_data]} {
+            puts {Error during read}
+            puts $usb_data
+            set usb_data {}
+        }
+
+        dict set data none $usb_data
+        dict set data uwt1 [lindex [uwt 1 $usb_data] 1]
+        dict set data uwt2 [lindex [uwt 2 $usb_data] 1]
+        dict set data uwt3 [lindex [uwt 3 $usb_data] 1]
+#        dict set data sum8 [sum8 $usb_data]
+
+        $yvec set [dict get $data $fltr_val]
+    }
+
+# -------------------------------------------------------------------------
+
+    OscDisplay instproc acquire_restart_loop {} {
+        my instvar after_handle
+
+        my acquire
+        my restart
+
+        set after_handle [after 1000 [myproc acquire_restart_loop]]
+    }
+
+# -------------------------------------------------------------------------
+
+    Class HstDisplay -parameter {
+        {number}
+        {master}
+    }
+
+# -------------------------------------------------------------------------
+
+    HstDisplay instproc init {} {
+        my instvar data xvec yvec
+
+        set xvec [vector #auto]
+        set yvec [vector #auto]
+        # fill one vector for the x axis with 4097 points
+        $xvec seq 0 4096
+
+        my reset
+
+        my setup
+
+        next
+    }
+
+# -------------------------------------------------------------------------
+
+    HstDisplay instproc destroy {} {
+        next
+    }
+
+# -------------------------------------------------------------------------
+
+    HstDisplay instproc reset {} {
+        my instvar data xvec yvec
+
+        dict set data none {}
+        dict set data uwt1 {}
+        dict set data uwt2 {}
+        dict set data uwt3 {}
+#        dict set data sum8 {}
+
+        $yvec set {}
+    }
+
+# -------------------------------------------------------------------------
+
+    HstDisplay instproc start {} {
+        my instvar config peak_mux base_mux
+
+        set peak_mux 1
+        set base_mux 0
+
+        trace add variable [myvar auto] write [myproc auto_update]
+        trace add variable [myvar peak] write [myproc peak_update]
+        trace add variable [myvar thrs] write [myproc thrs_update]
+        trace add variable [myvar base] write [myproc base_update]
+        trace add variable [myvar base_typ] write [myproc base_typ_update]
+        trace add variable [myvar base_val] write [myproc base_val_update]
+
+        ${config}.auto_check select
+        ${config}.peak_check select
+        ${config}.thrs_check select
+        ${config}.thrs_field set 10
+        ${config}.base_check select
+        ${config}.base_const select
+        ${config}.base_field set 35
+    }
+
+# -------------------------------------------------------------------------
+
+    HstDisplay instproc setup {} {
+        my instvar number master
+        my instvar data xvec yvec
+        my instvar config auto thrs thrs_val base base_typ base_val
+
+        my set restart_command [usb::convert 0001001${number}00000000]
+        my set acquire_command [usb::convert 0002001${number}00000000]
+
+        # create a graph widget and show a grid
+        set graph [graph ${master}.graph -height 250 -leftmargin 80]
+        $graph crosshairs configure -hide no -linewidth 2 -dashes { 1 1 }
+        $graph grid configure -hide no
+        $graph legend configure -hide yes
+        $graph axis configure x -min 0 -max 4096
+
+        set config [frame ${master}.config]
+
+        checkbutton ${config}.auto_check -text {auto update} -variable [myvar auto]
+
+        frame ${config}.spc1 -width 10 -height 10
+
+        checkbutton ${config}.peak_check -text {peak detect} -variable [myvar peak]
+
+        frame ${config}.spc2 -width 10 -height 10
+
+        checkbutton ${config}.thrs_check -text threshold -variable [myvar thrs]
+        spinbox ${config}.thrs_field -from 1 -to 4095 \
+            -increment 5 -width 10 -textvariable [myvar thrs_val] \
+            -validate all -vcmd {::mca::validate %P}
+
+        frame ${config}.spc3 -width 10 -height 10
+
+        checkbutton ${config}.base_check -text baseline -variable [myvar base]
+        radiobutton ${config}.base_auto -text automatic -variable [myvar base_typ] -value auto
+        radiobutton ${config}.base_const -text constant -variable [myvar base_typ] -value const
+        spinbox ${config}.base_field -from 1 -to 4095 \
+            -increment 5 -width 10 -textvariable [myvar base_val] \
+            -validate all -vcmd {::mca::validate %P}
+
+        frame ${config}.spc4 -width 10 -height 10
+
+        button ${config}.acquire -text Acquire \
+            -bg green -activebackground green -command [myproc acquire]
+        button ${config}.restart -text Restart \
+            -bg yellow -activebackground yellow -command [myproc restart]
+        button ${config}.register -text Register \
+            -bg lightblue -activebackground lightblue -command [myproc register]
+
+        grid ${config}.auto_check -sticky w
+        grid ${config}.spc1
+        grid ${config}.peak_check -sticky w
+        grid ${config}.spc2
+        grid ${config}.thrs_check -sticky w
+        grid ${config}.thrs_field -sticky ew -pady 1 -padx 5
+        grid ${config}.spc3
+        grid ${config}.base_check -sticky w
+        grid ${config}.base_auto -sticky w
+        grid ${config}.base_const -sticky w
+        grid ${config}.base_field -sticky ew -pady 1 -padx 5
+        grid ${config}.spc4
+        grid ${config}.acquire -sticky ew -pady 3 -padx 5
+        grid ${config}.restart -sticky ew -pady 3 -padx 5
+        grid ${config}.register -sticky ew -pady 3 -padx 5
+
+        grid ${graph} -row 0 -column 0 -sticky news
+        grid ${config} -row 0 -column 1
+
+        # enable zooming
+        Blt_ZoomStack $graph
+
+        #bind .graph <Motion> {%W crosshairs configure -position @%x,%y}
+
+        # create one element with data for the x and y axis, no dots
+        $graph element create Spectrum1 -symbol none -smooth step -xdata $xvec -ydata $yvec
+    }
+
+# -------------------------------------------------------------------------
+
+    HstDisplay instproc auto_update args {
+        my instvar auto after_handle
+        my instvar config
+        if {$auto} {
+            ${config}.acquire configure -state disabled
+            ${config}.register configure -state disabled
+
+            my acquire_loop
+        } else {
+            if {[my exists after_handle]} {
+                after cancel $after_handle
+            }
+            ${config}.acquire configure -state active
+            ${config}.register configure -state active
+        }
+    }
+
+# -------------------------------------------------------------------------
+
+    HstDisplay instproc mux {} {
+        my instvar peak_mux base_mux
+
+        format {%x%x%x%x} $base_mux $peak_mux 0 0
+    }
+
+# -------------------------------------------------------------------------
+
+    HstDisplay instproc peak_update args {
+        my instvar number peak peak_mux
+
+        set mux_addr [format %04x [expr {20 + ${number}}]]
+
+        if {$peak} {
+            set peak_mux 1
+            my send_data [usb::convert ${mux_addr}[my mux]00000000]
+        } else {
+            set peak_mux 0
+            my send_data [usb::convert ${mux_addr}[my mux]00000000]
+        }
+    }
+
+# -------------------------------------------------------------------------
+
+    HstDisplay instproc thrs_update args {
+        my instvar config number thrs thrs_val
+
+        set val_addr [format %04x [expr {14 + ${number}}]]
+        set value [format %04x $thrs_val]
+
+        if {$thrs} {
+            ${config}.thrs_field configure -state normal
+            my send_data [usb::convert ${val_addr}${value}00000000]
+        } else {
+            ${config}.thrs_field configure -state disabled
+            my send_data [usb::convert ${val_addr}000000000000]
+        }
+    }
+
+# -------------------------------------------------------------------------
+
+    HstDisplay instproc thrs_val_update args {
+        my instvar config number thrs_val
+
+        set val_addr [format %04x [expr {14 + ${number}}]]
+        set value [format %04x $thrs_val]
+
+        ${config}.base_field configure -state normal
+        my send_data [usb::convert ${val_addr}${value}00000000]
+    }
+
+# -------------------------------------------------------------------------
+
+    HstDisplay instproc base_update args {
+        my instvar config number base base_val base_mux
+
+        set mux_addr [format %04x [expr {20 + ${number}}]]
+        set val_addr [format %04x [expr {11 + ${number}}]]
+
+        if {$base} {
+            ${config}.base_auto configure -state normal
+            ${config}.base_const configure -state normal
+            my base_typ_update
+        } else {
+            ${config}.base_auto configure -state disabled
+            ${config}.base_const configure -state disabled
+            ${config}.base_field configure -state disabled
+            set base_mux 0
+            my send_data [usb::convert ${mux_addr}[my mux]00000000${val_addr}000000000000]
+        }
+    }
+
+# -------------------------------------------------------------------------
+
+    HstDisplay instproc base_typ_update args {
+        my instvar config number base_typ base_val base_mux
+
+        set mux_addr [format %04x [expr {20 + ${number}}]]
+        set val_addr [format %04x [expr {11 + ${number}}]]
+        set value [format %04x $base_val]
+
+        switch -- $base_typ {
+            auto {
+                ${config}.base_field configure -state disabled
+                set base_mux 1
+                my send_data [usb::convert ${mux_addr}[my mux]00000000]
+            }
+            const {
+                ${config}.base_field configure -state normal
+                set base_mux 0
+                my send_data [usb::convert ${mux_addr}[my mux]00000000${val_addr}${value}00000000]
+            }
+        }
+    }
+
+# -------------------------------------------------------------------------
+
+    HstDisplay instproc base_val_update args {
+        my instvar number base_val
+
+        set val_addr [format %04x [expr {11 + ${number}}]]
+        set value [format %04x $base_val]
+
+        my send_data [usb::convert ${val_addr}${value}00000000]
+    }
+
+# -------------------------------------------------------------------------
+
+    HstDisplay instproc save_data {data} {
+        set file [tk_getSaveFile]
+        if {[string equal $file {}]} {
+            return
+        }
+
+        set x [catch {set fid [open $file w+]}]
+        set y [catch {puts $fid $data}]
+        set z [catch {close $fid}]
+
+        if { $x || $y || $z || ![file exists $file] || ![file isfile $file] || ![file readable $file] } {
+            tk_messageBox -icon error \
+                -message "An error occurred while writing to \"$file\""
+        } else {
+            tk_messageBox -icon info \
+                -message "File \"$file\" written successfully"
+        }
+    }
+
+# -------------------------------------------------------------------------
+
+    HstDisplay instproc register {} {
+        my save_data [my set data]
+    }
+
+# -------------------------------------------------------------------------
+
+    HstDisplay instproc send_data {data} {
+        global usb_handle
+
+        if {[catch {$usb_handle writeRaw $data} result]} {
+            puts {Error during write}
+            puts $result
+        }
+    }
+
+# -------------------------------------------------------------------------
+
+    HstDisplay instproc restart {} {
+        my instvar restart_command
+        my send_data $restart_command
+    }
+
+# -------------------------------------------------------------------------
+
+    HstDisplay instproc acquire {} {
+        global usb_handle
+        my instvar xvec yvec data fltr_val
+        my instvar acquire_command
+
+        my send_data $acquire_command
+
+        set usb_data {}
+        if {[catch {$usb_handle readHex 4 4096} usb_data]} {
+            puts {Error during read}
+            puts $usb_data
+            set usb_data {}
+        }
+
+        set data $usb_data
+
+        $yvec set $usb_data
+    }
+
+# -------------------------------------------------------------------------
+
+    HstDisplay instproc acquire_loop {} {
+        my instvar after_handle
+
+        my acquire
+
+        set after_handle [after 1000 [myproc acquire_loop]]
+    }
+
+# -------------------------------------------------------------------------
+
+    namespace export HstDisplay
+    namespace export OscDisplay
+}
+
+set notebook [::blt::tabnotebook .notebook -side bottom]
+
+pack $notebook -expand 1 -fill both
+
+set window [frame ${notebook}.hst_2]
+$notebook insert end -text "Histogram" -window $window -fill both
+::mca::HstDisplay hst_2 -number 2 -master $window
+
+grid rowconfigure $window 0 -weight 1
+grid columnconfigure $window 0 -weight 1
+grid columnconfigure $window 1 -weight 0 -minsize 80
+
+set window [frame ${notebook}.osc_2]
+$notebook insert end -text "Pulse shape" -window $window -fill both
+::mca::OscDisplay osc_2 -number 2 -master $window
+
+grid rowconfigure $window 0 -weight 1
+grid columnconfigure $window 0 -weight 1
+grid columnconfigure $window 1 -weight 0 -minsize 80
+
+set usb_handle {}
+
+while {[catch {usb::connect 0x09FB 0x6001 1 1 0} usb_handle]} {
+    set answer [tk_messageBox -icon error -type retrycancel \
+        -message {Cannot access USB device} -detail $usb_handle]
+    if {[string equal $answer cancel]} break
+}
+
+hst_2 restart
+osc_2 restart
+
+hst_2 start
+osc_2 start
+
+# configure polarity
+# set polarity_command [usb::convert 000A011100000000]
+set polarity_command [usb::convert 000A001100000000]
+if {[catch {$usb_handle writeRaw $polarity_command} result]} {
+    puts {Error during write}
+    puts $result
+}
+
+hst_2 restart
+osc_2 restart
