diff options
Diffstat (limited to 'lib/simulator/sfrmap.tcl')
-rwxr-xr-x | lib/simulator/sfrmap.tcl | 523 |
1 files changed, 523 insertions, 0 deletions
diff --git a/lib/simulator/sfrmap.tcl b/lib/simulator/sfrmap.tcl new file mode 100755 index 0000000..d6d16d2 --- /dev/null +++ b/lib/simulator/sfrmap.tcl @@ -0,0 +1,523 @@ +#!/usr/bin/tclsh +# Part of MCU 8051 IDE ( http://mcu8051ide.sf.net ) + +############################################################################ +# Copyright (C) 2007-2009 by Martin Ošmera # +# martin.osmera@gmail.com # +# # +# This program is free software; you can redistribute it and#or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation; either version 2 of the License, or # +# (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with this program; if not, write to the # +# Free Software Foundation, Inc., # +# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # +############################################################################ + +# -------------------------------------------------------------------------- +# DESCRIPTION +# Implements window showing the map of avaliable special function register +# -------------------------------------------------------------------------- + +class SFRMap { + ## COMMON + common count 0 ;# Int: Counter of object instances + + ## PRIVATE + private variable dialog_opened 0 ;# Bool: Dialog window opened + private variable defined_sfr ;# List: Addresses of defined SFR in this dialog + private variable win ;# Widget: Dialog window + private variable enabled 0 ;# Bool: True if simulator is engaged + private variable validation_ena 0 ;# Bool: Entry boxes validation enabled + private variable main_frame ;# Widget: Frame containing registers + private variable det_name ;# Widget: Entry box on bottom bar (Register name) + private variable det_hex ;# Widget: Entry box on bottom bar (HEX) + private variable det_dec ;# Widget: Entry box on bottom bar (DEC) + private variable det_bin ;# Widget: Entry box on bottom bar (BIN) + private variable det_oct ;# Widget: Entry box on bottom bar (OCT) + private variable bottom_right_frame ;# Widget: Bottom right frame + private variable selected_entry -1 ;# Int: Address of selected entry box in the map + + constructor {} { + incr count + } + + destructor { + if {$dialog_opened} { + destroy $win + } + } + + ## Invoke dialog window + # @return void + public method sfrmap_invoke_dialog {} { + if {$dialog_opened} {return} + set dialog_opened 1 + + # Create dialog window + set enabled [$this is_frozen] + set win [toplevel .sfr_map$count -bg {#FFFFFF} -class {SFR map} -bg {#EEEEEE}] + + # Create other widgets + create_win_gui + + # Configure the window + wm iconphoto $win ::ICONS::16::kcmmemory_S + wm title $win "Map of SFR area - [string trim $this {:}] - MCU 8051 IDE" + wm resizable $win 0 0 + wm protocol $win WM_DELETE_WINDOW "$this sfrmap_close_dialog" + bindtags $win [list $win Toplevel all .] + } + + ## Create window widgets + # @return void + private method create_win_gui {} { + set main_frame [frame $win.main_frame -bg {#888888}] + + ## Create headers for main frame + # Horizontal headers + set header_idx 0 + for {set i 0; set j 8; set col 1} {$i < 8} {incr i; incr j; incr col} { + set k [format %X $j] + grid [label $main_frame.header_$header_idx \ + -text "$i/$k" -bg {#FFFFFF} -fg {#555555} \ + ] -sticky nsew -column $col -row 0 + incr header_idx + grid [label $main_frame.header_$header_idx \ + -text "$i/$k" -bg {#FFFFFF} -fg {#555555} \ + ] -sticky nsew -column $col -row 17 -pady 1 + incr header_idx + } + # Vertical headers + set row 1 + foreach left {F8h F0h E8h E0h D8h D0h C8h C0h B8h B0h A8h A0h 98h 90h 88h 80h} \ + right {FFh F7h EFh E7h DFh D7h CFh C7h BFh B7h AFh A7h 9Fh 97h 8Fh 87h} \ + { + grid [label $main_frame.header_$header_idx \ + -text $left -bg {#FFFFFF} -fg {#555555} \ + ] -sticky nsew -column 0 -row $row + incr header_idx + grid [label $main_frame.header_$header_idx \ + -text $right -bg {#FFFFFF} -fg {#555555} \ + ] -sticky nsew -column 9 -row $row -padx 1 + incr row + incr header_idx + } + # Corners + foreach row {0 0 17 17} col {0 9 0 9} { + grid [frame $main_frame.header_$header_idx -bg {#FFFFFF}] \ + -row $row -column $col -sticky nsew + incr header_idx + } + + # Create separate frame for each cell + set addr 128 + for {set row 16} {$row > 0} {incr row -1} { + for {set col 1} {$col < 9} {incr col} { + set frame [frame $main_frame.cell_$addr -bg {#DDDDDD} -padx 1] + grid $frame \ + -row $row -column $col \ + -sticky nsew -padx [expr {$col % 2}] \ + -pady [expr {$row % 2}] + incr addr + } + } + + # Insure than all cells have the same width and heigh + for {set i 1} {$i < 9} {incr i} { + grid columnconfigure $main_frame $i -uniform sfr_col + } + for {set i 1} {$i < 17} {incr i} { + grid rowconfigure $main_frame $i -uniform sfr_row + } + + # Create matrix of SFR + set validation_ena 0 + set defined_sfr {} + foreach reg [$this simulator_get_sfrs] { + set addr [lindex $reg 0] + set name [lindex $reg 1] + set row 0 + + lappend defined_sfr $addr + + switch -- $name { + {SBUFR} { + set name_d {SBUF R} + } + {SBUFT} { + set name_d {SBUF T} + } + default { + set name_d $name + } + } + + set n_addr [expr {$addr & 0x0FF}] + if {$addr > 0xFF} { + set row 1 + } + + if {!($addr % 8)} { + set fg {#00DDDD} + } { + set fg {#0000DD} + } + $main_frame.cell_$n_addr configure -bg {#FFFFFF} + grid [label $main_frame.lbl_${addr} \ + -text $name_d -bg {#FFFFFF} -fg $fg \ + ] -in $main_frame.cell_$n_addr -sticky nsw -row $row -column 0 + set entry [ttk::entry $main_frame.ent_${addr} \ + -validatecommand "$this sfrmap_validate $addr h %P m" \ + -style Simulator_WhiteBg.TEntry \ + -validate all \ + -takefocus 0 \ + -width 3 \ + -font ${::Simulator_GUI::entry_font} \ + ] + grid $entry -in $main_frame.cell_$n_addr -padx 1 -pady 1 -row $row -column 1 -sticky nse + $entry insert end [$this getSfr $addr] + if {!$enabled} { + $entry configure -state disabled + } + if {$row} { + foreach widget [list \ + $main_frame.lbl_${addr} $main_frame.lbl_${n_addr} \ + $main_frame.ent_${addr} $main_frame.ent_${n_addr} \ + ] { + catch {$widget configure -highlightthickness 0} + catch {$widget configure -pady 0} + catch {$widget configure -bd 0} + + $widget configure -font [font create -family $::DEFAULT_FIXED_FONT -size -3] + grid configure $widget -pady 0 -ipady 0 + } + foreach widget [list $main_frame.lbl_${addr} $main_frame.lbl_${n_addr}] { + $widget configure -pady 0 + } + grid rowconfigure $main_frame.cell_$n_addr 0 -pad 0 + grid rowconfigure $main_frame.cell_$n_addr 1 -pad 0 + } + grid columnconfigure $main_frame.cell_$n_addr 0 -weight 1 + + bindtags $entry [list $entry TEntry $win all .] + bind $entry <Motion> {help_window_show %X %Y+30} + bind $entry <Leave> {help_window_hide} + bind $entry <FocusIn> "$this sfrmap_map_cell_focused $addr $name" + set hex_addr [format %X $addr] + if {[string length $hex_addr] == 1} { + set hex_addr "0$hex_addr" + } + bind $entry <Enter> "create_help_window $win \[$this getSfr $addr\] {$hex_addr SFR}" + } + set validation_ena 1 + + ## Create bottom frame + set bottom_frame [frame $win.bottom_frame -bg {#FFFFFF}] + # Create label "Reserved" + pack [label $bottom_frame.res_0 -text [mc "Reserved"] -bg {#FFFFFF}] -side left + pack [label $bottom_frame.res_1 -width 6 -bg {#CCCCCC} -bd 1 -relief raised] \ + -side left -pady 5 + pack [frame $bottom_frame.frame_foo -width 20] -side left + # Create label "Bit addressable" + pack [label $bottom_frame.bit_0 -text [mc "Bit addressable"] -bg {#FFFFFF}] -side left + pack [label $bottom_frame.bit_1 -width 6 -bg {#00DDDD} -bd 1 -relief raised] \ + -side left -pady 5 + # Create bottom right frame (additional entry boxes) + set bottom_right_frame [frame $bottom_frame.bottom_right -bg {#FFFFFF}] + set det_name [label $bottom_right_frame.name_lbl \ + -bg {#FFFFFF} -fg {#0000DD} \ + ] + set det_hex [ttk::entry $bottom_right_frame.hex_entry \ + -validatecommand "$this sfrmap_validate {} h %P p" \ + -style Simulator_WhiteBg.TEntry \ + -validate all \ + -width 3 \ + ] + set det_dec [ttk::entry $bottom_right_frame.dec_entry \ + -validatecommand "$this sfrmap_validate {} d %P p" \ + -style Simulator_WhiteBg.TEntry \ + -validate all \ + -width 3 \ + ] + set det_bin [ttk::entry $bottom_right_frame.bin_entry \ + -validatecommand "$this sfrmap_validate {} b %P p" \ + -style Simulator_WhiteBg.TEntry \ + -validate all \ + -width 8 \ + ] + set det_oct [ttk::entry $bottom_right_frame.oct_entry \ + -validatecommand "$this sfrmap_validate {} o %P p" \ + -style Simulator_WhiteBg.TEntry \ + -validate all \ + -width 3 \ + ] + foreach entry [list $det_hex $det_dec $det_bin $det_oct] { + bind $entry <FocusIn> "$this sfrmap_panel_entrybox_focused" + bindtags $entry [list $entry TEntry $win all .] + } + pack [ttk::separator $bottom_right_frame.sep -orient vertical] -side left -fill y -padx 3 + pack $det_name -side left + + pack [label $bottom_right_frame.lbl_hex \ + -text [mc "HEX:"] -pady 0 -bg {#FFFFFF} \ + -font ${::Simulator_GUI::smallfont} \ + -fg ${::Simulator_GUI::small_color} \ + ] -side left + pack $det_hex -side left + pack [label $bottom_right_frame.lbl_dec \ + -text [mc "DEC:"] -pady 0 -bg {#FFFFFF} \ + -font ${::Simulator_GUI::smallfont} \ + -fg ${::Simulator_GUI::small_color} \ + ] -side left + pack $det_dec -side left + pack [label $bottom_right_frame.lbl_bin \ + -text [mc "BIN:"] -pady 0 -bg {#FFFFFF} \ + -font ${::Simulator_GUI::smallfont} \ + -fg ${::Simulator_GUI::small_color} \ + ] -side left + pack $det_bin -side left + pack [label $bottom_right_frame.lbl_oct \ + -text [mc "OCT:"] -pady 0 -bg {#FFFFFF} \ + -font ${::Simulator_GUI::smallfont} \ + -fg ${::Simulator_GUI::small_color} \ + ] -side left + pack $det_oct -side left + + # Pack main and bottom frame + pack $main_frame -fill both + pack $bottom_frame -side bottom -fill x + } + + ## Close the dialog window + # @return void + public method sfrmap_close_dialog {} { + if {!$dialog_opened} {return} + set dialog_opened 0 + destroy $win + } + + ## Binding for event <FocusIn> on SFR entry box in the matrix + # @parm Int addr - Register address + # @parm String name - Register name + # @return void + public method sfrmap_map_cell_focused {addr name} { + set selected_entry $addr + + # Pack bottom right frame if it has not been packed yet + if {![winfo viewable $bottom_right_frame]} { + pack $bottom_right_frame -side right -padx 5 + } + + # Adjust entry boxes + sfrmap_validate $addr h [$main_frame.ent_${addr} get] m + $det_name configure -text "${name}:" + + # Restore normal color + foreach entry [list $main_frame.ent_${addr} $det_hex $det_oct $det_bin $det_dec] { + $entry configure -style Simulator_WhiteBg.TEntry + } + + # Disable these entry boxes + if {!$enabled} { + foreach entry [list $det_hex $det_oct $det_bin $det_dec] { + $entry configure -state disabled + } + } + } + + ## Binding for event <FocusIn> on SFR entry box in the bottom right panel + # Restore normal color for all enty boxes related to the selected SFR + # @return void + public method sfrmap_panel_entrybox_focused {} { + foreach entry [list $main_frame.ent_${selected_entry} $det_hex $det_oct $det_bin $det_dec] { + $entry configure -style Simulator_WhiteBg.TEntry + } + } + + ## Set value for certain register + # @parm Int addr - Register address + # @parm Int value - New register value + # @return void + public method sfrmap_map_sync {addr val} { + # Check if this call has some meaning + if {!$dialog_opened || !$validation_ena} {return} + if {[lsearch $defined_sfr $addr] == -1} {return} + set original_val [$main_frame.ent_${addr} get] + if {[expr "0x$original_val"] == $val} { + return + } + + # Adjust value + set val [format %X $val] + if {[string length $val] == 1} { + set val "0$val" + } + + # Set value + $main_frame.ent_${addr} delete 0 end + $main_frame.ent_${addr} insert 0 $val + + # Highlight entry boxes + $main_frame.ent_${addr} configure -style Simulator_WhiteBg_HG.TEntry + if {$selected_entry == $addr} { + foreach entry [list $det_hex $det_oct $det_bin $det_dec] { + $entry configure -style Simulator_WhiteBg_HG.TEntry + } + } + } + + ## Validate value in some entry box in the matrix + # @parm Int addr - Register address + # @parm Char type - h == HEX; o == OCT; b == BIN; d == DEC + # @parm String value - Content to validate + # @parm Char from - m == Matrix; p == Bottom panel + # @return Bool - Result + public method sfrmap_validate {addr type value from} { + # Prevent recursion + if {!$validation_ena} {return 1} + set validation_ena 0 + + if {$from == {p}} { + set addr $selected_entry + } + + # Validate the value + set value [string trimleft $value 0] + if {$value == {}} { + set value 0 + } + switch -- $type { + h { + if {[string length $value] > 2 || ![string is xdigit $value]} { + set validation_ena 1 + return 0 + } + set value [expr "0x$value"] + } + d { + if {[string length $value] > 3 || ![string is digit $value]} { + set validation_ena 1 + return 0 + } + } + b { + if {[string length $value] > 8 || ![regexp {^[01]*$} $value]} { + set validation_ena 1 + return 0 + } + set value [NumSystem::bin2dec $value] + } + o { + if {[string length $value] > 3 || ![regexp {^[0-7]*$} $value]} { + set validation_ena 1 + return 0 + } + set value [expr "0$value"] + } + } + if {$value > 255 || $value < 0} { + set validation_ena 1 + return 0 + } + + # Synchronize with engine and simulator control panel + $this setSfr $addr [format %X $value] + $this SimGUI_disable_sync + $this Simulator_GUI_sync S $addr + $this SimGUI_enable_sync + + # Synchronize the rest of entry boxes related to this SFR + if {$selected_entry == $addr} { + if {$type != {d}} { + $det_dec delete 0 end + $det_dec insert 0 $value + } + if {$type != {b}} { + set txt [NumSystem::dec2bin $value] + set len [string length $txt] + if {$len != 8} { + set txt "[string repeat 0 [expr {8 - $len}]]$txt" + } + $det_bin delete 0 end + $det_bin insert 0 $txt + } + if {$type != {o}} { + set txt [format %o $value] + set len [string length $txt] + if {$len != 3} { + set txt "[string repeat 0 [expr {3 - $len}]]$txt" + } + $det_oct delete 0 end + $det_oct insert 0 $txt + } + } + set txt [format %X $value] + if {[string length $txt] == 1} { + set txt "0$txt" + } + if {$from == {p}} { + $main_frame.ent_${addr} delete 0 end + $main_frame.ent_${addr} insert 0 $txt + if {$selected_entry == $addr && $type != {h}} { + $det_hex delete 0 end + $det_hex insert 0 $txt + } + } elseif {$selected_entry == $addr} { + $det_hex delete 0 end + $det_hex insert 0 $txt + } + + # Done + set validation_ena 1 + return 1 + } + + ## Commint new set special function registers + # @return void + public method sfrmap_commit_new_sfr_set {} { + if {!$dialog_opened} {return} + foreach wdg [pack slaves $win] { + destroy $wdg + } + set validation_ena 0 + set selected_entry -1 + create_win_gui + } + + ## Set state of this panel + # @parm Bool bool - 0 == Disable; 1 == Enable + # @return void + public method sfrmap_setEnabled {bool} { + if {!$dialog_opened} {return} + set enabled $bool + if {$bool} { + set bool {normal} + } { + set bool {disabled} + } + foreach entry [list $det_hex $det_oct $det_bin $det_dec] { + $entry configure -state $bool + } + foreach addr [$this simulator_get_avaliable_sfr] { + $main_frame.ent_${addr} configure -state $bool + } + } + + ## Clear highlight of changed cells + # @return void + public method sfrmap_clear_hg {} { + if {!$dialog_opened} {return} + + foreach addr $defined_sfr { + $main_frame.ent_${addr} configure -style Simulator_WhiteBg.TEntry + } + } +} |