Version 6 of multiple timers

Updated 2006-03-31 23:44:07

if {0}{Jorge Moreno - March 31 2006

I needed to track equipment down times in a central supervision station, we have a panel with some light indicators and this script showing independent elapsed times.

It also uses dll10 [L1 ] to call dll functions to control a National Instruments Digital Input/Ouput Card (called DIO).

So I integrate code from Task Timer,Based numbers,dllcaller and get this...

note that the dio card is disables by default through variable "dioPresent" }

 set dioPresent 0 
 set lstOfTesters {.icthp4\
                         .icthp5\
                         .icthp7\
                         .icthp10\
                         .icthp14\
                         .icthp18\
                         .icthp22\
                         .icthp24\
                         .icthp26\
                         .icthp27\
                         .icthp28\
                         .icthp29\
                         .icthp30\
                         .icthp32\
                         .icthp33\
                  .icthp35\
                  .icthp36\
                  .future\
                         } 

 ######################################################
 ##
 ## Always on top, no resize
 ##
 ######################################################
 #wm attributes . -topmost 1
 #wm resizable . 0 0
 console show
 set ctr 0  

 if {$dioPresent} {
 load dll10
 #status = DIG_Prt_Config (deviceNumber, port, mode, dir)
 set i [::dll::call nidaq32.dll DIG_Prt_Config i {i 1} {i 0} {i 0} {i 1}]
 set i [::dll::call nidaq32.dll DIG_Prt_Config i {i 1} {i 1} {i 0} {i 1}]
 set i [::dll::call nidaq32.dll DIG_Prt_Config i {i 1} {i 2} {i 0} {i 1}]
 }
 ######################################################
 ##
 ## Timer procs
 ##
 ######################################################

 proc base {base number} {
    set negative [regexp ^-(.+) $number -> number] ;# (1)
    set digits {0 1 2 3 4 5 6 7 8 9 A B C D E F G H I J K L M N
        O P Q R S T U V W X Y Z a b c d e f g h i j k l m n o p
        q r s t u v w x y z}
    set res {}
    while {$number} {
        set digit [expr {$number % $base}]
        set res [lindex $digits $digit]$res
        set number [expr {$number / $base}]
    }
    if $negative {set res -$res}
    set res
 }

 proc getPortAndBit {focoNr} {
  #La asignacion consecutiva de puertos de la dio, se comporta como numeros octales, shifted by one.
  return [format "%02s" [base 8 [expr {$focoNr - 1}]]]
 }

 proc every {ms body} {
    eval $body
    after $ms [list every $ms $body]
 }

 proc timeElapsed {sec} {
    set hours [expr {$sec / 3600}]
    set mins [expr {($sec / 60) % 60}]
    return [format "%02d:%02d" $hours $mins]
 }

  proc fmtTime {sec} {
    return [clock format $sec -format %H:%M]
 }


 # unfmtTime: Take H:M and return decimal hours
 proc unfmtTime {s} {
    set t [split $s ":"]
    set hr [string trimleft [lindex $t 0] "0"]
    if {$hr == ""} {set hr 0}
    set min [string trimleft [lindex $t 1] "0"]
    if {$min == ""} {set min 0}
    set hr [expr {0.01 * round(100 * ($hr + (1.0 * $min)/60))}]

    return [format "%.2f" $hr]
 }

 ######################################################
 ##
 ## Timer procs
 ##
 ######################################################

 proc toggleTimer {win} {
 global timer dioPresent
    if {$timer($win-state)} {
        $win.top.buttons.t config -relief flat
        $win.top.buttons.t config -background green
        set timer($win-state) 0
        set timer($win-inicio) "--/-- --:--"
           resetTimer $win
        #DIG_Out_Line $cardno $port $line $value
        if {$dioPresent} {
            set i [::dll::call nidaq32.dll DIG_Out_Line i {i 1} "i $timer($win-port)" "i $timer($win-bit)" {i 0}]
        }
    } else {
        $win.top.buttons.t config -relief sunken
        $win.top.buttons.t config -background red
        if {$timer($win-reset)} {
            set timer($win-reset) 0
        }
        set timer($win-init) [clock sec]
        set timer($win-state) 1
        if {$dioPresent} {
            set i [::dll::call nidaq32.dll DIG_Out_Line i {i 1} "i $timer($win-port)" "i $timer($win-bit)" {i 1}]
        }
        updateTimer
    }
 }

 proc resetTimer {win} {
 global timer    
    set timer($win-reset) 1
    set timer($win-elapsed) "00:00"
    set timer($win-init) [clock sec]
    set timer($win-prev) 0
 }

 proc updateTimer {} {
 global timer
    set lastW ""
    foreach win [array names timer] {
        set dashIx [string first - $win]
        set win [string range $win 0 [incr dashIx -1]]
        if {$lastW != $win} {
            set lastW $win
            if {$timer($win-state)} {
                set elapsed_sec [expr {[clock sec] - $timer($win-init)}]
                set timer($win-elapsed) [timeElapsed $elapsed_sec]
                set timer($win-inicio) [clock format $timer($win-init) -format "%m/%d %k:%M"]
            }
        }
    }
 }


 proc timer_create {win title} {
 global timer ctr
 incr ctr
 puts "creating timer $ctr, [getPortAndBit $ctr]"
 # Are we timing, or not?
 set timer($win-state) 0
 # Has the timer been reset?
 set timer($win-reset) 1
 # Store previous time elapsed
 set timer($win-prev) 0
 set timer($win-elapsed) "00:00"
 set timer($win-inicio) "--/-- --:--"
 set timer($win-port) [string range [getPortAndBit $ctr] 0 0]
 set timer($win-bit) [string range [getPortAndBit $ctr] 1 1]
 puts $timer($win-port)
 puts $timer($win-bit)

 frame $win -class Radiobox
 ## -- Top frame
 frame $win.top
 pack  $win.top -side top
 label $win.top.l -textvar timer($win-inicio) -font {Tahoma 10}
 pack  $win.top.l -side left -padx 6

 # Buttons
 frame  $win.top.buttons
 pack   $win.top.buttons -side right -padx 6
 button $win.top.buttons.t -text $title -width 16 -background green
 pack   $win.top.buttons.t -side left

 ## -- Bottom frame
 frame $win.bottom
 pack  $win.bottom -side bottom
 label $win.bottom.l -textvar timer($win-elapsed) -font {Tahoma 20}
 pack $win.bottom.l
 $win.top.buttons.t config -command "toggleTimer $win"
 return $win
 }

 every [expr 1000 * 60] updateTimer
 foreach {uno dos} $lstOfTesters {
  timer_create $uno $uno
  timer_create $dos $dos
  grid $uno $dos
  puts "$uno $dos"
 }