diff options
Diffstat (limited to 'lib/pale/ds1620.tcl')
-rw-r--r-- | lib/pale/ds1620.tcl | 1730 |
1 files changed, 1730 insertions, 0 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 |