diff options
author | Andrej Shadura <andrewsh@debian.org> | 2018-05-08 15:59:29 +0200 |
---|---|---|
committer | Andrej Shadura <andrewsh@debian.org> | 2018-05-08 15:59:29 +0200 |
commit | 5b8466f7fae0e071c0f4eda13051c93313910028 (patch) | |
tree | 7061957f770e5e245ba00666dad912a2d44e7fdc /lib/utilities/rs232debugger.tcl |
Import Upstream version 1.3.7
Diffstat (limited to 'lib/utilities/rs232debugger.tcl')
-rwxr-xr-x | lib/utilities/rs232debugger.tcl | 1460 |
1 files changed, 1460 insertions, 0 deletions
diff --git a/lib/utilities/rs232debugger.tcl b/lib/utilities/rs232debugger.tcl new file mode 100755 index 0000000..dacb8d5 --- /dev/null +++ b/lib/utilities/rs232debugger.tcl @@ -0,0 +1,1460 @@ +#!/usr/bin/tclsh +# Part of MCU 8051 IDE ( http://mcu8051ide.sf.net ) + +############################################################################ +# Copyright (C) 2007-2009 by Martin Ošmera # +# martin.osmera@gmail.com # +# # +# This program is free software; you can redistribute it and#or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation; either version 2 of the License, or # +# (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with this program; if not, write to the # +# Free Software Foundation, Inc., # +# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # +############################################################################ + + +# -------------------------------------------------------------------------- +# DESCRIPTION +# Implements RS232/UART debugger +# -------------------------------------------------------------------------- + +class RS232Debugger { + ## COMMON + common count 0 ;# Int: Counter of class instances + # Font: Big bold font + common bold_font [font create \ + -family {helvetica} \ + -size -12 -weight {bold} \ + ] + # Font: Tiny normal font + common tiny_font [font create \ + -family {helvetica} \ + -size -9 -weight {normal} \ + ] + # Font: Tiny bold font + common tiny_font_bold [font create \ + -family {helvetica} \ + -size -9 -weight {bold} \ + ] + # Font: Normal font + common normal_font [font create \ + -family {helvetica} \ + -size -11 -weight {normal} \ + ] + # Font: Also normal font, but a bit larger + common big_font [font create \ + -family {helvetica} \ + -size -12 -weight {normal} \ + ] + # Int: Pool interval for selected RS232 interface + common POOL_INTERVAL 50 ;# mili-seconds + # List of Int: Available baud rates for RS232 + common available_baud_rates { + 50 75 110 134 150 200 + 300 600 1200 1800 2400 4800 + 9600 19200 38400 57600 115200 230400 + 460800 + } + + # List: Configuration list + common config_list $::CONFIG(RS232_DEBUGGER) + + + ## PRIVATE + private variable obj_idx ;# Int: Object index + private variable win ;# Widget: Dialog window + private variable connector_canvas ;# Widget: Canvas widget displaying the DE-9 connector + private variable port_combobox ;# Widget: Combobox for device file selection + private variable status_bar_label ;# Widget: Status bar + + private variable baud_cb ;# Widget: ComboBox for selecting baud rate + private variable parity_cb ;# Widget: ComboBox for selecting type of parity + private variable data_cb ;# Widget: ComboBox for selecting number of data bits + private variable stop_cb ;# Widget: ComboBox for selecting number of stop bits + private variable enable_reception_chb ;# Widget: Check button "Enable reception" + private variable close_connection_button ;# Widget: Button "Close connection" + + private variable leds ;# Array of CanvasObjects: LEDs indicating logical states on wires + private variable dtr_button ;# Widget: Button "DTR" + private variable rts_button ;# Widget: Button "RTS" + private variable break_button ;# Widget: Button "Break" + + private variable send_selected_button ;# Widget: Button "Send selected" + private variable clear_selected_rec_button ;# Widget: Button "Clear selected" in section "Receive" + private variable receive_here_button ;# Widget: Button "Receive here" + private variable clear_selected_snd_button ;# Widget: Button "Clear selected" in section "Send" + private variable receive_hexeditor ;# Object: Hexeditor intented for reception + private variable send_hexeditor ;# Object: Hexeditor intented for sending + + private variable pool_timer {} ;# Object: Pool timer object + private variable channel {} ;# Channel: Opened device file + private variable port_filename {} ;# String: Device file name + private variable reception_address 0 ;# Int: Address in reception hexeditor where received data are stored + private variable reception_enabled 1 ;# Bool: Reception enabled + private variable prev_tty_status ;# List: Previous TTY status (before any action performed by this code) + + private variable baud_conf {9600} ;# Int: Selected baud rate for communication + private variable parity_conf {n} ;# Char: Selected type of parity + private variable data_conf {8} ;# Int: Number of data bits + private variable stop_conf {1} ;# Int: Number of stop bits + + + ## Object constructor + constructor {} { + # Configure local ttk styles + ttk::style configure RS232Debugger_FileInUse.TCombobox \ + -fieldbackground {#DDFFDD} + ttk::style map RS232Debugger_FileInUse.TCombobox \ + -fieldbackground [list {readonly !readonly} {#DDFFDD}] + + ttk::style configure RS232Debugger_FileFound.TCombobox \ + -fieldbackground {#FFFFAA} + ttk::style map RS232Debugger_FileFound.TCombobox \ + -fieldbackground [list {readonly !readonly} {#FFFFAA}] + + ttk::style configure RS232Debugger_FileNotFound.TCombobox \ + -fieldbackground {#FFDDDD} + ttk::style map RS232Debugger_FileNotFound.TCombobox \ + -fieldbackground [list {readonly !readonly} {#FFDDDD}] + + ttk::style configure RS232Debugger_SignalAllDefault.TButton \ + -foreground {#000000} \ + -background {#DDDDDD} + ttk::style map RS232Debugger_SignalAllDefault.TButton \ + -background [list active {#EEEEEE}] + + ttk::style configure RS232Debugger_SignalTxDTrue.TButton \ + -background {#AAFFAA} \ + -foreground {#000000} + ttk::style map RS232Debugger_SignalTxDTrue.TButton \ + -background [list active {#DDFFDD}] \ + -foreground [list active {#00FF00}] + + ttk::style configure RS232Debugger_SignalNormalTrue.TButton \ + -background {#AAFFAA} \ + -foreground {#000000} + ttk::style map RS232Debugger_SignalNormalTrue.TButton \ + -background [list active {#DDFFDD}] \ + -foreground [list active {#00FF00}] + + ttk::style configure RS232Debugger_SignalTxDFalse.TButton \ + -background {#DDDDDD} \ + -foreground {#000000} + ttk::style map RS232Debugger_SignalTxDFalse.TButton \ + -background [list active {#EEEEEE}] \ + -foreground [list active {#000000}] + + ttk::style configure RS232Debugger_SignalNormalFalse.TButton \ + -background {#FFAAAA} \ + -foreground {#000000} + ttk::style map RS232Debugger_SignalNormalFalse.TButton \ + -background [list active {#FFDDDD}] \ + -foreground [list active {#FF0000}] + + + incr count + set obj_idx $count + + array set prev_tty_status {0 {} cts {} dsr {} ri {} dcd {} dtr {} rts {} break {}} + + # Validate and possibly correct configuration list + if {[lsearch -ascii -exact $available_baud_rates [lindex $config_list 0]] == -1} { + puts stderr [mc "RS232 DBG: Invalid baud rate, setting to default: %s" $baud_conf] + lset config_list 0 $baud_conf + } + if {[lsearch -ascii -exact {n o e m s} [lindex $config_list 1]] == -1} { + puts stderr [mc "RS232 DBG: Invalid parity, setting to default: %s" $parity_conf] + lset config_list 1 $parity_conf + } + if {[lsearch -ascii -exact {5 6 7 8} [lindex $config_list 2]] == -1} { + puts stderr [mc "RS232 DBG: Invalid data length, setting to default: %s" $data_conf] + lset config_list 2 $data_conf + } + if {[lsearch -ascii -exact {1 2} [lindex $config_list 3]] == -1} { + puts stderr [mc "RS232 DBG: Invalid stop bit length, setting to default: %s" $stop_conf] + lset config_list 3 $stop_conf + } + if {[lsearch -ascii -exact {0 1} [lindex $config_list 4]] == -1} { + puts stderr [mc "RS232 DBG: Invalid flag reception_enabled, setting to default: %s" $reception_enabled] + lset config_list 4 $reception_enabled + } + if {![string is digit -strict [lindex $config_list 9]] || [lindex $config_list 9] < 0 || [lindex $config_list 9] > 256} { + puts ">> {[lindex $config_list 9]}" + puts stderr [mc "RS232 DBG: Invalid reception address, setting to default: %s" $reception_address] + lset config_list 9 $reception_address + } + if {![string is digit -strict [lindex $config_list 7]] || [lindex $config_list 7] < 0 || [lindex $config_list 7] > 255} { + puts stderr [mc "RS232 DBG: Invalid current cell address, setting to default: %s" "0"] + lset config_list 7 0 + } + if {![string is digit -strict [lindex $config_list 8]] || [lindex $config_list 8] < 0 || [lindex $config_list 8] > 255} { + puts stderr [mc "RS232 DBG: Invalid current cell address, setting to default: %s" "0"] + lset config_list 8 0 + } + + # Load configuration list + set baud_conf [lindex $config_list 0] + set parity_conf [lindex $config_list 1] + set data_conf [lindex $config_list 2] + set stop_conf [lindex $config_list 3] + set reception_enabled [lindex $config_list 4] + set reception_address [expr {int([lindex $config_list 9])}] + if {$reception_address == 256} { + set reception_address 0 + } + + # Initialize GUI + create_gui + set_tty_controls_state 0 + + # Restore data displayed in hexeditors + foreach idx {5 6} hexedit [list $receive_hexeditor $send_hexeditor] { + set data [lindex $config_list $idx] + if {![llength $data]} { + continue + } + + for {set i 0} {$i < 0x100} {incr i} { + $hexedit setValue $i [lindex $data $i] + } + } + + # restore addresses of current cells in hexeditors + $receive_hexeditor setCurrentCell [lindex $config_list 7] + $send_hexeditor setCurrentCell [lindex $config_list 8] + } + + ## Object destructor + destructor { + # Create a new configuration list + set config_list [list \ + $baud_conf $parity_conf $data_conf \ + $stop_conf $reception_enabled \ + [$receive_hexeditor get_values 0 255] \ + [$send_hexeditor get_values 0 255] \ + [$receive_hexeditor getCurrentCell] \ + [$send_hexeditor getCurrentCell] \ + $reception_address \ + ] + + # Cancel pool timer + catch {after cancel $pool_timer} + + # Close opended channel + if {$channel !={}} { + catch {fileevent $channel readable {}} + catch {close $channel} + } + + # Destroy GUI + destroy $win + } + + ## Create dialog GUI + # @return void + private method create_gui {} { + # Create window + set win [toplevel .rs232debugger$count -class [mc "RS232 Debugger"] -bg {#EEEEEE}] + + # Create status bar + set status_bar_label [label $win.status_bar_label -justify left -pady 0 -anchor w] + pack $status_bar_label -side bottom -fill x + + # Create top frame + set top_frame [frame $win.top_frame] + create_top_frame $top_frame + pack $top_frame -fill x -anchor nw + + # Create bottom frame + set bottom_frame [frame $win.bottom_frame] + create_bottom_frame $bottom_frame + pack $bottom_frame -fill x -anchor nw + + $receive_hexeditor clearBgHighlighting 0 + $receive_hexeditor set_bg_hg $reception_address 1 0 + + # Configure window + wm title $win [mc "UART/RS232 Debugger - MCU 8051 IDE"] + wm iconphoto $win ::ICONS::16::chardevice + wm resizable $win 0 0 + wm protocol $win WM_DELETE_WINDOW "catch {delete object $this}" + } + + ## Set status bar tip for specified widget + # @parm Widget widget - Target widget + # @parm String text - Text of the stutus tip + # @return void + private method set_status_tip {widget text} { + bind $widget <Enter> "$status_bar_label configure -text {$text}" + bind $widget <Leave> "$status_bar_label configure -text {}" + } + + ## Draw DE-9 connector in the $connector_canvas + # @parm Int x - X offset + # @parm Int y - Y offset + # @return void + private method draw_connector {x y} { + ## Draw package + set coords { + 1 19 3 16 27 1 33 1 37 6 37 88 + 33 91 27 91 3 80 1 74 1 19 + } + + # Transform coordinates -- adjust them to the given origin + set coordinates [list] + set len [llength $coords] + for {set m 0; set n 1} {$n < $len} {incr m 2; incr n 2} { + lappend coordinates \ + [expr {[lindex $coords $m] + $x}] + lappend coordinates \ + [expr {[lindex $coords $n] + $y}] + } + + $connector_canvas create line $coordinates \ + -tags connector -width 1 -fill #000000 + + ## Draw pins + set coords { + 28 16 28 32 28 48 28 64 28 80 + 12 24 12 40 12 56 12 72 + } + set tags {dcd_pin rxd_pin txd_pin dtr_pin gnd_pin dsr_pin rts_pin cts_pin ri_pin} + + # Transform coordinates -- adjust them to the given origin + set len [llength $coords] + for {set m 0; set n 1; set i 0} {$n < $len} {incr m 2; incr n 2; incr i} { + $connector_canvas create oval \ + [expr {[lindex $coords $m] - 2 + $x}] \ + [expr {[lindex $coords $n] - 2 + $y}] \ + [expr {[lindex $coords $m] + 2 + $x}] \ + [expr {[lindex $coords $n] + 2 + $y}] \ + -tags connector -width 1 \ + -outline #000000 -tags [lindex $tags $i] + } + + ## Draw pin numbers + set coords { + 21 16 21 32 21 48 21 64 21 80 + 5 24 5 40 5 56 5 72 + } + set tags {{} dcd_num rxd_num txd_num dtr_num gnd_num dsr_num rts_num cts_num ri_num} + + # Transform coordinates -- adjust them to the given origin + set len [llength $coords] + for {set m 0; set n 1; set i 1} {$n < $len} {incr m 2; incr n 2; incr i} { + $connector_canvas create text \ + [expr {[lindex $coords $m] + $x}] \ + [expr {[lindex $coords $n] + $y}] \ + -tags connector -fill #000000 \ + -anchor center -justify center -text $i \ + -font $tiny_font -tags [lindex $tags $i] + } + + ## Draw common ground + set coords { + 31 80 60 80 60 105 53 105 67 105 + } + + # Transform coordinates -- adjust them to the given origin + set coordinates [list] + set len [llength $coords] + for {set m 0; set n 1} {$n < $len} {incr m 2; incr n 2} { + lappend coordinates \ + [expr {[lindex $coords $m] + $x}] + lappend coordinates \ + [expr {[lindex $coords $n] + $y}] + } + + $connector_canvas create line $coordinates \ + -tags gnd_wire -width 1 -fill #000000 + + $connector_canvas bind gnd_wire <Enter> "$this wire_enter gnd" + $connector_canvas bind gnd_wire <Leave> "$this wire_leave gnd" + + ## Write texts + $connector_canvas create text \ + [expr {$x + 10}] [expr {$y - 25}] \ + -anchor n -justify left \ + -font $big_font -text [mc "RS-232\nDTE"] + $connector_canvas create text \ + [expr {$x + 10}] [expr {$y + 100}] \ + -anchor n -justify left \ + -font $big_font -text [mc "DE-9"] + } + + ## Draw wires, LEDs and buttons in the $connector_canvas + # @parm Int x - X offset + # @parm Int y - Y offset + # @return void + private method draw_wires_and_controls {x y} { + ## DCD + set leds(dcd) [label $connector_canvas.dcd_led \ + -image ::ICONS::16::ledgray \ + ] + bind $leds(dcd) <Enter> "$this wire_enter dcd" + bind $leds(dcd) <Leave> "$this wire_leave dcd" + $connector_canvas create window \ + [expr {$x + 100}] [expr {$y + 1}] \ + -anchor center -window $leds(dcd) + $connector_canvas create line \ + [expr {$x + 31}] [expr {$y + 16}] \ + [expr {$x + 100}] [expr {$y + 16}] \ + [expr {$x + 100}] [expr {$y + 1}] \ + -width 1 -fill {#888888} -tags dcd_wire + $connector_canvas create line \ + [expr {$x + 74}] [expr {$y + 16}] \ + [expr {$x + 75}] [expr {$y + 16}] \ + -width 1 -fill {#888888} -tags dcd_wire \ + -arrow last + $connector_canvas create text \ + [expr {$x + 100}] [expr {$y - 7}] \ + -tags connector -fill #000000 \ + -anchor s -justify left -text [mc "DCD"]\ + -font $normal_font + + ## DSR + set leds(dsr) [label $connector_canvas.dsr_led \ + -image ::ICONS::16::ledgray \ + ] + bind $leds(dsr) <Enter> "$this wire_enter dsr" + bind $leds(dsr) <Leave> "$this wire_leave dsr" + $connector_canvas create window \ + [expr {$x + 135}] [expr {$y + 1}] \ + -anchor center -window $leds(dsr) + + $connector_canvas create line \ + [expr {$x + 15}] [expr {$y + 24}] \ + [expr {$x + 135}] [expr {$y + 24}] \ + [expr {$x + 135}] [expr {$y + 1}] \ + -width 1 -fill {#888888} -tags dsr_wire + $connector_canvas create line \ + [expr {$x + 74}] [expr {$y + 24}] \ + [expr {$x + 75}] [expr {$y + 24}] \ + -width 1 -fill {#888888} -tags dsr_wire \ + -arrow last + $connector_canvas create text \ + [expr {$x + 135}] [expr {$y - 7}] \ + -tags connector -fill #000000 \ + -anchor s -justify left -text [mc "DSR"]\ + -font $normal_font + + ## CTS + set leds(cts) [label $connector_canvas.cts_led \ + -image ::ICONS::16::ledgray \ + ] + bind $leds(cts) <Enter> "$this wire_enter cts" + bind $leds(cts) <Leave> "$this wire_leave cts" + $connector_canvas create window \ + [expr {$x + 170}] [expr {$y + 1}] \ + -anchor center -window $leds(cts) + + $connector_canvas create line \ + [expr {$x + 15}] [expr {$y + 56}] \ + [expr {$x + 170}] [expr {$y + 56}] \ + [expr {$x + 170}] [expr {$y + 1}] \ + -width 1 -fill {#888888} -tags cts_wire + $connector_canvas create line \ + [expr {$x + 74}] [expr {$y + 56}] \ + [expr {$x + 75}] [expr {$y + 56}] \ + -width 1 -fill {#888888} -tags cts_wire \ + -arrow last + $connector_canvas create text \ + [expr {$x + 170}] [expr {$y - 7}] \ + -tags connector -fill #000000 \ + -anchor s -justify left -text [mc "CTS"]\ + -font $normal_font + + ## RI + set leds(ri) [label $connector_canvas.ri_led \ + -image ::ICONS::16::ledgray \ + ] + bind $leds(ri) <Enter> "$this wire_enter ri" + bind $leds(ri) <Leave> "$this wire_leave ri" + $connector_canvas create window \ + [expr {$x + 205}] [expr {$y + 1}] \ + -anchor center -window $leds(ri) + + $connector_canvas create line \ + [expr {$x + 15}] [expr {$y + 72}] \ + [expr {$x + 205}] [expr {$y + 72}] \ + [expr {$x + 205}] [expr {$y + 1}] \ + -width 1 -fill {#888888} -tags ri_wire + $connector_canvas create line \ + [expr {$x + 74}] [expr {$y + 72}] \ + [expr {$x + 75}] [expr {$y + 72}] \ + -width 1 -fill {#888888} -tags ri_wire \ + -arrow last + $connector_canvas create text \ + [expr {$x + 205}] [expr {$y - 7}] \ + -tags connector -fill #000000 \ + -anchor s -justify left -text [mc "RI"] \ + -font $normal_font + + + ## DTR + set dtr_button [ttk::button $connector_canvas.dtr_button \ + -style RS232Debugger_SignalAllDefault.TButton \ + -command "$this invert_tty_status_bit dtr" \ + -text "-" \ + -width 2 \ + ] + bind $dtr_button <Enter> "$this wire_enter dtr" + bind $dtr_button <Leave> "$this wire_leave dtr" + $connector_canvas create window \ + [expr {$x + 100}] [expr {$y + 95}] \ + -anchor center -window $dtr_button + + $connector_canvas create line \ + [expr {$x + 31}] [expr {$y + 64}] \ + [expr {$x + 100}] [expr {$y + 64}] \ + [expr {$x + 100}] [expr {$y + 95}] \ + -width 1 -fill {#888888} -tags dtr_wire + $connector_canvas create line \ + [expr {$x + 46}] [expr {$y + 64}] \ + [expr {$x + 45}] [expr {$y + 64}] \ + -width 1 -fill {#888888} -tags dtr_wire \ + -arrow last + $connector_canvas create text \ + [expr {$x + 100}] [expr {$y + 105}] \ + -tags connector -fill #000000 \ + -anchor n -justify left -text [mc "DTR"]\ + -font $normal_font + + ## RTS + set rts_button [ttk::button $connector_canvas.rts_button \ + -style RS232Debugger_SignalAllDefault.TButton \ + -command "$this invert_tty_status_bit rts" \ + -text "-" \ + -width 2 \ + ] + bind $rts_button <Enter> "$this wire_enter rts" + bind $rts_button <Leave> "$this wire_leave rts" + $connector_canvas create window \ + [expr {$x + 135}] [expr {$y + 95}] \ + -anchor center -window $rts_button + + $connector_canvas create line \ + [expr {$x + 15}] [expr {$y + 40}] \ + [expr {$x + 135}] [expr {$y + 40}] \ + [expr {$x + 135}] [expr {$y + 95}] \ + -width 1 -fill {#888888} -tags rts_wire + $connector_canvas create line \ + [expr {$x + 46}] [expr {$y + 40}] \ + [expr {$x + 45}] [expr {$y + 40}] \ + -width 1 -fill {#888888} -tags rts_wire \ + -arrow last + $connector_canvas create text \ + [expr {$x + 135}] [expr {$y + 105}] \ + -tags connector -fill #000000 \ + -anchor n -justify left -text [mc "RTS"]\ + -font $normal_font + + ## TxD + set break_button [ttk::button $connector_canvas.break_button \ + -style RS232Debugger_SignalAllDefault.TButton \ + -command "$this invert_tty_status_bit break" \ + -text [mc "Break"] \ + -width 5 \ + ] + bind $break_button <Enter> "$this wire_enter txd" + bind $break_button <Leave> "$this wire_leave txd" + $connector_canvas create window \ + [expr {$x + 180}] [expr {$y + 95}] \ + -anchor center -window $break_button + + $connector_canvas create line \ + [expr {$x + 31}] [expr {$y + 48}] \ + [expr {$x + 180}] [expr {$y + 48}] \ + [expr {$x + 180}] [expr {$y + 95}] \ + -width 1 -fill {#0000FF} -tags txd_wire + $connector_canvas create line \ + [expr {$x + 46}] [expr {$y + 48}] \ + [expr {$x + 45}] [expr {$y + 48}] \ + -width 1 -fill {#0000FF} -tags txd_wire \ + -arrow last + $connector_canvas create line \ + [expr {$x + 180}] [expr {$y + 120}] \ + [expr {$x + 180}] [expr {$y + 105}] \ + -width 1 -fill {#0000FF} -arrow last + + ## RxD + $connector_canvas create line \ + [expr {$x + 31}] [expr {$y + 32}] \ + [expr {$x + 220}] [expr {$y + 32}] \ + [expr {$x + 220}] [expr {$y + 90}] \ + [expr {$x + 250}] [expr {$y + 120}] \ + -width 1 -fill {#0000FF} -tags rxd_wire \ + -arrow last + $connector_canvas create line \ + [expr {$x + 74}] [expr {$y + 32}] \ + [expr {$x + 75}] [expr {$y + 32}] \ + -width 1 -fill {#0000FF} -tags rxd_wire \ + -arrow last + + foreach wire {dcd dsr cts ri dtr rts txd rxd} { + $connector_canvas bind ${wire}_wire <Enter> "$this wire_enter $wire" + $connector_canvas bind ${wire}_wire <Leave> "$this wire_leave $wire" + } + } + + ## Create top frame in the dialog window (connector_canvas (left) and configuration (right)) + # @parm Widget target_frame - Parent frame + # @return void + private method create_top_frame {target_frame} { + + # + ## Connector canvas + # + + # Create canvas widget + set connector_canvas [canvas $target_frame.canvas \ + -width 280 -height 150 -bg {#EEEEEE} \ + -bd 0 -relief flat -highlightthickness 0 \ + ] + pack $connector_canvas -side left -anchor sw + + # Fill in the connector canvas + draw_connector 20 30 + draw_wires_and_controls 20 30 + + + + # + ## Configuration frame + # + + # Create labelframe + set conf_frame [ttk::labelframe $target_frame.conf_frame\ + -padding 5 \ + -labelwidget [label $target_frame.conf_label \ + -font $bold_font \ + -compound left \ + -text [mc "Port configuration"] \ + -image ::ICONS::16::configure \ + ] \ + ] + pack $conf_frame -side left -anchor nw + # - Physical port + grid [label $conf_frame.port_lbl \ + -text [mc "Physical port"] \ + ] -row 1 -column 1 -sticky w + set port_combobox [ttk::combobox $conf_frame.port_cb \ + -width 12 \ + -validate all \ + -validatecommand "$this port_combobox_validate %P" \ + -exportselection 0 \ + ] + bind $port_combobox <<ComboboxSelected>> \ + "$this port_combobox_accept" + bind $port_combobox <Return> "$this port_combobox_accept" + bind $port_combobox <KP_Enter> "$this port_combobox_accept" + + port_combobox_refresh + grid $port_combobox -row 1 -column 2 -sticky w + set_status_tip $port_combobox [mc "Special character file representing the target physical device"] + grid [ttk::button $conf_frame.port_combobox_refresh_button \ + -image ::ICONS::16::reload \ + -command "$this port_combobox_refresh" \ + -style Flat.TButton \ + ] -row 1 -column 3 -sticky w + set_status_tip $conf_frame.port_combobox_refresh_button [mc "Refresh list of relevant devices"] + # - Baud rate + grid [label $conf_frame.baud_lbl \ + -text [mc "Baud rate"] \ + ] -row 3 -column 1 -sticky w + set baud_cb [ttk::combobox $conf_frame.baud_cb \ + -state readonly \ + -width 6 \ + -exportselection 0 \ + -values $available_baud_rates \ + ] + bind $baud_cb <<ComboboxSelected>> \ + "$this change_port_config b \[$conf_frame.baud_cb get\]" + set_status_tip $baud_cb [mc "Connection speed in bps"] + grid $baud_cb -row 3 -column 2 -sticky w + $conf_frame.baud_cb current [lsearch [$conf_frame.baud_cb cget -values] $baud_conf] + # - Parity + grid [label $conf_frame.parity_lbl \ + -text [mc "Parity"] \ + ] -row 4 -column 1 -sticky w + set parity_cb [ttk::combobox $conf_frame.parity_cb \ + -values {none odd even mark space} \ + -state readonly \ + -width 6 \ + -exportselection 0 \ + ] + bind $parity_cb <<ComboboxSelected>> \ + "$this change_port_config p \[$conf_frame.parity_cb get\]" + set_status_tip $parity_cb [mc "Parity"] + grid $parity_cb -row 4 -column 2 -sticky w + $conf_frame.parity_cb current [lsearch {n o e m s} $parity_conf] + # - Data bits + grid [label $conf_frame.data_lbl \ + -text [mc "Data bits"] \ + ] -row 5 -column 1 -sticky w + set data_cb [ttk::combobox $conf_frame.data_cb \ + -state readonly \ + -width 1 \ + -values {5 6 7 8} \ + -exportselection 0 \ + ] + bind $data_cb <<ComboboxSelected>> \ + "$this change_port_config d \[$conf_frame.data_cb get\]" + set_status_tip $data_cb [mc "Number of data bits"] + grid $data_cb -row 5 -column 2 -sticky w + $conf_frame.data_cb current [lsearch [$conf_frame.data_cb cget -values] $data_conf] + # - Stop bits + grid [label $conf_frame.stop_lbl \ + -text [mc "Stop bits"] \ + ] -row 6 -column 1 -sticky w + set stop_cb [ttk::combobox $conf_frame.stop_cb \ + -state readonly \ + -width 1 \ + -values {1 2} \ + -exportselection 0 \ + ] + bind $stop_cb <<ComboboxSelected>> \ + "$this change_port_config s \[$conf_frame.stop_cb get\]" + set_status_tip $stop_cb [mc "Number of stop bits"] + grid $stop_cb -row 6 -column 2 -sticky w + $conf_frame.stop_cb current [lsearch [$conf_frame.stop_cb cget -values] $stop_conf] + # Bottom frame in configuration frame + set bottom_frame [frame $conf_frame.bottom_frame] + # - Enable reception + set enable_reception_chb [checkbutton $bottom_frame.enable_reception_chb\ + -text [mc "Enable reception"] -onvalue 1 -offvalue 0 \ + -command "$this reception_ena_dis" \ + -variable "::RS232Debugger::enable_reception${obj_idx}" \ + ] + set_status_tip $enable_reception_chb [mc "Display incoming data or discard them"] + set ::RS232Debugger::enable_reception${obj_idx} $reception_enabled + pack $enable_reception_chb -side left + # - Close connection + set close_connection_button [ttk::button \ + $bottom_frame.close_connection_button \ + -text [mc "Close"] \ + -compound left \ + -width 5 \ + -image ::ICONS::16::fileclose \ + -command "$this safely_terminate_connection" \ + ] + set_status_tip $close_connection_button [mc "Terminate connection"] + pack $close_connection_button -side right -padx 5 + + grid $bottom_frame -row 7 -column 1 -sticky we -columnspan 3 + } + + ## Create bottom frame (hexadecimal editors) + # @parm Widget target_frame - Parent frame + # @return void + private method create_bottom_frame {target_frame} { + # Create headers ("Data to send", "Received data") + grid [label $target_frame.lbl_a \ + -text [mc "Data to send"] \ + -compound right \ + -image ::ICONS::16::forward \ + -padx 15 -font $bold_font \ + ] -row 0 -column 1 -columnspan 2 + grid [label $target_frame.lbl_b \ + -text [mc "Received data"] \ + -compound left \ + -image ::ICONS::16::forward \ + -padx 15 -font $bold_font \ + ] -row 0 -column 3 -columnspan 2 + + # Create hexadecimal editors + set send_hexeditor [HexEditor #auto \ + $target_frame.send_hexeditor 8 32 2 \ + hex 1 1 5 256 \ + ] + [$send_hexeditor getLeftView] configure -exportselection 0 + $send_hexeditor bindSelectionAction "$this hexeditor_selection s" + grid $target_frame.send_hexeditor -row 1 -column 1 -columnspan 2 + + set receive_hexeditor [HexEditor #auto \ + $target_frame.receive_hexeditor 8 32 2 \ + hex 1 1 5 256 \ + ] + [$send_hexeditor getLeftView] configure -exportselection 0 + $receive_hexeditor bindSelectionAction "$this hexeditor_selection r" + grid $target_frame.receive_hexeditor -row 1 -column 3 -columnspan 2 + + # Create buttons "Send selected" and "Clear selected" in send part + set send_selected_button [ttk::button \ + $target_frame.send_selected_button \ + -text [mc "Send selected"] \ + -image ::ICONS::16::forward \ + -command "$this send_selected" \ + -compound left \ + -state disabled \ + ] + set clear_selected_snd_button [ttk::button \ + $target_frame.clear_selected_snd_button \ + -text [mc "Clear selected"] \ + -image ::ICONS::16::eraser \ + -command "$this clear_selected_snd" \ + -compound left \ + -state disabled \ + ] + set_status_tip $send_selected_button [mc "Send selected data"] + set_status_tip $clear_selected_snd_button [mc "Remove selected data"] + grid $send_selected_button -row 2 -column 1 -sticky we + grid $clear_selected_snd_button -row 2 -column 2 -sticky we + + # Create buttons "Receive here" and "Clear selected" in reception part + set receive_here_button [ttk::button \ + $target_frame.receive_here_button \ + -text [mc "Receive here"] \ + -image ::ICONS::16::down0 \ + -command "$this receive_here" \ + -compound left \ + ] + set clear_selected_rec_button [ttk::button \ + $target_frame.clear_selected_rec_button \ + -text [mc "Clear selected"] \ + -image ::ICONS::16::eraser \ + -command "$this clear_selected_rec" \ + -compound left \ + -state disabled \ + ] + set_status_tip $receive_here_button [mc "Receive data on current cursor position"] + set_status_tip $clear_selected_rec_button [mc "Remove selected data"] + grid $receive_here_button -row 2 -column 3 -sticky we + grid $clear_selected_rec_button -row 2 -column 4 -sticky we + } + + ## Accept new device file + # @return void + public method port_combobox_accept {} { + change_port_file [$port_combobox get] + } + + ## Validate contetnts of port combo box + # @parm String content - String to validate + # @return Bool - Allways true + public method port_combobox_validate {content} { + # Empty string + if {![string length $content]} { + $port_combobox configure -style TCombobox + return 1 + } + + # Exiting file + if {[file exists $content]} { + if {$port_filename == $content} { + $port_combobox configure -style RS232Debugger_FileInUse.TCombobox + } { + $port_combobox configure -style RS232Debugger_FileFound.TCombobox + } + # Not exiting file + } else { + $port_combobox configure -style RS232Debugger_FileNotFound.TCombobox + } + + return 1 + } + + ## Refresh list of possible values on port combobox + # @return void + public method port_combobox_refresh {} { + if {!$::MICROSOFT_WINDOWS} { ;# POSIX way + $port_combobox configure -values \ + [lsort -decreasing \ + [glob -directory {/dev} -nocomplain -type {c} -- {tty{S,USB}*}] \ + ] + + } else { ;# Microsoft Widnows way + set available_ms_windows_ports [list] + + for {set i 0} {$i < 10} {incr i} { + if {[file exists "COM${i}"]} { + lappend available_ms_windows_ports "COM${i}" + } + } + + $port_combobox configure -values $available_ms_windows_ports + } + } + + ## Change current device file + # @parm String filename - Path to the new device file + # @return void + private method change_port_file {filename} { + # File name is the same at the one already in use -> abort + if {$port_filename == $filename} { + return + } + + # Safely terminate current connection + set channel_prev $channel + safely_terminate_connection + if {$channel_prev != {}} { + catch { + close $channel_prev + } + } + + ## Try to open the device file + if {[catch { + if {!$::MICROSOFT_WINDOWS} { ;# POSIX way + set channel [open $filename {RDWR BINARY NONBLOCK}] + } { ;# MS Windows does not support NONBLOCK + set channel [open $filename {RDWR BINARY}] + } + + # -> Fail + } reason]} then { + safely_terminate_connection + after idle " + set reason {$reason} + tk_messageBox \ + -parent $win \ + -type ok \ + -icon error \ + -title {[mc {Access Error}]} \ + -message \"[mc {Unable to open the specified file}]\n\n\${reason}\"" + # -> Success + } else { + # Try to configure opened channel acording to specified parameters + if {[catch { + fconfigure $channel \ + -handshake none \ + -buffersize 0 \ + -mode $baud_conf,$parity_conf,$data_conf,$stop_conf + + fileevent $channel readable "$this receive_data" + + set pool_timer [after $POOL_INTERVAL "catch {$this pool_ttystatus}"] + set_tty_controls_state 1 + + # -> Fail + } reason]} then { + safely_terminate_connection + after idle " + tk_messageBox \ + -parent $win \ + -type ok \ + -icon error \ + -title {[mc {Access Error}]} \ + -message \"[mc {Unable to use the specified file}]\"" + # -> Success + } else { + $port_combobox configure -style RS232Debugger_FileInUse.TCombobox + set port_filename $filename + } + } + } + + ## Modify comlink attributes + # @parm Char what - Attribute ID + # @parm String value - Attribute value + # @return void + public method change_port_config {what value} { + switch -- $what { + {b} { ;# Baud rate + set baud_conf $value + } + {p} { ;# Parity bit + switch -- $value { + {none} { + set value {n} + } + {odd} { + set value {o} + } + {even} { + set value {e} + } + {mark} { + set value {m} + } + {space} { + set value {s} + } + } + set parity_conf $value + } + {d} { ;# Data bits + set data_conf $value + } + {s} { ;# Stop bits + set stop_conf $value + } + } + + # Cancel if there is no channel opened + if {$channel == {}} { + return + } + + # Change channel configuration + if {[catch { + fconfigure $channel -mode $baud_conf,$parity_conf,$data_conf,$stop_conf + } reason]} { + tk_messageBox \ + -parent $win \ + -type ok \ + -icon error \ + -title [mc "Uknown failure"] \ + -message [mc "Unable to change port configuration"] + } + } + + ## Handle selection event in hexeditor + # @parm Char editor - Editor ID + # @parm Bool anything_selected - 1 == anything selected; 0 == Nothing selected + # @return void + public method hexeditor_selection {editor anything_selected} { + if {$anything_selected} { + set state {normal} + } { + set state {disabled} + } + + if {$editor == {s}} { + $send_selected_button configure -state $state + $clear_selected_snd_button configure -state $state + } { + $clear_selected_rec_button configure -state $state + } + } + + ## Clear selected data in send hexeditor + # @return void + public method clear_selected_snd {} { + # Get range of text indexes determinating the selection + set rangeofselection [$send_hexeditor getRangeOfSelection] + if {$rangeofselection == {}} { + return + } + + # Determinate index of the start and end cell + set start_cell [lindex $rangeofselection 0] + set end_cell [lindex $rangeofselection 1] + + # Clear all selected cell one by one + for {set i $start_cell} {$i <= $end_cell} {incr i} { + $send_hexeditor setValue $i {} + } + } + + ## Send selected data over RS232 interface + # @return void + public method send_selected {} { + # Get range of text indexes determinating the selection + set rangeofselection [$send_hexeditor getRangeOfSelection] + if {$rangeofselection == {}} { + return + } + + # Abort if there was no channel opened + if {$channel == {}} { + tk_messageBox \ + -parent $win \ + -title [mc "IO Error"] \ + -type ok -icon warning \ + -message [mc "No port opened."] + return + } + + # Generate binary data from the selected hexadecimal string + set data {} + set start_cell [lindex $rangeofselection 0] + set end_cell [lindex $rangeofselection 1] + foreach value [$send_hexeditor get_values $start_cell $end_cell] { + if {$value == {}} { + continue + } + append data [format %c $value] + } + + # Send the generated binary data + if {[catch { + puts -nonewline $channel $data + flush $channel + } reason]} { + tk_messageBox \ + -parent $win \ + -title [mc "IO Error"] \ + -type ok -icon warning \ + -message [mc "Unable to send the data\n\n%s" $reason] + } + } + + ## Change reception adddress to address of the current cell + # @return void + public method receive_here {} { + set cell [$receive_hexeditor getCurrentCell] + set reception_address $cell + + $receive_hexeditor clearBgHighlighting 0 + $receive_hexeditor set_bg_hg $cell 1 0 + } + + ## Receive data from the channel + # This function is trigered automatically by fileevent facitily + # @return void + public method receive_data {} { + # Read binary data + set data [read $channel] + + # Discard the data if reception is not enabled + if {!$reception_enabled} { + return + } + + # Check if the data has non zero length + if {![string length $data]} { + unknown_port_io_error + return + } + + # Load the data into hexadecimal editor + set len [string bytelength $data] + $receive_hexeditor clearBgHighlighting 1 + for {set i 0} {$i < $len} {incr i} { + if {$reception_address >= 256} { + receive_buffer_overflow_warning_dialog + break + } + + scan [string index $data $i] %c byte + $receive_hexeditor setValue $reception_address $byte + + incr reception_address + } + $receive_hexeditor set_bg_hg [expr {$reception_address - 1}] 1 1 + $receive_hexeditor seeCell [expr {$reception_address - 1}] + } + + ## Diaply dialog "Not enough space in the receive buffer !" + # @return void + private method receive_buffer_overflow_warning_dialog {} { + if {[winfo exists .data_lost_dialog]} { + return + } + set dialog [toplevel .data_lost_dialog -class [mc "Error message"] -bg {#EEEEEE}] + + pack [label $dialog.label \ + -font $bold_font -compound left -padx 5 \ + -text [mc "Not enough space in the receive buffer !"] \ + -image ::ICONS::22::stop \ + ] -fill x -pady 5 -padx 5 + + pack [frame $dialog.frm] -pady 5 + pack [ttk::button $dialog.frm.ok_button \ + -text [mc "Ok"] \ + -command " + grab release $dialog + destroy $dialog + " \ + ] -side left + + pack [ttk::separator $dialog.sep -orient horizontal] -fill x -pady 10 + pack [checkbutton $dialog.enable_reception_chb \ + -text [mc "Keep reception enabled"] -onvalue 1 -offvalue 0 \ + -command "$this reception_ena_dis" \ + -variable "::RS232Debugger::enable_reception${obj_idx}" \ + ] -anchor w + + # Set window attributes + wm iconphoto $dialog ::ICONS::16::status_unknown + wm title $dialog [mc "Data lost"] + wm resizable $dialog 0 0 + wm transient $dialog $win + catch {grab $dialog} + wm protocol $dialog WM_DELETE_WINDOW " + grab release $dialog + destroy $dialog + " + raise $dialog + focus -force $dialog.frm.ok_button + tkwait window $dialog + } + + ## Clear selected data in receive hexeditor + # @return void + public method clear_selected_rec {} { + set rangeofselection [$receive_hexeditor getRangeOfSelection] + if {$rangeofselection == {}} { + return + } + + set start_cell [lindex $rangeofselection 0] + set end_cell [lindex $rangeofselection 1] + + for {set i $start_cell} {$i <= $end_cell} {incr i} { + $receive_hexeditor setValue $i {} + } + } + + ## Enable/Disable reception + # @return void + public method reception_ena_dis {} { + set reception_enabled [subst "\$::RS232Debugger::enable_reception${obj_idx}"] + } + + ## Read TTY status from the interface and update GUI accordingly + # @return void + public method pool_ttystatus {} { + # Setup the pool timer + set pool_timer [after $POOL_INTERVAL "catch {$this pool_ttystatus}"] + + # Read TTY status + if {[catch { + set ttystatus [fconfigure $channel -ttystatus] + }]} { + unknown_port_io_error + return + } + + # Check whether any change occured + if {$prev_tty_status(0) == $ttystatus} { + return + } { + set prev_tty_status(0) $ttystatus + } + + # Transform values read to these four variables: + set cts {} + set dsr {} + set ri {} + set dcd {} + set ts_len [llength $ttystatus] + for {set i 0; set j 1} {$i < $ts_len} {incr i 2; incr j 2} { + set key [lindex $ttystatus $i] + set val [lindex $ttystatus $j] + + switch -- $key { + {CTS} {set cts $val} + {DSR} {set dsr $val} + {RING} {set ri $val} + {DCD} {set dcd $val} + } + } + + # Update GUI accordingly + show_new_ttystatus $cts $dsr $ri $dcd + } + + ## Show new TTY status in the GUI + # @parm Bool cts - CTS line state + # @parm Bool dsr - DSR line state + # @parm Bool ri - RI line state + # @parm Bool dcd - DCD line state + # @return void + private method show_new_ttystatus args { + foreach signal {cts dsr ri dcd} value $args { + if {$prev_tty_status($signal) == $value} { + continue + } { + set prev_tty_status($signal) $value + } + + switch -- $value { + 0 { + set color {#FF0000} + set image ledred + } + 1 { + set color {#00FF00} + set image ledgreen + } + default { + set color {#888888} + set image ledgray + } + } + + $connector_canvas itemconfigure ${signal}_wire -fill $color + $leds($signal) configure -image ::ICONS::16::$image + } + } + + ## Report an unknown IO error occured on the interface + # Plus disable reception and safely terminate connection + # @return void + private method unknown_port_io_error {} { + # Disable reception + set reception_enabled 0 + set ::RS232Debugger::enable_reception${obj_idx} 0 + + # Safely terminate connection + safely_terminate_connection + $port_combobox configure -style RS232Debugger_FileFound.TCombobox + + # Display the error message + tk_messageBox \ + -parent $win \ + -title [mc "IO Error"] \ + -type ok -icon warning \ + -message [mc "There is something wrong with the port. Closing connection and disabling reception on this channel !"] + + update + } + + ## Safely terminate connection to the HW interface + # @return void + public method safely_terminate_connection {} { + catch {fileevent $channel readable {}} + catch { + after cancel $pool_timer + } + set prev_tty_status(0) {} + set channel {} + set port_filename {} + + show_new_ttystatus {} {} {} {} + set_tty_controls_state 0 + $port_combobox configure -style RS232Debugger_FileFound.TCombobox + } + + ## Enable or disable TTY controls + # @parm Bool enabled - 1 == Enable; 0 == Disable + # @return void + private method set_tty_controls_state {enabled} { + if {$enabled} { + set state {normal} + set state2 {readonly} + set_tty_controls_to_defaults + } { + set state {disabled} + set state2 {disabled} + set_tty_controls_to_unknown_state + } + + $dtr_button configure -state $state + $rts_button configure -state $state + $break_button configure -state $state + + $enable_reception_chb configure -state $state + $close_connection_button configure -state $state + + $baud_cb configure -state $state2 + $parity_cb configure -state $state2 + $data_cb configure -state $state2 + $stop_cb configure -state $state2 + } + + ## Set tty controls to defaults + # @return void + private method set_tty_controls_to_defaults {} { + set_new_tty_status dtr 0 + set_new_tty_status rts 0 + set_new_tty_status break 0 + } + + ## Set tty controls to unknown state + # @return void + private method set_tty_controls_to_unknown_state {} { + set_new_tty_status dtr {} + set_new_tty_status rts {} + set_new_tty_status break {} + } + + ## Invert tty status bit + # @parm String wire - Bit/Wire ID + # @return void + public method invert_tty_status_bit {wire} { + if {$prev_tty_status($wire) == {}} { + return + } + + set_new_tty_status $wire [expr {!$prev_tty_status($wire)}] + } + + ## Change color of the specified color + # @parm String wire - Wire ID + # @parm String value - New value (e.g. 0 or {}) + # @return void + private method set_new_tty_status {wire value} { + set prev_tty_status($wire) $value + + switch -- $value { + 0 { ;# Loical 0 + if {$wire == {break}} { + [subst "\${${wire}_button}"] configure -text {Break} \ + -style RS232Debugger_SignalTxDFalse.TButton + $connector_canvas itemconfigure txd_wire -fill {#0000FF} + } { + [subst "\${${wire}_button}"] configure -text {1} \ + -style RS232Debugger_SignalNormalFalse.TButton + $connector_canvas itemconfigure ${wire}_wire -fill {#FF0000} + } + } + 1 { ;# Logical 1 + if {$wire == {break}} { + [subst "\${${wire}_button}"] configure -text {BREAK} \ + -style RS232Debugger_SignalTxDTrue.TButton + $connector_canvas itemconfigure txd_wire -fill {#00FF00} + } { + [subst "\${${wire}_button}"] configure -text {0} \ + -style RS232Debugger_SignalNormalTrue.TButton + $connector_canvas itemconfigure ${wire}_wire -fill {#00FF00} + } + } + default { ;# Unknown state + if {$wire == {break}} { + [subst "\${${wire}_button}"] configure -text {Break} \ + -style RS232Debugger_SignalAllDefault.TButton + $connector_canvas itemconfigure txd_wire -fill {#0000FF} + } { + [subst "\${${wire}_button}"] configure -text {-} \ + -style RS232Debugger_SignalAllDefault.TButton + $connector_canvas itemconfigure ${wire}_wire -fill {#888888} + } + return + } + } + + if {[catch { + fconfigure $channel -ttycontrol [list $wire $value] + }]} { + unknown_port_io_error + return + } + } + + ## Handle "<Enter>" event on wire + # @parm String wire - Wire ID + # @return void + public method wire_enter {wire} { + $connector_canvas itemconfigure ${wire}_wire -width 2 + $connector_canvas itemconfigure ${wire}_pin -fill {#000000} + $connector_canvas itemconfigure ${wire}_num -font $tiny_font_bold + + set text {} + switch -- $wire { + {gnd} {set text [mc "RS232 pin: GND -- Common ground"]} + {dcd} {set text [mc "RS232 pin: DCD -- Carrier Detect"]} + {dsr} {set text [mc "RS232 pin: DSR -- Data Set Ready"]} + {cts} {set text [mc "RS232 pin: CTS -- Clear To Send"]} + {ri} {set text [mc "RS232 pin: RI -- Ring Indicator"]} + {dtr} {set text [mc "RS232 pin: DTR -- Data Terminal Ready"]} + {rts} {set text [mc "RS232 pin: RTS -- Request To Send"]} + {txd} {set text [mc "RS232 pin: TxD -- Transmitted Data"]} + {rxd} {set text [mc "RS232 pin: RxD -- Received Data"]} + } + $status_bar_label configure -text $text + } + + ## Handle "<Leave>" event on wire + # @parm String wire - Wire ID + # @return void + public method wire_leave {wire} { + $connector_canvas itemconfigure ${wire}_wire -width 1 + $connector_canvas itemconfigure ${wire}_pin -fill {#EEEEEE} + $connector_canvas itemconfigure ${wire}_num -font $tiny_font + + $status_bar_label configure -text {} + } +} |