summaryrefslogtreecommitdiff
path: root/lib/pale
diff options
context:
space:
mode:
authorAndrej Shadura <andrewsh@debian.org>2018-05-08 15:59:31 +0200
committerAndrej Shadura <andrewsh@debian.org>2018-05-08 15:59:31 +0200
commit47aa8b00b2b11df13a100489e0f904a4947177ef (patch)
treeb35c9acc778ea2f761f3c549f7bee2f4491b3144 /lib/pale
parent5b8466f7fae0e071c0f4eda13051c93313910028 (diff)
Import Upstream version 1.4.7
Diffstat (limited to 'lib/pale')
-rw-r--r--lib/pale/ds1620.tcl1730
-rw-r--r--lib/pale/file_interface.tcl983
-rw-r--r--lib/pale/hd44780_cgrom.tcl1624
-rw-r--r--lib/pale/lcd_hd44780.tcl2954
-rw-r--r--[-rwxr-xr-x]lib/pale/leddisplay.tcl133
-rw-r--r--[-rwxr-xr-x]lib/pale/ledmatrix.tcl132
-rw-r--r--[-rwxr-xr-x]lib/pale/ledpanel.tcl97
-rw-r--r--[-rwxr-xr-x]lib/pale/matrixkeypad.tcl110
-rw-r--r--[-rwxr-xr-x]lib/pale/multiplexedleddisplay.tcl142
-rw-r--r--[-rwxr-xr-x]lib/pale/pale.tcl185
-rw-r--r--[-rwxr-xr-x]lib/pale/simplekeypad.tcl108
-rw-r--r--[-rwxr-xr-x]lib/pale/virtual_hw_component.tcl142
-rw-r--r--lib/pale/virtual_uart_term.tcl1682
13 files changed, 9641 insertions, 381 deletions
diff --git a/lib/pale/ds1620.tcl b/lib/pale/ds1620.tcl
new file mode 100644
index 0000000..7c1df63
--- /dev/null
+++ b/lib/pale/ds1620.tcl
@@ -0,0 +1,1730 @@
+#!/usr/bin/tclsh
+# Part of MCU 8051 IDE ( http://mcu8051ide.sf.net )
+
+############################################################################
+# Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012 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 _DS1620_TCL ] } {
+set _DS1620_TCL _
+# <<< File inclusion guard
+
+
+# --------------------------------------------------------------------------
+# DESCRIPTION
+#
+# Consists of:
+# INTERNAL APPLICATION LOGIC
+# VIRTUAL HW COMMON INTERFACE -- CALLED FROM PALE ENGINE
+# VIRTUAL HW COMMON INTERFACE -- CALLED FROM THE BASE CLASS
+# --------------------------------------------------------------------------
+
+class Ds1620 {
+ inherit VirtualHWComponent
+
+ # 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} \
+ ]
+ # Font: Font to be used in the panel -- bold
+ common small_font [font create \
+ -size [expr {int(-9 * $::font_size_factor)}] \
+ -family {helvetica} \
+ ]
+
+ common COMPONENT_NAME "DS1620 temperature sensor" ;# Name of this component
+ common CLASS_NAME "Ds1620" ;# Name of this class
+ common COMPONENT_ICON {ds1620} ;# Icon for this panel (16x16)
+
+ # Configuration menu
+ common CONFMENU {
+ {checkbutton "Disable delays" {} {::Ds1620::_no_delays}
+ 1 0 0 {no_delays_changed}
+ ""}
+ {command {Show DS1620 log} {} 5 "show_log" {bar5}
+ "Display the log of events which are currently happening in the simulated DS1620 chip"}
+ {separator}
+ {command {Show help} {} 5 "show_help" {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" {} {::Ds1620::menu_keep_win_on_top}
+ 1 0 0 {keep_win_on_top_changed}
+ ""}
+ }
+
+ #
+ common STATUS_BITS {DONE THF TLF NVB 1 0 CPU 1SHOT}
+ common MAX_LOG_LENGTH 100 ;# Int: Maximum number of row in the log window
+ common SIGNAL_NAMES {DQ CLK RST TH TL TCOM}
+ common EEPROM_WRITE_CYCLE_TIME 10000
+ common T_CONVERSION_TIME_MS 750
+ common _no_delays 0
+
+ private variable input_error
+ private variable input_error_desc
+
+ 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 wires ;# Array of CanvasObject (line): Wire connection between the IC and the MCU
+ private variable temp_ind_y_offset
+ private variable temp_ind_x_offset
+ private variable temperature 22
+ private variable temp_point_y 0
+ private variable enaged ;# Array of Bool: enaged(port_num,bit_num) --> Is connected to this device ?
+ private variable ds1620_reg ;# Array of
+ private variable entrybox ;# Array of
+ private variable reg_bit ;# Array of
+ private variable status ;# Array of
+ private variable no_delays 0
+ private variable log_win_text {}
+ private variable warning_indicator {}
+ private variable time_mark 0 ;# Int: Time mark pointing to this point of time according to the MCU simulator engine
+ private variable keep_win_on_top 0 ;# Bool: Toplevel window
+ private variable log_time_mark 0
+ private variable log_window_geometry {}
+ private variable signal
+ 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 bit_number 0
+ private variable byte_received
+ private variable command_received 0
+ private variable reception_or_transmission 1
+ private variable receive_command_or_data 1
+ private variable number_of_bits
+ private variable data_to_send 0
+ private variable conversion_running 0
+ private variable delay_transmission 1
+ private variable communication_disabled 0
+ private variable write_to_NVM 0
+ private variable t_conversion_time_mark 0
+ private variable time_of
+ private variable pending_communication 0
+
+
+ # ------------------------------------------------------------------
+ # INTERNAL APPLICATION LOGIC
+ # ------------------------------------------------------------------
+
+ ## 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 ds1620_reg {
+ TH 30 TL 20
+ TEMP 392 PER_C 100
+ REMAIN 0 STATUS 136
+ }
+ array set signal {
+ CLK 0 CLK_prev 0
+ RST 0 RST_prev 0
+ DQ 0 DQ_prev 0
+ TH 0 TL 0
+ TCOM 0
+ }
+ array set time_of {
+ CLK_up 0 CLK_down 0
+ RST_up 0 RST_down 0
+ DQ_up 0 DQ_down 0
+ }
+ 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]
+ reset_ds1620
+ create_log
+
+ # ComboBoxes to default state
+ for {set i 0} {$i < 6} {incr i} {
+ $canvas_widget.cb_b$i current 0
+ $canvas_widget.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 $Ds1620::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..5)
+ # @return void
+ public method reconnect {i} {
+ # Adjust connections
+ set connection_port($i) [$canvas_widget.cb_p$i get]
+ set connection_pin($i) [$canvas_widget.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 < 6} {incr i} {
+ if {$i == 1 || $i == 2} {
+ continue
+ }
+
+ 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
+ }
+ }
+
+ ## Create GUI of this panel
+ # @return void
+ private method create_gui {} {
+ # Create panel window and canvas widget
+ set win [toplevel .ledpanel$count -class $component_name -bg ${::COMMON_BG_COLOR}]
+ set canvas_widget [canvas $win.canvas \
+ -bg white -width 0 -height 0 \
+ -highlightthickness 0 \
+ ]
+
+ $canvas_widget create text 85 145 \
+ -text [mc "Note"] \
+ -font $cb_font \
+ -anchor e
+ $canvas_widget create window 90 145 \
+ -window [ttk::entry $canvas_widget.usr_note \
+ -validate key \
+ -validatecommand "$this set_modified" \
+ ] \
+ -width 405 -anchor w
+ bindtags $canvas_widget.usr_note \
+ [list $canvas_widget.usr_note TEntry $win all .]
+
+
+ draw_ic_package 73 10
+ draw_combo_boxes 35 10
+ draw_temperature_indicator 245 20
+ draw_registers 280 30
+
+ adjust_temp_ind
+
+ # Create "ON/OFF" button
+ set start_stop_button [ttk::button $canvas_widget.start_stop_button \
+ -command "$this on_off_button_press" \
+ -style Flat.TButton \
+ -width 3 \
+ ]
+ DynamicHelp::add $canvas_widget.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"
+ $canvas_widget create window 30 135 -window $start_stop_button -anchor nw
+ bindtags $start_stop_button [list $start_stop_button TButton all .]
+
+ # Create configuration menu button
+ set conf_button [ttk::button $canvas_widget.conf_but \
+ -image ::ICONS::16::configure \
+ -style FlatWhite.TButton \
+ -command "$this config_menu" \
+ ]
+ setStatusTip -widget $conf_button -text [mc "Configure"]
+ $canvas_widget create window 28 135 -window $conf_button -anchor ne
+ bindtags $conf_button [list $conf_button TButton all .]
+
+ # Pack canvas
+ pack $canvas_widget -fill both -expand 1
+
+ # Set window parameters
+ wm minsize $win 500 160
+ wm iconphoto $win ::ICONS::16::$component_icon
+ wm title $win "[mc $component_name] - [$project cget -projectName] - MCU 8051 IDE"
+ wm resizable $win 0 0
+ wm protocol $win WM_DELETE_WINDOW "$this close_window"
+ bindtags $win [list $win Toplevel all .]
+ }
+
+ public method reg_bit_event {type reg bit_no} {
+ switch -- $type {
+ 1 {
+ set ds1620_reg($reg) [expr {$ds1620_reg($reg) ^ (1 << $bit_no)}]
+ update_reg $reg
+ }
+ {E} { ;# Enter
+ set bit [expr {$ds1620_reg($reg) & (1 << $bit_no)}]
+ if {$bit} {
+ set fill ${::BitMap::one_a_fill}
+ set outline ${::BitMap::one_a_outline}
+ } else {
+ set fill ${::BitMap::zero_a_fill}
+ set outline ${::BitMap::zero_a_outline}
+ }
+ $canvas_widget itemconfigure $reg_bit($reg,$bit_no) -outline $outline -fill $fill
+ $canvas_widget configure -cursor hand2
+ }
+ {L} { ;# Leave
+ set bit [expr {$ds1620_reg($reg) & (1 << $bit_no)}]
+ if {$bit} {
+ set fill ${::BitMap::one_fill}
+ set outline ${::BitMap::one_outline}
+ } else {
+ set fill ${::BitMap::zero_fill}
+ set outline ${::BitMap::zero_outline}
+ }
+ $canvas_widget itemconfigure $reg_bit($reg,$bit_no) -outline $outline -fill $fill
+ $canvas_widget configure -cursor left_ptr
+ }
+ }
+ }
+
+ private method draw_registers {x_offset y_offset} {
+ set labels [list {TH} {TL} {TEMP}]
+ for {set i 0} {$i < 3} {incr i} {
+ set reg_name [lindex $labels $i]
+
+ $canvas_widget create text \
+ [expr {$x_offset + 0}] [expr {$y_offset + ($i * 20)}] \
+ -text $reg_name \
+ -font $cb_font \
+ -anchor w
+
+ set sep 0
+ for {set j 0} {$j < 9} {incr j} {
+ set k [expr {8 - $j}]
+ set reg_bit($reg_name,$k) [$canvas_widget create rectangle \
+ [expr {$x_offset + 38 + ($j * 13) + $sep}] [expr {$y_offset + ($i * 20) - 7}] \
+ [expr {$x_offset + 38 + ($j * 13) + 10 + $sep}] [expr {$y_offset + ($i * 20) - 7 + 10}] \
+ -width 1 \
+ ]
+ switch -- $j {
+ 0 -
+ 4 {
+ incr sep 3
+ }
+ }
+
+ $canvas_widget bind $reg_bit($reg_name,$k) <Button-1> [list $this reg_bit_event 1 $reg_name $k]
+ $canvas_widget bind $reg_bit($reg_name,$k) <Enter> [list $this reg_bit_event E $reg_name $k]
+ $canvas_widget bind $reg_bit($reg_name,$k) <Leave> [list $this reg_bit_event L $reg_name $k]
+ }
+ set entrybox($reg_name) [ttk::entry $canvas_widget.reg_$reg_name \
+ -validate key \
+ -validatecommand [list $this validate_reg_entry $reg_name %P] \
+ -width 5 \
+ -font $cb_font \
+ ]
+ $canvas_widget create window \
+ [expr {$x_offset + 163}] [expr {$y_offset + ($i * 20) - 10}] \
+ -window $entrybox($reg_name) \
+ -anchor nw
+
+ $canvas_widget create text \
+ [expr {$x_offset + 202}] [expr {$y_offset + ($i * 20)}] \
+ -text {°C} \
+ -font $cb_font \
+ -anchor w
+ }
+
+ set i 7
+ set sep 0
+ foreach bit_name $STATUS_BITS {
+ set status($bit_name) [$canvas_widget create text \
+ [expr {$x_offset - 0 + $sep}] [expr {$y_offset + 70}] \
+ -text $bit_name \
+ -font $::Simulator_GUI::bitfont \
+ -anchor w
+ ]
+
+ if {$i != 3 && $i != 2} {
+ $canvas_widget bind $status($bit_name) <Enter> [list $this status_bit_event E $bit_name $i]
+ $canvas_widget bind $status($bit_name) <Leave> [list $this status_bit_event L $bit_name $i]
+ $canvas_widget bind $status($bit_name) <Button-1> [list $this status_bit_event 1 $bit_name $i]
+ } elseif {$i == 2} {
+ $canvas_widget itemconfigure $status($bit_name) -fill ${::Simulator_GUI::off_color}
+ } elseif {$i == 3} {
+ $canvas_widget itemconfigure $status($bit_name) -fill ${::Simulator_GUI::on_color}
+ }
+
+ incr i -1
+ incr sep 2
+ incr sep [expr {9 * [string length $bit_name]}]
+ }
+ }
+
+ public method validate_reg_entry {reg_name content} {
+ if {![string length $content]} {
+ return 1
+ }
+ if {[string index $content 0] == {-} && [string length $content] == 1} {
+ return 1
+ }
+ if {[regexp {^\-?\d+\.$} $content]} {
+ return 1
+ }
+
+ if {![regexp {^\-?(\d+(\.\d)?)?$} $content]} {
+ return 0
+ }
+
+ if {$content > 127.5 || $content < -128.0} {
+ return 0
+ }
+
+ if {$reg_name == {STATUS}} {
+ set ds1620_reg($reg_name) $content
+ } else {
+ set content [expr {int($content * 2)}]
+ if {$content < 0} {
+ set content [expr {$content & 0x1ff}]
+ }
+ set ds1620_reg($reg_name) $content
+ }
+ update_reg $reg_name 1
+
+ return 1
+ }
+
+ private method update_reg {reg_name {do_not_affect_entrybox 0}} {
+ if {$reg_name == {STATUS}} {
+ set i 7
+ foreach bit_name $STATUS_BITS {
+ if {$ds1620_reg(STATUS) & (1 << $i)} {
+ set color ${::Simulator_GUI::on_color}
+ } else {
+ set color ${::Simulator_GUI::off_color}
+ }
+ $canvas_widget itemconfigure $status($bit_name) -fill $color
+
+ incr i -1
+ }
+ } else {
+ for {set bit_no 0} {$bit_no < 9} {incr bit_no} {
+ set bit [expr {$ds1620_reg($reg_name) & (1 << $bit_no)}]
+ if {$bit} {
+ set outline ${::BitMap::one_outline}
+ set fill ${::BitMap::one_fill}
+ } else {
+ set outline ${::BitMap::zero_outline}
+ set fill ${::BitMap::zero_fill}
+ }
+ $canvas_widget itemconfigure $reg_bit($reg_name,$bit_no) -outline $outline -fill $fill
+ }
+
+ if {!$do_not_affect_entrybox} {
+ set dec_val [expr {$ds1620_reg($reg_name) & 0xff}]
+ if {$ds1620_reg($reg_name) & 0x100} {
+ set dec_val [expr {$dec_val - 256}]
+ }
+ set dec_val [expr {$dec_val / 2.0}]
+ $entrybox($reg_name) delete 0 end
+ $entrybox($reg_name) insert 0 $dec_val
+ }
+ }
+
+ if {$reg_name == {TEMP}} {
+ update_outputs_Th_Tl_Tcom
+ }
+ }
+
+ public method status_bit_event {type bit_name bit_no} {
+ switch -- $type {
+ {1} {
+ set ds1620_reg(STATUS) [expr {$ds1620_reg(STATUS) ^ (1 << $bit_no)}]
+ update_reg STATUS
+ }
+ {E} {
+ $canvas_widget configure -cursor hand2
+ $canvas_widget itemconfigure $status($bit_name) -font $::Simulator_GUI::bitfont_under
+ }
+ {L} {
+ $canvas_widget configure -cursor left_ptr
+ $canvas_widget itemconfigure $status($bit_name) -font $::Simulator_GUI::bitfont
+ }
+ }
+ }
+
+ private method draw_temperature_indicator {x_offset y_offset} {
+ set x $x_offset
+ set y $y_offset
+
+ set temp_ind_x_offset $x_offset
+ set temp_ind_y_offset $y_offset
+
+ for {set i 0} {$i <= 100} {incr i} {
+ $canvas_widget create line \
+ [expr {$x + 0}] [expr {$y + $i}] \
+ [expr {$x + 10}] [expr {$y + $i}] \
+ -fill [format {#%02x33%02x} [expr {255 - int($i * 2.55)}] [expr {int($i * 2.55)}]] \
+ -tags temperature_indicator
+ }
+
+ $canvas_widget create line \
+ [expr {$x - 0}] [expr {$y + 0}] \
+ [expr {$x - 15}] [expr {$y + 0}] \
+ [expr {$x + 25}] [expr {$y + 0}] \
+ [expr {$x + 10}] [expr {$y + 0}] \
+ -fill {#000000} -arrow both \
+ -tags {temperature_pointer temperature_indicator}
+
+ $canvas_widget create text [expr {$x - 40}] [expr {$y - 8}] \
+ -text {°C} \
+ -font $cb_font \
+ -anchor w \
+ -tags temperature_C
+ $canvas_widget create text [expr {$x + 50}] [expr {$y - 8}] \
+ -text {°F} \
+ -font $cb_font \
+ -anchor e \
+ -tags temperature_F
+
+
+ $canvas_widget bind temperature_indicator <Button-1> [list $this temp_ind_event 1 %y]
+ $canvas_widget bind temperature_indicator <Button-5> [list $this temp_ind_event 5]
+ $canvas_widget bind temperature_indicator <Button-4> [list $this temp_ind_event 4]
+ $canvas_widget bind temperature_indicator <B1-Motion> [list $this temp_ind_event 1 %y]
+ }
+
+ private method adjust_temp_ind {} {
+ set y [expr {100 - int(($temperature + 55) / 1.8)}]
+
+ $canvas_widget move temperature_pointer 0 [expr {$y - $temp_point_y}]
+ set temp_point_y $y
+
+ $canvas_widget itemconfigure temperature_C -text [format {%s%3.1f°C} [expr {$temperature > 0 ? "" : "-"}] $temperature]
+ $canvas_widget itemconfigure temperature_F -text [format {%s%3.1f°F} [expr {($temperature * (9.0/5) + 32) > 0 ? "" : "-"}] [expr {($temperature * (9.0/5) + 32)}]]
+ }
+
+ public method temp_ind_event {type {y 0}} {
+ switch -- $type {
+ 1 {
+ incr y -$temp_ind_y_offset
+ set temperature [expr {180 - int($y * 1.8) - 55}]
+ }
+ 4 { ;# Wheel up
+ set temperature [expr {$temperature + 0.5}]
+ }
+ 5 { ;# Wheel down
+ set temperature [expr {$temperature - 0.5}]
+ }
+ }
+
+ if {$temperature < -55} {
+ set temperature -55
+ } elseif {$temperature > 125} {
+ set temperature 125
+ }
+
+ adjust_temp_ind
+ }
+
+ private method draw_combo_boxes {x_offset y_offset} {
+ set x $x_offset
+ set y $y_offset
+
+ incr y 12
+
+ for {set i 0} {$i < 6} {incr i} {
+ $canvas_widget create window $x $y -anchor e \
+ -window [ttk::combobox $canvas_widget.cb_p$i \
+ -width 1 \
+ -font $cb_font \
+ -state readonly \
+ ]
+ bind $canvas_widget.cb_p$i <<ComboboxSelected>> "$this reconnect $i"
+
+ $canvas_widget create window $x $y -anchor w \
+ -window [ttk::combobox $canvas_widget.cb_b$i \
+ -width 1 \
+ -font $cb_font \
+ -values {- 0 1 2 3 4 5 6 7} \
+ -state readonly \
+ ]
+ bind $canvas_widget.cb_b$i <<ComboboxSelected>> "$this reconnect $i"
+
+ bindtags $canvas_widget.cb_p$i \
+ [list $canvas_widget.cb_p$i TCombobox all .]
+ bindtags $canvas_widget.cb_b$i \
+ [list $canvas_widget.cb_b$i TCombobox all .]
+
+ if {$i == 2} {
+ incr x 160
+ incr y -25
+ } else {
+ incr y 25
+ }
+ }
+
+ $canvas_widget create text \
+ [expr {$x_offset + 0}] \
+ [expr {$y_offset + 5 + 3*25}] \
+ -text [mc "PORT"] \
+ -font $cb_font \
+ -anchor e
+ $canvas_widget create text \
+ [expr {$x_offset + 5}] \
+ [expr {$y_offset + 5 + 3*25}] \
+ -text [mc "BIT"] \
+ -font $cb_font \
+ -anchor w
+
+ $canvas_widget create text \
+ [expr {$x_offset + 160}] \
+ [expr {$y_offset + 21}] \
+ -text [mc "PORT"] \
+ -font $cb_font \
+ -anchor e
+ $canvas_widget create text \
+ [expr {$x_offset + 165}] \
+ [expr {$y_offset + 21}] \
+ -text [mc "BIT"] \
+ -font $cb_font \
+ -anchor w
+ }
+
+ private method draw_ic_package {x_offset y_offset} {
+ $canvas_widget create line \
+ [expr {$x_offset + 15}] [expr {$y_offset + 0}] \
+ [expr {$x_offset + 70}] [expr {$y_offset + 0}] \
+ [expr {$x_offset + 70}] [expr {$y_offset + 100}] \
+ [expr {$x_offset + 15}] [expr {$y_offset + 100}] \
+ [expr {$x_offset + 15}] [expr {$y_offset + 0}] \
+ -fill {#000000}
+
+ $canvas_widget create text \
+ [expr {$x_offset + 42}] [expr {$y_offset + 102}] \
+ -text {DS1620} \
+ -anchor n \
+ -font [font create -family $::DEFAULT_FIXED_FONT -size -13]
+
+ set i 0
+ for {set x 0} {$x < 2} {incr x} {
+ for {set y 0} {$y < 4} {incr y} {
+ $canvas_widget create rectangle \
+ [expr {$x_offset + ($x * 70) + 0}] [expr {$y_offset + ($y * 25) + 5}] \
+ [expr {$x_offset + ($x * 70) + 15}] [expr {$y_offset + ($y * 25) + 20}] \
+ -fill {#ffffff}
+ $canvas_widget create text \
+ [expr {$x_offset + ($x * 70) + 7}] [expr {$y_offset + ($y * 25) + 13}] \
+ -text [lindex {1 2 3 4 8 7 6 5} $i] \
+ -font $cb_font
+ $canvas_widget create text \
+ [expr {$x_offset + ($x ? 39 : 10) + 7}] [expr {$y_offset + ($y * 25) + 13}] \
+ -text [lindex {DQ CLK RST GND V T T T} $i] \
+ -font $small_font \
+ -anchor w
+ if {$i > 3} {
+ $canvas_widget create text \
+ [expr {$x_offset + 45 + 7}] [expr {$y_offset + ($y * 25) + 18}] \
+ -text [lindex {{} {} {} {} dd high low com} $i] \
+ -font $small_font \
+ -anchor w
+ }
+
+ set line [$canvas_widget create line \
+ [expr {$x_offset + ($x ? 85 : -15)}] [expr {$y_offset + ($y * 25) + 12}] \
+ [expr {$x_offset + ($x ? 100 : 0)}] [expr {$y_offset + ($y * 25) + 12}] \
+ ]
+ if {$i < 3 || $i > 4} {
+ if {$i < 3} {
+ set j $i
+ } else {
+ set j [expr {$i - 2}]
+ }
+ set wires($j) $line
+
+ # GND
+ } elseif {$i == 3} {
+ $canvas_widget itemconfigure $line -fill {#00ff00}
+ $canvas_widget create line \
+ [expr {$x_offset - 15}] [expr {$y_offset + ($y * 25) + 12}] \
+ [expr {$x_offset - 15}] [expr {$y_offset + ($y * 25) + 27}] \
+ [expr {$x_offset - 7}] [expr {$y_offset + ($y * 25) + 27}] \
+ [expr {$x_offset - 23}] [expr {$y_offset + ($y * 25) + 27}] \
+ -fill {#00ff00}
+
+ # Vdd
+ } elseif {$i == 4} {
+ $canvas_widget itemconfigure $line -fill {#ff0000}
+ $canvas_widget create line \
+ [expr {$x_offset + 100}] [expr {$y_offset + ($y * 25) + 12}] \
+ [expr {$x_offset + 100}] [expr {$y_offset + ($y * 25) - 3}] \
+ -fill {#ff0000} -arrow last
+ }
+
+ incr i
+ }
+ }
+
+ $canvas_widget create arc \
+ [expr {$x_offset + 37}] [expr {$y_offset - 5}] \
+ [expr {$x_offset + 47}] [expr {$y_offset + 5}] \
+ -start 0 \
+ -extent -180
+ }
+
+ ## 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
+ }
+
+ ## 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 != {}} {
+ $canvas_widget delete $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
+ }
+ }
+
+ ## 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 "DS1620 log - MCU 8051 IDE"]
+ wm protocol $dialog WM_DELETE_WINDOW [list $this close_log_win]
+ bindtags $dialog [list $dialog Toplevel $win all .]
+ }
+
+ ## 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
+ }
+
+ ## Informs the DS1620 simulator about change of _no_delays flag (used by configuration menu)
+ # @return void
+ public method no_delays_changed {} {
+ set no_delays ${::Ds1620::_no_delays}
+ }
+
+ ## 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 [$canvas_widget create image 35 105 -anchor ne -image ::ICONS::16::status_unknown]
+ $canvas_widget bind $warning_indicator <Button-1> [list $this show_log]
+ $canvas_widget bind $warning_indicator <Enter> {%W configure -cursor hand2}
+ $canvas_widget bind $warning_indicator <Leave> {%W configure -cursor left_ptr}
+ }
+ }
+
+
+ # ------------------------------------------------------------------
+ # DS1620 INTERNAL FUNCTIONS
+ # ------------------------------------------------------------------
+
+ private method update_outputs_Th_Tl_Tcom {} {
+ set temp_dec $ds1620_reg(TEMP)
+ set th_dec $ds1620_reg(TH)
+ set tl_dec $ds1620_reg(TL)
+
+ if {$temp_dec & 0x100} {
+ incr temp_dec -512
+ }
+ if {$th_dec & 0x100} {
+ incr th_dec -512
+ }
+ if {$tl_dec & 0x100} {
+ incr tl_dec -512
+ }
+
+ if {$temp_dec > $th_dec} {
+ if {!$signal(TH)} {
+ write_to_log I [mc "Current temperature exceeds TH temperature"]
+ }
+
+ set signal(TH) 1
+ set signal(TCOM) 1
+
+ set ds1620_reg(STATUS) [expr {$ds1620_reg(STATUS) | 0x40}]
+ update_reg STATUS
+ } else {
+ set signal(TH) 0
+ }
+ if {$temp_dec < $tl_dec} {
+ if {!$signal(TL)} {
+ write_to_log I [mc "Current temperature is below TL temperature"]
+ }
+
+ set signal(TL) 1
+ set signal(TCOM) 0
+
+ set ds1620_reg(STATUS) [expr {$ds1620_reg(STATUS) | 0x20}]
+ update_reg STATUS
+ } else {
+ set signal(TL) 0
+ }
+ }
+
+ private method finalize_conversion {} {
+ # One-shot conversion mode
+ if {$ds1620_reg(STATUS) & 0x01} {
+ set conversion_running 0
+ }
+
+ if {$temperature < 0} {
+ set ds1620_reg(TEMP) [expr {512 - int($temperature * -2)}]
+ } else {
+ set ds1620_reg(TEMP) [expr {int($temperature * 2)}]
+ }
+ set ds1620_reg(STATUS) [expr {$ds1620_reg(STATUS) | 0x80}]
+ set ds1620_reg(REMAIN) [expr {int(rand() * 0x1ff)}]
+ update_reg TEMP
+ update_reg STATUS
+
+ if {!$no_delays} {
+ write_to_log I [mc "Temperature conversion finished"]
+ }
+ }
+
+ private method proceed_with_t_conversion {} {
+ if {!$t_conversion_time_mark} {
+ restart_t_conversion
+ }
+ if {$no_delays || $t_conversion_time_mark <= $time_mark} {
+ if {!$no_delays} {
+ restart_t_conversion
+ }
+ finalize_conversion
+ }
+ }
+
+ private method restart_t_conversion {} {
+ write_to_log I [mc "Temperature conversion will be completed when MCU time reach %dns" [expr {$time_mark + $T_CONVERSION_TIME_MS * 1000000}]]
+ set t_conversion_time_mark [expr {$time_mark + $T_CONVERSION_TIME_MS * 1000000}]
+ }
+
+ private method transmit_data {} {
+ if {0 && $delay_transmission} {
+ set delay_transmission 0
+ return 0
+ } else {
+ set signal(DQ) [expr {($data_to_send & (1 << $bit_number)) ? 1 : 0}]
+ incr bit_number
+
+ if {$bit_number == $number_of_bits} {
+ set communication_disabled 1
+ set pending_communication 0
+ }
+ return 1
+ }
+ }
+
+ private method receive_data {} {
+ if {!$bit_number} {
+ set byte_received 0
+ }
+ set byte_received [expr {$byte_received | ($signal(DQ) << $bit_number)}]
+ incr bit_number
+
+ if {$receive_command_or_data && $bit_number == 8} {
+ set bit_number 0
+ set command_received $byte_received
+
+ switch -- $command_received {
+ {170} { ;# Read Temperature [AAh]
+ write_to_log I [mc "Received command: Read Temperature \[AAh\] -- sending 9 data bits"]
+ set delay_transmission 1
+ set reception_or_transmission 0
+ set number_of_bits 9
+ set data_to_send $ds1620_reg(TEMP)
+ }
+ {1} { ;# Write TH [01h]
+ write_to_log I [mc "Received command: Write TH \[01h\] -- expecting 9 data bits"]
+ set receive_command_or_data 0
+ set number_of_bits 9
+ }
+ {2} { ;# Write TL [02h]
+ write_to_log I [mc "Received command: Write TL \[02h\] -- expecting 9 data bits"]
+ set receive_command_or_data 0
+ set number_of_bits 9
+ }
+ {161} { ;# Read TH [A1h]
+ write_to_log I [mc "Received command: Read TH \[A1h\] -- sending 9 data bits"]
+ set delay_transmission 1
+ set reception_or_transmission 0
+ set number_of_bits 9
+ set data_to_send $ds1620_reg(TH)
+ }
+ {162} { ;# Read TL [A2h]
+ write_to_log I [mc "Received command: Read TL \[A2h\] -- sending 9 data bits"]
+ set delay_transmission 1
+ set reception_or_transmission 0
+ set number_of_bits 9
+ set data_to_send $ds1620_reg(TL)
+ }
+ {160} { ;# Read Counter [A0h]
+ write_to_log I [mc "Received command: Read Counter \[A0h\] -- sending 9 data bits"]
+ set delay_transmission 1
+ set reception_or_transmission 0
+ set number_of_bits 9
+ set data_to_send $ds1620_reg(REMAIN)
+ }
+ {169} { ;# Read Slope [A9h]
+ write_to_log I [mc "Received command: Read Slope \[A9h\] -- sending 9 data bits"]
+ set delay_transmission 1
+ set reception_or_transmission 0
+ set number_of_bits 9
+ set data_to_send $ds1620_reg(PER_C)
+ }
+ {238} { ;# Start Convert T [EEh]
+ if {$ds1620_reg(STATUS) & 0x01} {
+ if {$conversion_running} {
+ write_to_log I [mc "Received command: Start Convert T \[EEh\] -- Starting T conversion on demand"]
+ } else {
+ write_to_log I [mc "Received command: Start Convert T \[EEh\] -- Restarting T conversion on demand"]
+ }
+ } else {
+ if {$conversion_running} {
+ write_to_log I [mc "Received command: Start Convert T \[EEh\] -- Starting continuous T conversion"]
+ } else {
+ write_to_log I [mc "Received command: Start Convert T \[EEh\] -- Restarting continuous T conversion"]
+ }
+ }
+
+ restart_t_conversion
+
+ set conversion_running 1
+ set communication_disabled 1
+ set pending_communication 0
+ }
+ {34} { ;# Stop Convert T [22h]
+ if {$conversion_running} {
+ if {$ds1620_reg(STATUS) & 0x01} {
+ write_to_log I [mc "Received command: Stop Convert T \[22h\] -- Stopping T conversion which is currently in progress"]
+ } else {
+ write_to_log I [mc "Received command: Stop Convert T \[22h\] -- Stopping continuous T conversion"]
+ }
+ restart_t_conversion
+ } else {
+ write_to_log W [mc "Received command: Stop Convert T \[22h\] -- No T conversion in progress -- command has no effect"]
+ }
+ set conversion_running 0
+ set communication_disabled 1
+ set pending_communication 0
+ }
+ {12} { ;# Write Config [0Ch]
+ write_to_log I [mc "Received command: Write Config \[0Ch\] -- expecting 8 data bits"]
+ set receive_command_or_data 0
+ set number_of_bits 8
+ }
+ {172} { ;# Read Config [ACh]
+ write_to_log I [mc "Received command: Read Config \[ACh\] -- sending 8 data bits"]
+ set delay_transmission 1
+ set reception_or_transmission 0
+ set number_of_bits 8
+ set data_to_send $ds1620_reg(STATUS)
+
+ }
+ default {
+ write_to_log E [mc "Received unknown command: %02Xh" $command_received]
+ }
+ }
+
+ } elseif {!$receive_command_or_data && $bit_number == $number_of_bits} {
+ set communication_disabled 1
+ set pending_communication 0
+
+ write_to_log I [mc "Received data: %03Xh -- finishing command" $byte_received]
+
+ switch -- $command_received {
+ {1} { ;# Write TH [01h]
+ if {$ds1620_reg(STATUS) & 0x10} {
+ write_to_log E [mc "Nonvolatile memory is still busy -- command ignored"]
+ } else {
+ set write_to_NVM [expr {[$project get_run_statistics 0] + $EEPROM_WRITE_CYCLE_TIME * 1000}]
+ set ds1620_reg(TH) $byte_received
+ update_reg TH
+
+ write_to_log I [mc "Commencing write to nonvolatile memory: TH := %02Xh" $byte_received]
+ }
+ }
+ {2} { ;# Write TL [02h]
+ if {$ds1620_reg(STATUS) & 0x10} {
+ write_to_log E [mc "Nonvolatile memory is still busy -- command ignored"]
+ } else {
+ set write_to_NVM [expr {[$project get_run_statistics 0] + $EEPROM_WRITE_CYCLE_TIME * 1000}]
+ set ds1620_reg(TL) $byte_received
+ update_reg TL
+
+ write_to_log I [mc "Commencing write to nonvolatile memory: TL := %02Xh" $byte_received]
+ }
+ }
+ {12} { ;# Write Config [0Ch]
+ if {$ds1620_reg(STATUS) & 0x10} {
+ write_to_log E [mc "Nonvolatile memory is still busy -- command ignored"]
+ } else {
+ set write_to_NVM [expr {[$project get_run_statistics 0] + $EEPROM_WRITE_CYCLE_TIME * 1000}]
+ set ds1620_reg(STATUS) [expr {($ds1620_reg(STATUS) & 0x9C) | ($byte_received & 0x63) | 0x10}]
+ update_reg STATUS
+
+ write_to_log I [mc "Commencing write to nonvolatile memory: STATUS/CONFIG := %02Xh" $byte_received]
+ }
+ }
+ }
+ }
+ }
+
+ private method check_proper_timing {event} {
+ set time_of($event) $time_mark
+ if {$no_delays} {
+ return
+ }
+
+ switch -- $event {
+ {DQ_up} {
+ # Check for valid t_CDH (CLK to Data Hold) >= 40
+ if {($time_mark < ($time_of(CLK_up) + 40)) || ($time_mark < ($time_of(CLK_down) + 40))} {
+ write_to_log E [mc "Bad timing: t_CDH (CLK to Data Hold) too low, must be at least 40ns"]
+ }
+ }
+ {DQ_down} {
+ # Check for valid t_CDH (CLK to Data Hold) >= 40
+ if {($time_mark < ($time_of(CLK_up) + 40)) || ($time_mark < ($time_of(CLK_down) + 40))} {
+ write_to_log E [mc "Bad timing: t_CDH (CLK to Data Hold) too low, must be at least 40ns"]
+ }
+ }
+ {RST_up} {
+ # Check for valid t_CWH (RST Inactive Time) >= 125
+ if {$command_received == 0x01 || $command_received == 0x02 || $command_received == 0x0C} {
+ set min_time [expr {$EEPROM_WRITE_CYCLE_TIME * 1000}]
+ } else {
+ set min_time 125
+ }
+ if {$time_mark < ($time_of(RST_down) + $min_time)} {
+ write_to_log E [mc "Bad timing: t_CWH (RST Inactive Time) too low, must be at least %dns" ${min_time}]
+ }
+ }
+ {RST_down} {
+ if {$signal(RST)} {
+ # Check for valid t_CCH (CLK to RST Hold) >= 40
+ if {$time_mark < ($time_of(CLK_up) + 40)} {
+ write_to_log E [mc "Bad timing: t_CCH (CLK to RST Hold too low, must be at least 40ns"]
+ }
+ }
+ }
+ {CLK_up} {
+ if {$signal(RST)} {
+ # Check for valid t_DC (Data to CLK Setup) >= 35
+ if {($time_mark < ($time_of(DQ_up) + 35)) || $time_mark < ($time_of(DQ_down) + 35)} {
+ write_to_log E [mc "Bad timing: t_DC (Data to CLK Setup) too low, must be at least 35ns"]
+ }
+ # Check for valid t_CL (CLK Low Time) >= 285ns
+ if {$time_mark < ($time_of(CLK_down) + 285)} {
+ write_to_log E [mc "Bad timing: t_CL (CLK Low Time) too low, must be at least 285ns"]
+ }
+ } else {
+ # Check for valid t_CNV (Convert Pulse Width) >= 250ns & <= 500ms
+ if {($time_mark < ($time_of(CLK_down) + 250)) || ($time_mark > ($time_of(CLK_down) + 500000000))} {
+ write_to_log E [mc "Bad timing: t_CNV (Convert Pulse Width) too low or too high, must be at least 250ns and at most 500ms"]
+ }
+
+ }
+ }
+ {CLK_down} {
+ # Check for valid t_CC (RST To CLK Setup) >= 100ns
+ if {$time_mark < ($time_of(RST_up) + 100)} {
+ write_to_log E [mc "Bad timing: t_CC (RST To CLK Setup) too low, must be at least 100ns"]
+ }
+ # Check for valid t_CH (CLK High Time) >= 285ns
+ if {$time_mark < ($time_of(CLK_up) + 285)} {
+ write_to_log E [mc "Bad timing: t_CH (CLK High Time) too low, must be at least 285ns"]
+ }
+ }
+ }
+ }
+
+ private method ds1620_core__evaluate {} {
+ # Continuous conversion mode or One-shot conversion mode
+ if {$conversion_running} {
+ proceed_with_t_conversion
+ # Stand-alone mode
+ } elseif {!($ds1620_reg(STATUS) & 0x02) && !$signal(RST) && !$signal(CLK)} {
+ proceed_with_t_conversion
+ }
+
+ if {$ds1620_reg(STATUS) & 0x10} {
+ if {$no_delays || $write_to_NVM <= $time_mark} {
+ write_to_log I [mc "Write to nonvolatile memory is complete"]
+ set ds1620_reg(STATUS) [expr {$ds1620_reg(STATUS) ^ 0x10}]
+ }
+ }
+
+ # RESET signal is high -- Communicate with MCU
+ if {$signal(RST)} {
+ # Detect raising edge on the DQ signal
+ # ____
+ # /
+ # ____/
+ if {!$signal(DQ_prev) && $signal(DQ)} {
+ check_proper_timing DQ_up
+ # Detect falling edge on the DQ signal
+ # ____
+ # \
+ # \____
+ } elseif {$signal(DQ_prev) && !$signal(DQ)} {
+ check_proper_timing DQ_down
+ }
+
+ # Detect raising edge on the RST signal
+ # ____
+ # /
+ # ____/
+ if {!$signal(RST_prev)} {
+ check_proper_timing RST_up
+ set pending_communication 1
+ write_to_log I [mc "RESET signal was driven high -- commencing communication over 3-wire protocol"]
+ }
+
+ # Detect falling edge on the CLOCK signal - output bit to DQ
+ # ____
+ # \
+ # \____
+ if {$signal(CLK_prev) && !$signal(CLK) && !$reception_or_transmission} {
+ check_proper_timing CLK_down
+ if {$communication_disabled} {
+ write_to_log W [mc "Transmission is no longer relevant"]
+ } else {
+ if {[transmit_data]} {
+ write_to_log I [mc "Transmitting bit #%d = %d" [expr {$bit_number - 1}] $signal(DQ)]
+ }
+ }
+
+ # Detect raising edge on the CLOCK signal - read bit from DQ
+ # ____
+ # /
+ # ____/
+ } elseif {!$signal(CLK_prev) && $signal(CLK) && $reception_or_transmission} {
+ check_proper_timing CLK_up
+ if {$communication_disabled} {
+ write_to_log W [mc "Reception is no longer relevant"]
+ } else {
+ write_to_log I [mc "Receiving bit #%d = %d" $bit_number $signal(DQ)]
+ receive_data
+ }
+ }
+
+ # RESET signal is low -- Terminate all communications and commence stand-alone operation
+ } else {
+ # Detect falling edge on the RST signal
+ # ____
+ # \
+ # \____
+ if {$signal(RST_prev)} {
+ check_proper_timing RST_down
+ write_to_log I [mc "Received RESET signal -- commencing stand-alone operation"]
+ }
+
+ # Detect raising edge on the CLOCK signal
+ # ____
+ # /
+ # ____/
+ if {!$signal(CLK_prev) && $signal(CLK)} {
+ check_proper_timing CLK_up
+ # Detect falling edge on the CLOCK signal - output bit to DQ
+ # ____
+ # \
+ # \____
+ } elseif {$signal(CLK_prev) && !$signal(CLK)} {
+ check_proper_timing CLK_down
+ }
+
+ if {$pending_communication} {
+ set pending_communication 0
+ write_to_log W [mc "Data communication over 3-wire protocol was terminated by RESET signal!"]
+ }
+
+ set bit_number 0
+ set reception_or_transmission 1
+ set receive_command_or_data 1
+ set communication_disabled 0
+ }
+ }
+
+ public method reset_ds1620 {} {
+ set ds1620_reg(TEMP) 392
+ set ds1620_reg(REMAIN) 0
+ set ds1620_reg(STATUS) [expr {($ds1620_reg(STATUS) & 0x03) | 0x88}]
+
+ foreach reg {TH TL TEMP STATUS} {
+ update_reg $reg
+ }
+ }
+
+ # ------------------------------------------------------------------
+ # 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 < 6} {incr i} {
+ $canvas_widget.cb_p$i configure -values $available_ports
+
+ if {[lsearch -ascii -exact $available_ports $connection_port($i)] == -1} {
+ $canvas_widget.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
+
+ read_inputs state
+
+ if {!$time_mark} {
+ set signal(CLK_prev) $signal(CLK)
+ set signal(RST_prev) $signal(RST)
+ if {$signal(DQ) != {}} {
+ set signal(DQ_prev) $signal(DQ)
+ }
+ }
+
+ if {$time_mark != [$project get_run_statistics 0]} {
+ set time_mark [$project get_run_statistics 0]
+ if {$input_error} {
+ write_to_log E $input_error_desc
+
+ set input_error 0
+ set input_error_desc {}
+ }
+
+ ds1620_core__evaluate
+ process_outputs state
+
+ set signal(CLK_prev) $signal(CLK)
+ set signal(RST_prev) $signal(RST)
+ if {$signal(DQ) != {}} {
+ set signal(DQ_prev) $signal(DQ)
+ }
+ }
+
+ # Reset last I/O error
+ set input_error 0
+ set input_error_desc {}
+
+ adjust_wire_colors state
+ }
+
+ private method process_outputs {_state} {
+ upvar $_state state
+
+ set lines_to_update [list 3 4 5]
+ if {!$signal(CLK) && $signal(RST)} {
+ lappend lines_to_update 0
+ }
+ foreach i $lines_to_update {
+ # Determinate index in the list of port states
+ set pp [which_port_pin $i]
+
+ # Not connected
+ if {[lindex $pp 0] == {-} || [lindex $pp 1] == {-}} {
+ continue
+ }
+
+ lset state $pp $signal([lindex $SIGNAL_NAMES $i])
+ }
+ }
+
+ private method read_inputs {_state} {
+ upvar $_state state
+
+ foreach i {2 1 0} {
+ # Determinate index in the list of port states
+ set pp [which_port_pin $i]
+
+ # Not connected
+ if {[lindex $pp 0] == {-} || [lindex $pp 1] == {-}} {
+ set signal_value {}
+ } else {
+ set signal_value [lindex $state $pp]
+ }
+
+ # Convert any possible I/O signal value to Boolean value
+ switch -- $signal_value {
+ {0} -
+ {1} {}
+ {=} {
+ set signal_value 0
+ }
+ default {
+ if {($i == 2) || ($i == 1) || ($i == 0 && $signal(RST))} {
+ set input_error 1
+ set input_error_desc [mc \
+ "Received an invalid input on signal %s" \
+ [lindex $SIGNAL_NAMES $i]
+ ]
+ set signal_value [expr {rand() > 0.5 ? 1 : 0}]
+ }
+ }
+ }
+ set signal([lindex $SIGNAL_NAMES $i]) $signal_value
+ }
+ }
+
+ private method adjust_wire_colors {_state} {
+ upvar $_state state
+
+ for {set i 0} {$i < 6} {incr i} {
+ # Determinate index in the list of port states
+ set pp [which_port_pin $i]
+
+ # Not connected
+ if {[lindex $pp 0] == {-} || [lindex $pp 1] == {-}} {
+ $canvas_widget itemconfigure $wires($i) -fill {#000000}
+ continue
+ }
+
+ # Determinate wire and LED color
+ switch -- [lindex $state $pp] {
+ {0} { ;# Logical 0
+ set wire_color {#00FF00}
+ }
+ {1} { ;# Logical 1
+ set wire_color {#FF0000}
+ }
+ {=} { ;# High forced to low
+ set wire_color {#FF00AA}
+ }
+ {} { ;# Not connected
+ set wire_color {#000000}
+ }
+ {?} { ;# No volatge
+ set wire_color {#888888}
+ }
+ default {
+ set wire_color {#FF8800}
+ }
+ }
+
+ $canvas_widget itemconfigure $wires($i) -fill $wire_color
+ }
+ }
+
+ ## 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] \
+ [$canvas_widget.usr_note get] \
+ $ds1620_reg(TH) \
+ $ds1620_reg(TL) \
+ $no_delays \
+ [wm geometry $win.log_window] \
+ [wm state $win.log_window] \
+ $temperature \
+ [expr {$ds1620_reg(STATUS) & 0x03}] \
+ $log_enabled \
+ $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} {
+ if {[catch {
+ # 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 minsize $win] {x}]]
+ }
+
+ # Load user note
+ $canvas_widget.usr_note delete 0
+ $canvas_widget.usr_note insert 0 [lindex $state 3]
+
+ set ds1620_reg(TH) [lindex $state 4]
+ set ds1620_reg(TL) [lindex $state 5]
+
+ set no_delays [lindex $state 6]
+
+ # Display the log window
+ set log_window_geometry [lindex $state 7]
+ if {[lindex $state 8] == {normal}} {
+ show_log
+ }
+
+ set temperature [lindex $state 9]
+ set ds1620_reg(STATUS) [expr {($ds1620_reg(STATUS) & 0xFC) | ([lindex $state 10] & 0x03)}]
+
+ set log_enabled [lindex $state 11]
+ if {$log_enabled} {
+ $log_on_off_chbut select
+ } else {
+ $log_on_off_chbut deselect
+ }
+
+ if {[lindex $state 12] != {}} {
+ set keep_win_on_top [lindex $state 12]
+ if {$keep_win_on_top} {
+ wm attributes $win -topmost 1 -alpha 0.8
+ }
+ }
+
+ # Restore state of ComboBoxes
+ for {set i 0} {$i < 6} {incr i} {
+ ## PIN
+ set pin $connection_pin($i)
+ if {$pin != {-}} {
+ set pin [expr {7 - $pin}]
+ }
+ set idx [lsearch -ascii -exact \
+ [$canvas_widget.cb_b$i cget -values] \
+ $pin \
+ ]
+ if {$idx == -1} {
+ set idx 0
+ }
+ $canvas_widget.cb_b$i current $idx
+
+ ## PORT
+ set idx [lsearch -ascii -exact \
+ [$canvas_widget.cb_p$i cget -values] \
+ $connection_port($i) \
+ ]
+ if {$idx == -1} {
+ set idx 0
+ }
+ $canvas_widget.cb_p$i current $idx
+ }
+
+ # Adjust internal logic and the rest of PALE
+ foreach reg {TH TL TEMP STATUS} {
+ update_reg $reg
+ }
+ adjust_temp_ind
+ evaluete_enaged_pins
+ $project pale_reevaluate_IO
+ update
+
+ # 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
+ }
+
+
+ # ------------------------------------------------------------------
+ # 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}::_no_delays $no_delays
+ 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]} {
+ reset_ds1620
+ }
+ }
+}
+
+# >>> File inclusion guard
+}
+# <<< File inclusion guard
diff --git a/lib/pale/file_interface.tcl b/lib/pale/file_interface.tcl
new file mode 100644
index 0000000..58f7293
--- /dev/null
+++ b/lib/pale/file_interface.tcl
@@ -0,0 +1,983 @@
+
+#!/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 _FILE_INTERFACE_TCL ] } {
+set _FILE_INTERFACE_TCL _
+# <<< File inclusion guard
+
+# --------------------------------------------------------------------------
+# DESCRIPTION
+# File interface for the PALE subsystem, allow to read files as input for
+# GPIO for simulated MCU and record changes in GPIO to a file
+# -------------------------------------------------------------------------
+
+class PaleFileInterface {
+ inherit VirtualHWComponent
+
+ # 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} \
+ ]
+ common text_font [font create \
+ -size [expr {int(-12 * $::font_size_factor)}] \
+ -family ${::DEFAULT_FIXED_FONT} \
+ ]
+ common text_font_bold [font create \
+ -weight bold \
+ -size [expr {int(-12 * $::font_size_factor)}] \
+ -family ${::DEFAULT_FIXED_FONT} \
+ ]
+
+ common COMPONENT_NAME "VHW File Interface" ;# Name of this component
+ common CLASS_NAME "PaleFileInterface" ;# Name of this class
+ common COMPONENT_ICON {compfile1} ;# Icon for this panel (16x16)
+
+ # Configuration menu
+ common CONFMENU {
+ {command {Sync. files now} {} 1 "sync" {filesave}
+ "Flush output file buffer"}
+ {checkbutton "Keep files synchronized" {} {::PaleFileInterface::_keep_sync}
+ 1 0 0 {keep_sync_changed}
+ ""}
+ {separator}
+ {command {Show help} {} 5 "show_help" {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" {} {::PaleFileInterface::menu_keep_win_on_top}
+ 1 0 0 {keep_win_on_top_changed}
+ ""}
+ }
+
+ common _keep_sync 0
+
+ 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 enaged ;# Array of Bool: enaged(port_num,bit_num) --> Is connected to this device ?
+ private variable keep_win_on_top 0 ;# Bool: Toplevel window
+ private variable cb
+ private variable usr_note
+
+ private variable read_text_widget
+ private variable read_file_entry
+ private variable read_select_file_but
+ private variable read_start_stop_but
+
+ private variable write_file_entry
+ private variable write_select_file_but
+ private variable write_start_stop_but
+ private variable write_trunc_but
+ private variable write_status_lbl
+
+ private variable file_to_read_is_opened 0
+ private variable file_to_write_to_is_opened 0
+
+ private variable file_to_read_channel {}
+ private variable file_to_write_to_channel {}
+
+ private variable current_input {}
+ private variable last_read_line {}
+ private variable last_written_line {}
+
+ private variable keep_sync 0
+ private variable write_counter
+
+
+ # ------------------------------------------------------------------
+ # INTERNAL APPLICATION LOGIC
+ # ------------------------------------------------------------------
+
+ ## Object constructor
+ # @parm Object _project - Project object
+ constructor {_project} {
+ # Configure local ttk styles
+ ttk::style configure PaleFileInterface_FileInUse.TEntry \
+ -fieldbackground {#DDFFDD}
+ ttk::style map PaleFileInterface_FileInUse.TEntry \
+ -fieldbackground [list {readonly !readonly} {#DDFFDD}]
+
+ ttk::style configure PaleFileInterface_FileFound.TEntry \
+ -fieldbackground {#FFFFAA}
+ ttk::style map PaleFileInterface_FileFound.TEntry \
+ -fieldbackground [list {readonly !readonly} {#FFFFAA}]
+
+ ttk::style configure PaleFileInterface_FileNotFound.TEntry \
+ -fieldbackground {#FFDDDD}
+ ttk::style map PaleFileInterface_FileNotFound.TEntry \
+ -fieldbackground [list {readonly !readonly} {#FFDDDD}]
+
+ # 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
+ set radio_buttons 1
+ array set connection_port {0 - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 - 10 - 11 - 12 - 13 - 14 - 15 -}
+ array set connection_pin {0 - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 - 10 - 11 - 12 - 13 - 14 - 15 -}
+ 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]
+
+ # ComboBoxes to default state
+ for {set i 0} {$i < 16} {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 $PaleFileInterface::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
+ }
+ }
+
+ ## 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 8} {$i < 16} {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
+ }
+ }
+
+ ## Reconnect the specified key to another port pin
+ # @parm Int i - Key number (0..7)
+ # @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
+
+ # Inform PALE system about the change in order
+ #+ to make immediate change in device states
+ if {$drawing_on} {
+ $project pale_reevaluate_IO
+ }
+
+ # Set flag modified
+ set_modified
+ }
+
+ public method keep_sync_changed {} {
+ set keep_sync ${::PaleFileInterface::_keep_sync}
+ }
+
+ public method sync {} {
+ if {$file_to_write_to_is_opened} {
+ flush $file_to_write_to_channel
+ }
+ }
+
+ ## Create GUI of this panel
+ # @return void
+ private method create_gui {} {
+ #
+ set win [toplevel .pale_file_interface$count -class $component_name -bg ${::COMMON_BG_COLOR}]
+
+
+ set top_frame [frame $win.top_frame]
+ # Create "ON/OFF" button
+ set start_stop_button [ttk::button $top_frame.start_stop_button \
+ -command "$this on_off_button_press" \
+ -style Flat.TButton \
+ -width 3 \
+ ]
+ DynamicHelp::add $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"
+ pack $start_stop_button -side left
+ bindtags $start_stop_button [list $start_stop_button TButton all .]
+ # Create configuration menu button
+ set conf_button [ttk::button $top_frame.conf_but \
+ -image ::ICONS::16::configure \
+ -style Flat.TButton \
+ -command "$this config_menu" \
+ ]
+ setStatusTip -widget $conf_button -text [mc "Configure"]
+ pack $conf_button -side left
+ bindtags $conf_button [list $conf_button TButton all .]
+ #
+ pack [label $top_frame.note_lbl -text [mc "Note: "]] -side left
+ set usr_note [ttk::entry $top_frame.usr_note \
+ -validate key \
+ -validatecommand [list $this set_modified] \
+ -width 0 \
+ ]
+ pack $usr_note -side left -fill x -expand 1
+ bindtags $top_frame.usr_note [list $top_frame.usr_note TEntry $win all .]
+
+ set write_labelframe [ttk::labelframe $win.write_labelframe -text [mc "Write"] -padding 5]
+ for {set i 0} {$i < 8} {incr i} {
+ set j $i
+
+ set cb(p$j) [ttk::combobox $write_labelframe.cb_p$i \
+ -width 1 \
+ -font $cb_font \
+ -state readonly \
+ ]
+
+ set cb(b$j) [ttk::combobox $write_labelframe.cb_b$i \
+ -width 1 \
+ -font $cb_font \
+ -values {- 0 1 2 3 4 5 6 7} \
+ -state readonly \
+ ]
+
+ grid $cb(p$j) -row 2 -column [expr {$i + 1}]
+ grid $cb(b$j) -row 3 -column [expr {$i + 1}]
+
+ bind $cb(p$j) <<ComboboxSelected>> [list $this reconnect $i]
+ bind $cb(b$j) <<ComboboxSelected>> [list $this reconnect $i]
+
+ bindtags $cb(p$j) [list $cb(p$j) TCombobox all .]
+ bindtags $cb(b$j) [list $cb(b$j) TCombobox all .]
+ }
+ grid [label $write_labelframe.port_lbl \
+ -text [mc "PORT"] \
+ ] -row 2 -column 0 -sticky w
+ grid [label $write_labelframe.pin_lbl \
+ -text [mc "PIN"] \
+ ] -row 3 -column 0 -sticky w
+ grid [label $write_labelframe.file_lbl \
+ -text [mc "File: "] \
+ ] -row 0 -column 0 -sticky w
+ set write_file_entry [ttk::entry $write_labelframe.entry \
+ -width 0 \
+ -validate key \
+ -validatecommand [list $this vcmd_write_file_entry %P] \
+ ]
+ DynamicHelp::add $write_file_entry -text [mc "Name of output file"]
+ setStatusTip -widget $write_file_entry -text [mc "Name of output file"]
+ bindtags $write_file_entry [list $write_file_entry TEntry $win all .]
+ grid $write_file_entry -row 0 -column 1 -columnspan 5 -sticky we
+ set write_select_file_but [ttk::button $write_labelframe.write_select_file_but \
+ -image ::ICONS::16::fileopen \
+ -style Flat.TButton \
+ -command [list $this write_select_file] \
+ ]
+ DynamicHelp::add $write_select_file_but -text [mc "Select file"]
+ setStatusTip -widget $write_select_file_but -text [mc "Select file"]
+ bindtags $write_select_file_but [list $write_select_file_but TButton all .]
+ grid $write_select_file_but -row 0 -column 6 -sticky we
+ set write_start_stop_but [ttk::button $write_labelframe.start_stop_but \
+ -image ::ICONS::16::player_play \
+ -style Flat.TButton \
+ -command [list $this write_start_stop] \
+ -state disabled \
+ ]
+ DynamicHelp::add $write_start_stop_but -text [mc "Open or close the file"]
+ setStatusTip -widget $write_start_stop_but -text [mc "Open or close the file"]
+ bindtags $write_start_stop_but [list $write_start_stop_but TButton all .]
+ grid $write_start_stop_but -row 0 -column 7 -sticky we
+ set write_trunc_but [ttk::button $write_labelframe.trunc_but \
+ -image ::ICONS::16::editdelete \
+ -style Flat.TButton \
+ -command [list $this write_trunc] \
+ -state disabled \
+ ]
+ DynamicHelp::add $write_trunc_but -text [mc "Truncate the file"]
+ setStatusTip -widget $write_trunc_but -text [mc "Truncate the file"]
+ bindtags $write_trunc_but [list $write_trunc_but TButton all .]
+ grid $write_trunc_but -row 0 -column 8 -sticky we
+ set write_status_lbl [label $write_labelframe.write_status_lbl \
+ -justify right -anchor e \
+ ]
+ grid $write_status_lbl -row 4 -column 0 -columnspan 9 -sticky e
+ grid rowconfigure $write_labelframe 1 -minsize 5
+
+ set read_labelframe [ttk::labelframe $win.read_labelframe -text [mc "Read"] -padding 5]
+ for {set i 0} {$i < 8} {incr i} {
+ set j [expr {$i + 8}]
+
+ set cb(p$j) [ttk::combobox $read_labelframe.cb_p$i \
+ -width 1 \
+ -font $cb_font \
+ -state readonly \
+ ]
+
+ set cb(b$j) [ttk::combobox $read_labelframe.cb_b$i \
+ -width 1 \
+ -font $cb_font \
+ -values {- 0 1 2 3 4 5 6 7} \
+ -state readonly \
+ ]
+
+ grid $cb(p$j) -row 2 -column [expr {$i + 1}]
+ grid $cb(b$j) -row 3 -column [expr {$i + 1}]
+
+ bind $cb(p$j) <<ComboboxSelected>> [list $this reconnect $j]
+ bind $cb(b$j) <<ComboboxSelected>> [list $this reconnect $j]
+
+ bindtags $cb(p$j) [list $cb(p$j) TCombobox all .]
+ bindtags $cb(b$j) [list $cb(b$j) TCombobox all .]
+ }
+ grid [label $read_labelframe.port_lbl \
+ -text [mc "PORT"] \
+ ] -row 2 -column 0 -sticky w
+ grid [label $read_labelframe.pin_lbl \
+ -text [mc "PIN"] \
+ ] -row 3 -column 0 -sticky w
+ set read_text_widget [text $read_labelframe.text \
+ -height 3 \
+ -width 0 \
+ -state disabled \
+ -font $text_font \
+ -tabstyle wordprocessor \
+ -undo 0 \
+ -exportselection 1 \
+ -wrap word \
+ ]
+ $read_text_widget tag configure tag_current_line -font $text_font_bold
+ $read_text_widget tag configure tag_log_0 -foreground {#00FF00}
+ $read_text_widget tag configure tag_log_1 -foreground {#FF0000}
+ $read_text_widget tag configure tag_hfl -foreground {#FF00AA}
+ $read_text_widget tag configure tag_nv -foreground {#888888}
+ $read_text_widget tag configure tag_noice -foreground {#FF8800}
+ DynamicHelp::add $read_text_widget -text [mc "View on the file"]
+ setStatusTip -widget $read_text_widget -text [mc "View on the file"]
+ bindtags $read_text_widget [list $read_text_widget Ttext $win all .]
+ grid $read_text_widget -row 4 -column 0 -columnspan 9 -sticky we
+ grid [label $read_labelframe.file_lbl \
+ -text [mc "File: "] \
+ ] -row 0 -column 0 -sticky w
+ set read_file_entry [ttk::entry $read_labelframe.entry \
+ -width 0 \
+ -validate key \
+ -validatecommand [list $this vcmd_read_file_entry %P] \
+ ]
+ DynamicHelp::add $read_file_entry -text [mc "Name of input file"]
+ setStatusTip -widget $read_file_entry -text [mc "Name of input file"]
+ bindtags $read_file_entry [list $read_file_entry TEntry $win all .]
+ grid $read_file_entry -row 0 -column 1 -columnspan 5 -sticky we
+ set read_select_file_but [ttk::button $read_labelframe.read_select_file_but \
+ -image ::ICONS::16::fileopen \
+ -style Flat.TButton \
+ -command [list $this read_select_file] \
+ ]
+ DynamicHelp::add $read_select_file_but -text [mc "Select file"]
+ setStatusTip -widget $read_select_file_but -text [mc "Select file"]
+ bindtags $read_select_file_but [list $read_select_file_but TButton all .]
+ grid $read_select_file_but -row 0 -column 6 -sticky we
+ set read_start_stop_but [ttk::button $read_labelframe.start_stop_but \
+ -image ::ICONS::16::player_play \
+ -style Flat.TButton \
+ -command [list $this read_start_stop] \
+ -state disabled \
+ ]
+ DynamicHelp::add $read_start_stop_but -text [mc "Open or close the file"]
+ setStatusTip -widget $read_start_stop_but -text [mc "Open or close the file"]
+ bindtags $read_start_stop_but [list $read_start_stop_but TButton all .]
+ grid $read_start_stop_but -row 0 -column 7 -sticky we
+ grid rowconfigure $read_labelframe 1 -minsize 5
+
+
+ pack $read_labelframe -fill x -pady 3 -padx 5 -side right
+ pack $top_frame -fill x -padx 5 -pady 2 -side bottom
+ pack $write_labelframe -fill x -pady 3 -padx 5
+
+ # Set window parameters
+ wm iconphoto $win ::ICONS::16::$component_icon
+ wm title $win "[mc $component_name] - [$project cget -projectName] - MCU 8051 IDE"
+ wm resizable $win 0 0
+ wm protocol $win WM_DELETE_WINDOW "$this close_window"
+ bindtags $win [list $win Toplevel all .]
+ }
+
+ ## Determinate which port pin is connected to the specified key
+ # @parm Int i - Key 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
+ }
+
+ # ------------------------------------------------------------------
+ # VIRTUAL HW COMMON INTERFACE -- CALLED FROM PALE ENGINE
+ # ------------------------------------------------------------------
+
+ ## 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 < 16} {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) {-}
+ }
+ }
+ }
+
+ ## Evaluate new state of ports
+ # @parm List state - Port states ( 5 x {8 x bit} -- {bit0 bit1 bit2 ... bit7} )
+ # @return state - New port states modified by this device
+ # format is the same as parameter $state
+ #
+ # 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 {$file_to_write_to_is_opened} {
+ set line [list]
+ for {set i 0} {$i < 8} {incr i} {
+ set pp [which_port_pin $i]
+
+ if {[lindex $pp 0] == {-} || [lindex $pp 1] == {-}} {
+ lappend line {-}
+ } else {
+ lappend line [lindex $state $pp]
+ }
+ }
+ if {$last_written_line != $line} {
+ set last_written_line $line
+
+ puts -nonewline $file_to_write_to_channel [$project get_run_statistics 0]
+ puts -nonewline $file_to_write_to_channel "\t"
+ puts $file_to_write_to_channel $line
+ if {$keep_sync} {
+ flush $file_to_write_to_channel
+ }
+ incr write_counter
+ $write_status_lbl configure -text [mc "%d changes recorded" $write_counter]
+ }
+ }
+
+ if {[catch {
+ if {$file_to_read_is_opened} {
+ if {$last_read_line == {}} {
+ set last_read_line [gets $file_to_read_channel]
+ }
+
+ while {![eof $file_to_read_channel]} {
+ if {
+ ($current_input == {})
+ ||
+ ([lindex $last_read_line 0] <= [$project get_run_statistics 0])
+ } then {
+ $read_text_widget configure -state normal
+ $read_text_widget delete 0.0 end
+ $read_text_widget insert 1.0 "\n\n"
+
+ $read_text_widget insert 1.0 $current_input
+ insert_last_read_line
+
+ set current_input $last_read_line
+ set flag 0
+ while {![eof $file_to_read_channel]} {
+ set last_read_line [gets $file_to_read_channel]
+ regsub -all {\s*#.*$} $last_read_line {} last_read_line
+ if {[string length $last_read_line]} {
+ set flag 1
+ break
+ }
+ }
+
+ if {$flag} {
+ $read_text_widget insert 3.0 $last_read_line
+ }
+ $read_text_widget configure -state disabled
+ } else {
+ break
+ }
+ }
+
+ if {[llength $current_input] != 9} {
+ error
+ }
+ for {set i 0} {$i < 0} {incr i} {
+ if {[lsearch -ascii -exact {| X ? - = 0 1} [lindex $current_input $i]] == -1} {
+ error
+ }
+ }
+
+ for {set i 8; set j 1} {$i < 16} {incr i; incr j} {
+ set pp [which_port_pin $i]
+
+ if {[lindex $pp 0] == {-} || [lindex $pp 1] == {-}} {
+ # nothing
+ } else {
+ lset state $pp [lindex $current_input $j]
+ }
+ }
+ }
+ }]} then {
+ tk_messageBox \
+ -parent $win \
+ -icon warning \
+ -title [mc "I/O Error"] \
+ -message [mc "File corrupted:\n\"%s\"." [$read_file_entry get]] \
+ -type ok
+ read_start_stop
+ }
+ }
+
+ private method insert_last_read_line {} {
+ $read_text_widget insert 2.0 $last_read_line
+ $read_text_widget tag add tag_current_line 2.0 3.0
+
+ set j 1
+ set k 0
+ for {set i 8} {$i > 0} {incr i -1} {
+ switch -- [lindex $last_read_line $i] {
+ {0} { ;# Logical 0
+ set tag {tag_log_0}
+ }
+ {1} { ;# Logical 1
+ set tag {tag_log_1}
+ }
+ {=} { ;# High forced to low
+ set tag {tag_hfl}
+ }
+ {?} { ;# No volatge
+ set tag {tag_nv}
+ }
+ default {
+ set tag {tag_noice}
+ }
+ }
+ $read_text_widget tag add $tag [list 2.0 lineend - ${j}c] [list 2.0 lineend - ${k}c]
+
+ incr j 2
+ incr k 2
+ }
+ }
+
+ ## 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] \
+ [$read_file_entry get] \
+ [$write_file_entry get] \
+ $keep_sync \
+ $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} {
+ if {[catch {
+ # 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]
+
+ $read_file_entry delete 0
+ $read_file_entry insert 0 [lindex $state 4]
+
+ $write_file_entry delete 0
+ $write_file_entry insert 0 [lindex $state 5]
+
+ set keep_sync [lindex $state 6]
+
+ if {[lindex $state 7] != {}} {
+ set keep_win_on_top [lindex $state 7]
+ if {$keep_win_on_top} {
+ wm attributes $win -topmost 1 -alpha 0.8
+ }
+ }
+
+ after 0 [subst {
+ update
+ $read_file_entry xview [$read_file_entry index end]
+ $write_file_entry xview [$write_file_entry index end]
+ }]
+
+ # Restore state of ComboBoxes
+ for {set i 0} {$i < 16} {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
+
+ # 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
+ }
+
+ public method read_select_file {{filename {}}} {
+ if {$filename != {}} {
+ $read_file_entry delete 0 end
+ $read_file_entry insert 0 [lindex $filename 1]
+
+ after 0 [subst {
+ update
+ $read_file_entry xview [$read_file_entry index end]
+ }]
+ } else {
+ select_file [mc "Select file for reading"] [$read_file_entry get] read_select_file
+ }
+ }
+
+ public method write_select_file {{filename {}}} {
+ if {$filename != {}} {
+ set filename [lindex $filename 1]
+ if {[file extension $filename] == {}} {
+ append filename {.gpio}
+ }
+ $write_file_entry delete 0 end
+ $write_file_entry insert 0 $filename
+ after 0 [subst {
+ update
+ $write_file_entry xview [$write_file_entry index end]
+ }]
+ } else {
+ select_file [mc "Select file for writing"] [$write_file_entry get] write_select_file
+ }
+ }
+
+ private method select_file {title initialfile cmd} {
+ if {$initialfile == {}} {
+ set directory [$project cget -projectPath]
+ } else {
+ set directory [file dirname $initialfile]
+ }
+
+ catch {delete object ::fsd}
+ KIFSD::FSD ::fsd \
+ -title $title \
+ -directory $directory \
+ -defaultmask 0 \
+ -multiple 0 \
+ -initialfile $initialfile \
+ -master $win \
+ -filetypes [list \
+ [list [mc "General Purpose Input Output"] {*.gpio}] \
+ [list [mc "All files"] {*}] \
+ ]
+
+ ::fsd setokcmd "$this $cmd \[list 1 \[::fsd get\]\]"
+ ::fsd activate
+ }
+
+ public method write_start_stop {{truncate 0}} {
+ # Stop
+ if {$file_to_write_to_is_opened} {
+ if {[catch {
+ close $file_to_write_to_channel
+ }]} then {
+ tk_messageBox \
+ -parent $win \
+ -icon warning \
+ -title [mc "I/O Error"] \
+ -message [mc "Unknown error occurred while closing file:\n\"%s\"." [$write_file_entry get]] \
+ -type ok
+ }
+ set last_written_line {}
+ set file_to_write_to_is_opened 0
+ $write_start_stop_but configure -image ::ICONS::16::player_play
+ $write_trunc_but configure -state disabled
+ $write_select_file_but configure -state normal
+ $write_file_entry configure -state normal
+ $write_file_entry configure -style PaleFileInterface_FileFound.TEntry
+ $write_status_lbl configure -text {}
+ set write_counter 0
+ # Start
+ } else {
+ if {[catch {
+ if {$truncate} {
+ set mode {w}
+ } else {
+ set mode {a}
+ }
+ set file_to_write_to_channel [open [$write_file_entry get] $mode]
+ }]} then {
+ tk_messageBox \
+ -parent $win \
+ -icon warning \
+ -title [mc "Unable to open file"] \
+ -message [mc "Unable to open file:\n\"%s\" for writing, please check your permissions." [$write_file_entry get]] \
+ -type ok
+ } else {
+ set file_to_write_to_is_opened 1
+ $write_start_stop_but configure -image ::ICONS::16::_player_pause
+ $write_trunc_but configure -state normal
+ $write_select_file_but configure -state disabled
+ $write_file_entry configure -state readonly
+ $write_file_entry configure -style PaleFileInterface_FileInUse.TEntry
+ }
+ }
+ }
+ public method write_trunc {} {
+ if {!$file_to_write_to_is_opened} {
+ return
+ }
+
+ write_start_stop
+ write_start_stop 1
+ }
+ public method read_start_stop {} {
+ # Stop
+ if {$file_to_read_is_opened} {
+ if {[catch {
+ close $file_to_read_channel
+ }]} then {
+ tk_messageBox \
+ -parent $win \
+ -icon warning \
+ -title [mc "I/O Error"] \
+ -message [mc "Unknown error occurred while closing file:\n\"%s\"." [$read_file_entry get]] \
+ -type ok
+ }
+ set file_to_read_is_opened 0
+ $read_start_stop_but configure -image ::ICONS::16::player_play
+ $read_select_file_but configure -state normal
+ $read_file_entry configure -state normal
+ $read_file_entry configure -style PaleFileInterface_FileFound.TEntry
+
+ $read_text_widget configure -state normal
+ $read_text_widget delete 0.0 end
+ $read_text_widget configure -state disabled
+ # Start
+ } else {
+ if {[catch {
+ set file_to_read_channel [open [$read_file_entry get] {r}]
+ }]} then {
+ tk_messageBox \
+ -parent $win \
+ -icon warning \
+ -title [mc "Unable to open file"] \
+ -message [mc "Unable to open file:\n\"%s\" for reading, please check your permissions." [$read_file_entry get]] \
+ -type ok
+ } else {
+ set file_to_read_is_opened 1
+ $read_start_stop_but configure -image ::ICONS::16::_player_pause
+ $read_select_file_but configure -state disabled
+ $read_file_entry configure -state readonly
+ $read_file_entry configure -style PaleFileInterface_FileInUse.TEntry
+ }
+ }
+ }
+ public method vcmd_read_file_entry {filename} {
+ if {![string length $filename]} {
+ $read_file_entry configure -style TEntry
+ $read_start_stop_but configure -state disabled
+ } elseif {[file exists $filename] && [file isfile $filename] && [file readable $filename]} {
+ if {!$file_to_read_is_opened} {
+ $read_file_entry configure -style PaleFileInterface_FileFound.TEntry
+ } else {
+ $read_file_entry configure -style PaleFileInterface_FileInUse.TEntry
+ }
+ $read_start_stop_but configure -state normal
+ } else {
+ $read_file_entry configure -style PaleFileInterface_FileNotFound.TEntry
+ $read_start_stop_but configure -state disabled
+ }
+
+ return 1
+ }
+ public method vcmd_write_file_entry {filename} {
+ if {![string length $filename]} {
+ $write_file_entry configure -style TEntry
+ $write_start_stop_but configure -state disabled
+ } elseif {[file exists $filename] && [file isfile $filename] && [file readable $filename]} {
+ if {!$file_to_write_to_is_opened} {
+ $write_file_entry configure -style PaleFileInterface_FileFound.TEntry
+ } else {
+ $write_file_entry configure -style PaleFileInterface_FileInUse.TEntry
+ }
+ $write_start_stop_but configure -state normal
+ } else {
+ $write_file_entry configure -style PaleFileInterface_FileNotFound.TEntry
+ $write_start_stop_but configure -state normal
+ }
+
+ return 1
+ }
+
+ # ------------------------------------------------------------------
+ # 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}::_keep_sync $keep_sync
+ 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 {} {
+ set state [$project pale_get_true_state]
+ new_state state
+ }
+}
+
+# >>> File inclusion guard
+}
+# <<< File inclusion guard
diff --git a/lib/pale/hd44780_cgrom.tcl b/lib/pale/hd44780_cgrom.tcl
new file mode 100644
index 0000000..0ce00c7
--- /dev/null
+++ b/lib/pale/hd44780_cgrom.tcl
@@ -0,0 +1,1624 @@
+#!/usr/bin/tclsh
+# Part of MCU 8051 IDE ( http://mcu8051ide.sf.net )
+
+
+############################################################################
+# Copyright (C) 2011 by Martin Ošmera and Monika Říhová (so far) #
+# 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. #
+############################################################################
+
+# ------------------------------------------------------------------------------
+#
+# This file contains font definitions for HD44780 display driver simulator,
+# which is a part of MCU 8051 IDE project.
+#
+# ------------------------------------------------------------------------------
+#
+# Format:
+# { <-- Start all font definitions
+# n × { <-- Start one font definitions
+# 240 × { <-- Start of one character definition (addr: [0x10,0xff])
+# 10 × { <-- Start of one row on the character patter (starting from the top)
+# 5 × {0|1} <-- Dots in the patter (0 == blank; 1 == filled)
+# } <-- End of one row on the character patter
+# } <-- End of one character definition
+# } <-- End one font definitions
+# } <-- End all font definitions
+#
+# ------------------------------------------------------------------------------
+#
+# An example of a character definition:
+#
+# { PATTERN: CHARACTER:
+# {1 1 1 1 0} | # # # #
+# {1 0 0 0 1} | # #
+# {1 0 0 0 1} | # #
+# {1 1 1 1 0} | # # # #
+# {1 0 0 0 1} | # #
+# {1 0 0 0 1} | # #
+# {1 1 1 1 0} | # # # #
+# {0 0 0 0 0} |
+# {0 0 0 0 0} |
+# {0 0 0 0 0} |
+# }
+#
+# ------------------------------------------------------------------------------
+
+common CGROM {
+{
+ {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ }
+ {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ }
+
+
+ {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 1 0 0} {0 0 1 0 0} {0 0 1 0 0} {0 0 1 0 0} {0 0 0 0 0}
+ {0 0 0 0 0} {0 0 1 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 1 0 1 0} {0 1 0 1 0} {0 1 0 1 0} {0 0 0 0 0} {0 0 0 0 0}
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 1 0 1 0} {0 1 0 1 0} {1 1 1 1 1} {0 1 0 1 0} {1 1 1 1 1}
+ {0 1 0 1 0} {0 1 0 1 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 1 0 0} {0 1 1 1 1} {1 0 1 0 0} {0 1 1 1 0} {0 0 1 0 1}
+ {1 1 1 1 0} {0 0 1 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {1 1 0 0 0} {1 1 0 0 1} {0 0 0 1 0} {0 0 1 0 0} {0 1 0 0 0}
+ {1 0 0 1 1} {0 0 0 1 1} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 1 1 0 0} {1 0 0 1 0} {1 0 1 0 0} {0 1 0 0 0} {1 0 1 0 1}
+ {1 0 0 1 0} {0 1 1 0 1} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 1 1 0 0} {0 0 1 0 0} {0 1 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ }
+ {
+ {0 0 0 1 0} {0 0 1 0 0} {0 1 0 0 0} {0 1 0 0 0} {0 1 0 0 0}
+ {0 0 1 0 0} {0 0 0 1 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 1 0 0 0} {0 0 1 0 0} {0 0 0 1 0} {0 0 0 1 0} {0 0 0 1 0}
+ {0 0 1 0 0} {0 1 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 1 0 0} {1 0 1 0 1} {0 1 1 1 0} {1 0 1 0 1}
+ {0 0 1 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 1 0 0} {0 0 1 0 0} {1 1 1 1 1} {0 0 1 0 0}
+ {0 0 1 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 1 1 0 0}
+ {0 0 1 0 0} {0 1 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {1 1 1 1 1} {0 0 0 0 0}
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ {0 1 1 0 0} {0 1 1 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 1} {0 0 0 1 0} {0 0 1 0 0} {0 1 0 0 0}
+ {1 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ }
+
+
+ {
+ {0 1 1 1 0} {1 0 0 0 1} {1 0 0 1 1} {1 0 1 0 1} {1 1 0 0 1}
+ {1 0 0 0 1} {0 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 1 0 0} {0 1 1 0 0} {0 0 1 0 0} {0 0 1 0 0} {0 0 1 0 0}
+ {0 0 1 0 0} {0 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 1 1 1 0} {1 0 0 0 1} {0 0 0 0 1} {0 0 0 1 0} {0 0 1 0 0}
+ {0 1 0 0 0} {1 1 1 1 1} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {1 1 1 1 1} {0 0 0 1 0} {0 0 1 0 0} {0 0 0 1 0} {0 0 0 0 1}
+ {1 0 0 0 1} {0 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 1 0} {0 0 1 1 0} {0 1 0 1 0} {1 0 0 1 0} {1 1 1 1 1}
+ {0 0 0 1 0} {0 0 0 1 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {1 1 1 1 1} {1 0 0 0 0} {1 1 1 1 0} {0 0 0 0 1} {0 0 0 0 1}
+ {1 0 0 0 1} {0 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 1 1 0} {0 1 0 0 0} {1 0 0 0 0} {1 1 1 1 0} {1 0 0 0 1}
+ {1 0 0 0 1} {0 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {1 1 1 1 1} {1 0 0 0 1} {0 0 0 0 1} {0 0 0 1 0} {0 0 1 0 0}
+ {0 0 1 0 0} {0 0 1 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ }
+ {
+ {0 1 1 1 0} {1 0 0 0 1} {1 0 0 0 1} {0 1 1 1 0} {1 0 0 0 1}
+ {1 0 0 0 1} {0 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 1 1 1 0} {1 0 0 0 1} {1 0 0 0 1} {0 1 1 1 1} {0 0 0 0 1}
+ {0 0 0 1 0} {0 1 1 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 1 1 0 0} {0 1 1 0 0} {0 0 0 0 0} {0 1 1 0 0}
+ {0 1 1 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 1 1 0 0} {0 1 1 0 0} {0 0 0 0 0} {0 1 1 0 0}
+ {0 0 1 0 0} {0 1 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 1 0} {0 0 1 0 0} {0 1 0 0 0} {1 0 0 0 0} {0 1 0 0 0}
+ {0 0 1 0 0} {0 0 0 1 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {1 1 1 1 1} {0 0 0 0 0} {1 1 1 1 1}
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 1 0 0 0} {0 0 1 0 0} {0 0 0 1 0} {0 0 0 0 1} {0 0 0 1 0}
+ {0 0 1 0 0} {0 1 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 1 1 1 0} {1 0 0 0 1} {0 0 0 0 1} {0 0 0 1 0} {0 0 1 0 0}
+ {0 0 0 0 0} {0 0 1 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ }
+
+
+ {
+ {0 1 1 1 0} {1 0 0 0 1} {0 0 0 0 1} {0 1 1 0 1} {1 0 1 0 1}
+ {1 0 1 0 1} {0 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 1 1 1 0} {1 0 0 0 1} {1 0 0 0 1} {1 0 0 0 1} {1 1 1 1 1}
+ {1 0 0 0 1} {1 0 0 0 1} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {1 1 1 1 0} {1 0 0 0 1} {1 0 0 0 1} {1 1 1 1 0} {1 0 0 0 1}
+ {1 0 0 0 1} {1 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 1 1 1 0} {1 0 0 0 1} {1 0 0 0 0} {1 0 0 0 0} {1 0 0 0 0}
+ {1 0 0 0 1} {0 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {1 1 1 0 0} {1 0 0 1 0} {1 0 0 0 1} {1 0 0 0 1} {1 0 0 0 1}
+ {1 0 0 1 0} {1 1 1 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {1 1 1 1 1} {1 0 0 0 0} {1 0 0 0 0} {1 1 1 1 0} {1 0 0 0 0}
+ {1 0 0 0 0} {1 1 1 1 1} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {1 1 1 1 1} {1 0 0 0 0} {1 0 0 0 0} {1 1 1 1 0} {1 0 0 0 0}
+ {1 0 0 0 0} {1 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 1 1 1 0} {1 0 0 0 1} {1 0 0 0 0} {1 0 1 1 1} {1 0 0 0 1}
+ {1 0 0 0 1} {0 1 1 1 1} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ }
+ {
+ {1 0 0 0 1} {1 0 0 0 1} {1 0 0 0 1} {1 1 1 1 1} {1 0 0 0 1}
+ {1 0 0 0 1} {1 0 0 0 1} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 1 1 1 0} {0 0 1 0 0} {0 0 1 0 0} {0 0 1 0 0} {0 0 1 0 0}
+ {0 0 1 0 0} {0 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 1 1 1} {0 0 0 1 0} {0 0 0 1 0} {0 0 0 1 0} {0 0 0 1 0}
+ {1 0 0 1 0} {0 1 1 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {1 0 0 0 1} {1 0 0 1 0} {1 0 1 0 0} {1 1 0 0 0} {1 0 1 0 0}
+ {1 0 0 1 0} {1 0 0 0 1} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {1 0 0 0 0} {1 0 0 0 0} {1 0 0 0 0} {1 0 0 0 0} {1 0 0 0 0}
+ {1 0 0 0 0} {1 1 1 1 1} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {1 0 0 0 1} {1 1 0 1 1} {1 0 1 0 1} {1 0 1 0 1} {1 0 0 0 1}
+ {1 0 0 0 1} {1 0 0 0 1} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {1 0 0 0 1} {1 0 0 0 1} {1 1 0 0 1} {1 0 1 0 1} {1 0 0 1 1}
+ {1 0 0 0 1} {1 0 0 0 1} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 1 1 1 0} {1 0 0 0 1} {1 0 0 0 1} {1 0 0 0 1} {1 0 0 0 1}
+ {1 0 0 0 1} {0 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ }
+
+
+ {
+ {1 1 1 1 0} {1 0 0 0 1} {1 0 0 0 1} {1 1 1 1 0} {1 0 0 0 0}
+ {1 0 0 0 0} {1 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 1 1 1 0} {1 0 0 0 1} {1 0 0 0 1} {1 0 0 0 1} {1 0 1 0 1}
+ {1 0 0 1 0} {0 1 1 0 1} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {1 1 1 1 0} {1 0 0 0 1} {1 0 0 0 1} {1 1 1 1 0} {1 0 1 0 0}
+ {1 0 0 1 0} {1 0 0 0 1} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 1 1 1 1} {1 0 0 0 0} {1 0 0 0 0} {0 1 1 1 0} {0 0 0 0 1}
+ {0 0 0 0 1} {1 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {1 1 1 1 1} {0 0 1 0 0} {0 0 1 0 0} {0 0 1 0 0} {0 0 1 0 0}
+ {0 0 1 0 0} {0 0 1 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {1 0 0 0 1} {1 0 0 0 1} {1 0 0 0 1} {1 0 0 0 1} {1 0 0 0 1}
+ {1 0 0 0 1} {0 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {1 0 0 0 1} {1 0 0 0 1} {1 0 0 0 1} {1 0 0 0 1} {1 0 0 0 1}
+ {0 1 0 1 0} {0 0 1 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {1 0 0 0 1} {1 0 0 0 1} {1 0 0 0 1} {1 0 1 0 1} {1 0 1 0 1}
+ {1 0 1 0 1} {0 1 0 1 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ }
+ {
+ {1 0 0 0 1} {1 0 0 0 1} {0 1 0 1 0} {0 0 1 0 0} {0 1 0 1 0}
+ {1 0 0 0 1} {1 0 0 0 1} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {1 0 0 0 1} {1 0 0 0 1} {1 0 0 0 1} {0 1 0 1 0} {0 0 1 0 0}
+ {0 0 1 0 0} {0 0 1 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {1 1 1 1 1} {0 0 0 0 1} {0 0 0 1 0} {0 0 1 0 0} {0 1 0 0 0}
+ {1 0 0 0 0} {1 1 1 1 1} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {1 1 1 0 0} {1 0 0 0 0} {1 0 0 0 0} {1 0 0 0 0} {1 0 0 0 0}
+ {1 0 0 0 0} {1 1 1 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {1 0 0 0 1} {0 1 0 1 0} {1 1 1 1 1} {0 0 1 0 0} {1 1 1 1 1}
+ {0 0 1 0 0} {0 0 1 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 1 1 1} {0 0 0 0 1} {0 0 0 0 1} {0 0 0 0 1} {0 0 0 0 1}
+ {0 0 0 0 1} {0 0 1 1 1} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 1 0 0} {0 1 0 1 0} {1 0 0 0 1} {0 0 0 0 0} {0 0 0 0 0}
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ {0 0 0 0 0} {1 1 1 1 1} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ }
+
+
+ {
+ {0 1 0 0 0} {0 0 1 0 0} {0 0 0 1 0} {0 0 0 0 0} {0 0 0 0 0}
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 1 1 1 0} {0 0 0 0 1} {0 1 1 1 1}
+ {1 0 0 0 1} {0 1 1 1 1} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {1 0 0 0 0} {1 0 0 0 0} {1 0 1 1 0} {1 1 0 0 1} {1 0 0 0 1}
+ {1 0 0 0 1} {1 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 1 1 1 0} {1 0 0 0 0} {1 0 0 0 0}
+ {1 0 0 0 1} {0 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 1} {0 0 0 0 1} {0 1 1 0 1} {1 0 0 1 1} {1 0 0 0 1}
+ {1 0 0 0 1} {0 1 1 1 1} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 1 1 1 0} {1 0 0 0 1} {1 1 1 1 1}
+ {1 0 0 0 0} {0 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 1 1 0} {0 1 0 0 1} {0 1 0 0 0} {1 1 1 0 0} {0 1 0 0 0}
+ {0 1 0 0 0} {0 1 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 1 1 1 1} {1 0 0 0 1} {1 0 0 0 1} {0 1 1 1 1}
+ {0 0 0 0 1} {0 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ }
+ {
+ {1 0 0 0 0} {1 0 0 0 0} {1 0 1 1 0} {1 1 0 0 1} {1 0 0 0 1}
+ {1 0 0 0 1} {1 0 0 0 1} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 1 0 0} {0 0 0 0 0} {0 1 1 0 0} {0 0 1 0 0} {0 0 1 0 0}
+ {0 0 1 0 0} {0 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 1 0} {0 0 0 0 0} {0 0 1 1 0} {0 0 0 1 0} {0 0 0 1 0}
+ {1 0 0 1 0} {0 1 1 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {1 0 0 0 0} {1 0 0 0 0} {1 0 0 1 0} {1 0 1 0 0} {1 1 0 0 0}
+ {1 0 1 0 0} {1 0 0 1 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 1 1 0 0} {0 0 1 0 0} {0 0 1 0 0} {0 0 1 0 0} {0 0 1 0 0}
+ {0 0 1 0 0} {0 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {1 1 0 1 0} {1 0 1 0 1} {1 0 1 0 1}
+ {1 0 0 0 1} {1 0 0 0 1} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {1 0 1 1 0} {1 1 0 0 1} {1 0 0 0 1}
+ {1 0 0 0 1} {1 0 0 0 1} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 1 1 1 0} {1 0 0 0 1} {1 0 0 0 1}
+ {1 0 0 0 1} {0 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ }
+
+
+ {
+ {0 0 0 0 0} {0 0 0 0 0} {1 1 1 1 0} {1 0 0 0 1} {1 1 1 1 0}
+ {1 0 0 0 0} {1 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 1 1 0 1} {1 0 0 1 1} {0 1 1 1 1}
+ {0 0 0 0 1} {0 0 0 0 1} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {1 0 1 1 0} {1 1 0 0 1} {1 0 0 0 0}
+ {1 0 0 0 0} {1 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 1 1 1 0} {1 0 0 0 0} {0 1 1 1 0}
+ {0 0 0 0 1} {1 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 1 0 0 0} {0 1 0 0 0} {1 1 1 0 0} {0 1 0 0 0} {0 1 0 0 0}
+ {0 1 0 0 1} {0 0 1 1 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {1 0 0 0 1} {1 0 0 0 1} {1 0 0 0 1}
+ {1 0 0 1 1} {0 1 1 0 1} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {1 0 0 0 1} {1 0 0 0 1} {1 0 0 0 1}
+ {0 1 0 1 0} {0 0 1 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {1 0 0 0 1} {1 0 1 0 1} {1 0 1 0 1}
+ {1 0 1 0 1} {0 1 0 1 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ }
+ {
+ {0 0 0 0 0} {0 0 0 0 0} {1 0 0 0 1} {0 1 0 1 0} {0 0 1 0 0}
+ {0 1 0 1 0} {1 0 0 0 1} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {1 0 0 0 1} {1 0 0 0 1} {0 1 1 1 1}
+ {0 0 0 0 1} {0 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {1 1 1 1 1} {0 0 0 1 0} {0 0 1 0 0}
+ {0 1 0 0 0} {1 1 1 1 1} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 1 0} {0 0 1 0 0} {0 0 1 0 0} {0 1 0 0 0} {0 0 1 0 0}
+ {0 0 1 0 0} {0 0 0 1 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 1 0 0} {0 0 1 0 0} {0 0 1 0 0} {0 0 1 0 0} {0 0 1 0 0}
+ {0 0 1 0 0} {0 0 1 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 1 0 0 0} {0 0 1 0 0} {0 0 1 0 0} {0 0 0 1 0} {0 0 1 0 0}
+ {0 0 1 0 0} {0 1 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 1 0 0} {0 0 0 1 0} {1 1 1 1 1} {0 0 0 1 0}
+ {0 0 1 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 1 0 0} {0 1 0 0 0} {1 1 1 1 1} {0 1 0 0 0}
+ {0 0 1 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ }
+
+
+ {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ }
+ {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ }
+
+
+ {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ }
+ {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ }
+
+
+ {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 1 1 1 0}
+ {0 1 0 1 0} {0 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 1 1 1} {0 0 1 0 0} {0 0 1 0 0} {0 0 1 0 0} {0 0 0 0 0}
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 1 0 0} {0 0 1 0 0}
+ {0 0 1 0 0} {1 1 1 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {1 0 0 0 0}
+ {0 1 0 0 0} {0 0 1 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 1 1 0 0} {0 1 1 0 0}
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {1 1 1 1 1} {0 0 0 0 1} {1 1 1 1 1} {0 0 0 0 1}
+ {0 0 0 1 0} {0 0 1 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 1 0} {0 0 1 0 0} {0 1 1 0 0}
+ {1 0 1 0 0} {0 0 1 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ }
+ {
+ {0 0 0 0 0} {0 0 0 0 0} {1 1 1 1 1} {0 0 0 0 1} {0 0 1 1 0}
+ {0 0 1 0 0} {0 1 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 1 0 0} {1 1 1 1 1} {1 0 0 0 1}
+ {0 0 0 0 1} {0 0 1 1 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {1 1 1 1 1} {0 0 1 0 0} {0 0 1 0 0}
+ {0 0 1 0 0} {1 1 1 1 1} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 1 0} {1 1 1 1 1} {0 0 1 1 0}
+ {0 1 0 1 0} {1 0 0 1 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 1 0 0 0} {1 1 1 1 1} {0 1 0 0 1}
+ {0 1 0 1 0} {0 1 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 1 1 1 0} {0 0 0 1 0}
+ {0 0 0 1 0} {1 1 1 1 1} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {1 1 1 1 0} {0 0 0 1 0} {1 1 1 1 0}
+ {0 0 0 1 0} {1 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {1 0 1 0 1} {1 0 1 0 1}
+ {0 0 0 0 1} {0 0 1 1 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ }
+
+
+ {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {1 1 1 1 1} {0 0 0 0 0}
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {1 1 1 1 1} {0 0 0 0 1} {0 0 1 0 1} {0 0 1 1 0} {0 0 1 0 0}
+ {0 0 1 0 0} {0 1 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 1} {0 0 0 1 0} {0 0 1 0 0} {0 1 1 0 0} {1 0 1 0 0}
+ {0 0 1 0 0} {0 0 1 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 1 0 0} {1 1 1 1 1} {1 0 0 0 1} {1 0 0 0 1} {0 0 0 0 1}
+ {0 0 0 1 0} {0 0 1 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {1 1 1 1 1} {0 0 1 0 0} {0 0 1 0 0} {0 0 1 0 0}
+ {0 0 1 0 0} {1 1 1 1 1} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 1 0} {1 1 1 1 1} {0 0 0 1 0} {0 0 1 1 0} {0 1 0 1 0}
+ {1 0 0 1 0} {0 0 0 1 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 1 0 0 0} {1 1 1 1 1} {0 1 0 0 1} {0 1 0 0 1} {0 1 0 0 1}
+ {0 1 0 0 1} {1 0 0 1 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 1 0 0} {1 1 1 1 1} {0 0 1 0 0} {1 1 1 1 1} {0 0 1 0 0}
+ {0 0 1 0 0} {0 0 1 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ }
+ {
+ {0 0 0 0 0} {0 1 1 1 1} {0 1 0 0 1} {1 0 0 0 1} {0 0 0 0 1}
+ {0 0 0 1 0} {0 0 1 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 1 0 0 0} {0 1 1 1 1} {1 0 0 1 0} {0 0 0 1 0} {0 0 0 1 0}
+ {0 0 0 1 0} {0 0 1 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {1 1 1 1 1} {0 0 0 0 1} {0 0 0 0 1} {0 0 0 0 1} {0 0 0 0 1}
+ {0 0 0 0 1} {1 1 1 1 1} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 1 0 1 0} {1 1 1 1 1} {0 1 0 1 0} {0 1 0 1 0} {0 0 0 1 0}
+ {0 0 1 0 0} {0 1 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {1 1 0 0 0} {0 0 0 0 1} {1 1 0 0 1} {0 0 0 0 1}
+ {0 0 0 1 0} {1 1 1 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {1 1 1 1 1} {0 0 0 0 1} {0 0 0 1 0} {0 0 1 0 0}
+ {0 1 0 1 0} {1 0 0 0 1} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 1 0 0 0} {1 1 1 1 1} {0 1 0 0 1} {0 1 0 1 0} {0 1 0 0 0}
+ {0 1 0 0 0} {0 0 1 1 1} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {1 0 0 0 1} {1 0 0 0 1} {0 1 0 0 1} {0 0 0 0 1}
+ {0 0 0 1 0} {0 1 1 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ }
+
+
+ {
+ {0 0 0 0 0} {0 1 1 1 1} {0 1 0 0 1} {1 0 1 0 1} {0 0 0 1 1}
+ {0 0 0 1 0} {0 1 1 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 1 0} {1 1 1 0 0} {0 0 1 0 0} {1 1 1 1 1} {0 0 1 0 0}
+ {0 0 1 0 0} {0 1 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {1 0 1 0 1} {1 0 1 0 1} {1 0 1 0 1} {0 0 0 0 1}
+ {0 0 0 1 0} {0 0 1 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 1 1 1 0} {0 0 0 0 0} {1 1 1 1 1} {0 0 1 0 0} {0 0 1 0 0}
+ {0 0 1 0 0} {0 1 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 1 0 0 0} {0 1 0 0 0} {0 1 0 0 0} {0 1 1 0 0} {0 1 0 1 0}
+ {0 1 0 0 0} {0 1 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 1 0 0} {0 0 1 0 0} {1 1 1 1 1} {0 0 1 0 0} {0 0 1 0 0}
+ {0 1 0 0 0} {1 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ {0 0 0 0 0} {1 1 1 1 1} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {1 1 1 1 1} {0 0 0 0 1} {0 1 0 1 0} {0 0 1 0 0}
+ {0 1 0 1 0} {1 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ }
+ {
+ {0 0 1 0 0} {1 1 1 1 1} {0 0 0 1 0} {0 0 1 0 0} {0 1 1 1 0}
+ {1 0 1 0 1} {0 0 1 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 1 0} {0 0 0 1 0} {0 0 0 1 0} {0 0 0 1 0} {0 0 0 1 0}
+ {0 0 1 0 0} {0 1 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 1 0 0} {0 0 0 1 0} {0 0 0 0 1} {1 0 0 0 1}
+ {1 0 0 0 1} {1 0 0 0 1} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 1 0 0 0} {0 1 0 0 0} {1 1 1 1 1} {0 1 0 0 0} {0 1 0 0 0}
+ {0 1 0 0 0} {0 0 1 1 1} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {1 1 1 1 1} {0 0 0 0 1} {0 0 0 0 1} {0 0 0 0 1}
+ {0 0 0 1 0} {0 1 1 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 1 0 0 0} {1 0 1 0 0} {0 0 0 1 0} {0 0 0 1 0}
+ {0 0 0 1 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 1 0 0} {1 1 1 1 1} {0 0 1 0 0} {0 0 1 0 0} {1 0 1 0 1}
+ {1 0 1 0 1} {0 0 1 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {1 1 1 1 1} {0 0 0 0 1} {0 0 0 0 1} {0 1 0 1 0}
+ {0 0 1 0 0} {0 0 0 1 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ }
+
+
+ {
+ {0 0 0 0 0} {0 1 1 1 0} {0 0 0 0 0} {0 1 1 1 0} {0 0 0 0 0}
+ {0 1 1 1 0} {0 0 0 0 1} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 1 0 0} {0 1 0 0 0} {1 0 0 0 0} {1 0 0 0 1}
+ {1 1 1 1 1} {0 0 0 0 1} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 1} {0 0 0 0 1} {0 1 0 1 0} {0 0 1 0 0}
+ {0 1 0 1 0} {1 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {1 1 1 1 1} {0 1 0 0 0} {1 1 1 1 1} {0 1 0 0 0}
+ {0 1 0 0 0} {0 0 1 1 1} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 1 0 0 0} {0 1 0 0 0} {1 1 1 1 1} {0 1 0 0 1} {0 1 0 1 0}
+ {0 1 0 0 0} {0 1 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 1 1 1 0} {0 0 0 1 0} {0 0 0 1 0} {0 0 0 1 0}
+ {0 0 0 1 0} {1 1 1 1 1} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {1 1 1 1 1} {0 0 0 0 1} {1 1 1 1 1} {0 0 0 0 1}
+ {0 0 0 0 1} {1 1 1 1 1} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 1 1 1 0} {0 0 0 0 0} {1 1 1 1 1} {0 0 0 0 1} {0 0 0 0 1}
+ {0 0 0 1 0} {0 0 1 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ }
+ {
+ {1 0 0 1 0} {1 0 0 1 0} {1 0 0 1 0} {1 0 0 1 0} {0 0 0 1 0}
+ {0 0 1 0 0} {0 1 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 1 0 0} {1 0 1 0 0} {1 0 1 0 0} {1 0 1 0 1}
+ {1 0 1 0 1} {1 0 1 1 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {1 0 0 0 0} {1 0 0 0 0} {1 0 0 0 1} {1 0 0 1 0}
+ {1 0 1 0 0} {1 1 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {1 1 1 1 1} {1 0 0 0 1} {1 0 0 0 1} {1 0 0 0 1}
+ {1 0 0 0 1} {1 1 1 1 1} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {1 1 1 1 1} {1 0 0 0 1} {1 0 0 0 1} {0 0 0 0 1}
+ {0 0 0 1 0} {0 0 1 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 1 1 0 0} {0 0 0 0 0} {0 0 0 0 1} {0 0 0 0 1}
+ {0 0 0 1 0} {1 1 1 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 1 0 0} {1 0 0 1 0} {0 1 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {1 1 1 0 0} {1 0 1 0 0} {1 1 1 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ }
+
+
+ {
+ {0 0 0 0 0} {0 0 0 0 0} {0 1 0 0 1} {1 0 1 0 1} {1 0 0 1 0}
+ {1 0 0 1 0} {0 1 1 0 1} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 1 0 1 0} {0 0 0 0 0} {0 1 1 1 0} {0 0 0 0 1} {0 1 1 1 1}
+ {1 0 0 0 1} {0 1 1 1 1} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 1 1 1 0} {1 0 0 0 1} {1 1 1 1 0}
+ {1 0 0 0 1} {1 1 1 1 0} {1 0 0 0 0} {1 0 0 0 0} {1 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 1 1 1 0} {1 0 0 0 0} {0 1 1 0 0}
+ {1 0 0 0 1} {0 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {1 0 0 0 1} {1 0 0 0 1} {1 0 0 0 1}
+ {1 0 0 1 1} {1 1 1 0 1} {1 0 0 0 0} {1 0 0 0 0} {1 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 1 1 1 1} {1 0 1 0 0} {1 0 0 1 0}
+ {1 0 0 0 1} {0 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 1 1 0} {0 1 0 0 1} {1 0 0 0 1}
+ {1 0 0 0 1} {1 1 1 1 0} {1 0 0 0 0} {1 0 0 0 0} {1 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 1 1 1 1} {1 0 0 0 1} {1 0 0 0 1}
+ {1 0 0 0 1} {0 1 1 1 1} {0 0 0 0 1} {0 0 0 0 1} {0 1 1 1 0}
+ }
+ {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 1 1 1} {0 0 1 0 0} {0 0 1 0 0}
+ {1 0 1 0 0} {0 1 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 1 0} {1 1 0 1 0} {0 0 0 1 0} {0 0 0 0 0}
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 1 0} {0 0 0 0 0} {0 0 1 1 0} {0 0 0 1 0} {0 0 0 1 0}
+ {0 0 0 1 0} {0 0 0 1 0} {0 0 0 1 0} {1 0 0 1 0} {0 1 1 0 0}
+ } {
+ {0 0 0 0 0} {0 1 0 1 0} {0 0 1 0 0} {0 1 0 1 0} {0 0 0 0 0}
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 1 0 0} {0 1 1 1 0} {1 0 1 0 0} {1 0 1 0 1}
+ {0 1 1 1 0} {0 0 1 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 1 0 0 0} {0 1 0 0 0} {1 1 1 0 0} {0 1 0 0 0} {1 1 1 0 0}
+ {0 1 0 0 0} {0 1 1 1 1} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 1 1 1 0} {0 0 0 0 0} {1 0 1 1 0} {1 1 0 0 1} {1 0 0 0 1}
+ {1 0 0 0 1} {1 0 0 0 1} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 1 0 1 0} {0 0 0 0 0} {0 1 1 1 0} {1 0 0 0 1} {1 0 0 0 1}
+ {1 0 0 0 1} {0 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ }
+
+
+ {
+ {0 0 0 0 0} {0 0 0 0 0} {1 0 1 1 0} {1 1 0 0 1} {1 0 0 0 1}
+ {1 0 0 0 1} {1 1 1 1 0} {1 0 0 0 0} {1 0 0 0 0} {1 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 1 1 0 1} {1 0 0 1 1} {1 0 0 0 1}
+ {1 0 0 0 1} {0 1 1 1 1} {0 0 0 0 1} {0 0 0 0 1} {0 0 0 0 1}
+ } {
+ {0 1 1 1 0} {1 0 0 0 1} {1 1 1 1 1} {1 0 0 0 1} {1 0 0 0 1}
+ {0 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 1 0 1 1} {1 0 1 0 1}
+ {1 1 0 1 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 1 1 1 0} {1 0 0 0 1} {1 0 0 0 1}
+ {0 1 0 1 0} {1 1 0 1 1} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 1 0 1 0} {0 0 0 0 0} {1 0 0 0 1} {1 0 0 0 1} {1 0 0 0 1}
+ {1 0 0 0 1} {1 0 0 1 1} {0 1 1 0 1} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {1 1 1 1 1} {1 0 0 0 0} {0 1 0 0 0} {0 0 1 0 0} {0 1 0 0 0}
+ {1 0 0 0 0} {1 1 1 1 1} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {1 1 1 1 1} {0 1 0 1 0} {0 1 0 1 0}
+ {0 1 0 1 0} {1 0 0 1 1} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ }
+ {
+ {1 1 1 1 1} {0 0 0 0 0} {1 0 0 0 1} {0 1 0 1 0} {0 0 1 0 0}
+ {0 1 0 1 0} {1 0 0 0 1} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {1 0 0 0 1} {1 0 0 0 1} {1 0 0 0 1}
+ {1 0 0 0 1} {0 1 1 1 1} {0 0 0 0 1} {0 0 0 0 1} {0 1 1 1 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 1} {1 1 1 1 0} {0 0 1 0 0} {1 1 1 1 1}
+ {0 0 1 0 0} {0 0 1 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {1 1 1 1 1} {0 1 0 0 0} {0 1 1 1 1}
+ {0 1 0 0 1} {1 0 0 0 1} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {1 1 1 1 1} {1 0 1 0 1} {1 1 1 1 1}
+ {1 0 0 0 1} {1 0 0 0 1} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 1 0 0} {0 0 0 0 0} {1 1 1 1 1} {0 0 0 0 0}
+ {0 0 1 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {1 1 1 1 1} {1 1 1 1 1} {1 1 1 1 1} {1 1 1 1 1} {1 1 1 1 1}
+ {1 1 1 1 1} {1 1 1 1 1} {1 1 1 1 1} {1 1 1 1 1} {1 1 1 1 1}
+ }
+} {
+} {
+ {
+ {0 0 0 0 0} {0 1 0 0 0} {0 1 1 0 0} {0 1 1 1 0} {0 1 1 1 1}
+ {0 1 1 1 0} {0 1 1 0 0} {0 1 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 1 0} {0 0 1 1 0} {0 1 1 1 0} {1 1 1 1 0}
+ {0 1 1 1 0} {0 0 1 1 0} {0 0 0 1 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 1 0 0 1} {1 0 0 1 0} {1 1 0 1 1} {0 0 0 0 0}
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {1 1 0 1 1} {0 1 0 0 1} {1 0 0 1 0} {0 0 0 0 0}
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 1 0 0} {0 1 1 1 0} {1 1 1 1 1} {0 0 0 0 0}
+ {0 0 1 0 0} {0 1 1 1 0} {1 1 1 1 1} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {1 1 1 1 1} {0 1 1 1 0} {0 0 1 0 0} {0 0 0 0 0}
+ {1 1 1 1 1} {0 1 1 1 0} {0 0 1 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 1 1 1 0} {1 1 1 1 1} {1 1 1 1 1}
+ {1 1 1 1 1} {0 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 1} {0 0 0 0 1} {0 0 1 0 1} {0 1 0 0 1}
+ {1 1 1 1 1} {0 1 0 0 0} {0 0 1 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ }
+ {
+ {0 0 0 0 0} {0 0 1 0 0} {0 1 1 1 0} {1 0 1 0 1} {0 0 1 0 0}
+ {0 0 1 0 0} {0 0 1 0 0} {0 0 1 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 1 0 0} {0 0 1 0 0} {0 0 1 0 0} {0 0 1 0 0}
+ {1 0 1 0 1} {0 1 1 1 0} {0 0 1 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 1 0 0} {0 0 0 1 0} {1 1 1 1 1}
+ {0 0 0 1 0} {0 0 1 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 1 0 0} {0 1 0 0 0} {1 1 1 1 1}
+ {0 1 0 0 0} {0 0 1 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 1 0} {0 0 1 0 0} {0 1 0 0 0} {0 0 1 0 0}
+ {0 0 0 1 0} {0 0 0 0 0} {1 1 1 1 1} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 1 0 0 0} {0 0 1 0 0} {0 0 0 1 0} {0 0 1 0 0}
+ {0 1 0 0 0} {0 0 0 0 0} {1 1 1 1 1} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 1 0 0} {0 0 1 0 0} {0 1 1 1 0}
+ {0 1 1 1 0} {1 1 1 1 1} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {1 1 1 1 1} {0 1 1 1 0} {0 1 1 1 0}
+ {0 0 1 0 0} {0 0 1 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ }
+
+
+ {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 1 0 0} {0 0 1 0 0} {0 0 1 0 0} {0 0 1 0 0}
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 1 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 1 0 1 0} {0 1 0 1 0} {0 1 0 1 0} {0 0 0 0 0}
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 1 0 1 0} {0 1 0 1 0} {1 1 1 1 1} {0 1 0 1 0}
+ {1 1 1 1 1} {0 1 0 1 0} {0 1 0 1 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 1 0 0} {0 1 1 1 1} {1 0 1 0 0} {0 1 1 1 0}
+ {0 0 1 0 1} {1 1 1 1 0} {0 0 1 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {1 1 0 0 0} {1 1 0 0 1} {0 0 0 1 0} {0 0 1 0 0}
+ {0 1 0 0 0} {1 0 0 1 1} {0 0 0 1 1} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 1 1 0 0} {1 0 0 1 0} {1 0 1 0 0} {0 1 0 0 0}
+ {1 0 1 0 1} {1 0 0 1 0} {0 1 1 0 1} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 1 1 0 0} {0 0 1 0 0} {0 1 0 0 0} {0 0 0 0 0}
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ }
+ {
+ {0 0 0 0 0} {0 0 0 1 0} {0 0 1 0 0} {0 1 0 0 0} {0 1 0 0 0}
+ {0 1 0 0 0} {0 0 1 0 0} {0 0 0 1 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 1 0 0 0} {0 0 1 0 0} {0 0 0 1 0} {0 0 0 1 0}
+ {0 0 0 1 0} {0 0 1 0 0} {0 1 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 1 0 0} {1 0 1 0 1} {0 1 1 1 0}
+ {1 0 1 0 1} {0 0 1 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 1 0 0} {0 0 1 0 0} {1 1 1 1 1}
+ {0 0 1 0 0} {0 0 1 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ {0 1 1 0 0} {0 0 1 0 0} {0 1 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {1 1 1 1 1}
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ {0 0 0 0 0} {0 1 1 0 0} {0 1 1 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 1} {0 0 0 1 0} {0 0 1 0 0}
+ {0 1 0 0 0} {1 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ }
+
+
+ {
+ {0 0 0 0 0} {0 1 1 1 0} {1 0 0 0 1} {1 0 0 1 1} {1 0 1 0 1}
+ {1 1 0 0 1} {1 0 0 0 1} {0 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 1 0 0} {0 1 1 0 0} {0 0 1 0 0} {0 0 1 0 0}
+ {0 0 1 0 0} {0 0 1 0 0} {0 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 1 1 1 0} {1 0 0 0 1} {0 0 0 0 1} {0 0 0 1 0}
+ {0 0 1 0 0} {0 1 0 0 0} {1 1 1 1 1} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {1 1 1 1 1} {0 0 0 1 0} {0 0 1 0 0} {0 0 0 1 0}
+ {0 0 0 0 1} {1 0 0 0 1} {0 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 1 0} {0 0 1 1 0} {0 1 0 1 0} {1 0 0 1 0}
+ {1 1 1 1 1} {0 0 0 1 0} {0 0 0 1 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {1 1 1 1 1} {1 0 0 0 0} {1 1 1 1 0} {0 0 0 0 1}
+ {0 0 0 0 1} {1 0 0 0 1} {0 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 1 1 0} {0 1 0 0 0} {1 0 0 0 0} {1 1 1 1 0}
+ {1 0 0 0 1} {1 0 0 0 1} {0 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {1 1 1 1 1} {1 0 0 0 1} {0 0 0 0 1} {0 0 0 1 0}
+ {0 0 1 0 0} {0 0 1 0 0} {0 0 1 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ }
+ {
+ {0 0 0 0 0} {0 1 1 1 0} {1 0 0 0 1} {1 0 0 0 1} {0 1 1 1 0}
+ {1 0 0 0 1} {1 0 0 0 1} {0 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 1 1 1 0} {1 0 0 0 1} {1 0 0 0 1} {0 1 1 1 1}
+ {0 0 0 0 1} {0 0 0 1 0} {0 1 1 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 1 1 0 0} {0 1 1 0 0} {0 0 0 0 0}
+ {0 1 1 0 0} {0 1 1 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 1 1 0 0} {0 1 1 0 0} {0 0 0 0 0}
+ {0 1 1 0 0} {0 0 1 0 0} {0 1 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 1 0} {0 0 1 0 0} {0 1 0 0 0} {1 0 0 0 0}
+ {0 1 0 0 0} {0 0 1 0 0} {0 0 0 1 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {1 1 1 1 1} {0 0 0 0 0}
+ {1 1 1 1 1} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 1 0 0 0} {0 0 1 0 0} {0 0 0 1 0} {0 0 0 0 1}
+ {0 0 0 1 0} {0 0 1 0 0} {0 1 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 1 1 1 0} {1 0 0 0 1} {0 0 0 0 1} {0 0 0 1 0}
+ {0 0 1 0 0} {0 0 0 0 0} {0 0 1 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ }
+
+
+ {
+ {0 0 0 0 0} {0 1 1 1 0} {1 0 0 0 1} {0 0 0 0 1} {0 1 1 0 1}
+ {1 0 1 0 1} {1 0 1 0 1} {0 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 1 1 1 0} {1 0 0 0 1} {1 0 0 0 1} {1 0 0 0 1}
+ {1 1 1 1 1} {1 0 0 0 1} {1 0 0 0 1} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {1 1 1 1 0} {1 0 0 0 1} {1 0 0 0 1} {1 1 1 1 0}
+ {1 0 0 0 1} {1 0 0 0 1} {1 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 1 1 1 0} {1 0 0 0 1} {1 0 0 0 0} {1 0 0 0 0}
+ {1 0 0 0 0} {1 0 0 0 1} {0 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {1 1 1 0 0} {1 0 0 1 0} {1 0 0 0 1} {1 0 0 0 1}
+ {1 0 0 0 1} {1 0 0 1 0} {1 1 1 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {1 1 1 1 1} {1 0 0 0 0} {1 0 0 0 0} {1 1 1 1 0}
+ {1 0 0 0 0} {1 0 0 0 0} {1 1 1 1 1} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {1 1 1 1 1} {1 0 0 0 0} {1 0 0 0 0} {1 1 1 1 0}
+ {1 0 0 0 0} {1 0 0 0 0} {1 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 1 1 1 0} {1 0 0 0 1} {1 0 0 0 0} {1 0 1 1 1}
+ {1 0 0 0 1} {1 0 0 0 1} {0 1 1 1 1} {0 0 0 0 0} {0 0 0 0 0}
+ }
+ {
+ {0 0 0 0 0} {1 0 0 0 1} {1 0 0 0 1} {1 0 0 0 1} {1 1 1 1 1}
+ {1 0 0 0 1} {1 0 0 0 1} {1 0 0 0 1} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 1 1 1 0} {0 0 1 0 0} {0 0 1 0 0} {0 0 1 0 0}
+ {0 0 1 0 0} {0 0 1 0 0} {0 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 1 1 1} {0 0 0 1 0} {0 0 0 1 0} {0 0 0 1 0}
+ {0 0 0 1 0} {1 0 0 1 0} {0 1 1 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {1 0 0 0 1} {1 0 0 1 0} {1 0 1 0 0} {1 1 0 0 0}
+ {1 0 1 0 0} {1 0 0 1 0} {1 0 0 0 1} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {1 0 0 0 0} {1 0 0 0 0} {1 0 0 0 0} {1 0 0 0 0}
+ {1 0 0 0 0} {1 0 0 0 0} {1 1 1 1 1} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {1 0 0 0 1} {1 1 0 1 1} {1 0 1 0 1} {1 0 1 0 1}
+ {1 0 0 0 1} {1 0 0 0 1} {1 0 0 0 1} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {1 0 0 0 1} {1 0 0 0 1} {1 1 0 0 1} {1 0 1 0 1}
+ {1 0 0 1 1} {1 0 0 0 1} {1 0 0 0 1} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 1 1 1 0} {1 0 0 0 1} {1 0 0 0 1} {1 0 0 0 1}
+ {1 0 0 0 1} {1 0 0 0 1} {0 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0}
+ }
+
+
+ {
+ {0 0 0 0 0} {1 1 1 1 0} {1 0 0 0 1} {1 0 0 0 1} {1 1 1 1 0}
+ {1 0 0 0 0} {1 0 0 0 0} {1 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 1 1 1 0} {1 0 0 0 1} {1 0 0 0 1} {1 0 0 0 1}
+ {1 0 1 0 1} {1 0 0 1 0} {0 1 1 0 1} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {1 1 1 1 0} {1 0 0 0 1} {1 0 0 0 1} {1 1 1 1 0}
+ {1 0 1 0 0} {1 0 0 1 0} {1 0 0 0 1} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 1 1 1 1} {1 0 0 0 0} {1 0 0 0 0} {0 1 1 1 0}
+ {0 0 0 0 1} {0 0 0 0 1} {1 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {1 1 1 1 1} {0 0 1 0 0} {0 0 1 0 0} {0 0 1 0 0}
+ {0 0 1 0 0} {0 0 1 0 0} {0 0 1 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {1 0 0 0 1} {1 0 0 0 1} {1 0 0 0 1} {1 0 0 0 1}
+ {1 0 0 0 1} {1 0 0 0 1} {0 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {1 0 0 0 1} {1 0 0 0 1} {1 0 0 0 1} {1 0 0 0 1}
+ {1 0 0 0 1} {0 1 0 1 0} {0 0 1 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {1 0 0 0 1} {1 0 0 0 1} {1 0 0 0 1} {1 0 1 0 1}
+ {1 0 1 0 1} {1 0 1 0 1} {0 1 0 1 0} {0 0 0 0 0} {0 0 0 0 0}
+ }
+ {
+ {0 0 0 0 0} {1 0 0 0 1} {1 0 0 0 1} {0 1 0 1 0} {0 0 1 0 0}
+ {0 1 0 1 0} {1 0 0 0 1} {1 0 0 0 1} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {1 0 0 0 1} {1 0 0 0 1} {1 0 0 0 1} {0 1 0 1 0}
+ {0 0 1 0 0} {0 0 1 0 0} {0 0 1 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {1 1 1 1 1} {0 0 0 0 1} {0 0 0 1 0} {0 0 1 0 0}
+ {0 1 0 0 0} {1 0 0 0 0} {1 1 1 1 1} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {1 1 1 0 0} {1 0 0 0 0} {1 0 0 0 0} {1 0 0 0 0}
+ {1 0 0 0 0} {1 0 0 0 0} {1 1 1 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {1 0 0 0 1} {0 1 0 1 0} {1 1 1 1 1} {0 0 1 0 0}
+ {1 1 1 1 1} {0 0 1 0 0} {0 0 1 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 1 1 1} {0 0 0 0 1} {0 0 0 0 1} {0 0 0 0 1}
+ {0 0 0 0 1} {0 0 0 0 1} {0 0 1 1 1} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 1 0 0} {0 1 0 1 0} {1 0 0 0 1} {0 0 0 0 0}
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ {0 0 0 0 0} {0 0 0 0 0} {1 1 1 1 1} {0 0 0 0 0} {0 0 0 0 0}
+ }
+
+
+ {
+ {0 0 0 0 0} {0 1 0 0 0} {0 0 1 0 0} {0 0 0 1 0} {0 0 0 0 0}
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 1 1 1 0} {0 0 0 0 1}
+ {0 1 1 1 1} {1 0 0 0 1} {0 1 1 1 1} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {1 0 0 0 0} {1 0 0 0 0} {1 0 1 1 0} {1 1 0 0 1}
+ {1 0 0 0 1} {1 0 0 0 1} {1 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 1 1 1 0} {1 0 0 0 0}
+ {1 0 0 0 0} {1 0 0 0 1} {0 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 1} {0 0 0 0 1} {0 1 1 0 1} {1 0 0 1 1}
+ {1 0 0 0 1} {1 0 0 0 1} {0 1 1 1 1} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 1 1 1 0} {1 0 0 0 1}
+ {1 1 1 1 1} {1 0 0 0 0} {0 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 1 1 0} {0 1 0 0 1} {0 1 0 0 0} {1 1 1 0 0}
+ {0 1 0 0 0} {0 1 0 0 0} {0 1 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 1 1 1 1} {1 0 0 0 1} {1 0 0 0 1}
+ {0 1 1 1 1} {0 0 0 0 1} {0 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0}
+ }
+ {
+ {0 0 0 0 0} {1 0 0 0 0} {1 0 0 0 0} {1 0 1 1 0} {1 1 0 0 1}
+ {1 0 0 0 1} {1 0 0 0 1} {1 0 0 0 1} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 1 0 0} {0 0 0 0 0} {0 1 1 0 0} {0 0 1 0 0}
+ {0 0 1 0 0} {0 0 1 0 0} {0 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 1 0} {0 0 0 0 0} {0 0 1 1 0} {0 0 0 1 0}
+ {0 0 0 1 0} {1 0 0 1 0} {0 1 1 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {1 0 0 0 0} {1 0 0 0 0} {1 0 0 1 0} {1 0 1 0 0}
+ {1 1 0 0 0} {1 0 1 0 0} {1 0 0 1 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 1 1 0 0} {0 0 1 0 0} {0 0 1 0 0} {0 0 1 0 0}
+ {0 0 1 0 0} {0 0 1 0 0} {0 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {1 1 0 1 0} {1 0 1 0 1}
+ {1 0 1 0 1} {1 0 0 0 1} {1 0 0 0 1} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {1 0 1 1 0} {1 1 0 0 1}
+ {1 0 0 0 1} {1 0 0 0 1} {1 0 0 0 1} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 1 1 1 0} {1 0 0 0 1}
+ {1 0 0 0 1} {1 0 0 0 1} {0 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0}
+ }
+
+
+ {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {1 1 1 1 0} {1 0 0 0 1}
+ {1 1 1 1 0} {1 0 0 0 0} {1 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 1 1 0 1} {1 0 0 1 1}
+ {0 1 1 1 1} {0 0 0 0 1} {0 0 0 0 1} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {1 0 1 1 0} {1 1 0 0 1}
+ {1 0 0 0 0} {1 0 0 0 0} {1 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 1 1 1 0} {1 0 0 0 0}
+ {0 1 1 1 0} {0 0 0 0 1} {1 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 1 0 0 0} {0 1 0 0 0} {1 1 1 0 0} {0 1 0 0 0}
+ {0 1 0 0 0} {0 1 0 0 1} {0 0 1 1 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {1 0 0 0 1} {1 0 0 0 1}
+ {1 0 0 0 1} {1 0 0 1 1} {0 1 1 0 1} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {1 0 0 0 1} {1 0 0 0 1}
+ {1 0 0 0 1} {0 1 0 1 0} {0 0 1 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {1 0 0 0 1} {1 0 1 0 1}
+ {1 0 1 0 1} {1 0 1 0 1} {0 1 0 1 0} {0 0 0 0 0} {0 0 0 0 0}
+ }
+ {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {1 0 0 0 1} {0 1 0 1 0}
+ {0 0 1 0 0} {0 1 0 1 0} {1 0 0 0 1} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {1 0 0 0 1} {1 0 0 0 1}
+ {0 1 1 1 1} {0 0 0 0 1} {0 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {1 1 1 1 1} {0 0 0 1 0}
+ {0 0 1 0 0} {0 1 0 0 0} {1 1 1 1 1} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 1 0} {0 0 1 0 0} {0 0 1 0 0} {0 1 0 0 0}
+ {0 0 1 0 0} {0 0 1 0 0} {0 0 0 1 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 1 0 0} {0 0 1 0 0} {0 0 1 0 0} {0 0 1 0 0}
+ {0 0 1 0 0} {0 0 1 0 0} {0 0 1 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 1 0 0 0} {0 0 1 0 0} {0 0 1 0 0} {0 0 0 1 0}
+ {0 0 1 0 0} {0 0 1 0 0} {0 1 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ {0 1 1 0 1} {1 0 0 1 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 1 0 0} {0 1 0 1 0} {1 0 0 0 1} {1 0 0 0 1}
+ {1 0 0 0 1} {1 1 1 1 1} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ }
+
+
+ {
+ {0 0 0 0 0} {1 1 1 1 1} {1 0 0 0 1} {1 0 0 0 0} {1 1 1 1 0}
+ {1 0 0 0 1} {1 0 0 0 1} {1 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 1 1 1 1} {0 0 1 0 1} {0 0 1 0 1} {0 1 0 0 1} {1 0 0 0 1}
+ {1 1 1 1 1} {1 0 0 0 1} {1 0 0 0 1} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {1 0 1 0 1} {1 0 1 0 1} {1 0 1 0 1} {0 1 1 1 0}
+ {1 0 1 0 1} {1 0 1 0 1} {1 0 1 0 1} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {1 1 1 1 0} {0 0 0 0 1} {0 0 0 0 1} {0 0 1 1 0}
+ {0 0 0 0 1} {0 0 0 0 1} {1 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {1 0 0 0 1} {1 0 0 0 1} {1 0 0 1 1} {1 0 1 0 1}
+ {1 1 0 0 1} {1 0 0 0 1} {1 0 0 0 1} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 1 0 1 0} {0 0 1 0 0} {1 0 0 0 1} {1 0 0 0 1} {1 0 0 1 1}
+ {1 0 1 0 1} {1 1 0 0 1} {1 0 0 0 1} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 1 1 1 1} {0 0 1 0 1} {0 0 1 0 1} {0 0 1 0 1}
+ {0 0 1 0 1} {1 0 1 0 1} {0 1 0 0 1} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {1 1 1 1 1} {1 0 0 0 1} {1 0 0 0 1} {1 0 0 0 1}
+ {1 0 0 0 1} {1 0 0 0 1} {1 0 0 0 1} {0 0 0 0 0} {0 0 0 0 0}
+ }
+ {
+ {0 0 0 0 0} {1 0 0 0 1} {1 0 0 0 1} {1 0 0 0 1} {0 1 0 1 0}
+ {0 0 1 0 0} {0 1 0 0 0} {1 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {1 0 0 0 1} {1 0 0 0 1} {1 0 0 0 1} {1 0 0 0 1}
+ {1 0 0 0 1} {1 1 1 1 1} {0 0 0 0 1} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {1 0 0 0 1} {1 0 0 0 1} {1 0 0 0 1} {0 1 1 1 1}
+ {0 0 0 0 1} {0 0 0 0 1} {0 0 0 0 1} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {1 0 1 0 1} {1 0 1 0 1} {1 0 1 0 1}
+ {1 0 1 0 1} {1 0 1 0 1} {1 1 1 1 1} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {1 0 1 0 1} {1 0 1 0 1} {1 0 1 0 1} {1 0 1 0 1}
+ {1 0 1 0 1} {1 1 1 1 1} {0 0 0 0 1} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {1 1 0 0 0} {0 1 0 0 0} {0 1 0 0 0} {0 1 1 1 0}
+ {0 1 0 0 1} {0 1 0 0 1} {0 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {1 0 0 0 1} {1 0 0 0 1} {1 0 0 0 1} {1 1 0 0 1}
+ {1 0 1 0 1} {1 0 1 0 1} {1 1 0 0 1} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 1 1 1 0} {1 0 0 0 1} {0 0 1 0 1} {0 1 0 1 1}
+ {0 0 0 0 1} {1 0 0 0 1} {0 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0}
+ }
+
+
+ {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 1 0 0 1} {1 0 1 0 1}
+ {1 0 0 1 0} {1 0 0 1 0} {0 1 1 0 1} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 1 0 0} {0 0 1 1 0} {0 0 1 0 1} {0 0 1 0 1}
+ {0 0 1 0 0} {1 1 1 0 0} {1 1 1 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {1 1 1 1 1} {1 0 0 0 1} {1 0 0 0 0} {1 0 0 0 0}
+ {1 0 0 0 0} {1 0 0 0 0} {1 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {1 1 1 1 1} {0 1 0 1 0}
+ {0 1 0 1 0} {0 1 0 1 0} {1 0 0 1 1} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {1 1 1 1 1} {1 0 0 0 0} {0 1 0 0 0} {0 0 1 0 0}
+ {0 1 0 0 0} {1 0 0 0 0} {1 1 1 1 1} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 1 1 1 1} {1 0 0 1 0}
+ {1 0 0 1 0} {1 0 0 1 0} {0 1 1 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 1 1 0} {0 0 1 0 1} {0 0 1 1 1} {0 0 1 0 1} {0 0 1 0 1}
+ {1 1 1 0 1} {1 1 0 1 1} {0 0 0 1 1} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 1} {0 1 1 1 0} {1 0 1 0 0}
+ {0 0 1 0 0} {0 0 1 0 0} {0 0 0 1 0} {0 0 0 0 0} {0 0 0 0 0}
+ }
+ {
+ {0 0 0 0 0} {0 0 1 0 0} {0 1 1 1 0} {0 1 1 1 0} {0 1 1 1 0}
+ {1 1 1 1 1} {0 0 1 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 1 1 1 0} {1 0 0 0 1} {1 0 0 0 1} {1 1 1 1 1}
+ {1 0 0 0 1} {1 0 0 0 1} {0 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 1 1 1 0} {1 0 0 0 1} {1 0 0 0 1}
+ {1 0 0 0 1} {0 1 0 1 0} {1 1 0 1 1} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 1 1 0} {0 1 0 0 1} {0 0 1 0 0} {0 1 0 1 0}
+ {1 0 0 0 1} {1 0 0 0 1} {0 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 1 0 1 1} {1 0 1 0 1}
+ {1 1 0 1 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 1 0 1 0} {1 1 1 1 1} {1 1 1 1 1}
+ {1 1 1 1 1} {0 1 1 1 0} {0 0 1 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 1 1 1 0} {1 0 0 0 0}
+ {0 1 1 0 0} {1 0 0 0 1} {0 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 1 1 1 0} {1 0 0 0 1} {1 0 0 0 1} {1 0 0 0 1}
+ {1 0 0 0 1} {1 0 0 0 1} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ }
+
+
+ {
+ {0 0 0 0 0} {1 1 0 1 1} {1 1 0 1 1} {1 1 0 1 1} {1 1 0 1 1}
+ {1 1 0 1 1} {1 1 0 1 1} {1 1 0 1 1} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 1 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 1 0 0}
+ {0 0 1 0 0} {0 0 1 0 0} {0 0 1 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 1 0 0} {0 1 1 1 0} {1 0 1 0 0} {1 0 1 0 0}
+ {1 0 1 0 1} {0 1 1 1 0} {0 0 1 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 1 1 0} {0 1 0 0 0} {0 1 0 0 0} {1 1 1 0 0}
+ {0 1 0 0 0} {0 1 0 0 1} {1 0 1 1 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {1 0 0 0 1} {0 1 1 1 0} {0 1 0 1 0}
+ {0 1 1 1 0} {1 0 0 0 1} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {1 0 0 0 1} {0 1 0 1 0} {1 1 1 1 1} {0 0 1 0 0}
+ {1 1 1 1 1} {0 0 1 0 0} {0 0 1 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 1 0 0} {0 0 1 0 0} {0 0 1 0 0} {0 0 0 0 0}
+ {0 0 1 0 0} {0 0 1 0 0} {0 0 1 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 1 1 0} {0 1 0 0 1} {0 0 1 0 0} {0 1 0 1 0}
+ {0 0 1 0 0} {1 0 0 1 0} {0 1 1 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ }
+ {
+ {0 0 0 0 0} {0 0 0 1 0} {0 0 1 0 1} {0 0 1 0 0} {1 1 1 1 1}
+ {0 0 1 0 0} {1 0 1 0 0} {0 1 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {1 1 1 1 1} {1 0 0 0 1} {1 0 1 0 1} {1 0 1 1 1}
+ {1 0 1 0 1} {1 0 0 0 1} {1 1 1 1 1} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 1 1 1 0} {0 0 0 0 1} {0 1 1 1 1} {1 0 0 0 1}
+ {0 1 1 1 1} {0 0 0 0 0} {1 1 1 1 1} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 1 0 1} {0 1 0 1 0} {1 0 1 0 0} {0 1 0 1 0}
+ {0 0 1 0 1} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {1 0 0 1 0} {1 0 1 0 1} {1 0 1 0 1} {1 1 1 0 1}
+ {1 0 1 0 1} {1 0 1 0 1} {1 0 0 1 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 1 1 1 1} {1 0 0 0 1} {1 0 0 0 1} {0 1 1 1 1}
+ {0 0 1 0 1} {0 1 0 0 1} {1 0 0 0 1} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {1 1 1 1 1} {1 0 0 0 1} {1 0 1 0 1} {1 0 0 0 1}
+ {1 0 0 1 1} {1 0 1 0 1} {1 1 1 1 1} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 1 0 0} {0 1 0 0 0} {0 1 1 0 0} {0 0 0 0 0}
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ }
+
+
+ {
+ {0 1 1 0 0} {1 0 0 1 0} {1 0 0 1 0} {1 0 0 1 0} {0 1 1 0 0}
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 1 0 0} {0 0 1 0 0} {1 1 1 1 1} {0 0 1 0 0}
+ {0 0 1 0 0} {0 0 0 0 0} {1 1 1 1 1} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 1 1 0 0} {1 0 0 1 0} {0 0 1 0 0} {0 1 0 0 0} {1 1 1 1 0}
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {1 1 1 0 0} {0 0 0 1 0} {0 1 1 0 0} {0 0 0 1 0} {1 1 1 0 0}
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {1 1 1 0 0} {1 0 0 1 0} {1 1 1 0 0} {1 0 0 0 0} {1 0 0 1 0}
+ {1 0 1 1 1} {1 0 0 1 0} {0 0 0 1 1} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {1 0 0 0 1} {1 0 0 0 1} {1 0 0 0 1} {1 0 0 1 1}
+ {1 1 1 0 1} {1 0 0 0 0} {1 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 1 1 1 1} {1 0 0 1 1} {1 0 0 1 1} {0 1 1 1 1}
+ {0 0 0 1 1} {0 0 0 1 1} {0 0 0 1 1} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 1 1 0 0}
+ {0 1 1 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ }
+ {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 1 0 1 0} {1 0 0 0 1}
+ {1 0 1 0 1} {1 0 1 0 1} {0 1 0 1 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 1 0 0 0} {1 1 0 0 0} {0 1 0 0 0} {0 1 0 0 0} {1 1 1 0 0}
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 1 1 1 0} {1 0 0 0 1} {1 0 0 0 1} {1 0 0 0 1}
+ {0 1 1 1 0} {0 0 0 0 0} {1 1 1 1 1} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {1 0 1 0 0} {0 1 0 1 0} {0 0 1 0 1}
+ {0 1 0 1 0} {1 0 1 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {1 0 0 0 1} {1 0 0 1 0} {1 0 1 0 0} {0 1 0 1 0} {1 0 1 1 0}
+ {0 1 0 1 0} {0 1 1 1 1} {0 0 0 1 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {1 0 0 0 1} {1 0 0 1 0} {1 0 1 0 0} {0 1 0 1 0} {1 0 1 0 1}
+ {0 0 0 0 1} {0 0 0 1 0} {0 0 1 1 1} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {1 1 0 0 0} {0 1 0 0 0} {1 1 0 0 0} {0 1 0 0 1} {1 1 0 1 1}
+ {0 0 1 0 1} {0 0 1 1 1} {0 0 0 0 1} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 1 0 0} {0 0 0 0 0} {0 0 1 0 0} {0 1 0 0 0}
+ {1 0 0 0 0} {1 0 0 0 1} {0 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0}
+ }
+
+
+ {
+ {0 1 0 0 0} {0 0 1 0 0} {0 0 1 0 0} {0 1 0 1 0} {1 0 0 0 1}
+ {1 1 1 1 1} {1 0 0 0 1} {1 0 0 0 1} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 1 0} {0 0 1 0 0} {0 0 1 0 0} {0 1 0 1 0} {1 0 0 0 1}
+ {1 1 1 1 1} {1 0 0 0 1} {1 0 0 0 1} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 1 0 0} {0 1 0 1 0} {0 0 0 0 0} {0 1 1 1 0} {1 0 0 0 1}
+ {1 1 1 1 1} {1 0 0 0 1} {1 0 0 0 1} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 1 1 0 1} {1 0 0 1 0} {0 0 0 0 0} {0 1 1 1 0} {1 0 0 0 1}
+ {1 1 1 1 1} {1 0 0 0 1} {1 0 0 0 1} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 1 0 1 0} {0 0 0 0 0} {0 0 1 0 0} {0 1 0 1 0} {1 0 0 0 1}
+ {1 1 1 1 1} {1 0 0 0 1} {1 0 0 0 1} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 1 0 0} {0 1 0 1 0} {0 0 1 0 0} {0 1 1 1 0} {1 0 0 0 1}
+ {1 1 1 1 1} {1 0 0 0 1} {1 0 0 0 1} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 1 1 1} {0 1 1 0 0} {1 0 1 0 0} {1 0 1 1 1}
+ {1 1 1 0 0} {1 0 1 0 0} {1 0 1 1 1} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 1 1 1 0} {1 0 0 0 1} {1 0 0 0 0} {1 0 0 0 0} {1 0 0 0 1}
+ {0 1 1 1 0} {0 0 0 1 0} {0 0 1 1 0} {0 0 0 0 0} {0 0 0 0 0}
+ }
+ {
+ {0 1 0 0 0} {0 0 1 0 0} {0 0 0 0 0} {1 1 1 1 1} {1 0 0 0 0}
+ {1 1 1 1 0} {1 0 0 0 0} {1 1 1 1 1} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 1 0} {0 0 1 0 0} {0 0 0 0 0} {1 1 1 1 1} {1 0 0 0 0}
+ {1 1 1 1 0} {1 0 0 0 0} {1 1 1 1 1} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 1 0 0} {0 1 0 1 0} {0 0 0 0 0} {1 1 1 1 1} {1 0 0 0 0}
+ {1 1 1 1 0} {1 0 0 0 0} {1 1 1 1 1} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 1 0 1 0} {0 0 0 0 0} {1 1 1 1 1} {1 0 0 0 0}
+ {1 1 1 1 0} {1 0 0 0 0} {1 1 1 1 1} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 1 0 0 0} {0 0 1 0 0} {0 0 0 0 0} {0 1 1 1 0} {0 0 1 0 0}
+ {0 0 1 0 0} {0 0 1 0 0} {0 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 1 0} {0 0 1 0 0} {0 0 0 0 0} {0 1 1 1 0} {0 0 1 0 0}
+ {0 0 1 0 0} {0 0 1 0 0} {0 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 1 0 0} {0 1 0 1 0} {0 0 0 0 0} {0 1 1 1 0} {0 0 1 0 0}
+ {0 0 1 0 0} {0 0 1 0 0} {0 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 1 0 1 0} {0 0 0 0 0} {0 1 1 1 0} {0 0 1 0 0}
+ {0 0 1 0 0} {0 0 1 0 0} {0 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0}
+ }
+
+
+ {
+ {0 0 0 0 0} {0 1 1 1 0} {0 1 0 0 1} {0 1 0 0 1} {1 1 1 0 1}
+ {0 1 0 0 1} {0 1 0 0 1} {0 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 1 1 0 1} {1 0 0 1 0} {0 0 0 0 0} {1 0 0 0 1} {1 1 0 0 1}
+ {1 0 1 0 1} {1 0 0 1 1} {1 0 0 0 1} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 1 0 0 0} {0 0 1 0 0} {0 1 1 1 0} {1 0 0 0 1} {1 0 0 0 1}
+ {1 0 0 0 1} {1 0 0 0 1} {0 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 1 0} {0 0 1 0 0} {0 1 1 1 0} {1 0 0 0 1} {1 0 0 0 1}
+ {1 0 0 0 1} {1 0 0 0 1} {0 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 1 0 0} {0 1 0 1 0} {0 0 0 0 0} {0 1 1 1 0} {1 0 0 0 1}
+ {1 0 0 0 1} {1 0 0 0 1} {0 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 1 1 0 1} {1 0 0 1 0} {0 0 0 0 0} {0 1 1 1 0} {1 0 0 0 1}
+ {1 0 0 0 1} {1 0 0 0 1} {0 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 1 0 1 0} {0 0 0 0 0} {0 1 1 1 0} {1 0 0 0 1} {1 0 0 0 1}
+ {1 0 0 0 1} {1 0 0 0 1} {0 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {1 0 0 0 1} {0 1 0 1 0} {0 0 1 0 0}
+ {0 1 0 1 0} {1 0 0 0 1} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ }
+ {
+ {0 1 1 1 0} {0 0 1 0 0} {0 1 1 1 0} {1 0 1 0 1} {0 1 1 1 0}
+ {0 0 1 0 0} {0 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 1 0 0 0} {0 0 1 0 0} {1 0 0 0 1} {1 0 0 0 1} {1 0 0 0 1}
+ {1 0 0 0 1} {1 0 0 0 1} {0 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 1 0} {0 0 1 0 0} {1 0 0 0 1} {1 0 0 0 1} {1 0 0 0 1}
+ {1 0 0 0 1} {1 0 0 0 1} {0 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 1 0 0} {0 1 0 1 0} {0 0 0 0 0} {1 0 0 0 1} {1 0 0 0 1}
+ {1 0 0 0 1} {1 0 0 0 1} {0 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 1 0 1 0} {0 0 0 0 0} {1 0 0 0 1} {1 0 0 0 1} {1 0 0 0 1}
+ {1 0 0 0 1} {1 0 0 0 1} {0 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 1 0} {0 0 1 0 0} {1 0 0 0 1} {0 1 0 1 0} {0 0 1 0 0}
+ {0 0 1 0 0} {0 0 1 0 0} {0 0 1 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {1 1 0 0 0} {0 1 0 0 0} {0 1 1 1 0} {0 1 0 0 1} {0 1 0 0 1}
+ {0 1 1 1 0} {0 1 0 0 0} {1 1 1 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 1 1 0} {0 1 0 0 1} {0 1 0 0 1} {0 1 1 1 0}
+ {0 1 0 0 1} {0 1 0 0 1} {1 0 1 1 0} {0 0 0 0 0} {0 0 0 0 0}
+ }
+
+
+ {
+ {0 1 0 0 0} {0 0 1 0 0} {0 0 0 0 0} {0 1 1 1 0} {0 0 0 0 1}
+ {0 1 1 1 1} {1 0 0 0 1} {0 1 1 1 1} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 1 0} {0 0 1 0 0} {0 0 0 0 0} {0 1 1 1 0} {0 0 0 0 1}
+ {0 1 1 1 1} {1 0 0 0 1} {0 1 1 1 1} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 1 1 0 1} {1 0 0 1 0} {0 0 0 0 0} {0 1 1 1 0} {0 0 0 0 1}
+ {0 1 1 1 1} {1 0 0 0 1} {0 1 1 1 1} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 1 0 0} {0 1 0 1 0} {0 0 0 0 0} {0 1 1 1 0} {0 0 0 0 1}
+ {0 1 1 1 1} {1 0 0 0 1} {0 1 1 1 1} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 1 0 1 0} {0 0 0 0 0} {0 1 1 1 0} {0 0 0 0 1}
+ {0 1 1 1 1} {1 0 0 0 1} {0 1 1 1 1} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 1 0 0} {0 1 0 1 0} {0 0 1 0 0} {0 1 1 1 0} {0 0 0 0 1}
+ {0 1 1 1 1} {1 0 0 0 1} {0 1 1 1 1} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {1 1 0 1 0} {0 0 1 0 1} {0 1 1 1 1}
+ {1 0 1 0 0} {1 0 1 0 1} {0 1 0 1 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 1 1 1 0} {1 0 0 0 0} {1 0 0 0 1}
+ {0 1 1 1 0} {0 0 1 0 0} {0 1 1 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ }
+ {
+ {0 1 0 0 0} {0 0 1 0 0} {0 0 0 0 0} {0 1 1 1 0} {1 0 0 0 1}
+ {1 1 1 1 1} {1 0 0 0 0} {0 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 1 0} {0 0 1 0 0} {0 0 0 0 0} {0 1 1 1 0} {1 0 0 0 1}
+ {1 1 1 1 1} {1 0 0 0 0} {0 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 1 0 0} {0 1 0 1 0} {0 0 0 0 0} {0 1 1 1 0} {1 0 0 0 1}
+ {1 1 1 1 1} {1 0 0 0 0} {0 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 1 0 1 0} {0 0 0 0 0} {0 1 1 1 0} {1 0 0 0 1}
+ {1 1 1 1 1} {1 0 0 0 0} {0 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 1 0 0 0} {0 0 1 0 0} {0 0 0 0 0} {0 0 1 0 0} {0 1 1 0 0}
+ {0 0 1 0 0} {0 0 1 0 0} {0 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 1 0} {0 0 1 0 0} {0 0 0 0 0} {0 0 1 0 0} {0 1 1 0 0}
+ {0 0 1 0 0} {0 0 1 0 0} {0 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 1 0 0} {0 1 0 1 0} {0 0 0 0 0} {0 0 1 0 0} {0 1 1 0 0}
+ {0 0 1 0 0} {0 0 1 0 0} {0 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 1 0 1 0} {0 0 0 0 0} {0 0 1 0 0} {0 1 1 0 0}
+ {0 0 1 0 0} {0 0 1 0 0} {0 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0}
+ }
+
+
+ {
+ {0 0 0 0 0} {1 0 1 0 0} {0 1 0 0 0} {1 0 1 0 0} {0 0 0 1 0}
+ {0 1 1 1 1} {1 0 0 0 1} {0 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 1 1 0 1} {1 0 0 1 0} {0 0 0 0 0} {1 0 1 1 0} {1 1 0 0 1}
+ {1 0 0 0 1} {1 0 0 0 1} {1 0 0 0 1} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 1 0 0 0} {0 0 1 0 0} {0 0 0 0 0} {0 1 1 1 0} {1 0 0 0 1}
+ {1 0 0 0 1} {1 0 0 0 1} {0 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 1 0} {0 0 1 0 0} {0 0 0 0 0} {0 1 1 1 0} {1 0 0 0 1}
+ {1 0 0 0 1} {1 0 0 0 1} {0 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 1 0 0} {0 1 0 1 0} {0 0 0 0 0} {0 1 1 1 0}
+ {1 0 0 0 1} {1 0 0 0 1} {0 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 1 1 0 1} {1 0 0 1 0} {0 0 0 0 0} {0 1 1 1 0}
+ {1 0 0 0 1} {1 0 0 0 1} {0 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 1 0 1 0} {0 0 0 0 0} {0 1 1 1 0} {1 0 0 0 1}
+ {1 0 0 0 1} {1 0 0 0 1} {0 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 0 0} {0 0 1 0 0} {0 0 0 0 0} {1 1 1 1 1}
+ {0 0 0 0 0} {0 0 1 0 0} {0 0 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ }
+ {
+ {0 0 0 0 0} {0 0 0 1 0} {0 0 1 0 0} {0 1 1 1 0} {1 0 1 0 1}
+ {0 1 1 1 0} {0 0 1 0 0} {0 1 0 0 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 1 0 0 0} {0 0 1 0 0} {0 0 0 0 0} {1 0 0 0 1} {1 0 0 0 1}
+ {1 0 0 0 1} {1 0 0 1 1} {0 1 1 0 1} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 1 0} {0 0 1 0 0} {0 0 0 0 0} {1 0 0 0 1} {1 0 0 0 1}
+ {1 0 0 0 1} {1 0 0 1 1} {0 1 1 0 1} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 1 0 0} {0 1 0 1 0} {0 0 0 0 0} {1 0 0 0 1} {1 0 0 0 1}
+ {1 0 0 0 1} {1 0 0 1 1} {0 1 1 0 1} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 1 0 1 0} {0 0 0 0 0} {1 0 0 0 1} {1 0 0 0 1}
+ {1 0 0 0 1} {1 0 0 1 1} {0 1 1 0 1} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 0 0 1 0} {0 0 1 0 0} {1 0 0 0 1} {1 0 0 0 1}
+ {0 1 1 1 1} {0 0 0 0 1} {0 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 1 1 0 0} {0 0 1 0 0} {0 0 1 1 0} {0 0 1 0 1}
+ {0 0 1 1 0} {0 0 1 0 0} {0 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0}
+ } {
+ {0 0 0 0 0} {0 1 0 1 0} {0 0 0 0 0} {1 0 0 0 1} {1 0 0 0 1}
+ {0 1 1 1 1} {0 0 0 0 1} {0 1 1 1 0} {0 0 0 0 0} {0 0 0 0 0}
+ }
+}
+
+}
diff --git a/lib/pale/lcd_hd44780.tcl b/lib/pale/lcd_hd44780.tcl
new file mode 100644
index 0000000..58484b5
--- /dev/null
+++ b/lib/pale/lcd_hd44780.tcl
@@ -0,0 +1,2954 @@
+#!/usr/bin/tclsh
+# Part of MCU 8051 IDE ( http://mcu8051ide.sf.net )
+
+############################################################################
+# Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012 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. #
+############################################################################
+
+# --------------------------------------------------------------------------
+# Thanks to Trevor Spiteri <trevor.spiteri@um.edu.mt> there are 2 bugs less:
+#
+# - [PATCH 1/2] Fix 4-bit instructions for HD44780
+# - [PATCH 2/2] Start 2nd row at 0x40 not at 40 for HD44780
+# --------------------------------------------------------------------------
+
+# >>> File inclusion guard
+if { ! [ info exists _LCD_HD44780_TCL ] } {
+set _LCD_HD44780_TCL _
+# <<< File inclusion guard
+
+
+# --------------------------------------------------------------------------
+# DESCRIPTION
+#
+# Simulator of LCD character display controlled by HD44780.
+# --------------------------------------------------------------------------
+
+class LcdHD44780 {
+ inherit VirtualHWComponent
+
+ common COMPONENT_NAME "LCD display" ;# Name of this component
+ common CLASS_NAME "LcdHD44780" ;# Name of this class
+ common COMPONENT_ICON {hd44780} ;# Icon for this panel (16x16)
+
+ # Configuration menu
+ common CONFMENU {
+ {cascade "Set font" 0 "hd44780" .set_rom_code false 1 {
+ {radiobutton "ROM code A00" {}
+ ::LcdHD44780::font_id {0}
+ "font_changed" 3 ""}
+ {radiobutton "ROM code A02" {}
+ ::LcdHD44780::font_id {2}
+ "font_changed" 3 ""}
+ }}
+ {cascade "Set character size" 0 "hd44780" .set_char_size false 1 {
+ {radiobutton "5 × 8" {}
+ ::LcdHD44780::char_size {0}
+ "char_size_changed" 5 ""}
+ {radiobutton "5 × 10" {}
+ ::LcdHD44780::char_size {1}
+ "char_size_changed" 5 ""}
+ }}
+ {separator}
+ {checkbutton "Disable delays" {} {::LcdHD44780::_no_delays}
+ 1 0 0 {no_delays_changed}
+ ""}
+ {checkbutton "Ignore errors" {} {::LcdHD44780::_ignore_errors}
+ 1 0 0 {ignore_errors_changed}
+ ""}
+ {separator}
+ {command {Show HD44780 log} {} 5 "show_log" {bar5}
+ "Display the log of events which are currently happening in the simulated HD44780 chip"}
+ {command {Show CGROM} {} 5 "show_cgrom" {kcmmemory}
+ "Display content of HD44780 Character Generator ROM"}
+ {command {Show CGRAM} {} 5 "show_cgram" {kcmmemory}
+ "Display content of HD44780 Character Generator RAM"}
+ {command {Show DDRAM} {} 5 "show_ddram" {kcmmemory}
+ "Display content of HD44780 Display data RAM"}
+ {separator}
+ {command {Reset HD44780} {} 6 "reset_hd44780" {rebuild}
+ "Reinitialize the simulated HD44780, but do not affect DDRAM and CGRAM"}
+ {command {Clear DDRAM & CGRAM} {} 6 "clear_xxRAM" {editdelete}
+ "Clear the entire Display Data RAM and Character Generator RAM"}
+ {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" {} {::LcdHD44780::menu_keep_win_on_top}
+ 1 0 0 {keep_win_on_top_changed}
+ ""}
+ }
+
+ # Font: Font to be used in the panel -- bold
+ common common_font [font create \
+ -weight bold \
+ -size [expr {int(-10 * ($::font_size_factor > 1.2 ? 1.2 : $font_size_factor))}] \
+ -family {helvetica} \
+ ]
+ # Font: Font to be used in the panel -- bold, underline
+ common common_font_u [font create \
+ -weight bold \
+ -size [expr {int(-10 * ($::font_size_factor > 1.2 ? 1.2 : $font_size_factor))}] \
+ -family {helvetica} \
+ -underline 1 \
+ ]
+
+ common ON_COLOR {#000000} ;# RGB: Color for darken pixels
+ common OFF_COLOR {#DDDDDD} ;# RGB: Color for blank pixels
+ common USER_DEF_COLOR {#AAAAFF} ;# RGB: Color used in CGROM table for user defined characters
+
+ # List: Names of IO signals of the simulated LCD display controller
+ common SIGNAL_NAMES [list {RS} {R/W} {E} {D7} {D6} {D5} {D4} {D3} {D2} {D1} {D0}]
+
+ # List: Keys for the array (status_led) of status LEDs
+ common STATUS_LEDS_NAMES [list {B} {S} {D} {C} {N} {F} {ID} {DL} {OMN} {BF}]
+
+ # List: Labels displayed beside of the status LEDs
+ common STATUS_LEDS_TEXTS [list {B} {S} {D} {C} {N} {F} {I/D} {DL} {OMN} {BF}]
+
+ # List: Help texts for the labels of the status LEDs
+ common STATUS_LEDS_HELPTEXTS [list \
+ [mc "Cursor blinking"] \
+ [mc "Accompanies display shift"] \
+ [mc "Display ON/OFF"] \
+ [mc "Cursor ON/OFF"] \
+ [mc "2 lines display / 1 line display"] \
+ [mc "5 × 10 dots / 5 × 8 dots"] \
+ [mc "Increment AC / Decrement AC"] \
+ [mc "8-bit data transfer / 4-bit data transfer"] \
+ [mc "One More Nibble to transfer / data transfer complete"] \
+ [mc "Internally operating / Instructions acceptable"] \
+ ]
+ common MAX_LOG_LENGTH 100 ;# Int: Maximum number of row in the log window
+ common CURSOR_BLINK_FREQUENCY 3 ;# Int: Frequency (in Hz) of cursor blinking
+
+ # Values used by the configuration menu
+ common _no_delays 0 ;# Bool: Disable delays (simulated execution times)
+ common _ignore_errors 0 ;# Bool: Do not display special error message dialog in cases when an error occurs
+ common font_id 0 ;# Int: Font ID to be used for addressing the CGROM
+ common char_size 0 ;# Bool: Character height from the HW point of view, 0 == 5x8; 1==5x10
+
+ # Load CGROM
+ source "${::LIB_DIRNAME}/pale/hd44780_cgrom.tcl"
+
+ private variable conf_color {red} ;# Color: Selected color for LED's
+ private variable keep_win_on_top 0 ;# Bool: Toplevel window
+ 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 enaged ;# Array of Bool: enaged(port_num,bit_num) --> Is connected to this device ?
+
+ private variable ddram_hexeditor {} ;# Object: Hexadecimal editor for editing content of DDRAM
+ private variable cgram_hexeditor {} ;# Object: Hexadecimal editor for editing content of CGRAM
+
+ private variable ddram_window_params {0 {}} ;# List: Parameters of DDRAM hex. editor window, format: {IS_VISIBLE GEOMETRY}
+ private variable cgram_window_params {0 {}} ;# List: Parameters of CGRAM hex. editor window, format: {IS_VISIBLE GEOMETRY}
+
+ private variable display_width ;# Int: LCD dot matrix width in number of characters which it is able to display on one line
+ private variable display_height ;# Int: LCD dot matrix height in number of text rows, it can be 1 one 2
+ private variable win_minwidth ;# Int: Minimum allowed width of the main window of this LCD display simulator in number of pixels
+
+ private variable input_error 0 ;# Bool: I/O error has occurred
+ private variable input_error_desc {} ;# String: Description of the last I/O error
+
+ private variable es_but_left_right ;# Widget: Button "Show/Hide right part of the window"
+ private variable es_but_up_down ;# Widget: Button "Show/Hide bottom part of the window"
+ private variable visible_lr 1 ;# Bool: Is the right part of the window currently visible
+ private variable visible_ud 1 ;# Bool: Is the bottom part of the window currently visible
+
+ private variable log_win_text {} ;# Widget: Text widget fro the log of events
+ private variable ignore_errors 0 ;# Bool: Do not display special error message dialog in cases when an error occurs
+ private variable time_mark 0 ;# Int: Time mark pointing to this point of time according to the MCU simulator engine
+ private variable log_time_mark 0 ;# Int: Time mark used to separate events in the log which happened during the same evaluation iteration
+ private variable no_delays 0 ;# Bool: Disable delays (simulated execution times)
+ 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 disp_frame ;# Widget: The black frame around the LCD dot matrix
+ private variable signal_label ;# Array of canvas objects: Labels above ComboBoxes for GPIO signal selection
+ private variable lcd_pixel ;# Array of canvas objects: Segments of LCD dot matrix
+ private variable cgram_pixel ;# Array of canvas objects: Same as lcd_pixel but for CGRAM
+ private variable entrybox ;# Array of Widgets: Entryboxes showing HD44780 registers, key is name of the register diaplyed the CGRAM viewer
+ private variable status_led ;# Array of Widgets: LEDs showing status of HD44780 flags like: S, F, D, B, etc.
+ private variable inhibit_vcmd 1 ;# Bool: Disable validation function for entryboxes like "IR:" or "AC:"
+
+ private variable ddram ;# Array: Display Data RAM
+ private variable cgram ;# List: Character Generator RAM, format: { 8× (char) { 8× (row) { 5× (column) {0|1} } } }
+ private variable inst_reg ;# Int: Instruction register (IR) as specified in the HD44780 manual
+ private variable data_reg ;# Int: Data register (DR) as specified in the HD44780 manual
+ private variable time_of_completion 0 ;# Int: Time (according to the MCU simulator engine) when the current operation will be finished
+ private variable address_counter 0 ;# Int: Address Counter (AC) as specified in the HD44780 manual, interval [0;0x7F]
+ private variable address_counter_old 0 ;# Int: The same as AC, but this one might contain an outdated information (incr./decr. delay)
+ private variable cursor_address 0 ;# Int: Current address (not position) of the cursor, interval [0;0x7F]
+ private variable cursor_timer {} ;# Timer: Timer for LCD cursor blinking
+ private variable return_value -1 ;# Int: Result of an READ operation, this value is supposed to be send to the data bus
+ private variable display_shift 0 ;# Int: Current display shift, this value suppose to be added to the AC, interval [0;0x7F]
+ private variable signal_E_prev 0 ;# Bool: Signal Enable, value from the last VHW evaluation iteration before this one
+ private variable signal_E 0 ;# Bool: Signal Enable
+ private variable signal_RS 0 ;# Bool: Signal Register Select
+ private variable signal_RW 0 ;# Bool: Signal Read/Write
+ private variable signal_D 0 ;# int: Value taken from the data bus
+
+ ## Array of HD44780 configuration flags
+ # KEY MEANING WHEN 0 MEANING WHEN 1
+ # --- ------------ ------------
+ # ID 0 == Decrement 1 == Increment
+ # S 0 == (Normal) 1 == Accompanies display shift
+ # D 0 == Display OFF 1 == Display ON
+ # C 0 == Cursor OFF 1 == Cursor ON
+ # B 0 == Cursor blinking OFF 1 == Cursor blinking ON
+ # DL 0 == 4-bit data transfer 1 == 8-bit data transfer
+ # N 0 == 1 line display 1 == 2 lines display
+ # F 0 == 5 × 8 dots 1 == 5 × 10 dots
+ # BF 0 == Instructions acceptable 1 == Internally operating
+ # OMN 0 == Transfer completed 1 == One More Nibble to transfer
+ # B_pre backup for ``B'' used by method clear_cursor in order to ensure correct erase of the cursor
+ # F_pre backup for ``F'' used by method clear_cursor in order to ensure correct erase of the cursor
+ private variable diver_cfg
+
+ private variable rom_code 0 ;# Int: Font ID, this is used for addressing the CGROM
+ private variable lcd_char_size 0 ;# Bool: Character height from the HW point of view, 0 == 5x8; 1==5x10
+
+ # ------------------------------------------------------------------
+ # GUI RELATED FUNCTIONS AND SO ON
+ # ------------------------------------------------------------------
+
+ ## 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
+
+ # Reset the array of MCU GPIO lines engaged by this device, for internal purposes only
+ for {set port 0} {$port < 5} {incr port} {
+ for {set bit 0} {$bit < 8} {incr bit} {
+ set enaged($port,$bit) 0
+ }
+ }
+
+ # Initialize array of HD44780 configuration flags
+ array set diver_cfg {
+ ID 1 S 0 D 0
+ C 0 B 0 DL 1
+ N 0 F 0 BF 0
+ OMN 0 B_pre 0 F_pre 0
+ }
+
+ # Set other object variables
+ set project $_project
+
+ # Inform PALE
+ $project pale_register_input_device $this
+ $project pale_set_modified
+ }
+
+ ## Object destructor
+ destructor {
+ # Inform PALE
+ $project pale_unregister_input_device $this
+
+ # Dispose the timer for cursor blinking
+ catch {
+ after cancel $cursor_timer
+ }
+
+ # Destroy GUI
+ if {[winfo exists $win]} {
+ 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 $LcdHD44780::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
+ }
+ }
+
+ ## 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 3} {$i < 11} {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
+ }
+ }
+
+ ## Reconnect the specified key to another port pin
+ # @parm Int i - Connection wire number ({0..3} => Row; {4..7} => Column)
+ # @return void
+ public method reconnect {i} {
+ # Adjust connections
+ set connection_port($i) [$canvas_widget.cb_p$i get]
+ set connection_pin($i) [$canvas_widget.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
+
+ # Inform PALE system about the change in order
+ #+ to make immediate change in device states
+ if {$drawing_on} {
+ $project pale_reevaluate_IO
+ }
+
+ # Set flag modified
+ set_modified
+ }
+
+ ## Create GUI of this panel
+ # @return void
+ private method create_gui {} {
+ # Create panel window and canvas widget
+ set win [toplevel .lcd_display$count -class $component_name -bg ${::COMMON_BG_COLOR}]
+
+ # Create the canvas widget which contains everything else visible in the window
+ set canvas_widget [canvas $win.canvas \
+ -bg {#FFFFFF} \
+ -width 0 \
+ -height 0 \
+ -highlightthickness 0 \
+ ]
+
+ # Draw LEDs showing status of HD44780 flags like: S, F, D, B, etc.
+ draw_status_leds
+
+ # Draw the LCD dot matrix
+ draw_display
+
+ # Create ComboBoxes for specifying the connections between this device and the MCU simulator
+ draw_comboboxes 3 [expr {$display_height * 35 + 10}]
+
+ # Draw CGRAM viewer/editor
+ draw_cgram 400 [expr {$display_height * 35 + 38}]
+
+ # Create the entryboxes showing the most important HD44780 registers in the panel above the CGRAM viewer
+ draw_entyboxes 400 [expr {$display_height * 35 + 20}]
+
+ # Create "ON/OFF" button
+ create_on_off_button 5 [expr {$display_height * 35 + ($display_height == 1 ? 15 : 12)}]
+
+ # Create configuration menu button
+ create_configuration_menu_button 370 [expr {$display_height * 35 + 63}] ;#[expr {$display_height * 35 + 40}]
+
+ # Create "Show/Hide" buttons
+ create_enlarge_shirnk_buttons 370 [expr {$display_height * 35 + 13}]
+
+ # Pack canvas
+ pack $canvas_widget -fill both -expand 1
+
+ # Set window parameters
+ configure_win
+
+ # Disable or enable the "Show/Hide" buttons according to configuration of the window
+ disena_es_buttons
+ }
+
+ ## Show or Hide the bottom part of the window
+ # @return void
+ public method show_hide0 {} {
+ # Hide
+ if {$visible_ud} {
+ set new_height [expr {$display_height * 35 + 38}]
+ set image {_1downarrow}
+
+ $canvas_widget move connections_configuration 0 100
+ $canvas_widget move config_menu_button -330 -50
+ $canvas_widget move show_hide_but -300 0
+ $canvas_widget move right_bottom_panel 0 100
+
+ if {$visible_lr} {
+ show_hide1 1
+ set visible_lr 1
+ }
+
+ # Show
+ } else {
+ set new_height [expr {$display_height * 35 + 102}]
+ set image {_1uparrow}
+
+ $canvas_widget move connections_configuration 0 -100
+ $canvas_widget move config_menu_button 330 50
+ $canvas_widget move show_hide_but 300 0
+ $canvas_widget move right_bottom_panel 0 -100
+
+ if {$visible_lr} {
+ set visible_lr 0
+ show_hide1
+ }
+ }
+
+ # Set new window geometry
+ set geometry [split [wm geometry $win] {=x+}]
+ lset geometry 1 $new_height
+ wm minsize $win 0 0
+ wm geometry $win "=[lindex $geometry 0]x[lindex $geometry 1]+[lindex $geometry 2]+[lindex $geometry 3]"
+
+ # Set other values
+ set visible_ud [expr {!$visible_ud}]
+ $es_but_up_down configure -image ::ICONS::16::$image
+ update idletasks
+ }
+
+ ## Show or Hide the right part of the window
+ # @parm Bool allow_even_smaller=0 - Allow the window to be even smaller than $win_minwidth, see the code for details
+ # @return void
+ public method show_hide1 {{allow_even_smaller 0}} {
+ # Hide
+ if {$visible_lr} {
+ if {$allow_even_smaller} {
+ # Set window width just to contain the LCD dot matrix, CGRAM and so on can be omitted here
+ set new_width [expr {8 + 23 * $display_width}]
+ if {$display_height == 1} {
+ incr new_width 123
+ } else {
+ incr new_width 73
+ }
+ } else {
+ set new_width [expr {$win_minwidth - 226}]
+ }
+ set image {_1rightarrow}
+
+ # Show
+ } else {
+ set new_width $win_minwidth
+ set image {_1leftarrow}
+ }
+
+ # Set new window geometry
+ set geometry [split [wm geometry $win] {=x+}]
+ lset geometry 0 $new_width
+ wm minsize $win 0 0
+ wm geometry $win "=[lindex $geometry 0]x[lindex $geometry 1]+[lindex $geometry 2]+[lindex $geometry 3]"
+
+ # Set other values
+ set visible_lr [expr {!$visible_lr}]
+ $es_but_left_right configure -image ::ICONS::16::$image
+
+ update idletasks
+ }
+
+ ## Disable or enable the "Show/Hide" buttons according to configuration of the window
+ # @return void
+ private method disena_es_buttons {} {
+ if {$display_width > 18} {
+ $es_but_left_right configure -state disabled
+ }
+ }
+
+ ## Create "Show/Hide" buttons at the specified coordinates
+ # @parm Int x - X coordinate
+ # @parm Int y - Y coordinate
+ # @return void
+ private method create_enlarge_shirnk_buttons {x y} {
+ # Button "Show/Hide the bottom part"
+ set but [ttk::button $canvas_widget.show_hide0 \
+ -style FlatWhite.TButton \
+ -command [list $this show_hide0] \
+ -image ::ICONS::16::_1uparrow \
+ ]
+ setStatusTip -widget $but -text [mc "Show or hide the bottom part"]
+ DynamicHelp::add $but -text [mc "Show or hide the bottom part"]
+ $canvas_widget create window $x $y -window $but -anchor nw -tags show_hide_but
+ bindtags $but [list $but TButton all .]
+ set es_but_up_down $but
+
+ # Button "Show/Hide the right part"
+ set but [ttk::button $canvas_widget.show_hide1 \
+ -style FlatWhite.TButton \
+ -command [list $this show_hide1] \
+ -image ::ICONS::16::_1leftarrow \
+ ]
+ setStatusTip -widget $but -text [mc "Show or hide the right part"]
+ DynamicHelp::add $but -text [mc "Show or hide the right part"]
+ $canvas_widget create window $x [expr {$y + 25}] -window $but -anchor nw
+ bindtags $but [list $but TButton all .]
+ set es_but_left_right $but
+ }
+
+ ## Create "ON/OFF" button at the specified coordinates
+ # @parm Int x - X coordinate
+ # @parm Int y - Y coordinate
+ # @return void
+ private method create_on_off_button {x y} {
+ # Create "ON/OFF" button
+ set start_stop_button [ttk::button $canvas_widget.start_stop_button \
+ -command [list $this on_off_button_press] \
+ -style Flat.TButton \
+ -width 3 \
+ ]
+ DynamicHelp::add $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"
+ $canvas_widget create window $x $y -window $start_stop_button -anchor nw
+ bindtags $start_stop_button [list $start_stop_button TButton all .]
+ }
+
+ ## Create menu button for the configuration menu at the specified coordinates
+ # @parm Int x - X coordinate
+ # @parm Int y - Y coordinate
+ # @return void
+ private method create_configuration_menu_button {x y} {
+ # Create configuration menu button
+ set conf_button [ttk::button $canvas_widget.conf_but \
+ -image ::ICONS::16::configure \
+ -style FlatWhite.TButton \
+ -command [list $this config_menu] \
+ ]
+ setStatusTip -widget $conf_button -text [mc "Configure"]
+ $canvas_widget create window $x $y -window $conf_button -anchor nw -tags config_menu_button
+ bindtags $conf_button [list $conf_button TButton all .]
+ }
+
+ ## Set main window parameters
+ # @return void
+ private method configure_win {} {
+ # Decide minum allowable window width
+ set win_minwidth [expr {8 + 23 * $display_width}]
+ if {$display_height == 1} {
+ incr win_minwidth 123
+ } {
+ incr win_minwidth 73
+ }
+ if {$win_minwidth < 625} {
+ set win_minwidth 625
+ }
+
+ # Set window parameters
+ wm minsize $win $win_minwidth [expr {$display_height * 35 + 102}]
+ wm iconphoto $win ::ICONS::16::$component_icon
+ wm title $win "$display_height × $display_width [mc $component_name] - [$project cget -projectName] - MCU 8051 IDE"
+ wm resizable $win 0 0
+ wm protocol $win WM_DELETE_WINDOW [list $this close_window]
+ bindtags $win [list $win Toplevel all .]
+ }
+
+ ## Determinate which port pin is connected to the specified HD44780 wire
+ # @parm Int i - HD44780 signal, see SIGNAL_NAMES for the numbers of the signals
+ # @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
+ }
+
+ ## Create ComboBoxes for specifying the connections between this device and the MCU simulator
+ # @parm Int x_offset - X coordinate where this suppose to be drawn
+ # @parm Int y_offset - Y coordinate where this suppose to be drawn
+ # @return void
+ private method draw_comboboxes {x_offset y_offset} {
+ set cb_l_y [expr {$y_offset + 13}]
+ set cb_p_y [expr {$y_offset + 33}]
+ set cb_b_y [expr {$y_offset + 53}]
+ set note_y [expr {$y_offset + 75}]
+
+ # Print labels and the user note entrybox
+ set x [expr {$x_offset + 30}]
+ $canvas_widget create text $x $cb_p_y \
+ -tags connections_configuration \
+ -text [mc "PORT"] \
+ -font $common_font \
+ -anchor e
+ $canvas_widget create text $x $cb_b_y \
+ -tags connections_configuration \
+ -text [mc "BIT"] \
+ -font $common_font \
+ -anchor e
+ $canvas_widget create text $x $note_y \
+ -tags connections_configuration \
+ -text [mc "NOTE"] \
+ -font $common_font \
+ -anchor e
+ incr x 5
+ $canvas_widget create window $x $note_y \
+ -tags connections_configuration \
+ -window [ttk::entry $canvas_widget.usr_note \
+ -validate key \
+ -validatecommand "$this set_modified" \
+ ] \
+ -width 325 -anchor w
+ bindtags $canvas_widget.usr_note \
+ [list $canvas_widget.usr_note TEntry $win all .]
+
+ # Create LES's and ComboBoxes
+ for {set i 0} {$i < 11} {incr i} {
+ # Label with name of the HD44780 pin
+ set signal_label($i) [$canvas_widget create text \
+ [expr {$x + 12}] $cb_l_y \
+ -tags connections_configuration \
+ -text [lindex $SIGNAL_NAMES $i] \
+ -font $common_font \
+ -anchor center \
+ -fill {#000000} \
+ ]
+
+ # MCU port selection ComboBoxe
+ $canvas_widget create window $x $cb_p_y \
+ -anchor w \
+ -tags connections_configuration \
+ -window [ttk::combobox $canvas_widget.cb_p$i \
+ -width 1 \
+ -font $common_font \
+ -state readonly \
+ ]
+ bind $canvas_widget.cb_p$i <<ComboboxSelected>> "$this reconnect $i"
+
+ # MCU port bit selection ComboBoxe
+ $canvas_widget create window $x $cb_b_y \
+ -anchor w \
+ -tags connections_configuration \
+ -window [ttk::combobox $canvas_widget.cb_b$i \
+ -width 1 \
+ -font $common_font \
+ -values {- 0 1 2 3 4 5 6 7} \
+ -state readonly \
+ ]
+ bind $canvas_widget.cb_b$i <<ComboboxSelected>> "$this reconnect $i"
+
+ # Finalize ...
+ bindtags $canvas_widget.cb_p$i \
+ [list $canvas_widget.cb_p$i TCombobox all .]
+ bindtags $canvas_widget.cb_b$i \
+ [list $canvas_widget.cb_b$i TCombobox all .]
+
+ incr x 30
+ }
+ }
+
+ ## Validator function for entryboxes with the most important HD44780 registers in the panel above the CGRAM viewer
+ # @parm String type - Entryboxes purpose; watched HD44780 register
+ # @parm String content - String to validate
+ # @return Bool - 1 == Passed; 0 == Incorrect input
+ public method vcmd {type content} {
+ if {$inhibit_vcmd} {
+ set inhibit_vcmd 1
+ return 1
+ }
+
+ # Allow empty strings
+ if {![string length $content]} {
+ set inhibit_vcmd 0
+ return 1
+ }
+
+ # Allow only hexadecimal digits up to length of two
+ if {![string is xdigit -strict $content] || [string length $content] > 2} {
+ set inhibit_vcmd 0
+ return 0
+ }
+
+ # Update the actual HD44780 register
+ set dec_value [expr "0x$content"]
+ switch -- $type {
+ {IR} { ;# Instruction Register
+ set inst_reg $dec_value
+ }
+ {DR} { ;# Data register
+ set data_reg $dec_value
+ }
+ {AC} { ;# Address counter
+ if {$dec_value > 0x7f} {
+ return 0
+ }
+ set address_counter $dec_value
+ set address_counter_old $dec_value
+ refresh_display
+ }
+ {SHIFT} { ;# Display Shift
+ if {$dec_value > 0x7f} {
+ return 0
+ }
+ set display_shift $dec_value
+ refresh_display
+ }
+ }
+
+ # Successfully done
+ set inhibit_vcmd 0
+ return 1
+ }
+
+ ## Update content of all entryboxes with the most important HD44780 registers in the panel above the CGRAM viewer
+ # @return void
+ private method update_entry_boxes {} {
+ set inhibit_vcmd 1
+
+ # Instruction Register
+ $entrybox(IR) delete 0 end
+ $entrybox(IR) insert 0 [format {%02X} $inst_reg]
+
+ # Data register
+ $entrybox(DR) delete 0 end
+ $entrybox(DR) insert 0 [format {%02X} $data_reg]
+
+ # Address counter
+ $entrybox(AC) delete 0 end
+ $entrybox(AC) insert 0 [format {%02X} $address_counter]
+
+ # Display Shift
+ $entrybox(SHIFT) delete 0 end
+ $entrybox(SHIFT) insert 0 [format {%02X} $display_shift]
+
+ set inhibit_vcmd 0
+ }
+
+ ## Create the entryboxes showing the most important HD44780 registers in the panel above the CGRAM viewer
+ # @parm Int x_offset - X coordinate where this suppose to be drawn
+ # @parm Int y_offset - Y coordinate where this suppose to be drawn
+ # @return void
+ private method draw_entyboxes {x_offset y_offset} {
+ set x $x_offset
+ set y $y_offset
+
+ incr x 15
+
+ # Instruction Register
+ $canvas_widget create text \
+ $x $y \
+ -text {IR:} \
+ -font $common_font \
+ -anchor e \
+ -tags right_bottom_panel
+ incr x 5
+ set entrybox(IR) [ttk::entry $canvas_widget.ir_ent \
+ -width 2 \
+ -font $common_font \
+ -validate key \
+ -validatecommand [list $this vcmd {IR} {%P}] \
+ ]
+ $canvas_widget create window $x $y \
+ -window $entrybox(IR) \
+ -anchor w \
+ -tags right_bottom_panel
+ incr x 50
+
+ # Data register
+ $canvas_widget create text \
+ $x $y \
+ -text {DR:} \
+ -font $common_font \
+ -anchor e \
+ -tags right_bottom_panel
+ incr x 5
+
+ set entrybox(DR) [ttk::entry $canvas_widget.dr_ent \
+ -width 2 \
+ -font $common_font \
+ -validate key \
+ -validatecommand [list $this vcmd {DR} {%P}] \
+ ]
+ $canvas_widget create window $x $y \
+ -window $entrybox(DR) \
+ -anchor w \
+ -tags right_bottom_panel
+ incr x 50
+
+ # Address counter
+ $canvas_widget create text \
+ $x $y \
+ -text {AC:} \
+ -font $common_font \
+ -anchor e \
+ -tags right_bottom_panel
+ incr x 5
+ set entrybox(AC) [ttk::entry $canvas_widget.ac_ent \
+ -width 2 \
+ -font $common_font \
+ -validate key \
+ -validatecommand [list $this vcmd {AC} {%P}] \
+ ]
+ $canvas_widget create window $x $y \
+ -window $entrybox(AC) \
+ -anchor w \
+ -tags right_bottom_panel
+ incr x 55
+
+ # Display Shift
+ $canvas_widget create text \
+ $x $y \
+ -text [mc "Shift:"] \
+ -font $common_font \
+ -anchor e \
+ -tags right_bottom_panel
+ incr x 5
+ set entrybox(SHIFT) [ttk::entry $canvas_widget.sh_ent \
+ -width 2 \
+ -font $common_font \
+ -validate key \
+ -validatecommand [list $this vcmd {SHIFT} {%P}] \
+ ]
+ $canvas_widget create window $x $y \
+ -window $entrybox(SHIFT) \
+ -anchor w \
+ -tags right_bottom_panel
+
+ # Configure binding tags
+ foreach key [array names entrybox] {
+ bindtags $entrybox($key) [list $entrybox($key) TEntry $win all .]
+ }
+ }
+
+ ## Draw CGRAM viewer/editor
+ # @parm Int x_offset - X coordinate where this suppose to be drawn
+ # @parm Int y_offset - Y coordinate where this suppose to be drawn
+ # @return void
+ private method draw_cgram {x_offset y_offset} {
+ $canvas_widget create text \
+ $x_offset [expr {$y_offset + 3}] \
+ -text {CGRAM:} \
+ -font $common_font \
+ -anchor w \
+ -tags right_bottom_panel
+ incr y_offset 10
+
+ set square_size 4
+ set sep 1
+ set sep2 3
+
+ set x $x_offset
+ set y [expr {$y_offset + 0}]
+ for {set k 0} {$k < 8} {incr k} {
+
+ for {set i 0} {$i < 8} {incr i} {
+ for {set j 0} {$j < 5} {incr j} {
+ set cgram_pixel($k,$j,$i) [$canvas_widget \
+ create rectangle $x $y \
+ [expr {$x + $square_size}] \
+ [expr {$y + $square_size}] \
+ -fill $OFF_COLOR \
+ -outline {#000000} \
+ -width 0
+ ]
+
+ foreach event {Enter Leave Button-1} {
+ $canvas_widget bind $cgram_pixel($k,$j,$i) <$event> \
+ [list $this cgram_pixel_event $event $k $j $i]
+ }
+
+ incr x $square_size
+ incr x $sep
+ }
+ incr x [expr {-5 * ($square_size + $sep)}]
+ incr y [expr {$square_size + $sep}]
+ }
+ $canvas_widget create text [expr {$x + (5 * $square_size) / 2}] [expr {$y + 8}] -text $k -font $common_font
+
+ incr x [expr {$sep2 + 5 * ($square_size + $sep)}]
+ incr y [expr {-8 * ($square_size + $sep)}]
+ }
+ }
+
+ ## Handle events on CGRAM viewer character points
+ # @parm String event - Event type (e.g. "Leave")
+ # @parm Int char - Number of character where it occurred
+ # @parm Int col - Column in the character
+ # @parm Int row - Row in the character
+ # @return void
+ public method cgram_pixel_event {event char col row} {
+ switch -- $event {
+ {Enter} { ;# Highlight the cell
+ $canvas_widget itemconfigure $cgram_pixel($char,$col,$row) -width 1
+ }
+ {Leave} { ;# "Unhighlight" cell
+ $canvas_widget itemconfigure $cgram_pixel($char,$col,$row) -width 0
+ }
+ {Button-1} { ;# Invert the cell and also adjust the CGRAM accordingly
+ set value [lindex $cgram [list $char $row $col]]
+ set value [expr {!$value}]
+
+ lset cgram [list $char $row $col] $value
+
+ if {$value} {
+ $canvas_widget itemconfigure $cgram_pixel($char,$col,$row) -fill $ON_COLOR
+ } else {
+ $canvas_widget itemconfigure $cgram_pixel($char,$col,$row) -fill $OFF_COLOR
+ }
+
+ if {$cgram_hexeditor != {}} {
+ set val 0
+ for {set j 0} {$j < 5} {incr j} {
+ set val [expr {$val | (([lindex $cgram [list $char $row $j]] ? 1 : 0) << $j)}]
+ }
+
+ set addr [expr {($char << 3) | $row}]
+ $cgram_hexeditor setValue $addr $val
+ $cgram_hexeditor setHighlighted $addr 1
+ }
+ }
+ }
+ }
+
+ ## Synchronize all of the status LEDs with current state of the HD44780 core
+ # @return void
+ private method adjust_status_leds {} {
+ foreach key $STATUS_LEDS_NAMES {
+ if {$diver_cfg($key)} {
+ set image {dot}
+ } else {
+ set image {dot_gray}
+ }
+ $canvas_widget itemconfigure $status_led($key) -image ::ICONS::16::$image
+ }
+ }
+
+ ## Invert the specified HD44780 configuration flag (e.g. F, S, D, B)
+ # This method suppose to be called from the status LEDs panel
+ # @parm String config_param_name - HD44780 flag, like B (Blink) or C (Cursor)
+ # @return void
+ public method change_config {config_param_name} {
+ set diver_cfg($config_param_name) [expr {$diver_cfg($config_param_name) ? 0 : 1}]
+ refresh_display
+ adjust_status_leds
+ }
+
+ ## Draw LEDs showing status of HD44780 flags like: S, F, D, B, etc.
+ # @parm Int x_offset - X coordinate where this suppose to be drawn
+ # @parm Int y_offset - Y coordinate where this suppose to be drawn
+ # @return void
+ private method draw_status_leds {{x_offset 6} {y_offset 5}} {
+ # Determinate dimensions of matrix of status LEDs
+ if {$display_height == 1} {
+ set rows 3
+ set cols 4
+ } {
+ set rows 5
+ set cols 2
+ }
+ set items_total 10
+
+ set k 0
+ for {set i 0} {$i < $cols} {incr i} {
+ for {set j 0} {$j < $rows} {incr j} {
+ # Create the LED
+ set status_led([lindex $STATUS_LEDS_NAMES $k]) \
+ [$canvas_widget create image $x_offset $y_offset -anchor nw -image ::ICONS::16::dot_gray]
+
+ # Create label for the LED
+ set label [label $canvas_widget.status_lbl_${k} \
+ -text [lindex $STATUS_LEDS_TEXTS $k] \
+ -fg {#000000} \
+ -bg {#FFFFFF} \
+ -font $common_font \
+ ]
+
+ # Set event some handlers for the label widget in order to make it work
+ #+ also as a button which changes value of the watched flag
+ bind $label <Enter> {+
+ %W configure \
+ -fg {#0000FF} \
+ -cursor hand2 \
+ -font ${::LcdHD44780::common_font_u}
+ }
+ bind $label <Leave> {+
+ %W configure \
+ -fg {#000000} \
+ -cursor left_ptr \
+ -font ${::LcdHD44780::common_font}
+ }
+ bind $label <Button-1> [list $this change_config [lindex $STATUS_LEDS_NAMES $k]]
+ ::DynamicHelp::add $label -text [lindex $STATUS_LEDS_HELPTEXTS $k]
+
+ # Show the label widget
+ $canvas_widget create window [expr {$x_offset + 10}] [expr {$y_offset - 3}] \
+ -anchor nw \
+ -window $label
+
+ incr y_offset 14
+ incr k
+
+ if {$k >= $items_total} {
+ break
+ }
+ }
+
+ incr y_offset [expr {$rows * -14}]
+ incr x_offset 25
+ }
+ }
+
+ ## Draw the LCD dot matrix
+ # @parm Int x_offset - X coordinate where this suppose to be drawn
+ # @parm Int y_offset - Y coordinate where this suppose to be drawn
+ # @return void
+ private method draw_display {{x_offset 73} {y_offset 3}} {
+ set square_size 3
+ set sep 1
+ set sep2 3
+
+ if {$display_height == 1} {
+ incr x_offset 50
+ }
+
+ set disp_frame [$canvas_widget create rectangle $x_offset $y_offset \
+ [expr {$x_offset + $sep2 - $sep + $display_width * ($sep2 + 5 * ($square_size + $sep))}] \
+ [expr {$y_offset + $sep2 - $sep + $display_height * ($sep2 + 8 * ($square_size + $sep)) + 2 * $lcd_char_size * ($square_size + $sep)}] \
+ -outline {#000000} -width 1 \
+ ]
+
+ incr x_offset $sep2
+ incr y_offset $sep2
+
+ set x $x_offset
+ set y $y_offset
+ for {set row 0} {$row < $display_height} {incr row} {
+ for {set col 0} {$col < $display_width} {incr col} {
+ for {set i 0} {$i < (8 + 2 * $lcd_char_size)} {incr i} {
+ for {set j 0} {$j < 5} {incr j} {
+ set lcd_pixel($col,$row,$j,$i) [$canvas_widget \
+ create rectangle $x $y \
+ [expr {$x + $square_size}] \
+ [expr {$y + $square_size}] \
+ -fill $OFF_COLOR \
+ -width 0
+ ]
+ incr x $square_size
+ incr x $sep
+ }
+ incr x [expr {-5 * ($square_size + $sep)}]
+ incr y [expr {$square_size + $sep}]
+ }
+ incr x [expr {$sep2 + 5 * ($square_size + $sep)}]
+ incr y [expr {(-8 - 2 * $lcd_char_size) * ($square_size + $sep)}]
+ }
+ set x $x_offset
+ incr y [expr {$sep2 + (8 + 2 * $lcd_char_size) * ($square_size + $sep)}]
+ }
+ }
+
+ ## Create and show CGRAM hex. editor window
+ # @return void
+ public method show_cgram {} {
+ if {[winfo exists $win.cgram_window]} {
+ raise $win.cgram_window
+ return
+ }
+
+ # Create dialog window
+ set dialog [toplevel $win.cgram_window -class {CGRAM (HD44780)} -bg ${::COMMON_BG_COLOR}]
+
+ # Create bottom frame
+ set bottom_frame [frame $dialog.bottom_frame]
+ pack [ttk::button $bottom_frame.close_but \
+ -text [mc "Close"] \
+ -compound left \
+ -image ::ICONS::16::button_cancel \
+ -command [list $this close_cgram_window] \
+ ] -side left -anchor w -padx 2 -pady 2
+ set cursor_lbl [label $bottom_frame.cur_val \
+ -text { } -fg {#0000FF} \
+ -font [font create \
+ -family $::DEFAULT_FIXED_FONT \
+ -size [expr {int(-12 * $::font_size_factor)}] \
+ -weight bold \
+ ] \
+ ]
+ pack $cursor_lbl -side right -anchor e -padx 5
+ pack [label $bottom_frame.cur_lbl \
+ -text [mc "Cursor: "] \
+ ] -side right -anchor e
+
+ # Create middle frame (hexeditor)
+ set hexeditor_frame $dialog.hexeditor_frame
+ set hexeditor [HexEditor #auto \
+ $hexeditor_frame 8 8 2 hex 1 0 3 64 \
+ ]
+ set cgram_hexeditor $hexeditor
+ $hexeditor showHideScrollbar 1
+ $hexeditor bindCellValueChanged [list $this write_to_cgram_from_hex_editor]
+ $hexeditor bindCellEnter [list $this show_address_in_hex_label $cursor_lbl]
+ $hexeditor bindCellLeave [list $cursor_lbl configure -text { }]
+ for {set i 0} {$i < 64} {incr i} {
+ set val 0
+ set pattern [lindex $cgram [expr {$i / 8}] [expr {$i % 8}]]
+ for {set j 0} {$j < 5} {incr j} {
+ set val [expr {$val | (([lindex $pattern $j] ? 1 : 0) << $j)}]
+ }
+ $hexeditor setValue $i $val
+ }
+ $hexeditor focus_left_view
+
+ pack $hexeditor_frame -fill both -expand 1
+ pack $bottom_frame -side bottom -fill x
+
+ # Configure dialog window
+ wm iconphoto $dialog ::ICONS::16::kcmmemory
+ wm title $dialog "CGRAM (HD44780) - [$::X::actualProject cget -projectName] - MCU 8051 IDE"
+ wm resizable $dialog 0 1
+ wm minsize $dialog 0 120
+ wm protocol $dialog WM_DELETE_WINDOW [list $this close_cgram_window]
+ if {[lindex $cgram_window_params 1] != {}} {
+ wm geometry $dialog [lindex $cgram_window_params 1]
+ }
+ }
+
+ ## Write a value to CGRAM (suppose to be used as a callback for CGRAM hex. editor window)
+ # @parm Int address - Address to CGRAM
+ # @parm Int data - New value to store in CGRAM (character pattern fragment -- one row)
+ public method write_to_cgram_from_hex_editor {address pattern} {
+ set char [expr {($address & 0x38) >> 3}]
+ set row [expr {$address & 0x07}]
+ set pattern [expr {$pattern & 0x1F}]
+
+ write_to_cgram $char $row $pattern 1
+ }
+
+ ## Close CGRAM hex. editor window if it is opened
+ # @return void
+ public method close_cgram_window {} {
+ if {$cgram_hexeditor == {}} {
+ return
+ }
+ set cgram_window_params [list 0 [wm geometry $win.cgram_window]]
+ destroy $win.cgram_window
+ set cgram_hexeditor {}
+ }
+
+ ## Create and show DDRAM hex. editor window
+ # @return void
+ public method show_ddram {} {
+ if {[winfo exists $win.ddram_window]} {
+ raise $win.ddram_window
+ return
+ }
+
+ # Create dialog window
+ set dialog [toplevel $win.ddram_window -class {DDRAM (HD44780)} -bg ${::COMMON_BG_COLOR}]
+
+ # Create bottom frame
+ set bottom_frame [frame $dialog.bottom_frame]
+ pack [ttk::button $bottom_frame.close_but \
+ -text [mc "Close"] \
+ -compound left \
+ -image ::ICONS::16::button_cancel \
+ -command [list $this close_ddram_window] \
+ ] -side left -anchor w -padx 2 -pady 2
+ set cursor_lbl [label $bottom_frame.cur_val \
+ -text { } -fg {#0000FF} \
+ -font [font create \
+ -family $::DEFAULT_FIXED_FONT \
+ -size [expr {int(-12 * $::font_size_factor)}] \
+ -weight bold \
+ ] \
+ ]
+ pack $cursor_lbl -side right -anchor e -padx 5
+ pack [label $bottom_frame.cur_lbl \
+ -text [mc "Cursor: "] \
+ ] -side right -anchor e
+
+ # Create middle frame (hexeditor)
+ set hexeditor_frame $dialog.hexeditor_frame
+ set hexeditor [HexEditor #auto \
+ $hexeditor_frame 8 10 2 hex 1 0 3 0x80 \
+ ]
+ set ddram_hexeditor $hexeditor
+ $hexeditor showHideScrollbar 1
+ $hexeditor bindCellValueChanged [list $this write_to_ddram_from_hex_editor]
+ $hexeditor bindCellEnter [list $this show_address_in_hex_label $cursor_lbl]
+ $hexeditor bindCellLeave [list $cursor_lbl configure -text { }]
+ for {set i 0} {$i < 0x80} {incr i} {
+ $hexeditor setValue $i $ddram($i)
+ }
+ $hexeditor focus_left_view
+
+ pack $hexeditor_frame -fill both -expand 1
+ pack $bottom_frame -side bottom -fill x
+
+ # Configure dialog window
+ wm iconphoto $dialog ::ICONS::16::kcmmemory
+ wm title $dialog "DDRAM (HD44780) - [$::X::actualProject cget -projectName] - MCU 8051 IDE"
+ wm resizable $dialog 0 1
+ wm minsize $dialog 0 120
+ wm protocol $dialog WM_DELETE_WINDOW [list $this close_ddram_window]
+ if {[lindex $ddram_window_params 1] != {}} {
+ wm geometry $dialog [lindex $ddram_window_params 1]
+ }
+ }
+
+ ## Write a value to DDRAM (suppose to be used as a callback for DDRAM hex. editor window)
+ # @parm Int address - Address to DDRAM
+ # @parm Int data - New value to store in DDRAM
+ # @return void
+ public method write_to_ddram_from_hex_editor {address data} {
+ write_to_ddram $address $data 1
+ }
+
+ ## Update cursor address label in xxRAM hex. editor window
+ # @parm Widget cursor_lbl - Cursor address label to update
+ # @parm Int dec_address - Decimal address to be shown in hexadecimal format
+ # @parm ... - Any other arguments are discarded
+ # @return void
+ public method show_address_in_hex_label {cursor_lbl dec_address args} {
+ $cursor_lbl configure -text "0x[format {%02X} $dec_address]"
+ }
+
+ ## Close DDRAM hex. editor window if it is opened
+ # @return void
+ public method close_ddram_window {} {
+ if {$ddram_hexeditor == {}} {
+ return
+ }
+ set ddram_window_params [list 0 [wm geometry $win.ddram_window]]
+ destroy $win.ddram_window
+ set ddram_hexeditor {}
+ }
+
+ ## Show Character Generator ROM, concrete table depends on variable $rom_code
+ # @return void
+ public method show_cgrom {} {
+ # Create the dialog window
+ set dialog "${win}_cgrom_${rom_code}"
+ if {[winfo exists $dialog]} {
+ raise $dialog
+ return
+ }
+ toplevel $dialog -class {HD44780 CGROM}
+ set cgrom_canvas [canvas $dialog.canvas \
+ -bg {#FFFFFF} \
+ ]
+
+ # Some parameters of the matrix where characters will be displayed
+ set sep 1 ;# LCD segment separator
+ set sep2 1 ;# Character column separator
+ set sep3 13 ;# Character row separator
+ set square_size 3 ;# LCD segment square size
+
+ set header_x_offset 15 ;# Position of the header
+ set header_y_offset 15 ;# Position of the header
+ set matrix_x_offset 30 ;# Position of the matrix
+ set matrix_y_offset 30 ;# Position of the matrix
+
+ # Create horizontal header
+ set x [expr {$matrix_x_offset + int(2.5 * ($square_size + $sep))}]
+ set y $header_y_offset
+ for {set i 0} {$i < 16} {incr i} {
+ $cgrom_canvas create text $x $y -text "[format {%X} $i]_" -font $common_font -fill {#FF0000}
+ incr x [expr {$sep3 + 5 * ($square_size + $sep)}]
+ }
+
+ # Create vertical header
+ set x $header_x_offset
+ set y [expr {$matrix_y_offset + 4 * ($square_size + $sep)}]
+ for {set i 0} {$i < 16} {incr i} {
+ $cgrom_canvas create text $x $y -text "_[format {%X} $i]" -font $common_font -fill {#FF0000}
+ incr y [expr {$sep2 + 10 * ($square_size + $sep)}]
+ }
+
+ # Create the matrix of characters
+ set x $matrix_x_offset
+ set y $matrix_y_offset
+ set char_code 0
+ for {set row 0} {$row < 16} {incr row} {
+ for {set col 0} {$col < 16} {incr col} {
+
+ # Draw character
+ set char_code [expr {16 * $col + $row}]
+ for {set i 0} {$i < 10} {incr i} {
+ for {set j 0} {$j < 5} {incr j} {
+ if {$col < 14 && $i > 7} {
+ set color {#FFFFFF}
+ } elseif {$char_code < 16} {
+ set color $USER_DEF_COLOR
+ } elseif {[lindex $CGROM [list $rom_code [expr {$char_code - 16}] $i $j]]} {
+ set color $ON_COLOR
+ } else {
+ set color $OFF_COLOR
+ }
+
+ $cgrom_canvas create rectangle $x $y \
+ [expr {$x + $square_size}] \
+ [expr {$y + $square_size}] \
+ -fill $color \
+ -width 0
+
+ incr x $square_size
+ incr x $sep
+ }
+ incr x [expr {-5 * ($square_size + $sep)}]
+ incr y [expr {$square_size + $sep}]
+ }
+ incr x [expr {$sep3 + 5 * ($square_size + $sep)}]
+ incr y [expr {-10 * ($square_size + $sep)}]
+
+ }
+ set x $matrix_x_offset
+ incr y [expr {$sep2 + 10 * ($square_size + $sep)}]
+ }
+
+ pack $cgrom_canvas -fill both -expand 1
+
+ # Set window parameters
+ wm minsize $dialog 555 690
+ wm iconphoto $dialog ::ICONS::16::kcmmemory
+ wm title $dialog [mc "HD44780 Character Generator ROM (ROM Code: A0%d) - MCU 8051 IDE" ${rom_code}]
+ wm resizable $dialog 0 0
+ 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 {} {
+ set dialog $win.log_window
+ if {[wm state $dialog] == {normal}} {
+ raise $dialog
+ return
+ }
+ if {![winfo exists $dialog]} {
+ return
+ }
+ wm deiconify $dialog
+ raise $dialog
+ }
+
+ ## Create the log dialog window, but do not show it until method show_log is called
+ # @parm String geometry={} - Desired geometry of the window, {} means default geometry
+ # @return void
+ public method create_log {{geometry {}}} {
+ # 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
+ # Button "Clear log"
+ 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
+ } {
+ $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 "HD44780 log - MCU 8051 IDE"]
+ wm protocol $dialog WM_DELETE_WINDOW [list $this close_log_win]
+ bindtags $dialog [list $dialog Toplevel $win all .]
+
+ if {$geometry != {}} {
+ wm geometry $dialog $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 HD44780 log window
+ # @return void
+ public method close_log_win {} {
+ set dialog $win.log_window
+ if {![winfo exists $dialog]} {
+ return
+ }
+
+ wm withdraw $dialog
+ }
+
+ ## Informs the HD44780 simulator about change of _no_delays flag (used by configuration menu)
+ # @return void
+ public method no_delays_changed {} {
+ set no_delays ${::LcdHD44780::_no_delays}
+ }
+
+ ## Informs the HD44780 simulator about change of _ignore_errors flag (used by configuration menu)
+ # @return void
+ public method ignore_errors_changed {} {
+ set ignore_errors ${::LcdHD44780::_ignore_errors}
+ }
+
+ ## Informs the HD44780 simulator about change of character size (used by configuration menu)
+ # @return void
+ public method char_size_changed {} {
+ set lcd_char_size ${::LcdHD44780::char_size}
+ if {$display_height == 2 && $lcd_char_size == 1} {
+ set lcd_char_size 0
+ return
+ }
+ accept_new_character_size
+ }
+
+ ## Informs the HD44780 simulator about change of font (used by configuration menu)
+ # @return void
+ public method font_changed {} {
+ set rom_code ${::LcdHD44780::font_id}
+ refresh_display
+ }
+
+ ## Adapt the LCD dot matrix to a new character size value, that means create additional
+ #+ dots and get rid of some of the dots currently displayed
+ # @return void
+ private method accept_new_character_size {} {
+ if {$display_height == 2} {
+ return
+ }
+
+ $canvas_widget delete $disp_frame
+ foreach key [array names lcd_pixel] {
+ $canvas_widget delete $lcd_pixel($key)
+ }
+ draw_display
+ refresh_display
+ }
+
+ ## 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
+
+ # Show also a special erro message dialog if this is a case of an error and if it is allowed
+ if {$type == {E} && !$ignore_errors} {
+ if {[$project sim_run_in_progress]} {
+ $project sim_run
+ } elseif {[$project sim_anim_in_progress]} {
+ $project sim_animate
+ }
+ tk_messageBox \
+ -parent $win \
+ -title [mc "HD44780 ERROR"] \
+ -icon error \
+ -type ok \
+ -message $string
+ }
+ }
+
+ # ------------------------------------------------------------------
+ # HD44780 CORE FUNCTIONS
+ # ------------------------------------------------------------------
+
+ ## HD44780 instruction: Clear Display
+ # Clears entire display and sets DDRAM address 0 in address counter.
+ # @return void
+ private method inst_ClearDisplay {} {
+ write_to_log I [mc "Received instruction: %s" "Clear Display"]
+ if {[must_not_be_enaged]} {return}
+ engage_core 1700
+
+ set address_counter 0
+ for {set i 0} {$i < 0x80} {incr i} {
+ write_to_ddram $i 20
+ }
+
+ update_entry_boxes
+ }
+
+ ## HD44780 instruction: Return Home
+ # Sets DDRAM address 0 in address counter. Also returns display from
+ #+ being shifted to original position. DDRAM contents remain unchanged.
+ # @return void
+ private method inst_ReturnHome {} {
+ write_to_log I [mc "Received instruction: %s" "Return Home"]
+ if {[must_not_be_enaged]} {return}
+ engage_core 1700
+
+ set address_counter 0
+ set display_shift 0
+
+ update_entry_boxes
+ refresh_display
+ }
+
+ ## HD44780 instruction: Entry Mode Set
+ # Sets cursor move direction and specifies display shift. These
+ #+ operations are performed during data write and read.
+ # @return void
+ private method inst_EntryModeSet {} {
+ write_to_log I [mc "Received instruction: %s" "Entry Mode Set"]
+ if {[must_not_be_enaged]} {return}
+ engage_core 40
+
+ set diver_cfg(ID) [expr {($inst_reg & 0x02) ? 1 : 0}]
+ set diver_cfg(S) [expr {($inst_reg & 0x01) ? 1 : 0}]
+
+ write_to_log I "I/D = $diver_cfg(ID), S = $diver_cfg(S)"
+
+ update_entry_boxes
+ adjust_status_leds
+ refresh_display
+ }
+
+ ## HD44780 instruction: Display On Off Control
+ # Sets entire display (D) on/off, cursor on/off (C), and blinking of
+ #+ cursor position character (B).
+ # @return void
+ private method inst_DisplayOnOffControl {} {
+ write_to_log I [mc "Received instruction: %s" "Display On Off Control"]
+ if {[must_not_be_enaged]} {return}
+ engage_core 40
+
+ set diver_cfg(D) [expr {($inst_reg & 0x04) ? 1 : 0}]
+ set diver_cfg(C) [expr {($inst_reg & 0x02) ? 1 : 0}]
+ set diver_cfg(B) [expr {($inst_reg & 0x01) ? 1 : 0}]
+
+ write_to_log I "D = $diver_cfg(D), C = $diver_cfg(C), B = $diver_cfg(B)"
+
+ update_entry_boxes
+ adjust_status_leds
+ refresh_display
+ }
+
+ ## HD44780 instruction: Cursor Or Display Shift
+ # Sets entire display (D) on/off, cursor on/off (C), and blinking of
+ #+ cursor position character (B).
+ # @return void
+ private method inst_CursorOrDisplayShift {} {
+
+ write_to_log I [mc "Received instruction: %s" "Cursor Or Display Shift"]
+ if {[must_not_be_enaged]} {return}
+ engage_core 40
+
+ set sc [expr {($inst_reg & 0x08) ? 1 : 0}]
+ set rl [expr {($inst_reg & 0x04) ? 1 : 0}]
+
+ write_to_log I "S/C = $sc, R/L = $rl"
+
+ # Shift display
+ if {$sc} {
+ # Right
+ if {$rl} {
+ incr display_shift -1
+ # Left
+ } else {
+ incr display_shift
+ }
+ # Move cursor
+ } else {
+ set address_counter_old $address_counter
+ # Right
+ if {$rl} {
+ incr address_counter
+ # Left
+ } else {
+ incr address_counter -1
+ }
+ move_cursor $address_counter
+ }
+
+ update_entry_boxes
+ refresh_display
+ }
+
+ ## HD44780 instruction: Function Set
+ # Sets interface data length (DL), number of display lines (N), and
+ #+ character font (F).
+ # @return void
+ private method inst_FunctionSet {} {
+ write_to_log I [mc "Received instruction: %s" "Function Set"]
+ if {[must_not_be_enaged]} {return}
+ engage_core 40
+
+ set diver_cfg(DL) [expr {($inst_reg & 0x10) ? 1 : 0}]
+ set diver_cfg(N) [expr {($inst_reg & 0x08) ? 1 : 0}]
+ set diver_cfg(F) [expr {($inst_reg & 0x04) ? 1 : 0}]
+
+ write_to_log I "DL = $diver_cfg(DL), N = $diver_cfg(N), F =$diver_cfg(F)"
+
+ update_entry_boxes
+ adjust_status_leds
+ refresh_display
+ }
+
+ ## HD44780 instruction: Set CGRAM Address
+ # Sets CGRAM address. CGRAM data is sent and received after this setting.
+ # @return void
+ private method inst_SetCGRAMAddress {} {
+ write_to_log I [mc "Received instruction: %s" "Set CGRAM Address"]
+ if {[must_not_be_enaged]} {return}
+ engage_core 40
+
+ set address_counter [expr {0x3F & $inst_reg}]
+
+ write_to_log I "ACG = $address_counter"
+
+ update_entry_boxes
+ }
+
+ ## HD44780 instruction: Set DDRAM Address
+ # Sets DDRAM address. DDRAM data is sent and received after this setting.
+ # @return void
+ private method inst_SetDDRAMAddress {} {
+ write_to_log I [mc "Received instruction: %s" "Set DDRAM Address"]
+ if {[must_not_be_enaged]} {return}
+ engage_core 40
+
+ set address_counter [expr {0x7F & $inst_reg}]
+ move_cursor $address_counter
+
+ write_to_log I "ADD = $address_counter"
+
+ update_entry_boxes
+ }
+
+ ## HD44780 instruction: Read Busy Flag & Address
+ # Reads busy flag (BF) indicating internal operation is being performed
+ #+ and reads address counter contents.
+ # @return void
+ private method inst_ReadBusyFlagAndAddress {} {
+ write_to_log I [mc "Received instruction: %s" "Read Busy Flag & Address"]
+
+ ## Simulate address counter update delay (approx. 6 us)
+ if {$diver_cfg(BF)} {
+ set return_value [expr {(($diver_cfg(BF) ? 1 : 0) << 7) + ($address_counter_old & 0x7f)}]
+ return
+ } elseif {($time_of_completion + 6) > [lindex [$project get_run_statistics] 0]} {
+ set return_value [expr {(($diver_cfg(BF) ? 1 : 0) << 7) + ($address_counter_old & 0x7f)}]
+ return
+ }
+
+ set return_value [expr {(($diver_cfg(BF) ? 1 : 0) << 7) + ($address_counter & 0x7f)}]
+ }
+
+ ## HD44780 instruction: Write Data To CG Or DDRAM
+ # Writes data into DDRAM or CGRAM.
+ # @return void
+ private method inst_WriteDataToCGOrDDRAM {} {
+ write_to_log I [mc "Received instruction: %s" "Write Data To CG Or DDRAM"]
+ if {[must_not_be_enaged]} {return}
+ engage_core 40
+
+ # Write to the Display Data RAM (DDRAM)
+ if {0x80 & $inst_reg} {
+ write_to_ddram $address_counter $data_reg
+ # Write to the Character Generator RAM (CGRAM)
+ } elseif {0x40 & $inst_reg} {
+ write_to_cgram [expr {($address_counter & 0xf8) >> 3}] [expr {$address_counter & 0x07}] $data_reg
+ # Write to nowhere -- Error condition, abort
+ } else {
+ write_to_log E [mc "Neither \"Set DDRAM Address\" nor \"Set CGRAM Address\" instruction was issued prior to the write instruction"]
+ return
+ }
+
+ # Perform automatic Address Counter (AC) update and display shift as described in the HD44780 manual
+ set address_counter_old $address_counter
+ if {$diver_cfg(ID)} {
+ incr address_counter
+ if {$diver_cfg(S)} {
+ incr display_shift -1
+ }
+ } else {
+ incr address_counter -1
+ if {$diver_cfg(S)} {
+ incr display_shift
+ }
+ }
+ set address_counter [expr {$address_counter % 0x80}]
+ set display_shift [expr {$display_shift % 0x80}]
+
+ # Synchronize with the LCD cursor
+ if {0x80 & $inst_reg} {
+ move_cursor $address_counter
+ }
+
+ # Update entry boxes showing content of some HD44780 registers
+ update_entry_boxes
+ }
+
+ ## HD44780 instruction: Read Data From CG Or DDRAM
+ # Reads data from DDRAM or CGRAM.
+ # @return void
+ private method inst_ReadDataFromCGOrDDRAM {} {
+ write_to_log I [mc "Received instruction: %s" "Read Data From CG Or DDRAM"]
+ if {[must_not_be_enaged]} {return}
+ engage_core 40
+
+ # Read from the Display Data RAM (DDRAM)
+ if {0x80 & $inst_reg} {
+ set return_value $ddram($address_counter)
+
+ # Read from the Character Generator RAM (CGRAM)
+ } elseif {0x40 & $inst_reg} {
+ set return_value 0
+ for {set i 4} {$i >= 0} {incr i -1} {
+ set return_value [expr {$return_value | ([lindex $cgram \
+ [expr {($address_counter & 0x38) >> 3}] \
+ [expr {$address_counter & 0x07}] \
+ [expr {4 - $i}]] << $i
+ )}]
+ }
+
+ # Read from nowhere -- Error condition, abort
+ } else {
+ write_to_log E [mc "Neither \"Set DDRAM Address\" nor \"Set CGRAM Address\" instruction was issued prior to the read instruction"]
+ return
+ }
+
+ # Perform automatic Address Counter (AC) update and display shift as described in the HD44780 manual
+ set address_counter_old $address_counter
+ if {$diver_cfg(ID)} {
+ incr address_counter
+ if {$diver_cfg(S)} {
+ incr display_shift -1
+ }
+ } else {
+ incr address_counter -1
+ if {$diver_cfg(S)} {
+ incr display_shift
+ }
+ }
+ set address_counter [expr {$address_counter % 0x80}]
+ set display_shift [expr {$display_shift % 0x80}]
+
+ # Synchronize with the LCD cursor
+ if {0x80 & $inst_reg} {
+ move_cursor $address_counter
+ }
+
+ # Update entry boxes showing content of some HD44780 registers
+ update_entry_boxes
+ }
+
+ ## Raise an error message if the core is engaged by some operation
+ # @return Bool - 0 == Not egaged; 1 == Is engaged
+ private method must_not_be_enaged {} {
+ if {$diver_cfg(BF)} {
+ if {$no_delays} {
+ set diver_cfg(BF) 0
+ } else {
+ write_to_log W [mc "Controller is busy, unable to execute requested instruction."]
+ return 1
+ }
+ } else {
+ return 0
+ }
+ }
+
+ ## Simulate the execution time of an operation
+ # @parm int time_us - Time for how long the HD44780 will be engaged by the operation in micro-seconds
+ # @return void
+ private method engage_core {time_us} {
+ # Mention it in the log
+ write_to_log I [mc "Commencing execution, this action will take %d micro-seonds to comply." $time_us]
+
+ # Skip delay if the simulator has been configure this way
+ if {$no_delays} {
+ set time_us 0
+ write_to_log I [mc "Skipping delay"]
+ }
+
+ # Set time when the execution will be completed (time is taken from the MCU simulator engine)
+ set time_of_completion [lindex [$project get_run_statistics] 0]
+ incr time_of_completion [expr {$time_us * 1000}]
+
+ # Set the Busy Flag
+ if {$no_delays} {
+ set diver_cfg(BF) 0
+ } else {
+ set diver_cfg(BF) 1
+ }
+
+ # Synchronize with the status LEDs
+ adjust_status_leds
+ }
+
+ ## Reset the simulated HD44780 controller
+ # @return void
+ public method reset_hd44780 {} {
+ set inhibit_vcmd 1 ;# Disable validation function for entryboxes like "IR:" or "AC:"
+
+ # Fill the DDRAM with 0x20 (SPACE) characters
+ clear_ddram
+
+ # Reset some object variables containing LCD display configuration
+ set display_shift 0 ;# Current display shift, this value suppose to be added to the AC
+ set address_counter 0 ;# Address Counter (AC) as specified in the HD44780 manual
+ set inst_reg 0 ;# Instruction register (IR) as specified in the HD44780 manual
+ set data_reg 0 ;# Data register (DR) as specified in the HD44780 manual
+
+ # Array of HD44780 configuration flags
+ set diver_cfg(ID) 1 ;# 0 == Decrement ; 1 == Increment
+ set diver_cfg(S) 0 ;# 0 == (Normal) ; 1 == Accompanies display shift
+ set diver_cfg(D) 0 ;# 0 == Display OFF ; 1 == Display ON
+ set diver_cfg(C) 0 ;# 0 == Cursor OFF ; 1 == Cursor ON
+ set diver_cfg(B) 0 ;# 0 == Cursor blinking OFF ; 1 == Cursor blinking ON
+ set diver_cfg(DL) 1 ;# 0 == 4-bit data transfer ; 1 == 8-bit data transfer
+ set diver_cfg(N) 0 ;# 0 == 1 line display ; 1 == 2 lines display
+ set diver_cfg(F) 0 ;# 0 == 5 × 8 dots ; 1 == 5 × 10 dots
+ set diver_cfg(BF) 0 ;# 0 == Instructions acceptable ; 1 == Internally operating
+ set diver_cfg(OMN) 0 ;# 0 == Transfer completed ; 1 == One More Nibble to transfer
+
+ clear_display ;# Ensure that that the LCD dot matrix is clear
+ clear_cursor ;# Make the LCD cursor disappear
+ adjust_status_leds ;# Synchronize with the status LEDs (right from the LCD dot matrix)
+ update_entry_boxes ;# Update entryboxes like "IR:" or "AC:"
+
+ # Mention this in the log
+ write_to_log I [mc "Device reset"]
+
+ set inhibit_vcmd 0 ;# Enable validation function for entryboxes like "IR:" or "AC:"
+ }
+
+ ## Write octet into Display Data RAM (DDRAM)
+ # @parm Int address - Address in DDRAM [0;7f]
+ # @parm Int char_code - Octet to write
+ # @parm Bool do_not_affect_hexeditor=0 - Do not synchronize wit the DDRAM hex editor window
+ # @return void
+ public method write_to_ddram {address char_code {do_not_affect_hexeditor 0}} {
+ # Validate the given address
+ if {$address > 0x7f} {
+ write_to_log W [mc "DDRAM address is too high: %d" $address]
+ }
+
+ # Write to the actual DDRAM
+ set ddram($address) $char_code
+
+ # Synchronize the DDRAM hex editor window if it is allowed and possible
+ if {$ddram_hexeditor != {} && !$do_not_affect_hexeditor} {
+ $ddram_hexeditor setValue $address $char_code
+ $ddram_hexeditor setHighlighted $address 1
+ }
+
+ # Determinate target position
+ set position [address_to_position $address]
+
+ # ABORT! if the target position is out of visible range
+ if {![is_position_visible $position]} {
+
+ return
+ }
+
+ ## Convert position into row and column
+ # Two lines display
+ if {$diver_cfg(N) && $display_height == 2 && $position >= 0x40} {
+ set col [expr {$position - 0x40}]
+ set row 1
+ # One line display
+ } else {
+ set col $position
+ set row 0
+ }
+
+ ## Get character bitmap image
+ # Access to CGRAM (Character Generator RAM)
+ if {$char_code < 16} {
+ set char_pattern [lindex $cgram $char_code]
+ # Access to CGROM (Character Generator ROM)
+ } else {
+ incr char_code -16
+ set char_pattern [lindex $CGROM [list $rom_code $char_code]]
+ }
+
+ # Determinate actual character height
+ if {$display_height == 1 && $diver_cfg(F)} {
+ set max_char_row [expr {8 + 2 * $lcd_char_size}]
+ } else {
+ set max_char_row 8
+ }
+
+ ## Adjust the LCD dot matrix
+ # Iterate over rows
+ for {set y 0} {$y < $max_char_row} {incr y} {
+ # Iterate over columns
+ for {set x 0} {$x < 5} {incr x} {
+ if {$diver_cfg(D) && [lindex $char_pattern [list $y $x]]} {
+ set color $ON_COLOR
+ } else {
+ set color $OFF_COLOR
+ }
+ $canvas_widget itemconfigure $lcd_pixel($col,$row,$x,$y) -fill $color
+ }
+ }
+ }
+
+ ## Write one row of character patter into the Character Generator RAM (CGRAM)
+ # @parm Int char_code - Number of the user defined character [0;7]
+ # @parm Int row - Row in the patter [0;7] (0 - top; 7 - bottom)
+ # @parm List data - Pattern fragment in decimal representation (e.g. 0x15 means {1 0 1 0 1} or 0x03 means {0 0 1 1 1})
+ # @parm Bool do_not_affect_hexeditor=0 - Do not synchronize wit the CGRAM hex editor window
+ # @return void
+ private method write_to_cgram {char_code row data {do_not_affect_hexeditor 0}} {
+
+ # Validate input data
+ if {$char_code > 7} {
+ write_to_log W [mc "CGRAM address is too high: %d" $char_code]
+ }
+ if {$data > 31} {
+ write_to_log W [mc "Value is too high: 0x%X" $data]
+ set data [expr {$data & 0x1f}]
+ }
+ set char_code [expr {$char_code % 8}]
+
+ # Convert the given pattern fragment to this format:
+ #+ {B B B B B}, where B is 0 or 1, 0 == blank dot, 1 == black dot
+ set char_pattern [list]
+ for {set i 4} {$i >= 0} {incr i -1} {
+ lappend char_pattern [expr {($data & (1 << $i)) ? 1 : 0}]
+ }
+
+ # Write to the CGRAM
+ lset cgram [list $char_code $row] $char_pattern
+
+ # Synchronize the CGRAM viewer
+ for {set col 0} {$col < 5} {incr col} {
+ if {[lindex $char_pattern $col]} {
+ set color $ON_COLOR
+ } else {
+ set color $OFF_COLOR
+ }
+ $canvas_widget itemconfigure $cgram_pixel($char_code,$col,$row) -fill $color
+ }
+
+ # Synchronize the CGRAM hex editor window if it is allowed and possible
+ if {$cgram_hexeditor != {} && !$do_not_affect_hexeditor} {
+ set addr [expr {($char_code << 3) | $row}]
+ $cgram_hexeditor setValue $addr $data
+ $cgram_hexeditor setHighlighted $addr 1
+ }
+ }
+
+ ## Fill the entire Character Generator RAM (CGRAM) with zeros
+ # @return void
+ private method clear_cgram {} {
+ # Dispose the CGRAM memory
+ set cgram [list]
+
+ # Generate an empty character pattern
+ set char [list]
+ for {set i 0} {$i < 8} {incr i} {
+ lappend char [list 0 0 0 0 0]
+ }
+
+ # Refill the CGRAM memory
+ for {set i 0} {$i < 16} {incr i} {
+ lappend cgram $char
+ }
+
+ # Synchronize the CGRAM viewer
+ if {$canvas_widget != {}} {
+ for {set i 0} {$i < 8} {incr i} {
+ for {set y 0} {$y < 8} {incr y} {
+ for {set x 0} {$x < 5} {incr x} {
+ $canvas_widget itemconfigure $cgram_pixel($i,$x,$y) -fill $OFF_COLOR
+ }
+ }
+ }
+ }
+
+ # Synchronize the CGRAM hex editor window if possible
+ if {$cgram_hexeditor != {}} {
+ for {set i 0} {$i < 64} {incr i} {
+ $cgram_hexeditor setValue $i 0
+ }
+ }
+ }
+
+ ## Fill the entire Display Data RAM (DDRAM) with 0x20 characters (SPACE), but do not refresh the display
+ # @return void
+ private method clear_ddram {} {
+ # Fill the DDRAM
+ for {set i 0} {$i < 0x80} {incr i} {
+ set ddram($i) 32 ;# 0x20 (SPACE) character
+ }
+
+ # Synchronize the DDRAM hex editor window is possible
+ if {$ddram_hexeditor != {}} {
+ for {set i 0} {$i < 0x80} {incr i} {
+ $ddram_hexeditor setValue $i $ddram($i)
+ }
+ }
+ }
+
+ ## Clear the entire Display Data RAM and Character Generator RAM
+ # @return void
+ public method clear_xxRAM {} {
+ clear_ddram
+ clear_cgram
+ refresh_display
+ }
+
+ ## Determinate whether the specified position is visible or not
+ # @parm Int position - Position address [0,7f]
+ # @return Bool - 1 == Visible; 0 == Not visible
+ private method is_position_visible {position} {
+ if {$position < 0} {
+ return 0
+ }
+
+ if {$position >= 0x80} {
+ return 0
+ }
+
+ if {$position >= $display_width} {
+ if {$display_height == 1} {
+ return 0
+ } else {
+ if {!$diver_cfg(N)} {
+ return 0
+ } elseif {$position < 0x40 || $position >= ($display_width + 0x40)} {
+ return 0
+ }
+ }
+ }
+
+ return 1
+ }
+
+ ## Refresh display according to the DDRAM content and (new) HD44780 configuration
+ # @return void
+ private method refresh_display {} {
+ for {set i 0} {$i < 0x80} {incr i} {
+ write_to_ddram $i $ddram($i) 1
+ }
+ move_cursor $address_counter
+ }
+
+ ## Ensure that that the LCD dot matrix is clear
+ # @return void
+ private method clear_display {} {
+ for {set row 0} {$row < $display_height} {incr row} {
+ for {set col 0} {$col < $display_width} {incr col} {
+ for {set i 0} {$i < (8 + 2 * $lcd_char_size)} {incr i} {
+ for {set j 0} {$j < 5} {incr j} {
+ $canvas_widget itemconfigure $lcd_pixel($col,$row,$j,$i) -fill $OFF_COLOR
+ }
+ }
+ }
+ }
+ }
+
+
+ ## Make the LCD cursor disappear
+ # @return void
+ private method clear_cursor {} {
+ # Determinate target position
+ set position [address_to_position $cursor_address]
+
+ # ABORT! if the target position is out of visible range
+ if {![is_position_visible $position]} {
+ return
+ }
+
+ ## Convert position into row and column
+ # Two lines display
+ if {$diver_cfg(N) && $display_height == 2 && $position >= 0x40} {
+ set col [expr {$position - 0x40}]
+ set row 1
+ # One line display
+ } else {
+ set col $position
+ set row 0
+ }
+
+ # Blinking cursor
+ if {$diver_cfg(B_pre)} {
+ if {$cursor_timer != {}} {
+ after cancel $cursor_timer
+ set cursor_timer {}
+ }
+
+ # Overwrite the cursor with actual character at its position
+ write_to_ddram $cursor_address $ddram($cursor_address) 1
+
+ # Normal cursor
+ } else {
+ if {$diver_cfg(F_pre)} {
+ if {$lcd_char_size} {
+ set max_char_row 9
+ } {
+ set max_char_row -1
+ }
+ } else {
+ set max_char_row 7
+ }
+ if {$max_char_row != -1} {
+ for {set x 0} {$x < 5} {incr x} {
+ $canvas_widget itemconfigure $lcd_pixel($col,$row,$x,$max_char_row) -fill $OFF_COLOR
+ }
+ }
+ }
+ }
+
+ ## Draw LCD cursor according to current HD44780 settings and at position given by variable $cursor_address
+ # @return void
+ private method draw_cursor {} {
+ # Cursor is disabled -- abort
+ if {!$diver_cfg(C)} {
+ return
+ }
+
+ # Determinate target position
+ set position [address_to_position $cursor_address]
+
+ # Abort if the target position is out of visible range
+ if {![is_position_visible $position]} {
+ return
+ }
+
+ ## Convert position into row and column
+ # Two lines display
+ if {$diver_cfg(N) && $display_height == 2 && $position >= 0x40} {
+ set col [expr {$position - 0x40}]
+ set row 1
+ # One line display
+ } else {
+ set col $position
+ set row 0
+ }
+
+ # Cursor appearance is affected also by the font size
+ if {$diver_cfg(F)} {
+ if {$lcd_char_size} {
+ set max_char_row 10
+ } else {
+ set max_char_row -1
+ }
+ } {
+ set max_char_row 8
+ }
+
+ set diver_cfg(B_pre) $diver_cfg(B)
+ set diver_cfg(F_pre) $diver_cfg(F)
+
+ # Draw blinking cursor
+ if {$diver_cfg(B)} {
+ # Stop the LCD cursor blinking timer
+ if {$cursor_timer != {}} {
+ after cancel $cursor_timer
+ }
+ # Normalize number of rows of the cursor rectangle
+ if {$max_char_row == -1} {
+ set max_char_row 8
+ }
+ # Draw the black cursor rectangle
+ for {set y 0} {$y < $max_char_row} {incr y} {
+ for {set x 0} {$x < 5} {incr x} {
+ $canvas_widget itemconfigure $lcd_pixel($col,$row,$x,$y) -fill $ON_COLOR
+ }
+ }
+ # Start the LCD cursor blinking timer
+ set cursor_timer [after [expr {int(1000 / $CURSOR_BLINK_FREQUENCY)}] [list $this cursor_timer_callback 1]]
+
+ # Draw normal cursor (a sort of underscore)
+ } else {
+ if {$max_char_row != -1} {
+ incr max_char_row -1
+ for {set x 0} {$x < 5} {incr x} {
+ $canvas_widget itemconfigure $lcd_pixel($col,$row,$x,$max_char_row) -fill $ON_COLOR
+ }
+ }
+ }
+ }
+
+ ## Move the LCD cursor to a new location
+ # @parm Int new_address - Address in DDRAM
+ # @return void
+ #
+ # Note: This function could be also used to refresh the cursor
+ private method move_cursor {new_address} {
+ clear_cursor
+ set cursor_address $new_address
+ draw_cursor
+ }
+
+ ## Callback function fo the LCD cursor blinking timer
+ # @parm Bool clear - 1 == Clear the cursor rectangle; 0 == Draw the cursor rectangle
+ # @return void
+ public method cursor_timer_callback {clear} {
+ if {$clear} {
+ clear_cursor
+
+ # Reset the LCD cursor blinking timer
+ if {$diver_cfg(B) && $diver_cfg(C)} {
+ set cursor_timer [after [expr {int(1000 / $CURSOR_BLINK_FREQUENCY)}] [list $this cursor_timer_callback 0]]
+ }
+
+ } elseif {$diver_cfg(B) && $diver_cfg(C)} {
+ draw_cursor
+ }
+ }
+
+ ## Convert the specified DDRAM address into position in the LCD dot matrix
+ # @parm int ddram_address - Address to convert, must be be in interval [0;7f]!
+ # @return Int - The position [0;7f]
+ private method address_to_position {ddram_address} {
+ # Two lines display
+ if {$diver_cfg(N)} {
+ set position [expr {($ddram_address + $display_shift) % 0x40}]
+ if {$ddram_address >= 0x40} {
+ incr position 0x40
+ }
+
+ # One line display
+ } else {
+ set position [expr {($ddram_address + $display_shift) % 0x80}]
+ }
+
+ return $position
+ }
+
+ ## Start execution of the requested instruction
+ # @see new_state
+ # @parm List state - Port states ( 5 x {8 x bit} -- {bit0 bit1 bit2 ... bit7} )
+ # @return state - New port states modified by this device
+ # format is the same as parameter $state
+ private method commence_operations {_state} {
+ upvar $_state state
+
+ # Detect falling edge on signal E (Enable) & Completed data transfer (in case of 4-bit mode)
+ #+ --> Input instruction or data
+ if {$signal_E_prev && !$signal_E && !$diver_cfg(OMN)} {
+ # Manage Busy Flag
+ if {$diver_cfg(BF)} {
+ # Simulated execution times are disabled
+ if {$no_delays} {
+ # Clear the Busy Flag unconditionally
+ set diver_cfg(BF) 0
+ adjust_status_leds
+ write_to_log I [mc "Operation finished"]
+
+ # Simulated execution times are enabled
+ } else {
+ # Clear the Busy Flag if the execution time already passed
+ set current_time [$project get_run_statistics 0]
+ if {$current_time >= $time_of_completion} {
+ set diver_cfg(BF) 0
+ adjust_status_leds
+ write_to_log I [mc "Operation finished"]
+ }
+ }
+ }
+
+ # Write to log the last I/O error if there is one
+ if {$input_error} {
+ write_to_log E [mc "Input is corrupted: %s" $input_error_desc]
+ }
+
+ # Input an "regular" instruction (write to the IR)
+ if {!$signal_RS && !$signal_RW} {
+ set return_value -1
+
+ # Update the IR (Instruction Register)
+ set inst_reg $signal_D
+ update_entry_boxes
+
+ # Instruction: Set DDRAM Address (1 ADD ADD ADD | ADD ADD ADD ADD)
+ if {0x80 & $signal_D} {
+ inst_SetDDRAMAddress
+
+ # Instruction: Set CGRAM Address (0 1 ACG ACG | ACG ACG ACG ACG)
+ } elseif {0x40 & $signal_D} {
+ inst_SetCGRAMAddress
+
+ # Instruction: Function Set (0 0 1 DL | N F - -)
+ } elseif {0x20 & $signal_D} {
+ inst_FunctionSet
+
+ # Instruction: Cursor Or Display Shift (0 0 0 1 | S/C R/L - -)
+ } elseif {0x10 & $signal_D} {
+ inst_CursorOrDisplayShift
+
+ # Instruction: Display On Off Control (0 0 0 0 | 1 D C B)
+ } elseif {0x08 & $signal_D} {
+ inst_DisplayOnOffControl
+
+ # Instruction: Entry Mode Set (0 0 0 0 | 0 1 I/D S)
+ } elseif {0x04 & $signal_D} {
+ inst_EntryModeSet
+
+ # Instruction: Return Home (0 0 0 0 | 0 0 1 -)
+ } elseif {0x02 & $signal_D} {
+ inst_ReturnHome
+
+ # Instruction: Clear Display (0 0 0 0 | 0 0 0 1)
+ } elseif {0x01 & $signal_D} {
+ inst_ClearDisplay
+
+ # Code 0 -- Invalid instruction
+ } else {
+ write_to_log W [mc "Invalid instruction: %2Xh" $signal_D]
+ }
+
+ # Read Busy Flag And Address
+ } elseif {!$signal_RS && $signal_RW} {
+ set data_reg $signal_D
+ update_entry_boxes
+ inst_ReadBusyFlagAndAddress
+
+ # Write Data To CG Or DDRAM
+ } elseif {$signal_RS && !$signal_RW} {
+ set return_value -1
+
+ set data_reg $signal_D
+ update_entry_boxes
+ inst_WriteDataToCGOrDDRAM
+
+ # Read Data From CG Or DDRAM
+ } elseif {$signal_RS && $signal_RW} {
+ set data_reg $signal_D
+ update_entry_boxes
+ inst_ReadDataFromCGOrDDRAM
+ }
+ }
+
+ # Detect signal Enable & Read request & Ready state (not busy) & Data waiting to be send ($return_value)
+ #+ --> Output data
+ if {$signal_E && $signal_RW && !$diver_cfg(BF) && $return_value != -1} {
+
+ # 8-bit transfer mode
+ if {$diver_cfg(DL)} {
+ for {set i 3} {$i < 11} {incr i} {
+ set pp [which_port_pin $i]
+ if {[lindex $pp 0] != {-} && [lindex $pp 1] != {-}} {
+ lset state $pp [expr {($return_value & (1 << (10 - $i))) ? 1 : 0}]
+ }
+ }
+
+ # 4-bit transfer mode
+ } else {
+ if {$diver_cfg(OMN)} {
+ set bus_offset 10
+ } else {
+ set bus_offset 14
+ }
+ for {set i 7} {$i < 11} {incr i} {
+ set pp [which_port_pin $i]
+ if {[lindex $pp 0] != {-} && [lindex $pp 1] != {-}} {
+ lset state $pp [expr {($return_value & (1 << ($bus_offset - $i))) ? 1 : 0}]
+ }
+ }
+
+ # Invert flag "One More Nibble"
+ set diver_cfg(OMN) [expr {$diver_cfg(OMN) ? 0 : 1}]
+ adjust_status_leds
+ }
+ }
+ }
+
+
+ # ------------------------------------------------------------------
+ # 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]]
+
+ # Configure the ComboBoxes
+ for {set i 0} {$i < 11} {incr i} {
+ $canvas_widget.cb_p$i configure -values $available_ports
+
+ if {[lsearch -ascii -exact $available_ports $connection_port($i)] == -1} {
+ $canvas_widget.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 state - New port states modified by this device
+ # format is the same as parameter $state
+ #
+ # 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
+
+ # Start execution of the last requested instruction. It's done this way in order to cope with
+ #+ multiple new_state invocations during the Virtual HW evaluation loop
+ if {$time_mark != [$project get_run_statistics 2]} {
+ commence_operations state
+ set time_mark [$project get_run_statistics 2]
+ set signal_E_prev $signal_E
+ }
+
+ # Reset last I/O error
+ set input_error 0
+ set input_error_desc {}
+
+ # Iterate over all I/O lines
+ for {set i 0} {$i < 11} {incr i} {
+ # Determinate index in the list of port states
+ set pp [which_port_pin $i]
+
+ # Not connected
+ if {[lindex $pp 0] == {-} || [lindex $pp 1] == {-}} {
+ $canvas_widget itemconfigure $signal_label($i) -fill {#000000}
+ set signal_value {}
+ } else {
+ set signal_value [lindex $state $pp]
+ }
+
+ # Determinate the color for the PIN label
+ switch -- $signal_value {
+ {0} { ;# Logical 0
+ set label_color {#00FF00}
+ }
+ {1} { ;# Logical 1
+ set label_color {#FF0000}
+ }
+ {=} { ;# High forced to low
+ set label_color {#00FF00}
+ }
+ {?} { ;# No volatge
+ set label_color {#888888}
+ }
+ {} { ;# Not connected
+ set label_color {#000000}
+ }
+ default {
+ set label_color {#FF8800}
+ }
+ }
+
+ # Change color of the PIN label
+ $canvas_widget itemconfigure $signal_label($i) -fill $label_color
+
+ # Convert any possible I/O signal value to Boolean value
+ switch -- $signal_value {
+ {0} -
+ {1} {}
+ {=} {
+ set signal_value 0
+ }
+ default {
+ if {$diver_cfg(DL) || $i >= 7} {
+ set input_error 1
+ set input_error_desc [mc \
+ "Received an invalid input on signal %s" \
+ [lindex $SIGNAL_NAMES $i]
+ ]
+ set signal_value [expr {rand() > 0.5 ? 1 : 0}]
+ }
+ }
+ }
+
+ # Process the input
+ switch -- $i {
+ {0} {
+ # Signal Register Select
+ set signal_RS $signal_value
+ }
+ {1} {
+ # Signal Read/Write
+ set signal_RW $signal_value
+ }
+ {2} {
+ # Signal Enable
+ set signal_E $signal_value
+ }
+ {3} -
+ {4} -
+ {5} -
+ {6} -
+ {7} -
+ {8} -
+ {9} -
+ {10} { ;# 8-bit data bus
+
+ # Set received data to zero when the first bit is received
+ if {$i == 3 && !$diver_cfg(OMN)} {
+ set signal_D 0
+ }
+
+ # 8-bit transfer mode
+ if {$diver_cfg(DL) && !$signal_RW} {
+ set signal_D [expr {$signal_D | ($signal_value << (10 - $i))}]
+
+ # 4-bit transfer mode -- accept data on rising edge of signal E (Enable) from DB4..DB7
+ } elseif {!$signal_RW && $signal_E_prev && !$signal_E && $i < 7} {
+ if {$diver_cfg(OMN)} {
+ set signal_D [expr {$signal_D | ($signal_value << (6 - $i))}]
+ } else {
+ set signal_D [expr {$signal_D | ($signal_value << (10 - $i))}]
+ }
+
+ if {$i == 6} {
+ if {$diver_cfg(OMN)} {
+ set diver_cfg(OMN) 0
+ write_to_log I [mc "Receiving the Less Significant Nibble (%02Xh)" [expr {$signal_D & 0x0F}]]
+ } else {
+ set diver_cfg(OMN) 1
+ write_to_log I [mc "Receiving the More Significant Nibble (%02Xh)" [expr {$signal_D & 0xF0}]]
+ }
+ adjust_status_leds
+ }
+ }
+ }
+ }
+ }
+ }
+
+ ## 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 {} {
+ # Get DDRAM hex editor windows parameters is it's visible
+ if {$ddram_hexeditor != {}} {
+ set ddram_window_params [list 1 [wm geometry $win.ddram_window]]
+ }
+ # Get CGRAM hex editor windows parameters is it's visible
+ if {$cgram_hexeditor != {}} {
+ set cgram_window_params [list 1 [wm geometry $win.cgram_window]]
+ }
+
+ # Formulate the result
+ return [list \
+ $class_name \
+ [list \
+ $display_height \
+ $display_width \
+ [wm geometry $win] \
+ [array get connection_port] \
+ [array get connection_pin] \
+ [$canvas_widget.usr_note get] \
+ $visible_lr \
+ $visible_ud \
+ $rom_code \
+ $lcd_char_size \
+ $ignore_errors \
+ $no_delays \
+ [wm geometry $win.log_window] \
+ [wm state $win.log_window] \
+ $ddram_window_params \
+ $cgram_window_params \
+ $log_enabled \
+ $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} {
+ if {[catch {
+ # Determinate whether we are re-configuring already operating
+ #+ HD44780 simulator or creating a new one from scratch
+ set new_instance [expr {![winfo exists $win]}]
+
+ # Set display width (number of columns) and height (number of rows)
+ if {$new_instance} {
+ set display_height [lindex $state 0]
+ set display_width [lindex $state 1]
+ }
+
+ # Load connections to the MCU (port numbers)
+ if {[llength [lindex $state 3]]} {
+ array set connection_port [lindex $state 3]
+ } else {
+ array set connection_port {0 - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 - 10 -}
+ }
+
+ # Load connections to the MCU (port pin numbers)
+ if {[llength [lindex $state 4]]} {
+ array set connection_pin [lindex $state 4]
+ } else {
+ array set connection_pin {0 - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 - 10 -}
+ }
+
+ # Set flags: "Right part visible" and "Bottom part visible"
+ if {[string length [lindex $state 6]]} {
+ set visible_lr [lindex $state 6]
+ }
+ if {[string length [lindex $state 7]]} {
+ set visible_ud [lindex $state 7]
+ }
+
+ # Set font to use (specification of character patterns not their size)
+ if {[string length [lindex $state 8]]} {
+ set rom_code [lindex $state 8]
+ }
+
+ # Set font size to use (could be 5×8 or 5×10)
+ if {[string length [lindex $state 9]]} {
+ set lcd_char_size [lindex $state 9]
+
+ # Validate value of character size parameter
+ if {$display_height == 2 && $lcd_char_size == 1} {
+ set lcd_char_size 0
+ }
+ }
+
+ # Flags: "Ignore errors" and "Disable delays"
+ if {[string length [lindex $state 10]]} {
+ set ignore_errors [lindex $state 10]
+ }
+ if {[string length [lindex $state 11]]} {
+ set no_delays [lindex $state 11]
+ }
+
+ # Log window parameters
+ set log_window_geometry [lindex $state 12]
+ set log_window_state [lindex $state 13]
+
+ # DDRAM and CGRAM hex editor windows parameters
+ if {[string length [lindex $state 14]]} {
+ set ddram_window_params [lindex $state 14]
+ }
+ if {[string length [lindex $state 15]]} {
+ set cgram_window_params [lindex $state 15]
+ }
+
+ # Enable or disable logging of events
+ if {[string length [lindex $state 16]]} {
+ set log_enabled [lindex $state 16]
+ }
+
+ if {[lindex $state 17] != {}} {
+ set keep_win_on_top [lindex $state 17]
+ }
+
+ # Fail
+ }]} then {
+ puts stderr "Unable to load configuration for $class_name"
+ return 0
+
+ # Success
+ } else {
+ if {$new_instance} {
+ # Create panel GUI
+ create_gui
+ create_log $log_window_geometry
+ reset_hd44780
+ mcu_changed
+
+ if {$keep_win_on_top} {
+ wm attributes $win -topmost 1
+ }
+
+ # Display the log window
+ if {$log_window_state == {normal}} {
+ show_log
+ }
+
+ # Initialize HD44780 simulator
+ clear_cgram
+ on_off [$project pale_is_enabled]
+ }
+
+ # Restore window geometry
+ if {[string length [lindex $state 2]]} {
+ wm geometry $win [regsub {^\=?\d+x\d+} [lindex $state 2] [regsub {\+\d+\+\d+} [wm geometry $win] {}]]
+ }
+
+ # Load user note
+ if {[string length [lindex $state 5]]} {
+ $canvas_widget.usr_note delete 0
+ $canvas_widget.usr_note insert 0 [lindex $state 5]
+ }
+
+ # Hide some parts of the window accordingly to the settings
+ if {!$visible_lr} {
+ set visible_lr 1
+ show_hide1
+ }
+ if {!$visible_ud} {
+ set visible_ud 1
+ show_hide0
+ }
+
+ # Adjust log enable/disable checkbox
+ if {$log_enabled} {
+ $log_on_off_chbut select
+ } else {
+ $log_on_off_chbut deselect
+ }
+
+ # Restore/Set state of ComboBoxes
+ for {set i 0} {$i < 11} {incr i} {
+ ## PIN
+ set pin $connection_pin($i)
+ if {$pin != {-}} {
+ set pin [expr {7 - $pin}]
+ }
+ set idx [lsearch -ascii -exact \
+ [$canvas_widget.cb_b$i cget -values] \
+ $pin \
+ ]
+ if {$idx == -1} {
+ set idx 0
+ }
+ $canvas_widget.cb_b$i current $idx
+
+ ## PORT
+ set idx [lsearch -ascii -exact \
+ [$canvas_widget.cb_p$i cget -values] \
+ $connection_port($i) \
+ ]
+ if {$idx == -1} {
+ set idx 0
+ }
+ if {[llength [$canvas_widget.cb_p$i cget -values]]} {
+ $canvas_widget.cb_p$i current $idx
+ }
+ }
+
+ # Adjust display appearance to fit the current character size
+ accept_new_character_size
+
+ # Adjust internal logic and the rest of PALE
+ evaluete_enaged_pins
+ $project pale_reevaluate_IO
+
+ # Display the DDRAM and CGRAM hex editor windows
+ if {$new_instance} {
+ if {[lindex $ddram_window_params 0]} {
+ show_ddram
+ }
+ if {[lindex $cgram_window_params 0]} {
+ show_cgram
+ }
+ }
+
+ # Accept new state of ports
+ if {$new_instance} {
+ set state [$project pale_get_true_state]
+ new_state state
+ }
+
+ # Finalize ...
+ clear_modified
+ update
+
+ return 1
+ }
+ }
+
+ ## Simulated MCU has been reset
+ # @return void
+ public method reset {} {
+ # There is nothing special what has to be done here, the
+ #+ controller, HD44780, has its own reset mechanism independent
+ #+ on the simulated MCU
+ }
+
+
+ # ------------------------------------------------------------------
+ # 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}::font_id $rom_code
+ set ::${class_name}::char_size $lcd_char_size
+ set ::${class_name}::_ignore_errors $ignore_errors
+ set ::${class_name}::_no_delays $no_delays
+ set ::${class_name}::menu_keep_win_on_top $keep_win_on_top
+ }
+
+ ## This method is called after configuration menu is created
+ # @return void
+ public method create_config_menu_special {} {
+ # Changing character size is allowed only for 1 line displays
+ if {$display_height == 2} {
+ set state {disabled}
+ } else {
+ set state {normal}
+ }
+ $conf_menu entryconfigure [mc "Set character size"] -state $state
+ }
+
+ ## 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} {
+ $text_widget insert insert [mc "LCD display controled by HD44780 driver\n\n"]
+
+ $text_widget insert insert [mc "This tool simulates a HD44780 character LCD of any size up to 2 rows and 64 columns. There are 11 lines serving as interface for the MCU, ``E'', ``RS'', ``R/W'' and ``D0''..``D7''. User can view end modify content of display data RAM (DDRAM), character generator RAM (CGRAM) and certain HD44780 registers: instruction register (IR), data register (DR), address counter (AC) and display shift, these registers are shown hexadecimal. User can also view content of character generator ROM (CGROM) and set font to use. All of the driver command are fully supported, all important events occurring in the simulated driver (HD44780) are recorded in the log. User can also see and modify certain HD44780 configuration flags like ``B'', ``S'', ``D'' and so on."]
+ }
+
+ ## 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 {} {
+ # Boot-up the controller, it takes 10ms according to manual
+ if {[$project pale_is_enabled]} {
+ # Clear CGRAM and reset the code
+ clear_cgram
+ reset_hd44780
+
+ # Update log
+ write_to_log I [mc "Starting the HD44780 boot-up sequence."]
+
+ # Ensure that that the LCD dot matrix is clear
+ clear_display
+
+ # On a real HW would take about 10 ms
+ engage_core 10000
+ }
+ }
+}
+
+# >>> File inclusion guard
+}
+# <<< File inclusion guard
diff --git a/lib/pale/leddisplay.tcl b/lib/pale/leddisplay.tcl
index 55b13a5..44cc7ad 100755..100644
--- a/lib/pale/leddisplay.tcl
+++ b/lib/pale/leddisplay.tcl
@@ -2,7 +2,7 @@
# Part of MCU 8051 IDE ( http://mcu8051ide.sf.net )
############################################################################
-# Copyright (C) 2007-2009 by Martin Ošmera #
+# Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012 by Martin Ošmera #
# martin.osmera@gmail.com #
# #
# This program is free software; you can redistribute it and#or modify #
@@ -21,6 +21,11 @@
# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #
############################################################################
+# >>> File inclusion guard
+if { ! [ info exists _LEDDISPLAY_TCL ] } {
+set _LEDDISPLAY_TCL _
+# <<< File inclusion guard
+
# --------------------------------------------------------------------------
# DESCRIPTION
@@ -36,7 +41,11 @@ class LedDisplay {
inherit VirtualHWComponent
# Font: Font to be used in the panel -- bold
- common cb_font [font create -weight bold -size -10 -family {helvetica}]
+ common cb_font [font create \
+ -weight bold \
+ -size [expr {int(-10 * $::font_size_factor)}] \
+ -family {helvetica} \
+ ]
common COMPONENT_NAME "LED Display" ;# Name of this component
common CLASS_NAME "LedDisplay" ;# Name of this class
common COMPONENT_ICON {leddisplay} ;# Icon for this panel (16x16)
@@ -53,16 +62,17 @@ class LedDisplay {
{#5555AA #0000FF}
{#AA55AA #8800FF}
}
+ common DIMMED_COLOR {#BBBBBB}
# Configuration menu
common CONFMENU {
{cascade {Common electrode} 7 "diode" .ca false 1 {
{radiobutton "Common anode" {}
::LedDisplay::cfg_common_anode 1
- "common_electrode_chanded" 7 ""}
- {radiobutton "Common catode" {}
+ "common_electrode_changed" 7 ""}
+ {radiobutton "Common cathode" {}
::LedDisplay::cfg_common_anode 0
- "common_electrode_chanded" 7 ""}
+ "common_electrode_changed" 7 ""}
}}
{cascade {Color} 0 "colorize" .color false 1 {
{radiobutton "Red" {}
@@ -92,15 +102,20 @@ class LedDisplay {
"Save configuration into a file"}
{command {Load configuration} {} 0 "load_from" {fileopen}
"Load configuration from a file"}
+ {separator}
+ {checkbutton "Window always on top" {} {::LedDisplay::menu_keep_win_on_top}
+ 1 0 0 {keep_win_on_top_changed}
+ ""}
}
private variable conf_led_color {red} ;# Color: Selected color for LED's
+ private variable keep_win_on_top 0 ;# Bool: Toplevel window
private variable leds ;# Array of CanvasObject (polygon): leds(segment_num) --> LED polygon
private variable wires ;# Array of CanvasObject (line): Wire connection LED with uC
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 common_anode 1 ;# Bool: 1 == common anode; 0 == common catode
+ private variable common_anode 1 ;# Bool: 1 == common anode; 0 == common cathode
# ------------------------------------------------------------------
# INTERNAL APPLICATION LOGIC
@@ -148,7 +163,7 @@ class LedDisplay {
# @return void
private method create_gui {} {
# Create panel window and canvas widget
- set win [toplevel .leddisplay$count -class $component_name -bg {#EEEEEE}]
+ set win [toplevel .leddisplay$count -class $component_name -bg ${::COMMON_BG_COLOR}]
set canvas_widget [canvas $win.canvas \
-bg white -width 0 -height 0 \
-highlightthickness 0 \
@@ -231,7 +246,7 @@ class LedDisplay {
-text [mc "PORT"] \
-font $cb_font \
-anchor ne
- $canvas_widget create text 50 5 \
+ $canvas_widget create text 42 5 \
-text [mc "BIT"] \
-font $cb_font \
-anchor nw
@@ -239,18 +254,18 @@ class LedDisplay {
-text [mc "PORT"] \
-font $cb_font \
-anchor ne
- $canvas_widget create text 210 5\
+ $canvas_widget create text 202 5\
-text [mc "BIT"] \
-font $cb_font \
-anchor nw
- $canvas_widget create text 5 155\
- -text [mc "Note"] \
- -font $cb_font \
- -anchor w
- $canvas_widget create window 40 155 \
+ $canvas_widget create text 35 160 \
+ -text [mc "Note"] \
+ -font $cb_font \
+ -anchor e
+ $canvas_widget create window 40 160 \
-window [ttk::entry $canvas_widget.usr_note \
- -validate all \
+ -validate key \
-validatecommand "$this set_modified" \
] \
-width 180 -anchor w
@@ -261,14 +276,25 @@ class LedDisplay {
pack $canvas_widget -fill both -expand 1
# Set window parameters
- wm geometry $win =230x170
+ wm minsize $win 230 175
wm iconphoto $win ::ICONS::16::$component_icon
- wm title $win "[mc $component_name] - [string trim $project {:}] - MCU 8051 IDE"
+ wm title $win "[mc $component_name] - [$project cget -projectName] - MCU 8051 IDE"
wm resizable $win 0 0
wm protocol $win WM_DELETE_WINDOW "$this close_window"
bindtags $win [list $win Toplevel all .]
}
+ ## 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 $LedDisplay::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 LED to another port pin
# @parm Int i - LED number (0..7)
# @return void
@@ -282,20 +308,22 @@ class LedDisplay {
# Change state of the device
if {$drawing_on} {
- new_state [$project pale_get_true_state]
+ set state [$project pale_get_true_state]
+ new_state state
}
# Set flag modified
set_modified
}
- ## LED's common electrode chanded
+ ## LED's common electrode changed
# @return void
- public method common_electrode_chanded {} {
+ public method common_electrode_changed {} {
set common_anode ${::LedDisplay::cfg_common_anode}
if {$drawing_on} {
- new_state [$project pale_get_true_state]
+ set state [$project pale_get_true_state]
+ new_state state
}
set_modified
}
@@ -306,7 +334,8 @@ class LedDisplay {
set conf_led_color ${::LedDisplay::color}
if {$drawing_on} {
- new_state [$project pale_get_true_state]
+ set state [$project pale_get_true_state]
+ new_state state
}
set_modified
}
@@ -404,8 +433,8 @@ class LedDisplay {
}
# Draw
- set leds($i) [$canvas_widget create polygon \
- $coordinates -width 0 -fill #888888 \
+ set leds($i) [$canvas_widget create polygon \
+ $coordinates -width 0 -fill $DIMMED_COLOR \
]
}
@@ -414,7 +443,7 @@ class LedDisplay {
set leds(7) [$canvas_widget create oval \
[expr {49 + $x}] [expr {77 + $y}] \
[expr {58 + $x}] [expr {86 + $y}] \
- -width 0 -fill #888888 \
+ -width 0 -fill $DIMMED_COLOR \
]
# Print segment labels
@@ -452,12 +481,12 @@ class LedDisplay {
# @return void
public method mcu_changed {} {
# Refresh lists of possible values in port selection ComboBoxes
- set avaliable_ports [concat - [$project pale_get_avaliable_ports]]
+ set available_ports [concat - [$project pale_get_available_ports]]
for {set i 0} {$i < 8} {incr i} {
- $canvas_widget.cb_p$i configure -values $avaliable_ports
+ $canvas_widget.cb_p$i configure -values $available_ports
- if {[lsearch -ascii -exact $avaliable_ports $connection_port($i)] == -1} {
+ if {[lsearch -ascii -exact $available_ports $connection_port($i)] == -1} {
$canvas_widget.cb_p$i current 0
set connection_port($i) {-}
}
@@ -472,11 +501,13 @@ class LedDisplay {
# '|' - High frequency
# 'X' - Access to external memory
# '?' - No volatge
- # '-' - Undeterminable value (some noise)
+ # '-' - Indeterminable value (some noise)
# '=' - High forced to low
# '0' - Logical 0
# '1' - Logical 1
- public method new_state {state} {
+ public method new_state {_state} {
+ upvar $_state state
+
# Determinate index of LED color in list COLORS
set color_idx [lsearch -ascii -exact \
{red orange yellow green blue purple} \
@@ -490,7 +521,7 @@ class LedDisplay {
# Not connected
if {[lindex $pp 0] == {-} || [lindex $pp 1] == {-}} {
- $canvas_widget itemconfigure $leds($i) -fill {#888888}
+ $canvas_widget itemconfigure $leds($i) -fill $DIMMED_COLOR
$canvas_widget itemconfigure $wires($i) -fill {#000000}
continue
}
@@ -500,7 +531,7 @@ class LedDisplay {
{0} { ;# Logical 0
if {$common_anode} {
set segment_color {2}
- } {
+ } else {
set segment_color {0}
}
set wire_color {#00FF00}
@@ -508,7 +539,7 @@ class LedDisplay {
{1} { ;# Logical 1
if {$common_anode} {
set segment_color {0}
- } {
+ } else {
set segment_color {2}
}
set wire_color {#FF0000}
@@ -533,8 +564,8 @@ class LedDisplay {
# Determinate segment color (true color, not just number)
if {!$segment_color} {
- set segment_color {#888888}
- } {
+ set segment_color $DIMMED_COLOR
+ } else {
incr segment_color -1
set segment_color [lindex $COLORS [list $color_idx $segment_color]]
}
@@ -563,6 +594,7 @@ class LedDisplay {
[$canvas_widget.usr_note get] \
$conf_led_color \
$common_anode \
+ $keep_win_on_top \
] \
]
}
@@ -578,7 +610,7 @@ class LedDisplay {
# Restore window geometry
if {[string length [lindex $state 2]]} {
- wm geometry $win [lindex $state 2]
+ wm geometry $win [regsub {^\=?\d+x\d+} [lindex $state 2] [join [wm minsize $win] {x}]]
}
# Load user note
@@ -592,6 +624,13 @@ class LedDisplay {
set common_anode 1
}
+ if {[lindex $state 6] != {}} {
+ set keep_win_on_top [lindex $state 6]
+ if {$keep_win_on_top} {
+ wm attributes $win -topmost 1 -alpha 0.8
+ }
+ }
+
# Restore state of ComboBoxes
for {set i 0} {$i < 8} {incr i} {
## PIN
@@ -620,12 +659,13 @@ class LedDisplay {
}
# Accept new state of ports
- new_state [$project pale_get_true_state]
+ set state [$project pale_get_true_state]
+ new_state state
update
# Fail
}]} then {
- puts "Unable to load config for $class_name"
+ puts "Unable to load configuration for $class_name"
return 0
# Success
@@ -638,7 +678,8 @@ class LedDisplay {
## Simulated MCU has been reseted
# @return void
public method reset {} {
- new_state [$project pale_get_true_state]
+ set state [$project pale_get_true_state]
+ new_state state
}
@@ -651,6 +692,7 @@ class LedDisplay {
public method config_menu_special {} {
set ::${class_name}::color $conf_led_color
set ::${class_name}::cfg_common_anode $common_anode
+ set ::${class_name}::menu_keep_win_on_top $keep_win_on_top
}
## This method is called after configuration menu has beed created
@@ -669,7 +711,7 @@ class LedDisplay {
#
# Note: There is defined text tag "tag_bold" in the text widget
public method show_help_special {text_widget} {
- $text_widget insert insert [mc "Virtual LED display with common anode (default) or catode. Each segment can be connected to any port pin of the simulated uC. Connections with the uC are made with ComboBoxes on the bottom of the panel. Panel configuration can be saved to a file (with extension vhc). And can be loaded from that file later.\n\n"]
+ $text_widget insert insert [mc "Virtual LED display with common anode (default) or cathode. Each segment can be connected to any port pin of the simulated uC. Connections with the uC are made with ComboBoxes on the bottom of the panel. Panel configuration can be saved to a file with extension vhc, and can be loaded from that file later.\n\n"]
set color_idx [lsearch -ascii -exact \
{red orange yellow green blue purple} \
@@ -679,7 +721,7 @@ class LedDisplay {
$text_widget insert insert [mc "LED states:"]
$text_widget tag add tag_bold {insert linestart} {insert lineend}
$text_widget insert insert [mc "\n "]
- $text_widget window create insert -pady 1 -create "frame $text_widget.f0 -bd 1 -width 14 -height 16 -bg #888888"
+ $text_widget window create insert -pady 1 -create "frame $text_widget.f0 -bd 1 -width 14 -height 16 -bg $DIMMED_COLOR"
$text_widget insert insert [mc " Off\n "]
$text_widget window create insert -pady 1 -create "frame $text_widget.f1 -bd 1 -width 14 -height 16 -bg [lindex $COLORS [list $color_idx 0]]"
$text_widget insert insert [mc " Fast blinking\n "]
@@ -700,8 +742,13 @@ class LedDisplay {
$canvas_widget itemconfigure $leds($i) -fill {#888888}
$canvas_widget itemconfigure $wires($i) -fill {#000000}
}
- } {
- new_state [$project pale_get_true_state]
+ } else {
+ set state [$project pale_get_true_state]
+ new_state state
}
}
}
+
+# >>> File inclusion guard
+}
+# <<< File inclusion guard
diff --git a/lib/pale/ledmatrix.tcl b/lib/pale/ledmatrix.tcl
index b739f53..1be1718 100755..100644
--- a/lib/pale/ledmatrix.tcl
+++ b/lib/pale/ledmatrix.tcl
@@ -2,7 +2,7 @@
# Part of MCU 8051 IDE ( http://mcu8051ide.sf.net )
############################################################################
-# Copyright (C) 2007-2009 by Martin Ošmera #
+# Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012 by Martin Ošmera #
# martin.osmera@gmail.com #
# #
# This program is free software; you can redistribute it and#or modify #
@@ -21,6 +21,11 @@
# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #
############################################################################
+# >>> File inclusion guard
+if { ! [ info exists _LEDMATRIX_TCL ] } {
+set _LEDMATRIX_TCL _
+# <<< File inclusion guard
+
# --------------------------------------------------------------------------
# DESCRIPTION
@@ -36,8 +41,12 @@ class LedMatrix {
inherit VirtualHWComponent
# Font: Font to be used in the panel -- bold
- common cb_font [font create -weight bold -size -10 -family {helvetica}]
- common COMPONENT_NAME "LED matrix" ;# Name of this component
+ common cb_font [font create \
+ -weight bold \
+ -size [expr {int(-10 * $::font_size_factor)}] \
+ -family {helvetica} \
+ ]
+ common COMPONENT_NAME "LED Matrix" ;# Name of this component
common CLASS_NAME "LedMatrix" ;# Name of this class
common COMPONENT_ICON {ledmatrix} ;# Icon for this panel (16x16)
@@ -135,7 +144,7 @@ class LedMatrix {
}}
{separator}
{command {All fade out} {} 0 "dim_all" {ledgray}
- "Dim all leds"}
+ "Dim all LEDs"}
{command {Show help} {} 5 "show_help" {help}
"Show brief help"}
{separator}
@@ -143,14 +152,19 @@ class LedMatrix {
"Save configuration into a file"}
{command {Load configuration} {} 0 "load_from" {fileopen}
"Load configuration from a file"}
+ {separator}
+ {checkbutton "Window always on top" {} {::LedMatrix::menu_keep_win_on_top}
+ 1 0 0 {keep_win_on_top_changed}
+ ""}
}
private variable conf_dim_interval 50 ;# Int: Interval to dim LED's in instruction cycles
private variable conf_matrix_mapping 0 ;# Int: Type of matrix mapping: 0 == Random; 1 == Row; 2 == Column
private variable conf_led_color {red} ;# Color: Selected color for LED's
+ private variable keep_win_on_top 0 ;# Bool: Toplevel window
## List of Bool: LED light up condition
- # Index 0 - Row must be in: 1 == log. 1; 0 = log. 0
- # Index 1 - Column must be in: 1 == log. 1; 0 = log. 0
+ # Index 0 - Row must be in: 1 == log. 1; 0 == log. 0
+ # Index 1 - Column must be in: 1 == log. 1; 0 == log. 0
private variable conf_led_cond {0 0}
private variable leds ;# Array of CanvasObject (image): LED's, leds(row,column)
private variable col ;# Array of CanvasObject (line): Column wires
@@ -216,6 +230,17 @@ class LedMatrix {
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 $LedMatrix::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 wire to another port pin
# @parm Char col_or_row - 'C' => Column; 'R' => Row
# @parm Int i - Wire number (0..7)
@@ -229,7 +254,7 @@ class LedMatrix {
set connection_pin(R$i) [expr {7 - $connection_pin(R$i)}]
}
# Column
- } {
+ } else {
set connection_port(C$i) [$canvas_widget.cb_c_p$i get]
set connection_pin(C$i) [$canvas_widget.cb_c_b$i get]
if {$connection_pin(C$i) != {-}} {
@@ -239,7 +264,8 @@ class LedMatrix {
# Change state of the device
if {$drawing_on} {
- new_state [$project pale_get_true_state] 1
+ set state [$project pale_get_true_state]
+ new_state state 1
}
# Set flag modified
@@ -272,7 +298,8 @@ class LedMatrix {
# Change state of the device
if {$drawing_on} {
- new_state [$project pale_get_true_state] 1
+ set state [$project pale_get_true_state]
+ new_state state 1
}
# Set flag modified
@@ -285,12 +312,13 @@ class LedMatrix {
set conf_led_cond ${::LedMatrix::cond}
if {$drawing_on} {
- new_state [$project pale_get_true_state]
+ set state [$project pale_get_true_state]
+ new_state state
}
set_modified
}
- ## Dim all LED's and reset their prevoius states
+ ## Dim all LED's and reset their previous states
# @return void
public method dim_all {} {
for {set i 0} {$i < 8} {incr i} {
@@ -308,7 +336,7 @@ class LedMatrix {
# @return void
private method create_gui {} {
# Create panel window and canvas widget
- set win [toplevel .ledmatrix$count -class $component_name -bg {#EEEEEE}]
+ set win [toplevel .ledmatrix$count -class $component_name -bg ${::COMMON_BG_COLOR}]
set canvas_widget [canvas $win.canvas \
-bg white -width 0 -height 0 \
-highlightthickness 0 \
@@ -318,7 +346,7 @@ class LedMatrix {
set led_sep 15
set sep 25
set y_0 100
- set x_0 85
+ set x_0 90
set y_1 [expr {$y_0 + 10}]
set x_1 [expr {$x_0 + 35}]
@@ -466,13 +494,13 @@ class LedMatrix {
-font $cb_font \
-anchor nw
- $canvas_widget create text 5 273 \
+ $canvas_widget create text 35 278 \
-text [mc "Note"] \
-font $cb_font \
- -anchor w
- $canvas_widget create window 40 273 \
+ -anchor e
+ $canvas_widget create window 40 278 \
-window [ttk::entry $canvas_widget.usr_note \
- -validate all \
+ -validate key \
-validatecommand "$this set_modified" \
] \
-width 230 -anchor w
@@ -490,7 +518,7 @@ class LedMatrix {
-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"
- $canvas_widget create window 2 20 -window $start_stop_button -anchor sw
+ $canvas_widget create window 2 22 -window $start_stop_button -anchor sw
bindtags $start_stop_button [list $start_stop_button TButton all .]
# Create configuration menu button
@@ -500,16 +528,16 @@ class LedMatrix {
-command "$this config_menu" \
]
setStatusTip -widget $conf_button -text [mc "Configure"]
- $canvas_widget create window 2 20 -window $conf_button -anchor nw
+ $canvas_widget create window 2 22 -window $conf_button -anchor nw
bindtags $conf_button [list $conf_button TButton all .]
# Pack canvas
pack $canvas_widget -fill both -expand 1
# Set window parameters
- wm geometry $win =275x285
+ wm minsize $win 280 295
wm iconphoto $win ::ICONS::16::$component_icon
- wm title $win "[mc $component_name] - [string trim $project {:}] - MCU 8051 IDE"
+ wm title $win "[mc $component_name] - [$project cget -projectName] - MCU 8051 IDE"
wm resizable $win 0 0
wm protocol $win WM_DELETE_WINDOW "$this close_window"
bindtags $win [list $win Toplevel all .]
@@ -538,17 +566,17 @@ class LedMatrix {
# @return void
public method mcu_changed {} {
# Refresh lists of possible values in port selection ComboBoxes
- set avaliable_ports [concat - [$project pale_get_avaliable_ports]]
+ set available_ports [concat - [$project pale_get_available_ports]]
for {set i 0} {$i < 8} {incr i} {
- $canvas_widget.cb_r_p$i configure -values $avaliable_ports
- $canvas_widget.cb_c_p$i configure -values $avaliable_ports
+ $canvas_widget.cb_r_p$i configure -values $available_ports
+ $canvas_widget.cb_c_p$i configure -values $available_ports
- if {[lsearch -ascii -exact $avaliable_ports $connection_port(R$i)] == -1} {
+ if {[lsearch -ascii -exact $available_ports $connection_port(R$i)] == -1} {
$canvas_widget.cb_r_p$i current 0
set connection_port(R$i) {-}
}
- if {[lsearch -ascii -exact $avaliable_ports $connection_port(C$i)] == -1} {
+ if {[lsearch -ascii -exact $available_ports $connection_port(C$i)] == -1} {
$canvas_widget.cb_c_p$i current 0
set connection_port(C$i) {-}
}
@@ -557,18 +585,20 @@ class LedMatrix {
## Accept new state of ports
# @parm List state - Port states ( 5 x {8 x bit} -- {bit0 bit1 bit2 ... bit7} )
- # @parm Bool preserve_prvious_state = 0 - Preserve previous state of component
+ # @parm Bool preserve_prvious_state=0 - Preserve previous state of component
# @return void
#
# Possible bit values:
# '|' - High frequency
# 'X' - Access to external memory
# '?' - No volatge
- # '-' - Undeterminable value (some noise)
+ # '-' - Indeterminable value (some noise)
# '=' - High forced to low
# '0' - Logical 0
# '1' - Logical 1
- public method new_state {state {preserve_prvious_state 0}} {
+ public method new_state {_state {preserve_prvious_state 0}} {
+ upvar $_state state
+
# Change column wire colors
for {set i 0} {$i < 8} {incr i} {
# Determinate index in the list of port states
@@ -668,22 +698,22 @@ class LedMatrix {
}
# Determinate row state in this way:
- #+ row_state = 0 => Dim
- #+ row_state = 1 => Half dim
- #+ row_state = 2 => Brighten
+ #+ row_state == 0 => Dim
+ #+ row_state == 1 => Half dim
+ #+ row_state == 2 => Brighten
set row_state [lindex $state $pp]
switch -- $row_state {
{0} { ;# Logical 0
if {[lindex $conf_led_cond 0]} {
set row_state 0
- } {
+ } else {
set row_state 2
}
}
{1} { ;# Logical 1
if {[lindex $conf_led_cond 0]} {
set row_state 2
- } {
+ } else {
set row_state 0
}
}
@@ -717,14 +747,14 @@ class LedMatrix {
{0} { ;# Logical 0
if {[lindex $conf_led_cond 1]} {
set image 0 ;# ledgray
- } {
+ } else {
set image 1 ;# shining LED
}
}
{1} { ;# Logical 1
if {[lindex $conf_led_cond 1]} {
set image 1 ;# shining LED
- } {
+ } else {
set image 0 ;# ledgray
}
}
@@ -831,6 +861,7 @@ class LedMatrix {
$conf_dim_interval \
$conf_led_cond \
$conf_matrix_mapping \
+ $keep_win_on_top \
] \
]
}
@@ -846,7 +877,7 @@ class LedMatrix {
# Restore window geometry
if {[string length [lindex $state 2]]} {
- wm geometry $win [lindex $state 2]
+ wm geometry $win [regsub {^\=?\d+x\d+} [lindex $state 2] [join [wm minsize $win] {x}]]
}
# Load user note
@@ -863,6 +894,13 @@ class LedMatrix {
set conf_matrix_mapping 0
}
+ if {[lindex $state 8] != {}} {
+ set keep_win_on_top [lindex $state 8]
+ if {$keep_win_on_top} {
+ wm attributes $win -topmost 1 -alpha 0.8
+ }
+ }
+
# Restore state of ComboBoxes
foreach foo {R C} bar {r c} {
for {set i 0} {$i < 8} {incr i} {
@@ -893,12 +931,13 @@ class LedMatrix {
}
# Accept new state of ports
- new_state [$project pale_get_true_state]
+ set state [$project pale_get_true_state]
+ new_state state
update
# Fail
}]} then {
- puts "Unable to load config for $class_name"
+ puts "Unable to load configuration for $class_name"
return 0
# Success
@@ -912,7 +951,8 @@ class LedMatrix {
# @return void
public method reset {} {
dim_all
- new_state [$project pale_get_true_state]
+ set state [$project pale_get_true_state]
+ new_state state
}
@@ -927,6 +967,7 @@ class LedMatrix {
set ::${class_name}::matrix_mapping $conf_matrix_mapping
set ::${class_name}::color $conf_led_color
set ::${class_name}::cond $conf_led_cond
+ set ::${class_name}::menu_keep_win_on_top $keep_win_on_top
}
## This method is called after configuration menu has beed created
@@ -945,7 +986,7 @@ class LedMatrix {
#
# Note: There is defined text tag "tag_bold" in the text widget
public method show_help_special {text_widget} {
- $text_widget insert insert [mc "This tool consists of 64 LED's. Each of them can be connected to any port pin of the simulated uC. Connections with the uC are made with ComboBoxes. Panel configuration can be saved to a file (with extension vhc). And can be loaded from that file later. Condition on which a LED lights up and LED colors are configurable. Also fade out interval is configurable.\n\n"]
+ $text_widget insert insert [mc "This tool consists of 64 LED's. Each of them can be connected to any port pin of the simulated uC. Connections with the uC are made with ComboBoxes. Panel configuration can be saved to a file with extension vhc, and can be loaded from that file later. Condition on which a LED lights up and LED colors are configurable. Also fade out interval is configurable.\n\n"]
$text_widget insert insert [mc "LED states:"]
$text_widget tag add tag_bold {insert linestart} {insert lineend}
@@ -975,8 +1016,13 @@ class LedMatrix {
-image ::ICONS::16::ledgray
}
}
- } {
- new_state [$project pale_get_true_state] 1
+ } else {
+ set state [$project pale_get_true_state]
+ new_state state 1
}
}
}
+
+# >>> File inclusion guard
+}
+# <<< File inclusion guard
diff --git a/lib/pale/ledpanel.tcl b/lib/pale/ledpanel.tcl
index a05bb79..a39799f 100755..100644
--- a/lib/pale/ledpanel.tcl
+++ b/lib/pale/ledpanel.tcl
@@ -2,7 +2,7 @@
# Part of MCU 8051 IDE ( http://mcu8051ide.sf.net )
############################################################################
-# Copyright (C) 2007-2009 by Martin Ošmera #
+# Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012 by Martin Ošmera #
# martin.osmera@gmail.com #
# #
# This program is free software; you can redistribute it and#or modify #
@@ -21,6 +21,11 @@
# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #
############################################################################
+# >>> File inclusion guard
+if { ! [ info exists _LEDPANEL_TCL ] } {
+set _LEDPANEL_TCL _
+# <<< File inclusion guard
+
# --------------------------------------------------------------------------
# DESCRIPTION
@@ -36,8 +41,12 @@ class LedPanel {
inherit VirtualHWComponent
# Font: Font to be used in the panel -- bold
- common cb_font [font create -weight bold -size -10 -family {helvetica}]
- common COMPONENT_NAME "LED panel" ;# Name of this component
+ common cb_font [font create \
+ -weight bold \
+ -size [expr {int(-10 * $::font_size_factor)}] \
+ -family {helvetica} \
+ ]
+ common COMPONENT_NAME "LED Panel" ;# Name of this component
common CLASS_NAME "LedPanel" ;# Name of this class
common COMPONENT_ICON {ledpanel} ;# Icon for this panel (16x16)
@@ -71,9 +80,14 @@ class LedPanel {
"Save configuration into a file"}
{command {Load configuration} {} 0 "load_from" {fileopen}
"Load configuration from a file"}
+ {separator}
+ {checkbutton "Window always on top" {} {::LedPanel::menu_keep_win_on_top}
+ 1 0 0 {keep_win_on_top_changed}
+ ""}
}
+ private variable keep_win_on_top 0 ;# Bool: Toplevel window
private variable conf_led_color {red} ;# Color: Selected color for LED's
private variable leds ;# Array of CanvasObject (image): LED's
private variable connection_port ;# Array of Int: Index is key number, value is port number or {-}
@@ -122,6 +136,17 @@ class LedPanel {
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 $LedPanel::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 LED to another port pin
# @parm Int i - LED number (0..7)
# @return void
@@ -135,7 +160,8 @@ class LedPanel {
# Change state of the device
if {$drawing_on} {
- new_state [$project pale_get_true_state]
+ set state [$project pale_get_true_state]
+ new_state state
}
# Set flag modified
@@ -148,7 +174,8 @@ class LedPanel {
set conf_led_color ${::LedPanel::color}
if {$drawing_on} {
- new_state [$project pale_get_true_state]
+ set state [$project pale_get_true_state]
+ new_state state
}
set_modified
}
@@ -157,7 +184,7 @@ class LedPanel {
# @return void
private method create_gui {} {
# Create panel window and canvas widget
- set win [toplevel .ledpanel$count -class $component_name -bg {#EEEEEE}]
+ set win [toplevel .ledpanel$count -class $component_name -bg ${::COMMON_BG_COLOR}]
set canvas_widget [canvas $win.canvas \
-bg white -width 0 -height 0 \
-highlightthickness 0 \
@@ -167,7 +194,7 @@ class LedPanel {
set led_y 35
set cb_p_y 65
set cb_b_y 85
- set usr_n_y 105
+ set usr_n_y 110
set x 50
$canvas_widget create text 5 $cb_p_y \
-text [mc "PORT"] \
@@ -177,16 +204,16 @@ class LedPanel {
-text [mc "BIT"] \
-font $cb_font \
-anchor w
- $canvas_widget create text 5 $usr_n_y \
+ $canvas_widget create text 30 $usr_n_y \
-text [mc "Note"] \
-font $cb_font \
- -anchor w
- $canvas_widget create window 208 $usr_n_y \
+ -anchor e
+ $canvas_widget create window 35 $usr_n_y \
-window [ttk::entry $canvas_widget.usr_note \
- -validate all \
+ -validate key \
-validatecommand "$this set_modified" \
] \
- -width 330
+ -width 330 -anchor w
bindtags $canvas_widget.usr_note \
[list $canvas_widget.usr_note TEntry $win all .]
@@ -253,9 +280,9 @@ class LedPanel {
pack $canvas_widget -fill both -expand 1
# Set window parameters
- wm geometry $win =380x120
+ wm minsize $win 380 130
wm iconphoto $win ::ICONS::16::$component_icon
- wm title $win "[mc $component_name] - [string trim $project {:}] - MCU 8051 IDE"
+ wm title $win "[mc $component_name] - [$project cget -projectName] - MCU 8051 IDE"
wm resizable $win 0 0
wm protocol $win WM_DELETE_WINDOW "$this close_window"
bindtags $win [list $win Toplevel all .]
@@ -332,12 +359,12 @@ class LedPanel {
# @return void
public method mcu_changed {} {
# Refresh lists of possible values in port selection ComboBoxes
- set avaliable_ports [concat - [$project pale_get_avaliable_ports]]
+ set available_ports [concat - [$project pale_get_available_ports]]
for {set i 0} {$i < 8} {incr i} {
- $canvas_widget.cb_p$i configure -values $avaliable_ports
+ $canvas_widget.cb_p$i configure -values $available_ports
- if {[lsearch -ascii -exact $avaliable_ports $connection_port($i)] == -1} {
+ if {[lsearch -ascii -exact $available_ports $connection_port($i)] == -1} {
$canvas_widget.cb_p$i current 0
set connection_port($i) {-}
}
@@ -352,11 +379,13 @@ class LedPanel {
# '|' - High frequency
# 'X' - Access to external memory
# '?' - No volatge
- # '-' - Undeterminable value (some noise)
+ # '-' - Indeterminable value (some noise)
# '=' - High forced to low
# '0' - Logical 0
# '1' - Logical 1
- public method new_state {state} {
+ public method new_state {_state} {
+ upvar $_state state
+
for {set i 0} {$i < 8} {incr i} {
# Determinate index in the list of port states
set pp [which_port_pin $i]
@@ -409,6 +438,7 @@ class LedPanel {
[wm geometry $win] \
[$canvas_widget.usr_note get] \
$conf_led_color \
+ $keep_win_on_top \
] \
]
}
@@ -424,7 +454,7 @@ class LedPanel {
# Restore window geometry
if {[string length [lindex $state 2]]} {
- wm geometry $win [lindex $state 2]
+ wm geometry $win [regsub {^\=?\d+x\d+} [lindex $state 2] [join [wm minsize $win] {x}]]
}
# Load user note
@@ -434,6 +464,13 @@ class LedPanel {
# Restore LED's configuration
set conf_led_color [lindex $state 4]
+ if {[lindex $state 5] != {}} {
+ set keep_win_on_top [lindex $state 5]
+ if {$keep_win_on_top} {
+ wm attributes $win -topmost 1 -alpha 0.8
+ }
+ }
+
# Restore state of ComboBoxes
for {set i 0} {$i < 8} {incr i} {
## PIN
@@ -462,12 +499,13 @@ class LedPanel {
}
# Accept new state of ports
- new_state [$project pale_get_true_state]
+ set state [$project pale_get_true_state]
+ new_state state
update
# Fail
}]} then {
- puts "Unable to load config for $class_name"
+ puts "Unable to load configuration for $class_name"
return 0
# Success
@@ -480,7 +518,8 @@ class LedPanel {
## Simulated MCU has been reseted
# @return void
public method reset {} {
- new_state [$project pale_get_true_state]
+ set state [$project pale_get_true_state]
+ new_state state
}
@@ -492,6 +531,7 @@ class LedPanel {
# @return void
public method config_menu_special {} {
set ::${class_name}::color $conf_led_color
+ set ::${class_name}::menu_keep_win_on_top $keep_win_on_top
}
## This method is called after configuration menu has beed created
@@ -510,7 +550,7 @@ class LedPanel {
#
# Note: There is defined text tag "tag_bold" in the text widget
public method show_help_special {text_widget} {
- $text_widget insert insert [mc "This tool consists of 8 LED's. Each of them can be connected to any port pin of the simulated uC. Connections with the uC are made with ComboBoxes on the bottom of the panel. Panel configuration can be saved to a file (with extension vhc). And can be loaded from that file later. LED colors are configurable.\n\n"]
+ $text_widget insert insert [mc "This tool consists of 8 LED's. Each of them can be connected to any port pin of the simulated uC. Connections with the uC are made with ComboBoxes on the bottom of the panel. Panel configuration can be saved to a file with extension vhc, and can be loaded from that file later. LED colors are configurable.\n\n"]
$text_widget insert insert [mc "LED states:"]
$text_widget tag add tag_bold {insert linestart} {insert lineend}
@@ -536,8 +576,13 @@ class LedPanel {
$canvas_widget itemconfigure $leds($i) \
-image ::ICONS::16::ledgray
}
- } {
- new_state [$project pale_get_true_state]
+ } else {
+ set state [$project pale_get_true_state]
+ new_state state
}
}
}
+
+# >>> File inclusion guard
+}
+# <<< File inclusion guard
diff --git a/lib/pale/matrixkeypad.tcl b/lib/pale/matrixkeypad.tcl
index 186ead0..9400741 100755..100644
--- a/lib/pale/matrixkeypad.tcl
+++ b/lib/pale/matrixkeypad.tcl
@@ -2,7 +2,7 @@
# Part of MCU 8051 IDE ( http://mcu8051ide.sf.net )
############################################################################
-# Copyright (C) 2007-2009 by Martin Ošmera #
+# Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012 by Martin Ošmera #
# martin.osmera@gmail.com #
# #
# This program is free software; you can redistribute it and#or modify #
@@ -21,6 +21,11 @@
# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #
############################################################################
+# >>> File inclusion guard
+if { ! [ info exists _MATRIXKEYPAD_TCL ] } {
+set _MATRIXKEYPAD_TCL _
+# <<< File inclusion guard
+
# --------------------------------------------------------------------------
# DESCRIPTION
@@ -36,15 +41,15 @@ class MatrixKeyPad {
inherit VirtualHWComponent
# Font: Font to be used in the panel -- bold
- common cb_font [font create \
- -weight bold \
- -size -10 \
- -family {helvetica} \
+ common cb_font [font create \
+ -weight bold \
+ -size [expr {int(-10 * $::font_size_factor)}] \
+ -family {helvetica} \
]
# Font: Font to be used in the panel -- normal weight
- common cb_font_n [font create \
- -size -10 \
- -family {helvetica} \
+ common cb_font_n [font create \
+ -size [expr {int(-10 * $::font_size_factor)}] \
+ -family {helvetica} \
]
common COMPONENT_NAME "Matrix Keypad" ;# Name of this component
@@ -64,9 +69,14 @@ class MatrixKeyPad {
"Save configuration into a file"}
{command {Load configuration} {} 0 "load_from" {fileopen}
"Load configuration from a file"}
+ {separator}
+ {checkbutton "Window always on top" {} {::MatrixKeyPad::menu_keep_win_on_top}
+ 1 0 0 {keep_win_on_top_changed}
+ ""}
}
- private variable radio_buttons ;# Bool: Disallow key combinations
+ private variable radio_buttons 0 ;# Bool: Disallow key combinations
+ private variable keep_win_on_top 0 ;# Bool: Toplevel window
private variable keys ;# Array of Bool: Indicates key press
private variable wire
private variable wire_o
@@ -138,6 +148,17 @@ class MatrixKeyPad {
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 $MatrixKeyPad::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
+ }
+ }
+
## Reevaluate array of MCU port pins engaged by this device
# @return void
private method evaluete_enaged_pins {} {
@@ -193,18 +214,18 @@ class MatrixKeyPad {
# @return void
private method create_gui {} {
# Create panel window and canvas widget
- set win [toplevel .matrixkeypad$count -class $component_name -bg {#EEEEEE}]
+ set win [toplevel .matrixkeypad$count -class $component_name -bg ${::COMMON_BG_COLOR}]
set canvas_widget [canvas $win.canvas \
-bg white -width 0 -height 0 \
-highlightthickness 0 \
]
# Create labels
- $canvas_widget create text 33 20 \
+ $canvas_widget create text 36 20 \
-text [mc "PORT"] \
-font $cb_font \
-anchor e
- $canvas_widget create text 35 20 \
+ $canvas_widget create text 38 20 \
-text [mc "BIT"] \
-font $cb_font \
-anchor w
@@ -218,13 +239,13 @@ class MatrixKeyPad {
-font $cb_font \
-anchor e
- $canvas_widget create text 5 220 \
+ $canvas_widget create text 35 220 \
-text [mc "Note"] \
-font $cb_font \
- -anchor w
- $canvas_widget create window 35 220 \
+ -anchor e
+ $canvas_widget create window 40 220 \
-window [ttk::entry $canvas_widget.usr_note \
- -validate all \
+ -validate key \
-validatecommand "$this set_modified" \
] \
-width 180 -anchor w
@@ -259,7 +280,7 @@ class MatrixKeyPad {
-state readonly \
]
bind $canvas_widget.cb_p$i <<ComboboxSelected>> "$this reconnect $i"
-
+
$canvas_widget create window $x $y -anchor w \
-window [ttk::combobox $canvas_widget.cb_b$i \
-width 1 \
@@ -289,7 +310,7 @@ class MatrixKeyPad {
-state readonly \
]
bind $canvas_widget.cb_p$i <<ComboboxSelected>> "$this reconnect $i"
-
+
$canvas_widget create window $x $cb_b_y -anchor center \
-window [ttk::combobox $canvas_widget.cb_b$i \
-width 1 \
@@ -334,9 +355,9 @@ class MatrixKeyPad {
pack $canvas_widget -fill both -expand 1
# Set window parameters
- wm geometry $win =225x235
+ wm minsize $win 225 240
wm iconphoto $win ::ICONS::16::$component_icon
- wm title $win "[mc $component_name] - [string trim $project {:}] - MCU 8051 IDE"
+ wm title $win "[mc $component_name] - [$project cget -projectName] - MCU 8051 IDE"
wm resizable $win 0 0
wm protocol $win WM_DELETE_WINDOW "$this close_window"
bindtags $win [list $win Toplevel all .]
@@ -455,7 +476,7 @@ class MatrixKeyPad {
$canvas_widget itemconfigure $rect($i) -outline #333333 -width 2
# Key released
- } {
+ } else {
$canvas_widget itemconfigure $lever(0$i) -fill #000000
$canvas_widget itemconfigure $lever(1$i) -fill #FFFFFF
$canvas_widget itemconfigure $text($i) -font $cb_font_n
@@ -469,7 +490,7 @@ class MatrixKeyPad {
public method key_leave {i} {
if {$keys($i)} {
set color {#333333}
- } {
+ } else {
set color {#CCCCCC}
}
$canvas_widget itemconfigure $rect($i) -outline $color
@@ -606,12 +627,12 @@ class MatrixKeyPad {
# @return void
public method mcu_changed {} {
# Refresh lists of possible values in port selection ComboBoxes
- set avaliable_ports [concat - [$project pale_get_avaliable_ports]]
+ set available_ports [concat - [$project pale_get_available_ports]]
for {set i 0} {$i < 8} {incr i} {
- $canvas_widget.cb_p$i configure -values $avaliable_ports
+ $canvas_widget.cb_p$i configure -values $available_ports
- if {[lsearch -ascii -exact $avaliable_ports $connection_port($i)] == -1} {
+ if {[lsearch -ascii -exact $available_ports $connection_port($i)] == -1} {
$canvas_widget.cb_p$i current 0
set connection_port($i) {-}
}
@@ -627,11 +648,13 @@ class MatrixKeyPad {
# '|' - High frequency
# 'X' - Access to external memory
# '?' - No volatge
- # '-' - Undeterminable value (some noise)
+ # '-' - Indeterminable value (some noise)
# '=' - High forced to low
# '0' - Logical 0
# '1' - Logical 1
- public method new_state {state} {
+ public method new_state {_state} {
+ upvar $_state state
+
# Local variables
set row_state [list {} {} {} {}] ;# State of rows
set col_state [list {} {} {} {}] ;# State of columns
@@ -650,7 +673,7 @@ class MatrixKeyPad {
if {$i < 4} {
lset row_state $i [lindex $state $pp]
# Columns
- } {
+ } else {
lset col_state [expr {$i - 4}] [lindex $state $pp]
}
}
@@ -718,7 +741,7 @@ class MatrixKeyPad {
if {$i < 4} {
lset state $pp [lindex $row_state $i]
# Columns
- } {
+ } else {
lset state $pp [lindex $col_state [expr {$i - 4}]]
}
}
@@ -738,9 +761,6 @@ class MatrixKeyPad {
$canvas_widget itemconfigure $item -fill $color
}
}
-
- # Return new port states
- return $state
}
## Withdraw panel window from the screen
@@ -761,6 +781,7 @@ class MatrixKeyPad {
[$canvas_widget.usr_note get] \
[array get keys] \
$radio_buttons \
+ $keep_win_on_top \
] \
]
}
@@ -776,7 +797,7 @@ class MatrixKeyPad {
# Restore window geometry
if {[string length [lindex $state 2]]} {
- wm geometry $win [lindex $state 2]
+ wm geometry $win [regsub {^\=?\d+x\d+} [lindex $state 2] [join [wm minsize $win] {x}]]
}
# Load user note
@@ -787,6 +808,13 @@ class MatrixKeyPad {
array set keys [lindex $state 4]
set radio_buttons [lindex $state 5]
+ if {[lindex $state 6] != {}} {
+ set keep_win_on_top [lindex $state 6]
+ if {$keep_win_on_top} {
+ wm attributes $win -topmost 1 -alpha 0.8
+ }
+ }
+
# Restore state of ComboBoxes
for {set i 0} {$i < 8} {incr i} {
## PIN
@@ -826,7 +854,7 @@ class MatrixKeyPad {
# Fail
}]} then {
- puts "Unable to load config for $class_name"
+ puts "Unable to load configuration for $class_name"
return 0
# Success
@@ -850,7 +878,8 @@ class MatrixKeyPad {
## This method is called before configuration menu invocation
# @return void
public method config_menu_special {} {
- set ::MatrixKeyPad::menu_radio_buttons $radio_buttons
+ set ::${class_name}::menu_radio_buttons $radio_buttons
+ set ::${class_name}::menu_keep_win_on_top $keep_win_on_top
}
## This method is called after configuration menu has beed created
@@ -864,7 +893,7 @@ class MatrixKeyPad {
#
# Note: There is defined text tag "tag_bold" in the text widget
public method show_help_special {text_widget} {
- $text_widget insert insert [mc "This tool consists of 16 switches connected in matrix. Connections with the uC are made with ComboBoxes. Panel configuration can be saved to a file (with extension vhc). And can be loaded from that file later. Wire colors are identical to colors used in graph representing IO ports.\n\n"]
+ $text_widget insert insert [mc "This tool consists of 16 switches connected in matrix. Connections with the uC are made with ComboBoxes. Panel configuration can be saved to a file with extension vhc, and can be loaded from that file later. Wire colors are identical to colors used in graph representing IO ports.\n\n"]
$text_widget insert insert [mc "Keypad can be configured in two ways:"]
$text_widget tag add tag_bold {insert linestart} {insert lineend}
$text_widget insert insert [mc "\n "]
@@ -873,7 +902,7 @@ class MatrixKeyPad {
$text_widget insert insert [mc " To allow key combinations\n Menu -> Check \"Radio buttons\"\n "]
$text_widget insert insert [mc "2)"]
$text_widget tag add tag_bold {insert linestart} {insert lineend}
- $text_widget insert insert [mc " To do not allow key combinations\n Menu -> Uncheck \"Radio buttons\""]
+ $text_widget insert insert [mc " To not allow key combinations\n Menu -> Uncheck \"Radio buttons\""]
}
## This method is called before panel window closure
@@ -884,6 +913,11 @@ class MatrixKeyPad {
## Commit new on/off state
# @return void
public method on_off_special {} {
- new_state [$project pale_get_true_state]
+ set state [$project pale_get_true_state]
+ new_state state
}
}
+
+# >>> File inclusion guard
+}
+# <<< File inclusion guard
diff --git a/lib/pale/multiplexedleddisplay.tcl b/lib/pale/multiplexedleddisplay.tcl
index 78976ad..8fcf042 100755..100644
--- a/lib/pale/multiplexedleddisplay.tcl
+++ b/lib/pale/multiplexedleddisplay.tcl
@@ -2,7 +2,7 @@
# Part of MCU 8051 IDE ( http://mcu8051ide.sf.net )
############################################################################
-# Copyright (C) 2007-2009 by Martin Ošmera #
+# Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012 by Martin Ošmera #
# martin.osmera@gmail.com #
# #
# This program is free software; you can redistribute it and#or modify #
@@ -21,6 +21,11 @@
# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #
############################################################################
+# >>> File inclusion guard
+if { ! [ info exists _MULTIPLEXEDLEDDISPLAY_TCL ] } {
+set _MULTIPLEXEDLEDDISPLAY_TCL _
+# <<< File inclusion guard
+
# --------------------------------------------------------------------------
# DESCRIPTION
# Implements PALE VHW component "Multiplexed LED display"
@@ -35,11 +40,12 @@ class MultiplexedLedDisplay {
inherit VirtualHWComponent
# Font: Font to be used in the panel -- bold
- common cb_font [font create \
- -weight bold -size -10 \
- -family {helvetica} \
+ common cb_font [font create \
+ -weight bold \
+ -size [expr {int(-10 * $::font_size_factor)}] \
+ -family {helvetica} \
]
- common COMPONENT_NAME "Multiplexed LED display" ;# Name of this component
+ common COMPONENT_NAME "Multiplexed LED Display" ;# Name of this component
common CLASS_NAME "MultiplexedLedDisplay" ;# Name of this class
common COMPONENT_ICON {mleddisplay} ;# Icon for this panel (16x16)
@@ -55,16 +61,17 @@ class MultiplexedLedDisplay {
{#5555AA #0000FF #5555FF}
{#AA55AA #8800FF #CC55FF}
}
+ common DIMMED_COLOR {#BBBBBB}
# Configuration menu
common CONFMENU {
{cascade {Common electrode} 7 "diode" .ca false 1 {
{radiobutton "Common anode" {}
::MultiplexedLedDisplay::cfg_common_anode 1
- "common_electrode_chanded" 7 ""}
- {radiobutton "Common catode" {}
+ "common_electrode_changed" 7 ""}
+ {radiobutton "Common cathode" {}
::MultiplexedLedDisplay::cfg_common_anode 0
- "common_electrode_chanded" 7 ""}
+ "common_electrode_changed" 7 ""}
}}
{cascade {Fade out interval} 5 "player_time" .dim false 1 {
{radiobutton "0" {}
@@ -126,7 +133,7 @@ class MultiplexedLedDisplay {
}}
{separator}
{command {All fade out} {} 0 "dim_all" {ledgray}
- "Dim all leds"}
+ "Dim all LEDs"}
{command {Show help} {} 5 "show_help" {help}
"Show brief help"}
{separator}
@@ -134,10 +141,15 @@ class MultiplexedLedDisplay {
"Save configuration into a file"}
{command {Load configuration} {} 0 "load_from" {fileopen}
"Load configuration from a file"}
+ {separator}
+ {checkbutton "Window always on top" {} {::MultiplexedLedDisplay::menu_keep_win_on_top}
+ 1 0 0 {keep_win_on_top_changed}
+ ""}
}
private variable conf_dim_interval 50 ;# Int: Interval to dim LED's in instruction cycles
private variable conf_led_color {red} ;# Color: Selected color for display segments
+ private variable keep_win_on_top 0 ;# Bool: Toplevel window
private variable leds ;# Array of CanvasObject (polygon): leds(display_num,segment_num) --> LED polygon
## Array of CanvasObject (line):
@@ -147,7 +159,7 @@ class MultiplexedLedDisplay {
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 prev_state ;# List: Previous port states
- private variable common_anode 1 ;# Bool: 1 == common anode; 0 == common catode
+ private variable common_anode 1 ;# Bool: 1 == common anode; 0 == common cathode
private variable t_state ;# List: Transistor states
@@ -213,7 +225,7 @@ class MultiplexedLedDisplay {
# @return void
private method create_gui {} {
# Create panel window and canvas widget
- set win [toplevel .multiplexedleddisplay$count -class {Mult. LED Display} -bg {#EEEEEE}]
+ set win [toplevel .multiplexedleddisplay$count -class {Mult. LED Display} -bg ${::COMMON_BG_COLOR}]
set canvas_widget [canvas $win.canvas \
-bg white -width 0 -height 0 \
-highlightthickness 0 \
@@ -396,12 +408,12 @@ class MultiplexedLedDisplay {
# Create EntryBox for user note
$canvas_widget create text 40 210 \
- -text {Note} \
+ -text [mc "Note"] \
-font $cb_font \
-anchor e
- $canvas_widget create window 40 210 \
+ $canvas_widget create window 45 210 \
-window [ttk::entry $canvas_widget.usr_note \
- -validate all \
+ -validate key \
-validatecommand "$this set_modified" \
] \
-width 380 -anchor w
@@ -412,14 +424,25 @@ class MultiplexedLedDisplay {
pack $canvas_widget -fill both -expand 1
# Set window parameters
- wm geometry $win =425x225
+ wm minsize $win 430 225
wm iconphoto $win ::ICONS::16::$component_icon
- wm title $win "[mc $component_name] - [string trim $project {:}] - MCU 8051 IDE"
+ wm title $win "[mc $component_name] - [$project cget -projectName] - MCU 8051 IDE"
wm resizable $win 0 0
wm protocol $win WM_DELETE_WINDOW "$this close_window"
bindtags $win [list $win Toplevel all .]
}
+ ## 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 $MultiplexedLedDisplay::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
+ }
+ }
+
## LED dim interval changed (meaningfull for multiplexed mode)
# @return void
public method dim_interval_changed {} {
@@ -427,14 +450,15 @@ class MultiplexedLedDisplay {
set_modified
}
- ## LED's common electrode chanded
+ ## LED's common electrode changed
# @return void
- public method common_electrode_chanded {} {
+ public method common_electrode_changed {} {
set common_anode ${::MultiplexedLedDisplay::cfg_common_anode}
if {$drawing_on} {
dim_all
- new_state [$project pale_get_true_state] 1
+ set state [$project pale_get_true_state]
+ new_state state 1
}
set_modified
}
@@ -445,12 +469,13 @@ class MultiplexedLedDisplay {
set conf_led_color ${::MultiplexedLedDisplay::color}
if {$drawing_on} {
- new_state [$project pale_get_true_state] 1
+ set state [$project pale_get_true_state]
+ new_state state 1
}
set_modified
}
- ## Dim all LED's and reset their prevoius states
+ ## Dim all LED's and reset their previous states
# @return void
public method dim_all {} {
for {set i 0} {$i < 8} {incr i} {
@@ -476,7 +501,7 @@ class MultiplexedLedDisplay {
if {$connection_pin($i) != {-}} {
set connection_pin($i) [expr {7 - $connection_pin($i)}]
}
- } {
+ } else {
set connection_port(T$i) [$canvas_widget.cb_t_p$i get]
set connection_pin(T$i) [$canvas_widget.cb_t_b$i get]
if {$connection_pin(T$i) != {-}} {
@@ -486,7 +511,8 @@ class MultiplexedLedDisplay {
# Change state of the device
if {$drawing_on} {
- new_state [$project pale_get_true_state] 1
+ set state [$project pale_get_true_state]
+ new_state state 1
}
# Set flag modified
@@ -711,7 +737,7 @@ class MultiplexedLedDisplay {
private method which_port_pin {type i} {
if {$type == {S}} {
return [list $connection_port($i) $connection_pin($i)]
- } {
+ } else {
return [list $connection_port(T$i) $connection_pin(T$i)]
}
}
@@ -732,13 +758,13 @@ class MultiplexedLedDisplay {
# @return void
public method mcu_changed {} {
# Refresh lists of possible values in port selection ComboBoxes
- set avaliable_ports [concat - [$project pale_get_avaliable_ports]]
+ set available_ports [concat - [$project pale_get_available_ports]]
# For segments ...
for {set i 0} {$i < 8} {incr i} {
- $canvas_widget.cb_p$i configure -values $avaliable_ports
+ $canvas_widget.cb_p$i configure -values $available_ports
- if {[lsearch -ascii -exact $avaliable_ports $connection_port($i)] == -1} {
+ if {[lsearch -ascii -exact $available_ports $connection_port($i)] == -1} {
$canvas_widget.cb_p$i current 0
set connection_port($i) {-}
}
@@ -746,9 +772,9 @@ class MultiplexedLedDisplay {
# For transistors ...
for {set i 0} {$i < 4} {incr i} {
- $canvas_widget.cb_t_p$i configure -values $avaliable_ports
+ $canvas_widget.cb_t_p$i configure -values $available_ports
- if {[lsearch -ascii -exact $avaliable_ports $connection_port(T$i)] == -1} {
+ if {[lsearch -ascii -exact $available_ports $connection_port(T$i)] == -1} {
$canvas_widget.cb_t_p$i current 0
set connection_port(T$i) {-}
}
@@ -757,18 +783,20 @@ class MultiplexedLedDisplay {
## Accept new state of ports
# @parm List state - Port states ( 5 x {8 x bit} -- {bit0 bit1 bit2 ... bit7} )
- # @parm Bool preserve_prvious_state = 0 - Preserve previous state of component
+ # @parm Bool preserve_prvious_state=0 - Preserve previous state of component
# @return void
#
# Possible bit values:
# '|' - High frequency
# 'X' - Access to external memory
# '?' - No volatge
- # '-' - Undeterminable value (some noise)
+ # '-' - Indeterminable value (some noise)
# '=' - High forced to low
# '0' - Logical 0
# '1' - Logical 1
- public method new_state {state {preserve_prvious_state 0}} {
+ public method new_state {_state {preserve_prvious_state 0}} {
+ upvar $_state state
+
# Determinate index of LED color in list COLORS
set color_idx [lsearch -ascii -exact \
{red orange yellow green blue purple} \
@@ -784,7 +812,7 @@ class MultiplexedLedDisplay {
if {[lindex $pp 0] == {-} || [lindex $pp 1] == {-}} {
set t_state($i) {}
# Connected
- } {
+ } else {
set t_state($i) [lindex $state $pp]
}
@@ -793,7 +821,7 @@ class MultiplexedLedDisplay {
{0} { ;# Logical 0
if {$common_anode} {
set t_state($i) 2
- } {
+ } else {
set t_state($i) 0
}
set wire_color {#FF0000}
@@ -801,7 +829,7 @@ class MultiplexedLedDisplay {
{1} { ;# Logical 1
if {$common_anode} {
set t_state($i) 0
- } {
+ } else {
set t_state($i) 2
}
set wire_color {#00FF00}
@@ -809,7 +837,7 @@ class MultiplexedLedDisplay {
{=} { ;# High forced to low
if {$common_anode} {
set t_state($i) 2
- } {
+ } else {
set t_state($i) 0
}
set wire_color {#00FF00}
@@ -842,7 +870,7 @@ class MultiplexedLedDisplay {
# Not connected
if {[lindex $pp 0] == {-} || [lindex $pp 1] == {-}} {
for {set j 0} {$j < 4} {incr j} {
- $canvas_widget itemconfigure $leds($j,$i) -fill {#555555}
+ $canvas_widget itemconfigure $leds($j,$i) -fill $DIMMED_COLOR -outline {#FFFFFF}
}
foreach item $wires($i) {
$canvas_widget itemconfigure $item -fill {#000000}
@@ -896,14 +924,14 @@ class MultiplexedLedDisplay {
set segment_color {0}
}
}
- } {
+ } else {
set segment_color {0}
}
}
{1} { ;# Logical 1
if {$common_anode} {
set segment_color {0}
- } {
+ } else {
switch -- $t_state($j) {
{2} {
set segment_color {2}
@@ -966,8 +994,8 @@ class MultiplexedLedDisplay {
# Determinate segment color (true color, not just number)
if {!$segment_color} {
- set segment_color {#555555}
- } {
+ set segment_color $DIMMED_COLOR
+ } else {
incr segment_color -1
set segment_color [lindex $COLORS [list $color_idx $segment_color]]
}
@@ -998,6 +1026,7 @@ class MultiplexedLedDisplay {
$conf_led_color \
$conf_dim_interval \
$common_anode \
+ $keep_win_on_top \
] \
]
}
@@ -1013,7 +1042,7 @@ class MultiplexedLedDisplay {
# Restore window geometry
if {[string length [lindex $state 2]]} {
- wm geometry $win [lindex $state 2]
+ wm geometry $win [regsub {^\=?\d+x\d+} [lindex $state 2] [join [wm minsize $win] {x}]]
}
# Load user note
@@ -1028,6 +1057,13 @@ class MultiplexedLedDisplay {
set common_anode 1
}
+ if {[lindex $state 7] != {}} {
+ set keep_win_on_top [lindex $state 7]
+ if {$keep_win_on_top} {
+ wm attributes $win -topmost 1 -alpha 0.8
+ }
+ }
+
## Restore state of ComboBoxes
# For segments ...
for {set i 0} {$i < 8} {incr i} {
@@ -1083,12 +1119,13 @@ class MultiplexedLedDisplay {
}
# Accept new state of ports
- new_state [$project pale_get_true_state]
+ set state [$project pale_get_true_state]
+ new_state state
update
# Fail
}]} then {
- puts stderr "Unable to load config for $class_name"
+ puts stderr "Unable to load configuration for $class_name"
puts stderr $::errorInfo
return 0
@@ -1103,7 +1140,8 @@ class MultiplexedLedDisplay {
# @return void
public method reset {} {
dim_all
- new_state [$project pale_get_true_state]
+ set state [$project pale_get_true_state]
+ new_state state
}
@@ -1117,6 +1155,7 @@ class MultiplexedLedDisplay {
set ::${class_name}::dim_interval $conf_dim_interval
set ::${class_name}::color $conf_led_color
set ::${class_name}::cfg_common_anode $common_anode
+ set ::${class_name}::menu_keep_win_on_top $keep_win_on_top
}
## This method is called after configuration menu has beed created
@@ -1135,7 +1174,7 @@ class MultiplexedLedDisplay {
#
# Note: There is defined text tag "tag_bold" in the text widget
public method show_help_special {text_widget} {
- $text_widget insert insert [mc "Virtual multiplexed LED display with common anode (default) or catode. Each segment can be connected to any port pin of the simulated uC. Connections with the uC are made with ComboBoxes. Panel configuration can be saved to a file (with extension vhc). And can be loaded from that file later. LED fade out interval and LED colors are configurable\n\n"]
+ $text_widget insert insert [mc "Virtual Multiplexed LED Display with common anode (default) or cathode. Each segment can be connected to any port pin of the simulated uC. Connections with the uC are made with ComboBoxes. Panel configuration can be saved to a file with extension vhc, and can be loaded from that file later. LED fade out interval and LED colors are configurable.\n\n"]
set color_idx [lsearch -ascii -exact \
{red orange yellow green blue purple} \
@@ -1145,7 +1184,7 @@ class MultiplexedLedDisplay {
$text_widget insert insert [mc "LED states:"]
$text_widget tag add tag_bold {insert linestart} {insert lineend}
$text_widget insert insert [mc "\n "]
- $text_widget window create insert -pady 1 -create "frame $text_widget.f0 -bd 1 -width 14 -height 16 -bg #888888"
+ $text_widget window create insert -pady 1 -create "frame $text_widget.f0 -bd 1 -width 14 -height 16 -bg $DIMMED_COLOR"
$text_widget insert insert [mc " Off\n "]
$text_widget window create insert -pady 1 -create "frame $text_widget.f1 -bd 1 -width 14 -height 16 -bg [lindex $COLORS [list $color_idx 0]]"
$text_widget insert insert [mc " Fast blinking\n "]
@@ -1172,8 +1211,13 @@ class MultiplexedLedDisplay {
}
}
}
- } {
- new_state [$project pale_get_true_state] 1
+ } else {
+ set state [$project pale_get_true_state]
+ new_state state 1
}
}
}
+
+# >>> File inclusion guard
+}
+# <<< File inclusion guard
diff --git a/lib/pale/pale.tcl b/lib/pale/pale.tcl
index 3b4b61c..37a3fe1 100755..100644
--- a/lib/pale/pale.tcl
+++ b/lib/pale/pale.tcl
@@ -2,7 +2,7 @@
# Part of MCU 8051 IDE ( http://mcu8051ide.sf.net )
############################################################################
-# Copyright (C) 2007-2009 by Martin Ošmera #
+# Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012 by Martin Ošmera #
# martin.osmera@gmail.com #
# #
# This program is free software; you can redistribute it and#or modify #
@@ -21,22 +21,33 @@
# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #
############################################################################
+# >>> File inclusion guard
+if { ! [ info exists _PALE_TCL ] } {
+set _PALE_TCL _
+# <<< File inclusion guard
+
# --------------------------------------------------------------------------
# DESCRIPTION
# PALE (Peripheral Abstraction Layer Engine) - simulates virtual hardware
# --------------------------------------------------------------------------
-# Load base class for Virtual HW components
-source "${::LIB_DIRNAME}/pale/virtual_hw_component.tcl"
-
-# Load Virtual HW components
-source "${::LIB_DIRNAME}/pale/ledpanel.tcl"
-source "${::LIB_DIRNAME}/pale/leddisplay.tcl"
-source "${::LIB_DIRNAME}/pale/ledmatrix.tcl"
-source "${::LIB_DIRNAME}/pale/multiplexedleddisplay.tcl"
-source "${::LIB_DIRNAME}/pale/simplekeypad.tcl"
-source "${::LIB_DIRNAME}/pale/matrixkeypad.tcl"
+if {$::GUI_AVAILABLE} {
+ # Load base class for Virtual HW components
+ source "${::LIB_DIRNAME}/pale/virtual_hw_component.tcl"
+
+ # Load Virtual HW components
+ source "${::LIB_DIRNAME}/pale/ledpanel.tcl"
+ source "${::LIB_DIRNAME}/pale/leddisplay.tcl"
+ source "${::LIB_DIRNAME}/pale/ledmatrix.tcl"
+ source "${::LIB_DIRNAME}/pale/multiplexedleddisplay.tcl"
+ source "${::LIB_DIRNAME}/pale/simplekeypad.tcl"
+ source "${::LIB_DIRNAME}/pale/matrixkeypad.tcl"
+ source "${::LIB_DIRNAME}/pale/lcd_hd44780.tcl"
+ source "${::LIB_DIRNAME}/pale/ds1620.tcl"
+ source "${::LIB_DIRNAME}/pale/virtual_uart_term.tcl"
+ source "${::LIB_DIRNAME}/pale/file_interface.tcl"
+}
class Pale {
private variable scenario_file {} ;# String: Name of PALE scenario file
@@ -49,7 +60,7 @@ class Pale {
private variable portConfig ;# Array of Int: Index 0..4, defines port pin functions
private variable portConfig_mod 0 ;# Bool: $portConfig contain special configuration
- private variable instruction_cycles 0 ;# Int: Nummber of instruction cycles performed during this simulation cycle
+ private variable instruction_cycles 0 ;# Int: Number of instruction cycles performed during this simulation cycle
private variable last_output {} ;# List: 5x{8x{...}} Last port outputs
private variable last_input {} ;# List: 5x{8x{...}} Last port inputs
@@ -130,7 +141,7 @@ class Pale {
# Try to open the file
if {[catch {
- set file [open $scenario_file "w" 420]
+ set file [open $scenario_file "w" 0640]
}]} then {
puts stderr "Unable to save to file: \"$scenario_file\""
return 0
@@ -138,8 +149,7 @@ class Pale {
# Save data to the file
puts $file "# MCU 8051 IDE: Virtual HW configuration file"
- puts $file "# Date: [clock format [clock seconds] -format {%D}]"
- puts $file "# Project: [string trim $this {:}]\n"
+ puts $file "# Project: [$this cget -projectName]\n"
foreach dev [concat $output_devices $input_devices] {
puts $file [$dev get_config]
}
@@ -177,7 +187,7 @@ class Pale {
if {![string first $prj_path $scenario_file]} {
return [string range $scenario_file [string length $prj_path] end]
# Return absolute directory location
- } {
+ } else {
return $scenario_file
}
}
@@ -210,7 +220,7 @@ class Pale {
![file exists $filename] ||
![file isfile $filename] ||
(!$::MICROSOFT_WINDOWS && ![file readable $filename])
- } {
+ } then {
return 0
}
@@ -259,7 +269,7 @@ class Pale {
$obj set_config $conf
# Error detected
}]} then {
- puts stderr "Unable to create PALE object: \"$obj\", maybe you are using old version of MCU 8051 IDE\n"
+ puts stderr "Unable to create PALE object: \"$obj\", maybe you are using an old version of MCU 8051 IDE.\n"
puts stderr $::errorInfo
catch {
@@ -387,7 +397,7 @@ class Pale {
{X} { ;# Access to external memory
append result [expr {rand() < 0.5}]
}
- {-} { ;# Undeterminable value (some noise)
+ {-} { ;# Indeterminable value (some noise)
append result [expr {rand() < 0.5}]
}
{|} { ;# High frequency
@@ -406,21 +416,18 @@ class Pale {
}
## Read Real Port Pin Voltage - 1 bit value (0 or 1)
- # @parm List - {port_number bit_number}
- # @parm Int = 0 - Position in history (positive number)
+ # @parm List pn_bn - {port_number bit_number}
+ # @parm Int position=0 - Position in history (positive number)
# @return Bool - Boolean value
- public method pale_RRPPV args {
+ public method pale_RRPPV {pn_bn {position 0}} {
if {!$is_enabled} {return 1}
# Parse input arguments
- set port [lindex $args {0 0}]
- set bit [lindex $args {0 1}]
- set position [lindex $args 1]
+ set port [lindex $pn_bn 0]
+ set bit [lindex $pn_bn 1]
# Adjust arguments
- if {![string length $position]} {
- set position 0
- } elseif {$position < 0} {
+ if {$position < 0} {
set position [expr {[llength $portState] + $position}]
}
set bit [expr {7 - $bit}]
@@ -453,30 +460,20 @@ class Pale {
}
## Write to port with bypassed latch (takes effect on next simulation cycle)
- # @parm Int - Port number
- # @parm List - New value -- list of 8 values {bit0 bit1 bit2 ... bit7}
+ # @parm Int port - Port number
+ # @parm List value - New value -- list of 8 values {bit0 bit1 bit2 ... bit7}
# '0' - Logical 0
# '1' - Logical 1
# '|' - High frequency pulse
# 'X' - Access to external memory
# '?' - No volatge
- # '-' - Undeterminable value (some noise)
+ # '-' - Indeterminable value (some noise)
# '=' - High forced to low
- # @parm Int = 0 - Position in history (zero or negative number)
+ # @parm Int position=0 - Position in history (zero or negative number)
# @return void
- public method pale_WPBL args {
+ public method pale_WPBL {port value {position 0}} {
if {!$is_enabled} {return}
- # Parse input arguments
- set port [lindex $args 0]
- set value [lindex $args 1]
- set position [lindex $args 2]
-
- # Adjust arguments
- if {![string length $position]} {
- set position 0
- }
-
# Set value
for {set bit 0} {$bit < 8} {incr bit} {
lappend special_func [list $port $bit $value $position]
@@ -484,30 +481,24 @@ class Pale {
}
## Write to port bit with bypassed latch
- # @parm List - {port_number bit_number}
- # @parm Char - New value
+ # @parm List pn_bn - {port_number bit_number}
+ # @parm Char value - New value
# '0' - Logical 0
# '1' - Logical 1
# '|' - High frequency pulse
# 'X' - Access to external memory
# '?' - No volatge
- # '-' - Undeterminable value (some noise)
+ # '-' - Indeterminable value (some noise)
# '=' - High forced to low
- # @parm Int = 0 - Position in history (zero or negative number)
+ # @parm Int position=0 - Position in history (zero or negative number)
# @return void
- public method pale_WPBBL args {
+ public method pale_WPBBL {pn_bn value {position 0}} {
if {!$is_enabled} {return}
# Parse input arguments
- set port [lindex $args {0 0}]
- set bit [lindex $args {0 1}]
- set value [lindex $args 1]
- set position [lindex $args 2]
+ set port [lindex $pn_bn 0]
+ set bit [lindex $pn_bn 1]
- # Adjust arguments
- if {![string length $position]} {
- set position 0
- }
set bit [expr {7 - $bit}]
# Set value
@@ -583,7 +574,7 @@ class Pale {
for {set i -1; set j 0} {$j < $instruction_cycles} {incr i; incr j} {
if {$i < 0} {
set previous_output_state $last_output
- } {
+ } else {
set previous_output_state [lindex $portOutput $i]
}
foreach prev $previous_output_state new [lindex $portOutput $j] port {0 1 2 3 4} {
@@ -638,16 +629,16 @@ class Pale {
set last_output [lindex $portOutput end]
set last_input [lindex $portInput end]
set last_state [lindex $portState end]
- set portLatch [list]
- set portOutput [list]
- set portInput [list]
+ set portLatch [list]
+ set portOutput [list]
+ set portInput [list]
set special_func [list]
# Inform output devices about the new port outputs
foreach dev $output_devices {
- $dev new_state $last_state
- update
+ $dev new_state last_state
}
+ update
}
## Determinate resulting value when two values clash on one wire
@@ -678,7 +669,7 @@ class Pale {
{?} { ;# No volatge
return $in1
}
- {-} { ;# Undeterminable value (some noise)
+ {-} { ;# Indeterminable value (some noise)
return {-}
}
{=} { ;# High forced to low
@@ -690,7 +681,7 @@ class Pale {
{1} { ;# Logical 1
if {$in1 == {?}} {
return 1
- } {
+ } else {
return $in1
}
}
@@ -712,8 +703,10 @@ class Pale {
# Call all input devices
foreach dev $input_devices {
# Call device to change the current state
- set input [$dev new_state $input]
- update
+ $dev new_state input
+
+ # Clear list of devices already confronted with the new state
+ set already_evaluated [list]
# Inform all other devices interconnected with this one
for {set p 0} {$p < 5} {incr p} {
@@ -729,17 +722,22 @@ class Pale {
# Call all affected devices
foreach affected_dev $engaged_pins($p,$b) {
+ # Do not confront the device with itself
if {$affected_dev == $dev} {
continue
}
- set input [$affected_dev new_state $input]
- update
+ # Do not confront the device with another device more than once per ``foreach dev ...'' iteration
+ if {[lsearch -ascii -exact $already_evaluated $affected_dev] != -1} {
+ continue
+ }
+
+ lappend already_evaluated $affected_dev
+ $affected_dev new_state input
}
# Again call the current device
- set input [$dev new_state $input]
- update
+ $dev new_state input
}
}
}
@@ -762,9 +760,9 @@ class Pale {
# Inform output devices about the new port outputs
foreach dev $output_devices {
- $dev new_state $last_state
- update
+ $dev new_state last_state
}
+ update
}
## Call input devices to evaluate input values
@@ -776,8 +774,10 @@ class Pale {
# Call all input devices
foreach dev $input_devices {
# Call device to change the current state
- set input [$dev new_state $input]
- update
+ $dev new_state input
+
+ # Clear list of devices already confronted with the new state
+ set already_evaluated [list]
# Inform all other devices interconnected with this one
for {set p 0} {$p < 5} {incr p} {
@@ -793,17 +793,21 @@ class Pale {
# Call all affected devices
foreach affected_dev $engaged_pins($p,$b) {
+ # Do not confront the device with itself
if {$affected_dev == $dev} {
continue
}
- set input [$affected_dev new_state $input]
- update
+ # Do not confront the device with another device more than once per ``foreach dev ...'' iteration
+ if {[lsearch -ascii -exact $already_evaluated $affected_dev] != -1} {
+ continue
+ }
+
+ $affected_dev new_state input
}
# Again call the current device
- set input [$dev new_state $input]
- update
+ $dev new_state input
}
}
}
@@ -890,6 +894,9 @@ class Pale {
pale_disengage_pin_by_input_device $p $b $object
}
}
+
+ # Make this change in the environment visible right away
+ pale_reevaluate_IO
}
## Inform PALE system about that than some input device is
@@ -907,6 +914,9 @@ class Pale {
# * PALE VHW component must extend class "VirtualHWComponent"
# * Input devices CAN affect port inputs, output cannot
public method pale_engage_pin_by_input_device {port pin dev} {
+ if {[lsearch -ascii -exact $engaged_pins($port,$pin) $dev] != -1} {
+ return
+ }
lappend engaged_pins($port,$pin) $dev
}
@@ -928,6 +938,7 @@ class Pale {
# * Input devices CAN affect port inputs, output cannot
public method pale_disengage_pin_by_input_device {port pin dev} {
set idx [lsearch -ascii -exact $engaged_pins($port,$pin) $dev]
+
if {$idx == -1} {
return
}
@@ -955,7 +966,7 @@ class Pale {
# '|' - High frequency pulse
# 'X' - Access to external memory
# '?' - No volatge
- # '-' - Undeterminable value (some noise)
+ # '-' - Indeterminable value (some noise)
# '=' - High forced to low
public method pale_get_output_state {} {
return $last_output
@@ -969,15 +980,15 @@ class Pale {
# '|' - High frequency pulse
# 'X' - Access to external memory
# '?' - No volatge
- # '-' - Undeterminable value (some noise)
+ # '-' - Indeterminable value (some noise)
# '=' - High forced to low
public method pale_get_true_state {} {
return $last_state
}
- ## Get list of avaliable port number on the current MCU
+ ## Get list of available port number on the current MCU
# @return List of Int - e.g. {1 3}
- public method pale_get_avaliable_ports {} {
+ public method pale_get_available_ports {} {
return [lindex [$this get_ports_info] 1]
}
@@ -988,4 +999,14 @@ class Pale {
$dev mcu_changed
}
}
+
+ ## Get number of instruction cycles performed during this simulation cycle
+ # @return Int - Number of instruction cycles
+ public method pale_get_number_of_instruction_cycles {} {
+ return $instruction_cycles
+ }
+}
+
+# >>> File inclusion guard
}
+# <<< File inclusion guard
diff --git a/lib/pale/simplekeypad.tcl b/lib/pale/simplekeypad.tcl
index d7baa83..0889106 100755..100644
--- a/lib/pale/simplekeypad.tcl
+++ b/lib/pale/simplekeypad.tcl
@@ -2,7 +2,7 @@
# Part of MCU 8051 IDE ( http://mcu8051ide.sf.net )
############################################################################
-# Copyright (C) 2007-2009 by Martin Ošmera #
+# Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012 by Martin Ošmera #
# martin.osmera@gmail.com #
# #
# This program is free software; you can redistribute it and#or modify #
@@ -21,6 +21,11 @@
# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #
############################################################################
+# >>> File inclusion guard
+if { ! [ info exists _SIMPLEKEYPAD_TCL ] } {
+set _SIMPLEKEYPAD_TCL _
+# <<< File inclusion guard
+
# --------------------------------------------------------------------------
# DESCRIPTION
@@ -36,15 +41,15 @@ class SimpleKeyPad {
inherit VirtualHWComponent
# Font: Font to be used in the panel -- bold
- common cb_font [font create \
- -weight bold \
- -size -10 \
- -family {helvetica} \
+ common cb_font [font create \
+ -weight bold \
+ -size [expr {int(-10 * $::font_size_factor)}] \
+ -family {helvetica} \
]
# Font: Font to be used in the panel -- normal weight
- common cb_font_n [font create \
- -size -10 \
- -family {helvetica} \
+ common cb_font_n [font create \
+ -size [expr {int(-10 * $::font_size_factor)}] \
+ -family {helvetica} \
]
common COMPONENT_NAME "Simple Keypad" ;# Name of this component
@@ -63,9 +68,14 @@ class SimpleKeyPad {
"Save configuration into a file"}
{command {Load configuration} {} 0 "load_from" {fileopen}
"Load configuration from a file"}
+ {separator}
+ {checkbutton "Window always on top" {} {::SimpleKeyPad::menu_keep_win_on_top}
+ 1 0 0 {keep_win_on_top_changed}
+ ""}
}
- private variable radio_buttons ;# Bool: Disallow key combinations
+ private variable radio_buttons 0 ;# Bool: Disallow key combinations
+ private variable keep_win_on_top 0 ;# Bool: Toplevel window
private variable keys ;# Array of Bool: Indicates key press
private variable wire ;# Array of CanvasObject (line): Wires connected to MCU pins
private variable wire_o ;# Array of CanvasObject (oval): Wires connected to MCU pins
@@ -74,7 +84,7 @@ class SimpleKeyPad {
private variable text ;# Array of CanvasObject (text): Key descriptions
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 enaged ;# Array of Bool: enaged(port_num,bit_num) --> Is connected to this device ?
+ private variable enaged ;# Array of Bool: enaged(port_num,bit_num) --> Is connected to this device?
# ------------------------------------------------------------------
@@ -181,12 +191,12 @@ class SimpleKeyPad {
# @return void
private method create_gui {} {
# Create panel window and canvas widget
- set win [toplevel .simplekeypad$count -class $component_name -bg {#EEEEEE}]
+ set win [toplevel .simplekeypad$count -class $component_name -bg ${::COMMON_BG_COLOR}]
set canvas_widget [canvas $win.canvas -bg white -width 0 -height 0]
set cb_p_y 65
set cb_b_y 85
- set usr_n_y 105
+ set usr_n_y 110
set x 50
# Create labels
@@ -198,13 +208,13 @@ class SimpleKeyPad {
-text [mc "BIT"] \
-font $cb_font \
-anchor w
- $canvas_widget create text 5 $usr_n_y \
+ $canvas_widget create text 32 $usr_n_y \
-text [mc "Note"] \
-font $cb_font \
- -anchor w
+ -anchor e
$canvas_widget create window 37 $usr_n_y \
-window [ttk::entry $canvas_widget.usr_note \
- -validate all \
+ -validate key \
-validatecommand "$this set_modified" \
] \
-width 220 -anchor w
@@ -251,7 +261,7 @@ class SimpleKeyPad {
-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"
- $canvas_widget create window 2 20 -window $start_stop_button -anchor sw
+ $canvas_widget create window 2 22 -window $start_stop_button -anchor sw
bindtags $start_stop_button [list $start_stop_button TButton all .]
# Create configuration menu button
@@ -261,16 +271,16 @@ class SimpleKeyPad {
-command "$this config_menu" \
]
setStatusTip -widget $conf_button -text [mc "Configure"]
- $canvas_widget create window 2 20 -window $conf_button -anchor nw
+ $canvas_widget create window 2 22 -window $conf_button -anchor nw
bindtags $conf_button [list $conf_button TButton all .]
# Pack canvas
pack $canvas_widget -fill both -expand 1
# Set window parameters
- wm geometry $win =260x120
+ wm minsize $win 265 125
wm iconphoto $win ::ICONS::16::$component_icon
- wm title $win "[mc $component_name] - [string trim $project {:}] - MCU 8051 IDE"
+ wm title $win "[mc $component_name] - [$project cget -projectName] - MCU 8051 IDE"
wm resizable $win 0 0
wm protocol $win WM_DELETE_WINDOW "$this close_window"
bindtags $win [list $win Toplevel all .]
@@ -319,7 +329,7 @@ class SimpleKeyPad {
$canvas_widget itemconfigure $rect($i) -outline #333333 -width 2
# Key released
- } {
+ } else {
$canvas_widget itemconfigure $lever(0$i) -fill #000000
$canvas_widget itemconfigure $lever(1$i) -fill #FFFFFF
$canvas_widget itemconfigure $text($i) -font $cb_font_n
@@ -333,7 +343,7 @@ class SimpleKeyPad {
public method key_leave {i} {
if {$keys($i)} {
set color {#333333}
- } {
+ } else {
set color {#CCCCCC}
}
$canvas_widget itemconfigure $rect($i) -outline $color
@@ -436,6 +446,17 @@ class SimpleKeyPad {
set radio_buttons $::SimpleKeyPad::menu_radio_buttons
}
+ ## 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 $SimpleKeyPad::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
+ }
+ }
+
# ------------------------------------------------------------------
# VIRTUAL HW COMMON INTERFACE -- CALLED FROM PALE ENGINE
# ------------------------------------------------------------------
@@ -444,12 +465,12 @@ class SimpleKeyPad {
# @return void
public method mcu_changed {} {
# Refresh lists of possible values in port selection ComboBoxes
- set avaliable_ports [concat - [$project pale_get_avaliable_ports]]
+ set available_ports [concat - [$project pale_get_available_ports]]
for {set i 0} {$i < 8} {incr i} {
- $canvas_widget.cb_p$i configure -values $avaliable_ports
+ $canvas_widget.cb_p$i configure -values $available_ports
- if {[lsearch -ascii -exact $avaliable_ports $connection_port($i)] == -1} {
+ if {[lsearch -ascii -exact $available_ports $connection_port($i)] == -1} {
$canvas_widget.cb_p$i current 0
set connection_port($i) {-}
}
@@ -465,11 +486,13 @@ class SimpleKeyPad {
# '|' - High frequency
# 'X' - Access to external memory
# '?' - No volatge
- # '-' - Undeterminable value (some noise)
+ # '-' - Indeterminable value (some noise)
# '=' - High forced to low
# '0' - Logical 0
# '1' - Logical 1
- public method new_state {state} {
+ public method new_state {_state} {
+ upvar $_state state
+
# Iterate over keys
for {set i 0} {$i < 8} {incr i} {
# Determinate index in the list of port states
@@ -479,7 +502,7 @@ class SimpleKeyPad {
if {[lindex $pp 0] == {-} || [lindex $pp 1] == {-} || !$drawing_on} {
if {$keys($i)} {
set wire_color {#00DD00}
- } {
+ } else {
set wire_color {#000000}
}
@@ -522,9 +545,6 @@ class SimpleKeyPad {
$canvas_widget itemconfigure $lever($keys(${i})${i}) -fill $wire_color
$canvas_widget itemconfigure $wire_o($i) -outline $wire_color
}
-
- # Return new port states
- return $state
}
## Withdraw panel window from the screen
@@ -545,6 +565,7 @@ class SimpleKeyPad {
[$canvas_widget.usr_note get] \
[array get keys] \
$radio_buttons \
+ $keep_win_on_top \
] \
]
}
@@ -560,7 +581,7 @@ class SimpleKeyPad {
# Restore window geometry
if {[string length [lindex $state 2]]} {
- wm geometry $win [lindex $state 2]
+ wm geometry $win [regsub {^\=?\d+x\d+} [lindex $state 2] [join [wm minsize $win] {x}]]
}
# Load user note
@@ -570,6 +591,12 @@ class SimpleKeyPad {
# Restore keys configuration and states
array set keys [lindex $state 4]
set radio_buttons [lindex $state 5]
+ if {[lindex $state 6] != {}} {
+ set keep_win_on_top [lindex $state 6]
+ if {$keep_win_on_top} {
+ wm attributes $win -topmost 1
+ }
+ }
# Restore state of ComboBoxes
for {set i 0} {$i < 8} {incr i} {
@@ -608,7 +635,7 @@ class SimpleKeyPad {
# Fail
}]} then {
- puts "Unable to load config for $class_name"
+ puts "Unable to load configuration for $class_name"
return 0
# Success
@@ -621,7 +648,8 @@ class SimpleKeyPad {
## Simulated MCU has been reseted
# @return void
public method reset {} {
- new_state [$project pale_get_true_state]
+ set state [$project pale_get_true_state]
+ new_state state
}
# ------------------------------------------------------------------
@@ -631,7 +659,8 @@ class SimpleKeyPad {
## This method is called before configuration menu invocation
# @return void
public method config_menu_special {} {
- set ::SimpleKeyPad::menu_radio_buttons $radio_buttons
+ set ::${class_name}::menu_radio_buttons $radio_buttons
+ set ::${class_name}::menu_keep_win_on_top $keep_win_on_top
}
## This method is called after configuration menu has beed created
@@ -645,7 +674,7 @@ class SimpleKeyPad {
#
# Note: There is defined text tag "tag_bold" in the text widget
public method show_help_special {text_widget} {
- $text_widget insert insert [mc "This tool consists of 8 switches. Each of them can connect any port pin of the simulated uC to the ground. Connections with the uC are made with ComboBoxes on the bottom of the panel. Panel configuration can be saved to a file (with extension vhc). And can be loaded from that file later. Wire colors are identical to colors used in graph representing IO ports.\n\n"]
+ $text_widget insert insert [mc "This tool consists of 8 switches. Each of them can connect any port pin of the simulated uC to ground. Connections with the uC are made with ComboBoxes on the bottom of the panel. Panel configuration can be saved to a file with extension vhc, and can be loaded from that file later. Wire colors are identical to colors used in graph representing IO ports.\n\n"]
$text_widget insert insert [mc "Keypad can be configured in two ways:"]
$text_widget tag add tag_bold {insert linestart} {insert lineend}
$text_widget insert insert [mc "\n "]
@@ -654,7 +683,7 @@ class SimpleKeyPad {
$text_widget insert insert [mc " To allow key combinations\n Menu -> Check \"Radio buttons\"\n "]
$text_widget insert insert [mc "2)"]
$text_widget tag add tag_bold {insert linestart} {insert lineend}
- $text_widget insert insert [mc " To do not allow key combinations\n Menu -> Uncheck \"Radio buttons\""]
+ $text_widget insert insert [mc " To not allow key combinations\n Menu -> Uncheck \"Radio buttons\""]
}
## This method is called before panel window closure
@@ -665,6 +694,11 @@ class SimpleKeyPad {
## Commit new on/off state
# @return void
public method on_off_special {} {
- new_state [$project pale_get_true_state]
+ set state [$project pale_get_true_state]
+ new_state state
}
}
+
+# >>> File inclusion guard
+}
+# <<< File inclusion guard
diff --git a/lib/pale/virtual_hw_component.tcl b/lib/pale/virtual_hw_component.tcl
index e0fb00b..c7a637d 100755..100644
--- a/lib/pale/virtual_hw_component.tcl
+++ b/lib/pale/virtual_hw_component.tcl
@@ -2,7 +2,7 @@
# Part of MCU 8051 IDE ( http://mcu8051ide.sf.net )
############################################################################
-# Copyright (C) 2007-2009 by Martin Ošmera #
+# Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012 by Martin Ošmera #
# martin.osmera@gmail.com #
# #
# This program is free software; you can redistribute it and#or modify #
@@ -21,6 +21,11 @@
# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #
############################################################################
+# >>> File inclusion guard
+if { ! [ info exists _VIRTUAL_HW_COMPONENT_TCL ] } {
+set _VIRTUAL_HW_COMPONENT_TCL _
+# <<< File inclusion guard
+
# --------------------------------------------------------------------------
# DESCRIPTION
@@ -32,13 +37,15 @@ class VirtualHWComponent {
common hlp_dlg_count 0 ;# Int: Counter of help dialog instances
# Create fonts used in the text
- common hlp_normal_font [font create \
- -family {helvetica} \
- -size -14 -weight {normal} \
+ common hlp_normal_font [font create \
+ -family {helvetica} \
+ -size [expr {int(-14 * $::font_size_factor)}] \
+ -weight {normal} \
]
- common hlp_bold_font [font create \
- -family {helvetica} \
- -size -14 -weight {bold} \
+ common hlp_bold_font [font create \
+ -family {helvetica} \
+ -size [expr {int(-14 * $::font_size_factor)}] \
+ -weight {bold} \
]
protected variable config_menu_created 0 ;# Bool: COnfiguration menu created
@@ -47,9 +54,9 @@ class VirtualHWComponent {
protected variable modified 0 ;# Bool: Flag modified
protected variable project ;# Object: Project object
- protected variable win ;# Widget: Dialog window
+ protected variable win {} ;# Widget: Dialog window
protected variable drawing_on 1 ;# Bool: Flag panel enabled
- protected variable canvas_widget ;# Widget: Canvas widget - crucial part of the window
+ protected variable canvas_widget {} ;# Widget: Canvas widget - crucial part of the window
protected variable start_stop_button ;# Widget: Button "ON/OFF"
protected variable conf_button ;# Widget: Button to invoke configuration menu
@@ -78,7 +85,7 @@ class VirtualHWComponent {
-icon question \
-parent $win \
-title [mc "Component modified"] \
- -message [mc "Do you want to save configuration of this panel before closing ?"] \
+ -message [mc "Do you want to save the configuration of this panel before closing?"] \
] {
{yes} {
save_as
@@ -105,6 +112,10 @@ class VirtualHWComponent {
set modified 1
$project pale_set_modified
+ if {[winfo exists $win]} {
+ wm title $win "\[modified\] [regsub {^\[modified\] } [wm title $win] {}]"
+ }
+
return 1
}
@@ -112,6 +123,10 @@ class VirtualHWComponent {
# @return void
public method clear_modified {} {
set modified 0
+
+ if {[winfo exists $win]} {
+ wm title $win [regsub {^\[modified\] } [wm title $win] {}]
+ }
}
## Invoke configuration menu
@@ -136,9 +151,9 @@ class VirtualHWComponent {
# @return void
protected method create_config_menu {} {
set config_menu_created 1
- set conf_menu $canvas_widget.conf_menu
- menuFactory [subst "\${${class_name}::CONFMENU}"] \
- $conf_menu 0 "$this " 0 {}
+ set conf_menu $win.conf_menu
+ menuFactory [subst -nocommands "\${${class_name}::CONFMENU}"] \
+ $conf_menu 0 "$this " 0 {} [$this info class]
$this create_config_menu_special
}
@@ -149,14 +164,14 @@ class VirtualHWComponent {
# Create file selection dialog
catch {delete object ::fsd}
KIFSD::FSD ::fsd \
- -title "[mc {Save configuration}] - [mc $component_name] - [string trim $project {:}] - MCU 8051 IDE" \
+ -title "[mc {Save configuration}] - [mc $component_name] - [$project cget -projectName] - MCU 8051 IDE" \
-master $win \
-directory [$project cget -projectPath] \
-initialfile [file tail $current_filename] \
- -defaultmask 0 -multiple 0 -filetypes {
- {{VH component} {*.vhc} }
- {{All files} {*} }
- }
+ -defaultmask 0 -multiple 0 -filetypes [list \
+ [list [mc "VH component"] {*.vhc} ] \
+ [list [mc "All files"] {*} ] \
+ ]
# Open file after press of OK button
::fsd setokcmd "$this save_config_to_file \[::fsd get\]"
@@ -171,14 +186,14 @@ class VirtualHWComponent {
# Create file selection dialog
catch {delete object ::fsd}
KIFSD::FSD ::fsd \
- -title "[mc {Load configuration}] - [mc $component_name] - [string trim $project {:}] - MCU 8051 IDE" \
+ -title "[mc {Load configuration}] - [mc $component_name] - [$project cget -projectName] - MCU 8051 IDE" \
-master $win \
-directory [$project cget -projectPath] \
-initialfile [file tail $current_filename] \
- -defaultmask 0 -multiple 0 -filetypes {
- {{VH component} {*.vhc} }
- {{All files} {*} }
- }
+ -defaultmask 0 -multiple 0 -filetypes [list \
+ [list [mc "VH component"] {*.vhc} ] \
+ [list [mc "All files"] {*} ] \
+ ]
# Open file after press of OK button
::fsd setokcmd "$this load_config_from_file \[::fsd get\]"
@@ -208,9 +223,9 @@ class VirtualHWComponent {
-icon question \
-parent $win \
-title [mc "Overwrite file"] \
- -message [mc "A file with name '%s' already exists. Do you want to overwrite it ?" [file tail $filename]]
+ -message [mc "A file with name '%s' already exists. Do you want to overwrite it?" [file tail $filename]]
] != {yes}
- } {
+ } then {
return 0
}
}
@@ -224,7 +239,7 @@ class VirtualHWComponent {
# Try to open the file
if {[catch {
- set file [open $filename {w} 420]
+ set file [open $filename {w} 0640]
}]} then {
tk_messageBox \
-type ok \
@@ -241,15 +256,14 @@ class VirtualHWComponent {
# Save configuration to the file
puts $file "# MCU 8051 IDE: Virtual HW component configuration file"
- puts $file "# Date: [clock format [clock seconds] -format {%D}]"
- puts $file "# Project: [string trim $project {:}]"
+ puts $file "# Project: [$project cget -projectName]"
puts $file "# Component: $component_name\n"
puts $file $config
# Finalize
set current_filename $filename
close $file
- set modified 0
+ clear_modified
return 1
}
@@ -310,18 +324,19 @@ class VirtualHWComponent {
# Finalize ...
set current_filename $filename
close $file
- set modified 0
+ clear_modified
return 1
}
## Show help dialog
+ # @parm Bool leave_empty=0 - Do not write implicitly anything into the help window
# @return void
- public method show_help {} {
+ public method show_help {{leave_empty 0}} {
# Increment counter of help dialog instances
incr hlp_dlg_count
# Create toplevel window
- set dialog [toplevel .help_dialog_${class_name}_${hlp_dlg_count} -class {Help} -bg {#EEEEEE}]
+ set dialog [toplevel .help_dialog_${class_name}_${hlp_dlg_count} -class {Help} -bg ${::COMMON_BG_COLOR}]
## Create top frame (header and icon)
set top_frame [frame $dialog.top_frame]
@@ -332,7 +347,7 @@ class VirtualHWComponent {
# Header text
pack [label $top_frame.header_label \
-anchor w -justify left \
- -text $component_name \
+ -text [namespace eval ::$class_name "mc {$component_name}"] \
] -side left
pack $top_frame -anchor n -pady 2
@@ -351,20 +366,15 @@ class VirtualHWComponent {
-command "$text_widget yview" \
] -side right -fill y
# Finalize ...
- pack $main_frame -fill both -expand 1
+ pack $main_frame -fill both -expand 1 -padx 2
- ## Create bottom frame (button close)
- # Separator
- pack [ttk::separator $dialog.sep \
- -orient horizontal \
- ] -fill x
# Button "Close"
pack [ttk::button $dialog.close_button \
-text [mc "Close"] \
-compound left \
-image ::ICONS::16::button_cancel \
-command "destroy $dialog" \
- ] -ipady 0
+ ] -ipady 0 -pady 2
# Create text tags in the text widget
@@ -373,30 +383,32 @@ class VirtualHWComponent {
# Fill in the text widget with the help message
$this show_help_special $text_widget
- ## Display section "Wire colors"
- $text_widget insert insert "\n\n"
- $text_widget insert insert [mc "Wire colors:"]
- $text_widget tag add tag_bold {insert linestart} {insert lineend}
- $text_widget insert insert "\n"
- # Create canvas widget
- set cw [canvas $text_widget.canvas\
- -bg {#FFFFFF} \
- -takefocus 0 \
- -cursor left_ptr \
- -bd 0 -relief flat \
- -width 170 -height 110 \
- ]
- bind $cw <Button-5> "$text_widget yview scroll +5 units; break"
- bind $cw <Button-4> "$text_widget yview scroll -5 units; break"
- # Fill in the canvas widget
- $project Graph_create_legend $cw 1
- # Show the canvas widget
- $text_widget window create insert -window $cw
+ if {!$leave_empty} {
+ ## Display section "Wire colors"
+ $text_widget insert insert "\n\n"
+ $text_widget insert insert [mc "Wire colors:"]
+ $text_widget tag add tag_bold {insert linestart} {insert lineend}
+ $text_widget insert insert "\n"
+ # Create canvas widget
+ set cw [canvas $text_widget.canvas\
+ -bg {#FFFFFF} \
+ -takefocus 0 \
+ -cursor left_ptr \
+ -bd 0 -relief flat \
+ -width 170 -height 110 \
+ ]
+ bind $cw <Button-5> "$text_widget yview scroll +5 units; break"
+ bind $cw <Button-4> "$text_widget yview scroll -5 units; break"
+ # Fill in the canvas widget
+ $project Graph_create_legend $cw 1
+ # Show the canvas widget
+ $text_widget window create insert -window $cw
+ }
# Finalize ...
$text_widget configure -state disabled
- wm minsize $dialog 300 300
- wm title $dialog $component_name
+ wm minsize $dialog [expr {int(300 * $::font_size_factor)}] [expr {int(300 * $::font_size_factor)}]
+ wm title $dialog [namespace eval ::$class_name "mc {$component_name}"]
wm iconphoto $dialog ::ICONS::16::help
focus -force $dialog.close_button
}
@@ -411,13 +423,17 @@ class VirtualHWComponent {
## Adjust apparence of "ON/OFF" button
# Turn ON
if {$state} {
- $start_stop_button configure -style GreenBg.TButton -text "ON"
+ $start_stop_button configure -style GreenBg.TButton -text [mc "ON"]
# Turn OFF
} else {
- $start_stop_button configure -style RedBg.TButton -text "OFF"
+ $start_stop_button configure -style RedBg.TButton -text [mc "OFF"]
}
# Call component specific procedure
$this on_off_special
}
}
+
+# >>> File inclusion guard
+}
+# <<< File inclusion guard
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