# virtual temperature controller using multiple controllers regulation the same T
#

namespace eval multit {} {
}

proc stdConfig::multit {label full_label slaves {slaves_with_offset 0} {offset 0} {rt_auto 0}} {
  variable hostport none
  variable name
  variable path
  
  controller syncedprot 30
  prop write stdSct::complete
  
  pollperiod 1 1
  
  obj multi_t -drive wr
  if {[info proc stdConfig::tdrive] eq ""} {
    namespace eval :: {
      source drivers/trun.tcl
    }
  }
  tdrive $name -log 1
  hsetprop $path/set check "multit::check_with_offset /set $slaves $slaves_with_offset"
  hsetprop $path/set visible false
  hsetprop $path label set

  kids $full_label {
    node reg rd
    prop read "multit::poll {{} /reg /htr} $slaves"

    node ramp out
    prop check "multit::check_set /ramp $slaves"

    node pb out
    prop label "prop. band"
    prop check "multit::check_set /pb $slaves"

    node rt out
    prop label "int. t"
    prop help "int. t \[sec\]"
    prop check "multit::check_set /rt $slaves"

    node rt_auto par $rt_auto
    if {$rt_auto == 0} {
      prop visible false
    }
    prop label "int. t * t_set"
    prop help "calculate int.t from this value (set to 0 for manual int.t)"

    node td out
    prop label "deriv. t"
    prop help "deriv. t \[sec\]"
    prop check "multit::check_set /td $slaves"

    node manual out
    prop check "multit::check_set /manual $slaves"
    prop enum 1

    node manual_output out
    prop check "multit::check_set /manual_output $slaves"

    node htr upd
    
    if {$offset ne "0"} {
      node offset -text par $offset
      prop width 20
    }
  }
}

proc multit::check_set {relpath slaves} {
  foreach a $slaves {
    hset $a$relpath [sct target]
  }
  sct update [sct target]
}

proc multit::check_with_offset {relpath slaves {slaves_with_offset ""}} {
  if {[sct target] == 0} {
    hset [sct parent]/manual_output 0
    hset [sct parent]/manual 1
  } elseif {[sctval [sct parent]/manual]} {
    hset [sct parent]/manual 0
  }
  foreach a $slaves {
    hset $a$relpath [sct target]
    set rta [hval [sct parent]/rt_auto]
    if {$relpath eq "/set" && $rta != 0} {
      set rt [expr $rta / max(20, [sct target])]
      if {abs($rt - [hvali [sct parent]/rt]) >= 1} {
        hset [sct parent]/rt $rt
      }
    }
  }
  foreach a $slaves_with_offset {
    set formula [string map {$ "" "[" "(" "]" ")" "%" "* $t * 0.01"} [silent 0 hval $a/offset]]
    set t [sct target]
    if {$t != 0} {
      set t [expr "\$t + $formula"]
    }
    hset $a$relpath $t
  }
  sct update [sct target]
  hsetprop [sct objectPath] target [sct target]
}

proc multit::poll {relpaths slaves} {
  foreach relpath $relpaths {
    set n 0
    set sum 0
    foreach a $slaves {
      catch {
        set sum [expr $sum + [hval $a$relpath]]
        incr n
      }
    }
    if {$n > 0} {
      updateval [sct objectPath]$relpath [expr $sum / double($n)]
    }
  }
  return idle
}

