summaryrefslogtreecommitdiff
path: root/lib/pale/ds1620.tcl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/pale/ds1620.tcl')
-rw-r--r--lib/pale/ds1620.tcl1730
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