summaryrefslogtreecommitdiff
path: root/lib/pale/virtual_uart_term.tcl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/pale/virtual_uart_term.tcl')
-rw-r--r--lib/pale/virtual_uart_term.tcl1682
1 files changed, 1682 insertions, 0 deletions
diff --git a/lib/pale/virtual_uart_term.tcl b/lib/pale/virtual_uart_term.tcl
new file mode 100644
index 0000000..f78b803
--- /dev/null
+++ b/lib/pale/virtual_uart_term.tcl
@@ -0,0 +1,1682 @@
+#!/usr/bin/tclsh
+# Part of MCU 8051 IDE ( http://mcu8051ide.sf.net )
+
+############################################################################
+# Copyright (C) 2011 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. #
+############################################################################
+
+# >>> File inclusion guard
+if { ! [ info exists _VIRTUAL_UART_TERM_TCL ] } {
+set _VIRTUAL_UART_TERM_TCL _
+# <<< File inclusion guard
+
+# --------------------------------------------------------------------------
+# DESCRIPTION
+#
+# -------------------------------------------------------------------------
+
+class VirtualUARTTerminal {
+ inherit VirtualHWComponent
+
+ # Font: Big bold font
+ common bold_font [font create \
+ -family {helvetica} \
+ -size [expr {int(-12 * $::font_size_factor)}] -weight {bold} \
+ ]
+ # Font: Tiny normal font
+ common tiny_font [font create \
+ -family {helvetica} \
+ -size [expr {int(-9 * $::font_size_factor)}] -weight {normal} \
+ ]
+ # Font: Tiny bold font
+ common tiny_font_bold [font create \
+ -family {helvetica} \
+ -size [expr {int(-9 * $::font_size_factor)}] -weight {bold} \
+ ]
+ # Font: Normal font
+ common normal_font [font create \
+ -family {helvetica} \
+ -size [expr {int(-11 * $::font_size_factor)}] -weight {normal} \
+ ]
+ # Font: Also normal font, but a bit larger
+ common big_font [font create \
+ -family {helvetica} \
+ -size [expr {int(-12 * $::font_size_factor)}] -weight {normal} \
+ ]
+ # Font: Font to be used in the panel -- bold
+ common cb_font [font create \
+ -weight bold \
+ -size [expr {int(-10 * $::font_size_factor)}] \
+ -family {helvetica} \
+ ]
+
+ # 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
+ }
+
+ common COMPONENT_NAME "Virtual UART Terminal" ;# Name of this component
+ common CLASS_NAME "VirtualUARTTerminal" ;# Name of this class
+ common COMPONENT_ICON {chardevice} ;# Icon for this panel (16x16)
+
+ # Configuration menu
+ common CONFMENU {
+ {command {Show log window} {} 5 "show_log" {bar5}
+ "Display the log of events which are currently happening in the simulated UART driver"}
+ {separator}
+ {command {Show help} {} 5 "show_help 1" {help}
+ "Show brief help"}
+ {separator}
+ {command {Save configuration} {} 0 "save_as" {filesave}
+ "Save configuration into a file"}
+ {command {Load configuration} {} 0 "load_from" {fileopen}
+ "Load configuration from a file"}
+ {separator}
+ {checkbutton "Window always on top" {} {::VirtualUARTTerminal::menu_keep_win_on_top}
+ 1 0 0 {keep_win_on_top_changed}
+ ""}
+ }
+
+ common rect_size 12
+ common empty_fill {#888888}
+ common empty_outline {#AAAAAA}
+
+ common MAX_LOG_LENGTH 100 ;# Int: Maximum number of row in the log window
+
+ ## PRIVATE
+ private variable status_bar_label ;# Widget: Status bar
+
+ private variable connection_port ;# Array of Int: Index is key number, value is port number or {-}
+ private variable connection_pin ;# Array of Int: Index is key number, value is bit number or {-}
+
+ 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
+
+ private variable baud_cb ;#
+ private variable parity_cb ;#
+ private variable data_cb ;#
+ private variable stop_cb ;#
+
+ private variable send_selected_button
+ private variable clear_selected_snd_button
+ private variable clear_selected_rec_button
+
+ private variable enaged ;# Array of Bool: enaged(port_num,bit_num) --> Is connected to this device ?
+ private variable usr_note
+ private variable cb
+ private variable sbuf_r_canvas
+ private variable sbuf_t_canvas
+ private variable keep_win_on_top 0 ;# Bool: Toplevel window
+
+ private variable controls_frame
+
+ private variable log_win_text {}
+ private variable warning_indicator {}
+ private variable log_time_mark 0
+ private variable log_window_geometry {}
+ private variable log_enabled 1 ;# Bool: Logging of events enabled (slower simulation)
+ private variable log_on_off_chbut ;# Widget: Checkbox for enabling and disabling the logging of events
+
+ private variable time_mark 0 ;# Int: Time mark pointing to this point of time according to the MCU simulator engine
+ private variable bit_time 104166.666
+ private variable bit_rect
+ private variable arrow
+ private variable reg_val
+
+ private variable graph_position
+ private variable graph_prev_state
+ private variable graph_elements
+
+ private variable send_hexeditor
+ private variable receive_hexeditor
+ private variable reception_address 0
+
+ private variable rxd_signal 1 ;# Bool:
+ private variable rxd_signal_prev 1
+ private variable reception_in_progress 0
+ private variable reception_bit_no
+ private variable reception_sample_time
+ private variable reception_data 0
+
+ private variable output_buffer {}
+ private variable transmission_in_prog 0
+ private variable byte_to_send -1
+ private variable transmission_bit_no -1
+ private variable transmission_sample_time
+ private variable last_txd 1
+
+
+ ## Object constructor
+ # @parm Object _project - Project object
+ constructor {_project} {
+ # Set object variables identifing this component (see the base class)
+ set component_name $COMPONENT_NAME
+ set class_name $CLASS_NAME
+ set component_icon $COMPONENT_ICON
+
+ # Set other object variables
+ set project $_project
+ array set connection_port {0 - 1 - 2 - 3 - 4 - 5 -}
+ array set connection_pin {0 - 1 - 2 - 3 - 4 - 5 -}
+ array set arrow {
+ r {}
+ r8 {}
+ t {}
+ t8 {}
+ }
+ array set reg_val {
+ rxd {}
+ txd {}
+ }
+ array set graph_position {
+ t 0 r 0
+ }
+ array set graph_prev_state {
+ t 1 r 1
+ }
+ array set graph_elements {
+ t {} r {}
+ }
+
+ for {set port 0} {$port < 5} {incr port} {
+ for {set bit 0} {$bit < 8} {incr bit} {
+ set enaged($port,$bit) 0
+ }
+ }
+
+ # Inform PALE
+ $project pale_register_input_device $this
+ $project pale_set_modified
+
+ # Create panel GUI
+ create_gui
+ mcu_changed
+ on_off [$project pale_is_enabled]
+ create_log
+
+ # ComboBoxes to default state
+ for {set i 0} {$i < 2} {incr i} {
+ $cb(b$i) current 0
+ $cb(p$i) current 0
+ }
+ }
+
+ ## Object destructor
+ destructor {
+ # Inform PALE
+ $project pale_unregister_input_device $this
+
+ # Destroy GUI
+ destroy $win
+ }
+
+ ## Value of configuration menu variable "keep_win_on_top" has been changed
+ # @return void
+ public method keep_win_on_top_changed {} {
+ set keep_win_on_top $VirtualUARTTerminal::menu_keep_win_on_top
+ if {$keep_win_on_top} {
+ wm attributes $win -topmost 1 -alpha 0.8
+ } else {
+ wm attributes $win -topmost 0 -alpha 1.0
+ }
+ }
+
+ ## Reconnect the specified line to another port pin
+ # @parm Int i - line number (0..1)
+ # @return void
+ public method reconnect {i} {
+ # Adjust connections
+ set connection_port($i) [$cb(p$i) get]
+ set connection_pin($i) [$cb(b$i) get]
+ if {$connection_pin($i) != {-}} {
+ set connection_pin($i) [expr {7 - $connection_pin($i)}]
+ }
+
+ # Reevaluate array of MCU port pins engaged by this device
+ evaluete_enaged_pins
+
+ # Change state of the device
+ if {$drawing_on} {
+ $project pale_reevaluate_IO
+ }
+
+ # Set flag modified
+ set_modified
+ }
+
+ ## Reevaluate array of MCU port pins engaged by this device
+ # @return void
+ private method evaluete_enaged_pins {} {
+ # Mark all as disengaged and infrom PALE
+ for {set port 0} {$port < 5} {incr port} {
+ for {set bit 0} {$bit < 8} {incr bit} {
+ if {$enaged($port,$bit)} {
+ $project pale_disengage_pin_by_input_device $port $bit $this
+ set enaged($port,$bit) 0
+ }
+ }
+ }
+
+ # Find the engaged ones and infrom PALE
+ for {set i 0} {$i < 1} {incr i} {
+ set port $connection_port($i)
+ set bit $connection_pin($i)
+
+ if {$port == {-} || $bit == {-}} {
+ continue
+ }
+
+ set enaged($port,$bit) 1
+ $project pale_engage_pin_by_input_device $port $bit $this
+ }
+ }
+
+ ## Invoke interrupt monitor window
+ # @return void
+ private method create_gui {} {
+ set dialog_opened 1
+
+ # Create window
+ set win [toplevel .virtual_uart_term$count -class [mc "UART Monitor"] -bg ${::COMMON_BG_COLOR}]
+ incr count
+
+ # 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
+
+ set main_frame [frame $win.main_frame]
+ create_top_frame $main_frame ;# Create top frame
+ create_bottom_frame $main_frame ;# Create bottom frame
+ pack $main_frame -fill both -expand 1
+
+ # Configure window
+ wm title $win "[mc $component_name] - [$project cget -projectName] - MCU 8051 IDE"
+ wm iconphoto $win ::ICONS::16::_chardevice
+ wm resizable $win 0 0
+ wm protocol $win WM_DELETE_WINDOW [list $this close_window]
+ bindtags $win [list $win Toplevel all .]
+ }
+
+ ## Create the log dialog window, but do not show it until method show_log is called
+ # @return void
+ public method create_log {} {
+ # Create the dialog window (hidden for now)
+ set dialog $win.log_window
+ toplevel $dialog
+ wm withdraw $dialog
+
+ ## Create main frame (text and scrollbar)
+ set main_frame [frame $dialog.main_frame]
+ # Text widget
+ set text_widget [text $main_frame.text \
+ -width 0 -height 0 -font $hlp_normal_font \
+ -yscrollcommand [list $main_frame.scrollbar set] \
+ -wrap word -padx 5 -pady 5 -state disabled \
+ ]
+ set log_win_text $text_widget
+ bindtags $text_widget [list $text_widget Text $win all .]
+ pack $text_widget -side left -fill both -expand 1
+ # Create text tag in the text widget
+ $text_widget tag configure tag_info -foreground {#FFFFFF} -background {#0000EE}
+ $text_widget tag configure tag_warning -foreground {#FFFFFF} -background {#EE8800}
+ $text_widget tag configure tag_error -foreground {#FFFFFF} -background {#DD0000}
+ $text_widget tag configure tag_line \
+ -background {#DDDDDD} \
+ -font [font create \
+ -family ${::DEFAULT_FIXED_FONT} \
+ -size -1 \
+ ]
+
+ # Scrollbar
+ pack [ttk::scrollbar $main_frame.scrollbar \
+ -orient vertical \
+ -command [list $text_widget yview] \
+ ] -side right -fill y
+ # Finalize ...
+ pack $main_frame -fill both -expand 1 -padx 2
+
+ # Create bottom frame
+ set bottom_frame [frame $dialog.bottom_frame]
+ # Button "Close"
+ pack [ttk::button $bottom_frame.close_button \
+ -text [mc "Close"] \
+ -compound left \
+ -image ::ICONS::16::button_cancel \
+ -command [list $this close_log_win] \
+ ] -side right
+ pack [ttk::button $bottom_frame.clear_button \
+ -text [mc "Clear log"] \
+ -compound left \
+ -image ::ICONS::16::editdelete \
+ -command "
+ $text_widget configure -state normal
+ $text_widget delete 0.0 end
+ $text_widget configure -state disabled
+ " \
+ ] -side left
+ # CheckBox: "Enable log"
+ set log_on_off_chbut [checkbutton $bottom_frame.on_off_chbut \
+ -command [list $this log_on_off] \
+ -text [mc "Enable log"] \
+ ]
+ if {$log_enabled} {
+ $log_on_off_chbut select
+ } else {
+ $log_on_off_chbut deselect
+ }
+ setStatusTip -widget $log_on_off_chbut -text [mc "Disabled logging may notably improve simulation speed"]
+ DynamicHelp::add $log_on_off_chbut -text [mc "Disabled logging may notably improve simulation speed"]
+ pack $log_on_off_chbut -side left -padx 5
+ pack $bottom_frame -pady 2 -padx 5 -fill x
+
+ # Set window parameters
+ wm minsize $dialog [expr {int(300 * $::font_size_factor)}] [expr {int(150 * $::font_size_factor)}]
+ wm iconphoto $dialog ::ICONS::16::bar5
+ wm title $dialog [mc "UART simulator log - MCU 8051 IDE"]
+ wm protocol $dialog WM_DELETE_WINDOW [list $this close_log_win]
+ bindtags $dialog [list $dialog Toplevel $win all .]
+ }
+
+ ## Show the log window
+ # The log window must have been once created by method create_log prior to
+ #+ the call to this method
+ # @return void
+ public method show_log {} {
+ if {$warning_indicator != {}} {
+ destroy $warning_indicator
+ set warning_indicator {}
+ }
+
+ set dialog $win.log_window
+ if {[wm state $dialog] == {normal}} {
+ raise $dialog
+ return
+ }
+ if {![winfo exists $dialog]} {
+ return
+ }
+ wm deiconify $dialog
+ if {$log_window_geometry != {}} {
+ wm geometry $dialog $log_window_geometry
+ }
+ }
+
+ ## Enable or disable logging of events
+ # @return void
+ public method log_on_off {} {
+ set log_enabled [expr {!$log_enabled}]
+
+ # Set flag modified
+ set_modified
+ }
+
+ ## Close the DS1620 log window
+ # @return void
+ public method close_log_win {} {
+ set dialog $win.log_window
+ if {![winfo exists $dialog]} {
+ return
+ }
+
+ set log_window_geometry [wm geometry $dialog]
+ wm withdraw $dialog
+ }
+
+ ## Set status bar tip for specified widget
+ # @parm Widget widget - Target widget
+ # @parm String text - Text of the stutus tip
+ # @return void
+ private method termial_set_status_tip {widget text} {
+ bind $widget <Enter> "$status_bar_label configure -text {$text}"
+ bind $widget <Leave> "$status_bar_label configure -text {}"
+ }
+
+ private method create_top_top_frame {target_frame} {
+ set target_frame [frame $target_frame.target_frame -pady 5 -padx 5]
+ set controls_frame $target_frame
+
+ # - Baud rate
+ grid [label $target_frame.baud_lbl \
+ -text [mc "Baud rate"] \
+ ] -row 1 -column 5 -sticky w
+ set baud_cb [ttk::combobox $target_frame.baud_cb \
+ -state readonly \
+ -width 6 \
+ -exportselection 0 \
+ -values $available_baud_rates \
+ ]
+ bind $baud_cb <<ComboboxSelected>> \
+ "$this change_port_config b \[$target_frame.baud_cb get\]"
+ termial_set_status_tip $baud_cb [mc "Connection speed in bps"]
+ grid $baud_cb -row 1 -column 6 -sticky w
+ $target_frame.baud_cb current [lsearch [$target_frame.baud_cb cget -values] $baud_conf]
+ # - Parity
+ grid [label $target_frame.parity_lbl \
+ -text [mc "Parity"] \
+ ] -row 2 -column 5 -sticky w
+ set parity_cb [ttk::combobox $target_frame.parity_cb \
+ -values {none odd even} \
+ -state readonly \
+ -width 6 \
+ -exportselection 0 \
+ ]
+ bind $parity_cb <<ComboboxSelected>> \
+ "$this change_port_config p \[$target_frame.parity_cb get\]"
+ termial_set_status_tip $parity_cb [mc "Parity"]
+ grid $parity_cb -row 2 -column 6 -sticky w
+ $target_frame.parity_cb current [lsearch {n o e m s} $parity_conf]
+ # - Data bits
+ grid [label $target_frame.data_lbl \
+ -text [mc "Data bits"] \
+ ] -row 1 -column 8 -sticky w
+ set data_cb [ttk::combobox $target_frame.data_cb \
+ -state readonly \
+ -width 1 \
+ -values {5 6 7 8} \
+ -exportselection 0 \
+ ]
+ bind $data_cb <<ComboboxSelected>> \
+ "$this change_port_config d \[$target_frame.data_cb get\]"
+ termial_set_status_tip $data_cb [mc "Number of data bits"]
+ grid $data_cb -row 1 -column 9 -sticky w
+ $target_frame.data_cb current [lsearch [$target_frame.data_cb cget -values] $data_conf]
+ # - Stop bits
+ grid [label $target_frame.stop_lbl \
+ -text [mc "Stop bits"] \
+ ] -row 2 -column 8 -sticky w
+ set stop_cb [ttk::combobox $target_frame.stop_cb \
+ -state readonly \
+ -width 1 \
+ -values {1 2} \
+ -exportselection 0 \
+ ]
+ bind $stop_cb <<ComboboxSelected>> \
+ "$this change_port_config s \[$target_frame.stop_cb get\]"
+ termial_set_status_tip $stop_cb [mc "Number of stop bits"]
+ grid $stop_cb -row 2 -column 9 -sticky w
+ $target_frame.stop_cb current [lsearch [$target_frame.stop_cb cget -values] $stop_conf]
+
+ # Create "ON/OFF" button
+ set start_stop_button [ttk::button $target_frame.start_stop_button \
+ -command [list $this on_off_button_press] \
+ -style Flat.TButton \
+ -width 3 \
+ ]
+ DynamicHelp::add $target_frame.start_stop_button \
+ -text [mc "Turn HW simulation on/off"]
+ setStatusTip -widget $start_stop_button -text [mc "Turn HW simulation on/off"]
+ bind $start_stop_button <Button-3> "$this on_off_button_press; break"
+ bindtags $start_stop_button [list $start_stop_button TButton all .]
+ grid $start_stop_button -row 1 -column 1 -sticky w
+
+ # Create configuration menu button
+ set conf_button [ttk::button $target_frame.conf_but \
+ -image ::ICONS::16::configure \
+ -style Flat.TButton \
+ -command [list $this config_menu] \
+ ]
+ setStatusTip -widget $conf_button -text [mc "Configure"]
+ bindtags $conf_button [list $conf_button TButton all .]
+ grid $conf_button -row 1 -column 2 -sticky w
+
+ grid [label $target_frame.note_lbl \
+ -text [mc "Note:"] \
+ ] -row 2 -column 1 -sticky w
+ set usr_note [ttk::entry $target_frame.usr_note \
+ -validate key \
+ -validatecommand [list $this set_modified] \
+ -width 30 \
+ ]
+ bindtags $usr_note [list $usr_note TEntry all .]
+ grid $usr_note -row 2 -column 2 -sticky w
+
+ grid columnconfigure $target_frame 4 -weight 1
+ grid columnconfigure $target_frame 7 -minsize 10
+
+ return $target_frame
+ }
+
+ ##
+ # @parm Widget target_frame - Parent frame
+ # @return Widget - Created frame
+ private method create_sbuf_t_frame {target_frame} {
+ set sbuf_t_frame [frame $target_frame.sbuf_t_frame]
+ set sbuf_t_canvas [canvas $sbuf_t_frame.sbuf_t_canvas \
+ -bg $::COMMON_BG_COLOR \
+ -width 250 \
+ -height 60 \
+ -highlightthickness 0 \
+ ]
+ set canvas $sbuf_t_canvas
+
+ set cb(p0) [ttk::combobox $canvas.cb_p0 \
+ -width 1 \
+ -font $cb_font \
+ -state readonly \
+ ]
+ bind $cb(p0) <<ComboboxSelected>> [list $this reconnect 0]
+ bindtags $cb(p0) [list $cb(p0) TCombobox all .]
+
+ set cb(b0) [ttk::combobox $canvas.cb_b0 \
+ -width 1 \
+ -font $cb_font \
+ -values {- 0 1 2 3 4 5 6 7} \
+ -state readonly \
+ ]
+ bind $cb(b0) <<ComboboxSelected>> [list $this reconnect 0]
+ bindtags $cb(b0) [list $cb(b0) TCombobox all .]
+
+ $canvas create text 45 0 \
+ -text {TxD} \
+ -font ${::Simulator_GUI::bitfont} \
+ -anchor ne
+ $canvas create window 30 40 \
+ -window $cb(p0) \
+ -anchor ne
+ $canvas create window 30 40 \
+ -window $cb(b0) \
+ -anchor nw
+ $canvas create text 45 20 \
+ -text {SBUF-T} \
+ -font ${::Simulator_GUI::bitfont} \
+ -anchor ne
+ $canvas create text 210 0 \
+ -text {Parity} \
+ -font ${::Simulator_GUI::bitfont} \
+ -anchor nw
+ set reg_val(txd) [$canvas create text 210 20 \
+ -text { -- } \
+ -font ${::Simulator_GUI::bitfont} \
+ -anchor nw \
+ ]
+
+ set labels [list S 0 1 2 3 4 5 6 7 P S]
+
+ set x 50
+ set y 20
+ for {set i 0} {$i < 11} {incr i} {
+ if {$i == 1 || $i == 9 || $i == 10} {
+ incr x 3
+ } else {
+ incr x 1
+ }
+
+ set bit_rect(t,$i) [$canvas create rectangle $x $y \
+ [expr {$x + $rect_size}] [expr {$y + $rect_size}] \
+ -fill $empty_fill -outline $empty_outline \
+ ]
+ $canvas create text \
+ [expr {$x + ($rect_size / 2)}] \
+ [expr {$y + ($rect_size / 2)}] \
+ -text [lindex $labels $i] \
+ -font $tiny_font
+
+ incr x $rect_size
+ }
+
+ # Create dash line pointing to parity bit
+ set pos [expr {55 + $rect_size + 9 * ($rect_size + 1) - ($rect_size + 1) / 2}]
+ $canvas create line 210 6 $pos 6 $pos 20 -arrow none -dash {,}
+
+ # Draw graph grid
+ for {set x 65} {$x < 250} {incr x 5} {
+ $canvas create line $x 43 $x 58 -fill {#AAAAAA} -tags grid -dash .
+ }
+
+ pack $sbuf_t_canvas -padx 5 -pady 5 -fill x
+ return $sbuf_t_frame
+ }
+
+ ##
+ # @parm Widget target_frame - Parent frame
+ # @return Widget - Created frame
+ private method create_sbuf_r_frame {target_frame} {
+ set sbuf_r_frame [frame $target_frame.sbuf_r_frame]
+ set sbuf_r_canvas [canvas $sbuf_r_frame.sbuf_r_canvas \
+ -bg $::COMMON_BG_COLOR \
+ -width 250 \
+ -height 60 \
+ -highlightthickness 0 \
+ ]
+ set canvas $sbuf_r_canvas
+
+ set cb(p1) [ttk::combobox $canvas.cb_p1 \
+ -width 1 \
+ -font $cb_font \
+ -state readonly \
+ ]
+ bind $cb(p1) <<ComboboxSelected>> [list $this reconnect 1]
+ bindtags $cb(p1) [list $cb(p1) TCombobox all .]
+
+ set cb(b1) [ttk::combobox $canvas.cb_b1 \
+ -width 1 \
+ -font $cb_font \
+ -values {- 0 1 2 3 4 5 6 7} \
+ -state readonly \
+ ]
+ bind $cb(b1) <<ComboboxSelected>> [list $this reconnect 1]
+ bindtags $cb(b1) [list $cb(b1) TCombobox all .]
+
+ $canvas create text 45 0 \
+ -text {RxD} \
+ -font ${::Simulator_GUI::bitfont} \
+ -anchor ne
+ $canvas create window 30 40 \
+ -window $cb(p1) \
+ -anchor ne
+ $canvas create window 30 40 \
+ -window $cb(b1) \
+ -anchor nw
+ $canvas create text 45 20 \
+ -text {SBUF-R} \
+ -font ${::Simulator_GUI::bitfont} \
+ -anchor ne
+ $canvas create text 210 0 \
+ -text {Parity} \
+ -font ${::Simulator_GUI::bitfont} \
+ -anchor nw
+ set reg_val(rxd) [$canvas create text 210 20 \
+ -text { -- } \
+ -font ${::Simulator_GUI::bitfont} \
+ -anchor nw \
+ ]
+
+ set labels [list S 0 1 2 3 4 5 6 7 P S]
+
+ set x 50
+ set y 20
+ for {set i 0} {$i < 11} {incr i} {
+ if {$i == 1 || $i == 9 || $i == 10} {
+ incr x 3
+ } else {
+ incr x 1
+ }
+
+ set bit_rect(r,$i) [$canvas create rectangle $x $y \
+ [expr {$x + $rect_size}] [expr {$y + $rect_size}] \
+ -fill $empty_fill -outline $empty_outline \
+ ]
+ $canvas create text \
+ [expr {$x + ($rect_size / 2)}] \
+ [expr {$y + ($rect_size / 2)}] \
+ -font $tiny_font \
+ -text [lindex $labels $i]
+
+ incr x $rect_size
+ }
+
+ set_bit_arrow r 0
+
+ set pos [expr {55 + $rect_size + 9 * ($rect_size + 1) - ($rect_size + 1) / 2}]
+ $canvas create line 210 6 $pos 6 $pos 20 -arrow none -dash {,}
+
+ # Draw graph grid
+ for {set x 65} {$x < 250} {incr x 5} {
+ $canvas create line $x 43 $x 58 -fill {#AAAAAA} -tags grid -dash .
+ }
+
+ pack $sbuf_r_canvas -padx 5 -pady 5 -fill x
+ return $sbuf_r_frame
+ }
+
+ ## 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} {
+ grid [create_top_top_frame $target_frame] -row 1 -column 1 -sticky nwes -columnspan 4 -padx 1
+ grid [create_sbuf_t_frame $target_frame] -row 2 -column 1 -sticky nwes -columnspan 2 -padx 1
+ grid [create_sbuf_r_frame $target_frame] -row 2 -column 3 -sticky nwes -columnspan 2 -padx 1
+ }
+
+ ## 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 4 -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 4 -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 [list $this hexeditor_selection s]
+ grid $target_frame.send_hexeditor -row 5 -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 [list $this hexeditor_selection r]
+ $receive_hexeditor set_bg_hg $reception_address 1 0
+ grid $target_frame.receive_hexeditor -row 5 -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 [list $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 [list $this clear_selected_snd]\
+ -compound left \
+ -state disabled \
+ ]
+ termial_set_status_tip $send_selected_button [mc "Send selected data"]
+ termial_set_status_tip $clear_selected_snd_button [mc "Remove selected data"]
+ grid $send_selected_button -row 6 -column 1 -sticky we
+ grid $clear_selected_snd_button -row 6 -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 [list $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 [list $this clear_selected_rec]\
+ -compound left \
+ -state disabled \
+ ]
+ termial_set_status_tip $receive_here_button [mc "Receive data on current cursor position"]
+ termial_set_status_tip $clear_selected_rec_button [mc "Remove selected data"]
+ grid $receive_here_button -row 6 -column 3 -sticky we
+ grid $clear_selected_rec_button -row 6 -column 4 -sticky we
+ }
+
+ ## Determinate which port pin is connected to the specified LED
+ # @parm Int i - LED number
+ # @return List - {port_number bit_number}
+ private method which_port_pin {i} {
+ return [list $connection_port($i) $connection_pin($i)]
+ }
+
+ ## Handle "ON/OFF" button press
+ # Turn whole PALE system on or off
+ # @return void
+ public method on_off_button_press {} {
+ $project pale_all_on_off
+ }
+
+ 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 {}
+ }
+ }
+
+ 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 {}
+ }
+ }
+
+ public method send_selected {} {
+ # Get range of text indexes determinating the selection
+ set rangeofselection [$send_hexeditor getRangeOfSelection]
+ if {$rangeofselection == {}} {
+ return
+ }
+
+ if {$transmission_in_prog} {
+ return
+ }
+
+ set transmission_in_prog 1
+ set byte_to_send -1
+ set output_buffer [list]
+ 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
+ }
+ lappend output_buffer [expr "0x$value"]
+ }
+
+ write_to_log I [mc "TxD: Starting transmission of block"]
+
+ $send_selected_button configure \
+ -text [mc "Stop transmission"] \
+ -image ::ICONS::16::fileclose \
+ -command [$this stop_transmission]
+ }
+
+ public method hexeditor_selection {source anything_selected} {
+ if {$anything_selected} {
+ set state {normal}
+ } else {
+ set state {disabled}
+ }
+
+ if {$source == {s}} {
+ if {!$transmission_in_prog} {
+ $send_selected_button configure -state $state
+ }
+ $clear_selected_snd_button configure -state $state
+ } else {
+ $clear_selected_rec_button configure -state $state
+ }
+ }
+
+ public method change_port_config {what new_value} {
+ switch -- $what {
+ b {
+ set baud_conf $new_value
+ set bit_time [expr {1000000000.0 / $baud_conf}]
+ }
+ p {
+ switch -- $new_value {
+ {none} {
+ set new_value {n}
+ }
+ {odd} {
+ set new_value {o}
+ }
+ {even} {
+ set new_value {e}
+ }
+ }
+
+ set parity_conf $new_value
+ }
+ d {
+ set data_conf $new_value
+ }
+ s {
+ set stop_conf $new_value
+ }
+ }
+ }
+
+ ## 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
+ }
+
+ private method set_bit_color {interface bit state} {
+ if {$interface == {r}} {
+ set canvas $sbuf_r_canvas
+ } else {
+ set canvas $sbuf_t_canvas
+ }
+
+ if {$state == 1} {
+ set fill ${::BitMap::one_fill}
+ set outline ${::BitMap::one_outline}
+ } elseif {$state == 0} {
+ set fill ${::BitMap::zero_fill}
+ set outline ${::BitMap::zero_outline}
+ } elseif {$state == -1} {
+ set fill {#888888}
+ set outline {#AAAAAA}
+ }
+
+ $canvas itemconfigure $bit_rect($interface,$bit) \
+ -fill $fill \
+ -outline $outline
+ }
+
+ private method set_bit_arrow {interface position} {
+ if {$interface == {r}} {
+ set canvas $sbuf_r_canvas
+ } else {
+ set canvas $sbuf_t_canvas
+ }
+
+ if {$arrow($interface) != {}} {
+ $canvas delete $arrow($interface)
+ }
+ if {$position != -1} {
+ if {!$position} {
+ set corr 0
+ } elseif {$position >= 1 && $position <= 8} {
+ set corr 2
+ } elseif {$position == 9} {
+ set corr 4
+ } else {
+ set corr 6
+ }
+
+ set pos [expr {51 + $rect_size + $position * ($rect_size + 1) - ($rect_size + 1) / 2 + $corr}]
+ set arrow($interface) [$canvas create line 50 6 $pos 6 $pos 20 -arrow last]
+ }
+ }
+
+ private method highlight_arrow {interface highlight} {
+ if {$interface == {r}} {
+ set canvas $sbuf_r_canvas
+ } else {
+ set canvas $sbuf_t_canvas
+ }
+
+ $canvas itemconfigure $arrow($interface) -width [expr {($highlight ? 1 : 0) + 1}]
+ }
+
+ private method graph_clear {interface} {
+ if {$interface == {r}} {
+ set canvas $sbuf_r_canvas
+ } else {
+ set canvas $sbuf_t_canvas
+ }
+
+ $canvas delete graph
+
+ set graph_position($interface) 0
+ set graph_prev_state($interface) 1
+ set graph_elements($interface) [list]
+ }
+
+ private method graph_draw {interface state} {
+ if {$interface == {r}} {
+ set canvas $sbuf_r_canvas
+ } else {
+ set canvas $sbuf_t_canvas
+ }
+
+ if {$graph_position($interface) == 185} {
+ $canvas move graph -1 0
+ foreach item [lindex $graph_elements($interface) 0] {
+ $canvas delete $item
+ }
+ set graph_elements($interface) [lreplace $graph_elements($interface) 0 0]
+ incr graph_position($interface) -1
+ }
+
+ set x_0 [expr {65 + $graph_position($interface)}]
+ set x_1 [expr {$x_0 + 1}]
+
+ switch -- $graph_prev_state($interface) {
+ 0 {
+ switch -- $state {
+ 0 { ;# 0 --> 0
+ lappend graph_elements($interface) [list \
+ [$canvas create line $x_0 58 $x_1 58 -tags graph -fill {#00FF00}] \
+ ]
+ }
+ 1 { ;# 0 --> 1
+ lappend graph_elements($interface) [list \
+ [$canvas create line $x_0 43 $x_0 50 -tags graph -fill {#FF0000}] \
+ [$canvas create line $x_0 50 $x_0 58 -tags graph -fill {#00FF00}] \
+ ]
+ }
+ default {
+ lappend graph_elements($interface) [list \
+ [$canvas create line $x_0 43 $x_0 58 -tags graph -fill {#0000FF}] \
+ ]
+ }
+ }
+ }
+ 1 {
+ switch -- $state {
+ 0 { ;# 1 --> 0
+ lappend graph_elements($interface) [list \
+ [$canvas create line $x_0 43 $x_0 50 -tags graph -fill {#FF0000}] \
+ [$canvas create line $x_0 50 $x_0 58 -tags graph -fill {#00FF00}] \
+ ]
+ }
+ 1 { ;# 1 --> 1
+ lappend graph_elements($interface) [list \
+ [$canvas create line $x_0 43 $x_1 43 -tags graph -fill {#FF0000}] \
+ ]
+ }
+ default {
+ lappend graph_elements($interface) [list \
+ [$canvas create line $x_0 43 $x_0 58 -tags graph -fill {#0000FF}] \
+ ]
+ }
+ }
+ }
+ default {
+ lappend graph_elements($interface) [list \
+ [$canvas create line $x_0 43 $x_0 58 -tags graph -fill {#0055FF}] \
+ ]
+ }
+ }
+
+ incr graph_position($interface)
+ set graph_prev_state($interface) $state
+ }
+
+ ## Write a message to the log
+ # @parm Char type - Message type "I" == Information; "W" == Warning; "E" == Error
+ # @parm String string - Text of the message
+ # @return void
+ private method write_to_log {type string} {
+ # Do not do anything if the log is not available at all
+ if {!$log_enabled || $log_win_text == {}} {
+ return
+ }
+
+ # Enable the text widget
+ $log_win_text configure -state normal
+
+ # Manage the log length, the number of row in the log must not exceed the specified maximum
+ if {int([$log_win_text index end]) > ($MAX_LOG_LENGTH + 1)} {
+ set diff [expr {int([$log_win_text index end]) - $MAX_LOG_LENGTH}]
+ $log_win_text delete 1.0 $diff.0
+ }
+ $log_win_text mark set insert {end -1l lineend}
+
+ # Insert separators (horizontal lines) between events with the same time mark
+ if {$time_mark && $log_time_mark != $time_mark} {
+ set log_time_mark $time_mark
+ $log_win_text insert insert "\n"
+ $log_win_text tag add tag_line insert-1l insert
+ }
+
+ # Insert the information about the message type
+ switch -- $type {
+ {I} { ;# Information
+ $log_win_text insert insert [mc "\[INFO\] "]
+ $log_win_text tag add tag_info {insert linestart} insert-1c
+ }
+ {W} { ;# Warning
+ $log_win_text insert insert [mc "\[WARNING\] "]
+ $log_win_text tag add tag_warning {insert linestart} insert-1c
+ }
+ {E} { ;# Error
+ $log_win_text insert insert [mc "\[ERROR\] "]
+ $log_win_text tag add tag_error {insert linestart} insert-1c
+ }
+ }
+
+ # Insert the message itself
+ $log_win_text insert insert $string
+ $log_win_text insert insert "\n"
+ $log_win_text see insert
+
+ # Disable the text widget
+ $log_win_text configure -state disabled
+
+ #
+ if {$type == {E} && $warning_indicator == {}} {
+ set warning_indicator [label $controls_frame.w_lbl \
+ -image ::ICONS::16::status_unknown \
+ -cursor hand2 \
+ ]
+ grid $warning_indicator -row 2 -column 4
+ bind $warning_indicator <Button-1> [list $this show_log]
+ }
+ }
+
+ # ------------------------------------------------------------------
+ # UART SIMULATOR CORE
+ # ------------------------------------------------------------------
+
+ private method transmission_control {{txd {}}} {
+ if {!$transmission_in_prog} {
+ return $txd
+ }
+
+ if {$byte_to_send == -1} {
+ if {[manage_output_buffer $txd]} {
+ return $txd
+ }
+ }
+
+ if {$time_mark >= $transmission_sample_time} {
+ if {$time_mark >= ($transmission_sample_time + $bit_time)} {
+ write_to_log E [mc "Simulated MCU has clock frequency set too low to even receive the transmitted data!"]
+ } else {
+ stop_transmission 1
+ update_last_txd $txd
+ }
+ }
+
+ return $last_txd
+ }
+
+ private method manage_output_buffer {txd} {
+ if {![llength $output_buffer]} {
+ set transmission_in_prog 0
+
+ $sbuf_t_canvas itemconfigure $reg_val(txd) -text { -- }
+ for {set i 0} {$i < 11} {incr i} {
+ set_bit_color t $i -1
+ }
+
+ highlight_arrow t 0
+ set_bit_arrow t -1
+
+ write_to_log I [mc "TxD: Transmission of block finished"]
+
+ return 1
+ }
+
+ set byte_to_send [lindex $output_buffer 0]
+ set output_buffer [lreplace $output_buffer 0 0]
+ set transmission_bit_no -1
+ set transmission_sample_time 0
+
+ $sbuf_t_canvas itemconfigure $reg_val(txd) -text [format {0x%02X} $byte_to_send]
+
+ set_bit_color t 0 0
+ for {set i 1} {$i <= $data_conf} {incr i} {
+ set_bit_color t $i [expr {$byte_to_send & (1 << ($i - 1))}]
+ }
+ for {set i $data_conf} {$i < 8} {incr i} {
+ set_bit_color t $i -1
+ }
+ if {$parity_conf != {n}} {
+ set_bit_color t 9 [compute_parity $byte_to_send]
+ } else {
+ set_bit_color t 9 -1
+ }
+ set_bit_color t 10 1
+ set_bit_arrow t 0
+ highlight_arrow t 1
+
+ write_to_log I [mc "TxD: Starting transmission of byte: 0x%02X" $byte_to_send]
+
+ return 0
+ }
+
+ private method update_last_txd {txd} {
+ if {$transmission_bit_no == -1} {
+ set transmission_sample_time [expr {$time_mark + $bit_time}]
+ } else {
+ set transmission_sample_time [expr {$transmission_sample_time + $bit_time}]
+ }
+
+ # Send START bit
+ if {$transmission_bit_no == -1} {
+ set txd 0
+ set transmission_bit_no 0
+
+ # Send DATA bit
+ } elseif {$transmission_bit_no < $data_conf} {
+ set txd [expr {($byte_to_send & (1 << $transmission_bit_no)) ? 1 : 0}]
+ incr transmission_bit_no
+
+ # Send PARITY or STOP bit
+ } elseif {$transmission_bit_no == $data_conf} {
+ if {$parity_conf != {n}} {
+ set txd [compute_parity $byte_to_send]
+ set transmission_bit_no 9
+ } else {
+ set txd 1
+ set transmission_bit_no 10
+ }
+
+ # Send STOP bit
+ } elseif {$transmission_bit_no == 9} {
+ set txd 1
+ set transmission_bit_no 10
+
+ # Send STOP bit / End of transmission
+ } elseif {$transmission_bit_no == 10} {
+ set txd 1
+ if {$stop_conf == 1} {
+ write_to_log I [mc "TxD: Transmission of byte: 0x%02X complete" $byte_to_send]
+ set byte_to_send -1
+ } else {
+ set transmission_bit_no 11
+ }
+
+ # End of transmission
+ } elseif {$transmission_bit_no == 11} {
+ write_to_log I [mc "TxD: Transmission of byte: 0x%02X complete" $byte_to_send]
+ set byte_to_send -1
+ }
+
+ if {$transmission_bit_no < 11} {
+ set_bit_arrow t $transmission_bit_no
+ }
+
+ set last_txd $txd
+ }
+
+ public method stop_transmission {{internal_error 0}} {
+ set output_buffer {}
+ set byte_to_send -1
+
+ $sbuf_t_canvas itemconfigure $reg_val(txd) -text { -- }
+ $send_selected_button configure \
+ -text [mc "Send selected"] \
+ -image ::ICONS::16::forward \
+ -command [list $this send_selected]
+
+ if {$internal_error} {
+ write_to_log I [mc "TxD: Transmission TERMINATED on user request"]
+ } else {
+ write_to_log W [mc "TxD: Transmission TERMINATED due to an error"]
+ }
+ }
+
+ private method reception_control {} {
+ if {$reception_in_progress} {
+ if {$time_mark >= $reception_sample_time} {
+ set reception_data [expr {$reception_data | (($rxd_signal ? 1 : 0) << $reception_bit_no)}]
+ set reception_sample_time [expr {$reception_sample_time + $bit_time}]
+ $sbuf_r_canvas itemconfigure $reg_val(rxd) -text [format {0x%02X} [expr {($reception_data & 0x1fe) >> 1}]]
+
+ if {$reception_bit_no < 11} {
+ set_bit_color r $reception_bit_no $rxd_signal
+ }
+
+ incr reception_bit_no
+
+ if {$reception_bit_no == ($data_conf + 1)} {
+ set reception_bit_no 9
+
+ if {$parity_conf == {n}} {
+ incr reception_bit_no
+
+ }
+ } elseif {$reception_bit_no == 10 && $stop_conf == 1} {
+ incr reception_bit_no
+ }
+
+ if {$reception_bit_no < 11} {
+ set_bit_arrow r $reception_bit_no
+ }
+ highlight_arrow r 1
+
+ if {$reception_bit_no == 12} {
+ set_bit_arrow r 0
+ highlight_arrow r 0
+ $sbuf_r_canvas itemconfigure $reg_val(rxd) -text { -- }
+ for {set i 0} {$i < 11} {incr i} {
+ set_bit_color r $i -1
+ }
+ reception_complete
+ }
+ } else {
+ highlight_arrow r 0
+ }
+ } else {
+ if {$rxd_signal_prev && !$rxd_signal} {
+ set reception_in_progress 1
+ set reception_bit_no 1
+ set reception_data 0
+ set reception_sample_time [expr {$time_mark + $bit_time * 1.5}]
+
+ set_bit_color r 0 0
+ set_bit_arrow r 1
+
+ write_to_log I [mc "RxD: Receiving byte, address = 0x%02X" $reception_address]
+ }
+ }
+ }
+
+ private method reception_complete {} {
+ set reception_in_progress 0
+
+ if {$reception_address >= 255} {
+ set reception_address 0
+ write_to_log W [mc "RxD: Reception buffer overflow"]
+ }
+
+ set data [expr {($reception_data & 0x1fe) >> 1}]
+ $receive_hexeditor setValue $reception_address $data
+ $receive_hexeditor set_bg_hg $reception_address 1 1
+
+ # Verify rceived byte
+ if {$parity_conf != {n}} {
+ if {[compute_parity $data] != (($data & 0x20) ? 1 : 0)} {
+ write_to_log E [mc "RxD: Parity flag doesn't match"]
+ }
+ }
+ if {!(($data & 0x80) ? 1 : 0) || (($stop_conf > 1) && !(($data & 0x40) ? 1 : 0))} {
+ write_to_log E [mc "RxD: Invalid STOP bit(s)"]
+ }
+
+ write_to_log I [mc "RxD: Byte received, address = 0x%02X, data = 0x%02X" $reception_address $data]
+
+ incr reception_address
+ $receive_hexeditor seeCell $reception_address
+ }
+
+ private method compute_parity {data} {
+ set count 0
+ set mask 1
+ for {set i 0} {$i < 8} {incr i} {
+ if {$data & $mask} {
+ incr count
+ }
+ set mask [expr {$mask << 1}]
+ }
+
+ set data [expr {($count % 2) ? 1 : 0}]
+ if {$parity_conf == {o}} {
+ set data [expr {!$data}]
+ }
+
+ return $data
+ }
+
+ # ------------------------------------------------------------------
+ # VIRTUAL HW COMMON INTERFACE
+ # ------------------------------------------------------------------
+
+ ## Simulated MCU has been changed
+ # @return void
+ public method mcu_changed {} {
+ # Refresh lists of possible values in port selection ComboBoxes
+ set available_ports [concat - [$project pale_get_available_ports]]
+
+ for {set i 0} {$i < 2} {incr i} {
+ $cb(p$i) configure -values $available_ports
+
+ if {[lsearch -ascii -exact $available_ports $connection_port($i)] == -1} {
+ $cb(p$i) current 0
+ set connection_port($i) {-}
+ }
+ }
+ }
+
+ ## Accept new state of ports
+ # @parm List state - Port states ( 5 x {8 x bit} -- {bit0 bit1 bit2 ... bit7} )
+ # @return void
+ #
+ # Possible bit values:
+ # '|' - High frequency
+ # 'X' - Access to external memory
+ # '?' - No volatge
+ # '-' - Indeterminable value (some noise)
+ # '=' - High forced to low
+ # '0' - Logical 0
+ # '1' - Logical 1
+ public method new_state {_state} {
+ upvar $_state state
+
+ if {$time_mark == [$project get_run_statistics 0]} {
+ return
+ }
+ set time_mark [$project get_run_statistics 0]
+ set cycles [$project pale_get_number_of_instruction_cycles]
+
+ # --------------------------------------------------------------
+ # TxD part
+ # --------------------------------------------------------------
+ set pp [which_port_pin 0]
+
+ if {[lindex $pp 0] != {-} && [lindex $pp 1] != {-}} {
+ lset state $pp [transmission_control [lindex $state $pp]]
+ } else {
+ transmission_control
+ }
+ for {set i 0} {$i < $cycles} {incr i} {
+ graph_draw t $last_txd
+ }
+
+ # --------------------------------------------------------------
+ # RxD part
+ # --------------------------------------------------------------
+ set pp [which_port_pin 1]
+
+ if {[lindex $pp 0] != {-} && [lindex $pp 1] != {-}} {
+ reception_control
+
+ set rxd_signal_prev $rxd_signal
+ set rxd_signal [lindex $state $pp]
+
+ # Convert any possible I/O signal value to Boolean value
+ switch -- $rxd_signal {
+ {0} -
+ {1} {}
+ {=} {
+ set rxd_signal 0
+ }
+ default {
+ write_to_log E [mc "RxD: Input corrupted!"]
+ }
+ }
+
+ for {set i 0} {$i < $cycles} {incr i} {
+ graph_draw r [$project pale_RRPPV $pp $i]
+ }
+ }
+ }
+
+ ## Withdraw panel window from the screen
+ # @return void
+ public method withdraw_window {} {
+ wm withdraw $win
+ }
+
+ ## Get panel configuration list (usable with method "set_config")
+ # @return List - configuration list
+ public method get_config {} {
+ return [list \
+ $class_name \
+ [list \
+ [array get connection_port] \
+ [array get connection_pin] \
+ [wm geometry $win] \
+ [$usr_note get] \
+ $baud_conf \
+ $parity_conf \
+ $data_conf \
+ $stop_conf \
+ [$send_hexeditor get_values 0 255] \
+ [$send_hexeditor getCurrentCell] \
+ [$receive_hexeditor get_values 0 255] \
+ [$receive_hexeditor getCurrentCell] \
+ $reception_address \
+ [wm geometry $win.log_window] \
+ [wm state $win.log_window] \
+ $keep_win_on_top \
+ ] \
+ ]
+ }
+
+ ## Set panel configuration from list gained from method "get_config"
+ # @parm List state - Configuration list
+ # @return void
+ public method set_config {state} {
+ # Load connections to the MCU
+ array set connection_port [lindex $state 0]
+ array set connection_pin [lindex $state 1]
+
+ # Restore window geometry
+ if {[string length [lindex $state 2]]} {
+ wm geometry $win [regsub {^\=?\d+x\d+} [lindex $state 2] [join [wm size $win] {x}]]
+ }
+
+ # Load user note
+ $usr_note delete 0
+ $usr_note insert 0 [lindex $state 3]
+
+ set baud_conf [lindex $state 4]
+ set bit_time [expr {1000000000.0 / $baud_conf}]
+ set parity_conf [lindex $state 5]
+ set data_conf [lindex $state 6]
+ set stop_conf [lindex $state 7]
+
+ $baud_cb current [lsearch [$baud_cb cget -values] $baud_conf]
+ $parity_cb current [lsearch {n o e} $parity_conf]
+ $data_cb current [lsearch [$data_cb cget -values] $data_conf]
+ $stop_cb current [lsearch [$stop_cb cget -values] $stop_conf]
+
+ for {set i 0} {$i < 0x100} {incr i} {
+ $send_hexeditor setValue $i [lindex $state [list 8 $i]]
+ }
+ $send_hexeditor setCurrentCell [lindex $state 9]
+ for {set i 0} {$i < 0x100} {incr i} {
+ $receive_hexeditor setValue $i [lindex $state [list 10 $i]]
+ }
+ $receive_hexeditor setCurrentCell [lindex $state 11]
+ set reception_address [lindex $state 12]
+ $receive_hexeditor clearBgHighlighting 0
+ $receive_hexeditor set_bg_hg $reception_address 1 0
+
+ # Display the log window
+ set log_window_geometry [lindex $state 13]
+ if {[lindex $state 14] == {normal}} {
+ show_log
+ }
+
+ if {[lindex $state 15] != {}} {
+ set keep_win_on_top [lindex $state 15]
+ if {$keep_win_on_top} {
+ wm attributes $win -topmost 1 -alpha 0.8
+ }
+ }
+
+ # Restore state of ComboBoxes
+ for {set i 0} {$i < 2} {incr i} {
+ ## PIN
+ set pin $connection_pin($i)
+ if {$pin != {-}} {
+ set pin [expr {7 - $pin}]
+ }
+ set idx [lsearch -ascii -exact \
+ [$cb(b$i) cget -values] \
+ $pin \
+ ]
+ if {$idx == -1} {
+ set idx 0
+ }
+ $cb(b$i) current $idx
+
+ ## PORT
+ set idx [lsearch -ascii -exact \
+ [$cb(p$i) cget -values] \
+ $connection_port($i) \
+ ]
+ if {$idx == -1} {
+ set idx 0
+ }
+ $cb(p$i) current $idx
+ }
+
+ # Adjust internal logic and the rest of PALE
+ evaluete_enaged_pins
+ $project pale_reevaluate_IO
+ update
+
+ if {[catch {
+ # Fail
+ }]} then {
+ puts "Unable to load configuration for $class_name"
+ return 0
+
+ # Success
+ } else {
+ clear_modified
+ return 1
+ }
+ }
+
+ ## Simulated MCU has been reseted
+ # @return void
+ public method reset {} {
+ set state [$project pale_get_true_state]
+ new_state state
+
+ graph_clear t
+ graph_clear r
+ }
+
+
+ # ------------------------------------------------------------------
+ # VIRTUAL HW COMMON INTERFACE -- CALLED FROM THE BASE CLASS
+ # ------------------------------------------------------------------
+
+ ## This method is called before configuration menu invocation
+ # @return void
+ public method config_menu_special {} {
+ set ::${class_name}::menu_keep_win_on_top $keep_win_on_top
+ }
+
+ ## This method is called after configuration menu has beed created
+ # @return void
+ public method create_config_menu_special {} {
+ }
+
+ ## This method is called to fill in the help dialog
+ # @parm Widget text_widget - Target text widget
+ # @return void
+ #
+ # Note: There is defined text tag "tag_bold" in the text widget
+ public method show_help_special {text_widget} {
+ }
+
+ ## This method is called before panel window closure
+ # @return void
+ public method close_window_special {} {
+ }
+
+ ## Commit new on/off state
+ # @return void
+ public method on_off_special {} {
+ if {[$project pale_is_enabled]} {
+ graph_clear t
+ graph_clear r
+ }
+ }
+}
+
+# >>> File inclusion guard
+}
+# <<< File inclusion guard