initial commit
This commit is contained in:
626
tcl/drivers/trun.tcl
Normal file
626
tcl/drivers/trun.tcl
Normal file
@@ -0,0 +1,626 @@
|
||||
# general temperature driver
|
||||
namespace eval trun {
|
||||
}
|
||||
|
||||
global startupList
|
||||
if {![info exists startupList(drivers/trun.tcl)]} {
|
||||
set startupList(drivers/trun.tcl) 0
|
||||
}
|
||||
|
||||
# this function might be used to make an object t-driveable
|
||||
|
||||
proc stdConfig::tdrive args {
|
||||
variable name
|
||||
variable node
|
||||
variable path
|
||||
variable ctrl
|
||||
variable fastperiod
|
||||
|
||||
scanargs $args var -title -getcmd self -setcmd self -log 0 -getsample 0 -dbl 0 -limitscript 0
|
||||
|
||||
set node $path
|
||||
prop read trun::read_run
|
||||
# make read action fast
|
||||
$ctrl poll $node $fastperiod read read
|
||||
prop checklimits trun::checklimits
|
||||
prop halt trun::halt
|
||||
prop write trun::write
|
||||
prop status idle
|
||||
prop help $name
|
||||
prop runlabel "actual"
|
||||
prop getcmd $getcmd
|
||||
prop setcmd $setcmd
|
||||
prop getsample $getsample
|
||||
prop limitscript $limitscript
|
||||
prop initime [clock seconds]
|
||||
prop init 1
|
||||
if {$getcmd eq "self"} {
|
||||
prop selfupdate 0
|
||||
} else {
|
||||
prop selfupdate 1
|
||||
}
|
||||
prop dif 0
|
||||
|
||||
kids $title {
|
||||
if {[string match {set*} $setcmd]} {
|
||||
node mainloop -text out
|
||||
default $setcmd
|
||||
prop visible false
|
||||
prop check trun::checkmainloop
|
||||
prop write stdSct::complete
|
||||
} else {
|
||||
node set out
|
||||
default 0
|
||||
prop write trun::writeset
|
||||
}
|
||||
|
||||
node target upd
|
||||
|
||||
node running -int upd
|
||||
|
||||
node tolerance par 1
|
||||
|
||||
node maxwait par 3600
|
||||
|
||||
node settle par 0
|
||||
|
||||
if {$log} {
|
||||
|
||||
node log -text out
|
||||
prop check trun::logcmd
|
||||
prop write stdSct::complete
|
||||
prop visible false
|
||||
|
||||
kids hidden {
|
||||
|
||||
node mean upd
|
||||
|
||||
node m2 upd
|
||||
|
||||
node stddev upd
|
||||
|
||||
node n upd
|
||||
}
|
||||
}
|
||||
if {$dbl} {
|
||||
node dblctrl par 0
|
||||
prop label "double control"
|
||||
prop enum 1
|
||||
# prop enum off=0,normal=1,new=2
|
||||
|
||||
kids "double control settings" {
|
||||
node tshift out
|
||||
prop check trun::dblctrl_tshift
|
||||
prop write stdSct::complete
|
||||
default 0
|
||||
|
||||
if {$dbl} {
|
||||
node mode par 1
|
||||
} else {
|
||||
node mode par -1
|
||||
}
|
||||
prop enum disabled=-1,inactive=0,stable=1,up=2,down=3
|
||||
|
||||
node shift_up upd
|
||||
|
||||
node shift_lo upd
|
||||
|
||||
node t_min upd
|
||||
|
||||
node t_max upd
|
||||
|
||||
node int2 par 300
|
||||
|
||||
node prop_up par 0.4
|
||||
|
||||
node prop_lo par 0.8
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
set node $path
|
||||
}
|
||||
|
||||
proc stdConfig::trun {{title temperature} {getcmd self} {setcmd self}} {
|
||||
variable path
|
||||
controller syncedprot 10
|
||||
|
||||
pollperiod 1
|
||||
obj trun -drive wr
|
||||
stdConfig::tdrive $title $getcmd $setcmd
|
||||
}
|
||||
|
||||
|
||||
proc trun::dblctrl_filter {value name period filtimes lowerVar upperVar} {
|
||||
upvar $lowerVar lv
|
||||
upvar $upperVar uv
|
||||
set n 0
|
||||
set mn $value
|
||||
set mx $value
|
||||
foreach {tim1 tim2} $filtimes {
|
||||
incr n
|
||||
set lower [silent $value sct ${name}_mn_$n]
|
||||
set upper [silent $value sct ${name}_mx_$n]
|
||||
if {$tim1 <= 0} {
|
||||
set w1 1
|
||||
} else {
|
||||
set w1 [expr 1 - exp(- $period / double($tim1))]
|
||||
}
|
||||
if {$tim2 <= 0} {
|
||||
set w2 1
|
||||
} else {
|
||||
set w2 [expr 1 - exp(- $period / double($tim2))]
|
||||
}
|
||||
set u $mx
|
||||
set dif [expr $mx - $upper]
|
||||
if {$dif > 0} {
|
||||
set mx [expr $upper + $w1 * $dif]
|
||||
} else {
|
||||
set mx [expr $upper + $w2 * $dif]
|
||||
}
|
||||
set dif [expr $mn - $lower]
|
||||
if {$dif < 0} {
|
||||
set mn [expr $lower + $w1 * $dif]
|
||||
} else {
|
||||
set mn [expr $lower + $w2 * $dif]
|
||||
}
|
||||
sct ${name}_mx_$n $mx
|
||||
sct ${name}_mn_$n $mn
|
||||
}
|
||||
if {$upper < $mx} {
|
||||
set upper $mx
|
||||
}
|
||||
if {$lower > $mn} {
|
||||
set lower $mn
|
||||
}
|
||||
set lv $lower
|
||||
set uv $upper
|
||||
return $n
|
||||
}
|
||||
|
||||
proc trun::dblctrl_tshift {} {
|
||||
hsetprop [sct parent [sct parent]] resetdblctrl 1
|
||||
sct update [sct target]
|
||||
}
|
||||
|
||||
proc trun::dblctrl_crop {mn mx} {
|
||||
if {$mn > [sct tf_upper]} {
|
||||
set d [expr $mn - [sct tf_upper]]
|
||||
for {set n 0} {$n < [sct tf_n]} {incr n} {
|
||||
sct tf_mn_$n [expr [sct tf_mn_$n] + $d]
|
||||
}
|
||||
}
|
||||
if {$mx < [sct tf_lower]} {
|
||||
set d [expr $mx - [sct tf_lower]]
|
||||
for {set n 0} {$n < [sct tf_n]} {incr n} {
|
||||
sct tf_mx_$n [expr [sct tf_mx_$n] + $d]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
proc trun::dblctrl {tm ts tr setpdif {active 1}} {
|
||||
# active=1: active, active=2: suspended, else "sleeping"
|
||||
set d [expr $tr - $ts]
|
||||
set tshift [hvali [sct]/dblctrl/tshift]
|
||||
set flist {10 20}
|
||||
set int2 [hvali [sct]/dblctrl/int2]
|
||||
if {[silent 0 sct resetdblctrl]} {
|
||||
sct resetdblctrl 0
|
||||
set t0 [expr $ts + $tshift]
|
||||
clientput "reset double control tm $tm ts $ts tshift $tshift"
|
||||
if {$tm > $t0} {
|
||||
set t1 $tm
|
||||
} else {
|
||||
set t1 $t0
|
||||
set t0 $tm
|
||||
}
|
||||
sct tf_m_mx_1 $t1
|
||||
sct tf_m_mx_2 $t1
|
||||
sct tf_m_mx_3 $t1
|
||||
sct tf_m_mn_1 $t0
|
||||
sct tf_m_mn_2 $t0
|
||||
sct tf_m_mn_3 $t0
|
||||
sct tf_s_mx_1 $ts
|
||||
sct tf_s_mn_1 $ts
|
||||
return
|
||||
}
|
||||
# lappend flist [expr $int2 * 0.06]
|
||||
# lappend flist [expr $int2 * 0.5]
|
||||
# lappend flist [expr $int2 * 0.67]
|
||||
# lappend flist [expr $int2 * 2.0 + 10]
|
||||
lappend flist [expr $int2 * 0.3]
|
||||
lappend flist [expr $int2 * 0.5]
|
||||
lappend flist [expr $int2 * 1.0]
|
||||
lappend flist [expr $int2 * 1.5 + 10]
|
||||
sct tf_n [dblctrl_filter $tm tf_m 5 $flist mLower mUpper]
|
||||
sct tf_upper $mUpper
|
||||
sct tf_lower $mLower
|
||||
dblctrl_filter $ts tf_s 5 {10 20} sLower sUpper
|
||||
if {[silent 0 sct logfilter]} {
|
||||
clientput "$sLower $sUpper filter $mLower $mUpper $flist"
|
||||
}
|
||||
hupdate [sct]/dblctrl/t_max $mUpper
|
||||
hupdate [sct]/dblctrl/t_min $mLower
|
||||
set target [hvali [sct]/target]
|
||||
set dblmode [silent -1 hvali [sct]/dblctrl/mode]
|
||||
if {$active != 1} {
|
||||
if {$active == 0 && $dblmode > 0} {
|
||||
internalset [sct]/set $target
|
||||
}
|
||||
hupdate [sct]/dblctrl/mode 0 ;# inactive
|
||||
return
|
||||
}
|
||||
set shift_lo [expr $mLower - $sUpper]
|
||||
set shift_up [expr $mUpper - $sLower]
|
||||
set dif2 [expr $d - [sct dif]]
|
||||
if {$setpdif > 0} {
|
||||
if {$target > $ts + 1.0 && $target >= 20} {
|
||||
if {$dblmode != 2} {
|
||||
set dblmode 2 ;# up
|
||||
clientput "dblctrl mode up"
|
||||
}
|
||||
}
|
||||
} elseif {$setpdif < 0} {
|
||||
if {$tr != 0} {
|
||||
set tshift [expr $tshift / (1 - $setpdif / double($tr))]
|
||||
}
|
||||
if {$target < $ts - 1.0 && $target >= 20} {
|
||||
if {$dblmode != 3} {
|
||||
set dblmode 3 ;# down
|
||||
clientput "dblctrl mode down"
|
||||
}
|
||||
}
|
||||
}
|
||||
set td [expr $target - $ts]
|
||||
if {$dblmode != 1} { # not stable
|
||||
set tol [expr pow($td, 2) / ($target + $ts) * 2.0]
|
||||
set shift_up [expr $shift_up + $tol]
|
||||
set shift_lo [expr $shift_lo - $tol]
|
||||
}
|
||||
hupdate [sct]/dblctrl/shift_up $shift_up
|
||||
hupdate [sct]/dblctrl/shift_lo $shift_lo
|
||||
# hupdate [sct]/dblctrl/t_max [expr $ts + $shift_up - $tshift]
|
||||
# hupdate [sct]/dblctrl/t_min [expr $ts + $shift_lo - $tshift]
|
||||
if {$tshift > $shift_up} {
|
||||
set tshift $shift_up
|
||||
} elseif {$tshift < $shift_lo} {
|
||||
set tshift $shift_lo
|
||||
}
|
||||
hupdate [sct]/dblctrl/tshift $tshift
|
||||
|
||||
#clientput $td
|
||||
if {$dblmode == 2} { # up
|
||||
if {$td <= 0} {
|
||||
set dblmode 1
|
||||
clientput "dblctrl mode stable"
|
||||
} else {
|
||||
set tshift [expr $tshift + [hvali [sct]/dblctrl/prop_up] * $td]
|
||||
}
|
||||
} elseif {$dblmode == 3} { # down
|
||||
if {$td >= 0} {
|
||||
set dblmode 1
|
||||
clientput "dblctrl mode stable"
|
||||
} else {
|
||||
set tshift [expr $tshift + [hvali [sct]/dblctrl/prop_lo] * $td]
|
||||
}
|
||||
}
|
||||
hupdate [sct]/dblctrl/mode $dblmode
|
||||
if {abs($tshift) > $target * 0.5} {
|
||||
if {$tshift > 0} {
|
||||
set tshift [expr $target * 0.5]
|
||||
} else {
|
||||
set tshift [expr - $target * 0.5]
|
||||
}
|
||||
}
|
||||
set setp [expr $target + $tshift]
|
||||
catch {
|
||||
set setlimit [hvali [sct]/set/limit]
|
||||
if {$target <= $setlimit && $setp > $setlimit} {
|
||||
set setp $setlimit
|
||||
}
|
||||
}
|
||||
if {abs([hvali [sct]/set] - $setp) > $setp * 1e-5} {
|
||||
if {[silent "" hgetpropval [sct]/set/reg geterror] eq ""} {
|
||||
if {[sct limitscript] ne "0"} {
|
||||
set setp [eval "[sct limitscript] $setp fix"]
|
||||
}
|
||||
internalset [sct]/set $setp
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
proc trun::minmax {minvar maxvar first args} {
|
||||
upvar $minvar min
|
||||
upvar $maxvar max
|
||||
set min $first
|
||||
set max $first
|
||||
foreach v $args {
|
||||
if {$v > $max} {
|
||||
set max $v
|
||||
} elseif {$v < $min} {
|
||||
set min $v
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
proc trun::dblctrl2 {tm ts tr setpdif {active 1}} {
|
||||
set ft [expr [sct filtertime] * 0.2]
|
||||
if {$tr != [sct oldtr]} {
|
||||
sct oldtr $tr
|
||||
set ft 6.0
|
||||
} else {
|
||||
set ft [format %.2f [expr $ft + 0.332]]
|
||||
}
|
||||
sct filtertime [expr 5 * $ft]
|
||||
set w [expr 1.0 / $ft]
|
||||
set target [hvali [sct]/target]
|
||||
set y [expr $tm - $ts]
|
||||
set yy [silent $y sct yy]
|
||||
set yy1 [silent $y sct yy1]
|
||||
set dd [silent 0 sct dd]
|
||||
set cc [silent 0 sct cc]
|
||||
set cc1 [silent 0 sct cc1]
|
||||
|
||||
set yy1 [expr $yy1 + ($y - $yy1) * $w]
|
||||
set d [expr ($yy1 - $yy) * $w]
|
||||
set yy [expr $yy + $d]
|
||||
set c [expr ($d - $dd) * 2 * $w]
|
||||
set dd [expr $dd + $c]
|
||||
set cc1 [expr $cc1 + ($c - $cc1) * 4 * $w]
|
||||
set cc [expr $cc + ($cc1 - $cc) * 4 * $w]
|
||||
|
||||
sct yy $yy
|
||||
sct yy1 $yy1
|
||||
sct dd $dd
|
||||
sct cc $cc
|
||||
sct cc1 $cc1
|
||||
|
||||
set s [expr 7 / $w / 6]
|
||||
#clientput [format "%8.4g %8.4g %8.4g %8.4g" $y $yy [expr $dd * $s] [expr 0.25 * $cc * $s * $s]]
|
||||
set tshift [hvali [sct]/dblctrl/tshift]
|
||||
set yd [expr $yy + $dd * $s]
|
||||
set ys [expr $yd + 0.25 * $cc * $s * $s]
|
||||
minmax mn mx $yy $yd $ys
|
||||
if {$mx < $tshift} {
|
||||
set tshift $mx
|
||||
} elseif {$mn > $tshift} {
|
||||
set tshift $mn
|
||||
}
|
||||
if {abs($tshift) > $target * 0.2} {
|
||||
if {$tshift > 0} {
|
||||
set tshift [expr $target * 0.2]
|
||||
} else {
|
||||
set tshift [expr - $target * 0.2]
|
||||
}
|
||||
}
|
||||
hupdate [sct]/dblctrl/tshift $tshift
|
||||
hupdate [sct]/dblctrl/shift_up $mx
|
||||
hupdate [sct]/dblctrl/shift_lo $mn
|
||||
set setp [expr $target + $tshift]
|
||||
if {abs([hvali [sct]/set] - $setp) > $setp * 1e-5} {
|
||||
if {[silent "" hgetpropval [sct]/set/reg geterror] eq ""} {
|
||||
internalset [sct]/set $setp
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
proc trun::read_run {} {
|
||||
if {[sct init]} {
|
||||
foreach kid [hinfo [sct]] {
|
||||
if {[string match {set*} $kid]} {
|
||||
hsetprop [sct]/[sct setcmd] setmaintarget "trun::setmaintarget [sct]"
|
||||
}
|
||||
}
|
||||
sct init 0
|
||||
}
|
||||
if {[sct status] eq "run"} {
|
||||
set running 1
|
||||
} else {
|
||||
set running 0
|
||||
}
|
||||
hupdate [sct]/running $running
|
||||
set cmd [sct getcmd]
|
||||
if {$cmd eq "self"} {
|
||||
set tmain [hvali [sct]]
|
||||
} else {
|
||||
set tmain [result "silent none $cmd"]
|
||||
if {$tmain eq "none"} {
|
||||
sct geterror "invalid"
|
||||
return idle
|
||||
} else {
|
||||
hdelprop [sct] geterror
|
||||
}
|
||||
}
|
||||
set cmd [sct getsample]
|
||||
set tsample $tmain
|
||||
set dblctrl 0
|
||||
if {$cmd ne "0"} {
|
||||
if {[regexp {hvali (.*)} $cmd -> path]} {
|
||||
if {[silent "" hgetpropval $path geterror] ne ""} {
|
||||
set cmd error
|
||||
}
|
||||
}
|
||||
catch {
|
||||
set tsample [result $cmd]
|
||||
set dblctrl [silent 0 hvali [sct]/dblctrl]
|
||||
}
|
||||
}
|
||||
if {$dblctrl} {
|
||||
if {[hval [sct]/dblctrl/mode] == 0} { # inactive -> stable
|
||||
hupdate [sct]/dblctrl/mode 1
|
||||
}
|
||||
set value $tsample
|
||||
} else {
|
||||
set value $tmain
|
||||
}
|
||||
sct tsample $tsample
|
||||
if {[sct selfupdate]} {
|
||||
set err [silent "" hvali [sct]/status]
|
||||
if {$err eq ""} {
|
||||
sct update $tsample
|
||||
} else {
|
||||
sct geterror $err
|
||||
}
|
||||
}
|
||||
if {[sct status] eq "run"} {
|
||||
if {[clock seconds] > [sct startrun] + [hvali [sct]/maxwait]} {
|
||||
clientput "timeout when driving [sct objectName]"
|
||||
sct status idle
|
||||
} elseif {abs($value - [sct target]) < [hvali [sct]/tolerance]} {
|
||||
set remaining 0
|
||||
set settle [hvali [sct]/settle]
|
||||
if {![sct intolerance]} {
|
||||
set startsettle [expr [clock seconds] - [sct settletime]]
|
||||
if {$startsettle > [sct startsettle] + 10} {
|
||||
set remaining [expr $settle - [sct settletime]]
|
||||
}
|
||||
sct startsettle $startsettle
|
||||
sct intolerance 1
|
||||
}
|
||||
if {[clock seconds] >= [sct startsettle] + [hvali [sct]/settle]} {
|
||||
sct status idle
|
||||
} elseif {$remaining > 0} {
|
||||
clientput "[sct objectName] in tolerance, wait $remaining sec."
|
||||
sct printit 1
|
||||
}
|
||||
} else {
|
||||
if {[sct intolerance]} {
|
||||
sct settletime [expr [clock seconds] - [sct startsettle]]
|
||||
sct intolerance 0
|
||||
}
|
||||
if {[sct printit]} {
|
||||
sct printit 0
|
||||
clientput "[sct objectName] out of tolerance"
|
||||
}
|
||||
}
|
||||
}
|
||||
set now [DoubleTime]
|
||||
set tr [silent none sct target]
|
||||
if {$tr eq "none"} {
|
||||
set tr $tmain
|
||||
} else {
|
||||
set dif [expr abs($tr) - [hvali [sct]/target]]
|
||||
updateval_u [sct]/target $tr 0
|
||||
set dblmode [silent -1 hval [sct]/dblctrl/mode]
|
||||
if {$dblmode >= 0} { # not disabled
|
||||
if {[sct initime] == 0} {
|
||||
# initialization has finished
|
||||
if {$now < [silent 0 sct dblctrl_sleep]} {
|
||||
dblctrl $tmain $tsample $tr $dif 2
|
||||
} else {
|
||||
dblctrl $tmain $tsample $tr $dif $dblctrl
|
||||
}
|
||||
} else {
|
||||
if {[clock seconds] > [sct initime] + 30} {
|
||||
sct initime 0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
set stat [silent 0 sct statistics]
|
||||
if {$stat > 0 && $now > $stat + 10} {
|
||||
sct statistics $now
|
||||
set n [hvali [sct]/log/n]
|
||||
set mean [hvali [sct]/log/mean]
|
||||
set m2 [hvali [sct]/log/m2]
|
||||
incr n
|
||||
set delta [expr $tsample - $mean]
|
||||
set mean [expr $mean + $delta / $n]
|
||||
set m2 [expr $m2 + $delta * ($tsample - $mean)]
|
||||
hupdate [sct]/log/n $n
|
||||
hupdate [sct]/log/mean $mean
|
||||
hupdate [sct]/log/m2 $m2
|
||||
|
||||
if {$n > 1} {
|
||||
hupdate [sct]/log/stddev [expr sqrt($m2/ ($n - 1))]
|
||||
}
|
||||
}
|
||||
return idle
|
||||
}
|
||||
|
||||
proc trun::write {} {
|
||||
if {[silent 0 sct writestatus] eq "start"} {
|
||||
# initiated by a run/drive command
|
||||
sct status run
|
||||
sct startrun [clock seconds]
|
||||
sct settletime 0
|
||||
sct intolerance 0
|
||||
sct startsettle 0
|
||||
sct printit 0
|
||||
sct print "run [sct objectName] to [sct target]"
|
||||
}
|
||||
set cmd [sct setcmd]
|
||||
set setp [sct target]
|
||||
if {[silent -1 hval [sct]/dblctrl/mode] > 0} {
|
||||
set setp [expr $setp + [silent 0 hvali [sct]/dblctrl/tshift]]
|
||||
}
|
||||
if {$cmd eq "self"} {
|
||||
internalset [sct]/set $setp
|
||||
} elseif {[string match {set*} $cmd]} {
|
||||
internalset [sct]/[hval [sct]/mainloop] $setp
|
||||
} else {
|
||||
eval $cmd $setp
|
||||
hupdate [sct]/set $setp
|
||||
}
|
||||
return idle
|
||||
}
|
||||
|
||||
proc trun::writeset {} {
|
||||
if {[hgetpropval [sct parent] setcmd] ne "self"} {
|
||||
internalset [sct objectPath] [sct target]
|
||||
}
|
||||
sct print "[sct sicscommand] = [sct target]"
|
||||
return idle
|
||||
}
|
||||
|
||||
proc trun::checklimits {} {
|
||||
# TODO: does the following harm?
|
||||
hupdate [sct]/target [sct target]
|
||||
if {[sct limitscript] ne "0"} {
|
||||
eval "[sct limitscript] [sct target]"
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
proc trun::checkmainloop {} {
|
||||
hsetprop [sct parent] setcmd [sct target]
|
||||
if {[string match {set*} [sct target]]} {
|
||||
set channel [sctval [sct parent]/[sct target]/channel]
|
||||
set chnode [hgetpropval [sct parent] channel_$channel]
|
||||
hsetprop [sct parent] getsample "hvali $chnode"
|
||||
hsetprop [sct parent] getcmd "hvali $chnode"
|
||||
}
|
||||
sct update [sct target]
|
||||
}
|
||||
|
||||
proc trun::halt {} {
|
||||
sct status posfault
|
||||
return idle
|
||||
}
|
||||
|
||||
proc trun::logcmd {} {
|
||||
sct update [sct target]
|
||||
switch -- [sct target] {
|
||||
clear {
|
||||
hupdate [sct]/n 0
|
||||
hupdate [sct]/mean 0
|
||||
hupdate [sct]/m2 0
|
||||
hupdate [sct]/stddev 0
|
||||
hsetprop [sct parent] statistics 1
|
||||
}
|
||||
getmean {
|
||||
if {[hvali [sct]/n] == 0} {
|
||||
set mean [hgetpropval [sct parent] tsample]
|
||||
} else {
|
||||
set mean [hvali [sct]/mean]
|
||||
}
|
||||
sct print "[lindex [sct sicscommand] 0] mean = $mean stddev = [hvali [sct]/stddev]"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
proc trun::setmaintarget {path value} {
|
||||
if {[sct] eq $path/[silent 0 sctval $path/mainloop]} {
|
||||
hsetprop $path target $value
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user