namespace eval warmup {
}

proc stdConfig::warmup {} {
  variable name

  controller syncedprot
  pollperiod 1 1

  obj Warmup wr
  prop read warmup::poll
  prop write warmup::write
  prop enum 1
  prop label "warmup control for SCH5"
  prop endtime 0
  prop start 0
  default 1
  kids "warmup control" {
    node trig par 10
    prop help "switch on sample heater when ts < target - trig and tm < target"

    node weight par 0.4
    prop help "switch off sample heater when ts > target - weight * (target - ts)"

    node limit par 70
    prop help "do not use warmup when target < limit"

    node timef par 0.5
    prop label "settle time factor"
    prop help "reset double control after (timef * int2) sec"

    node abruptstop par 1
    prop enum 1
    prop label "abrupt stop"
    prop help "switch off sample heater immediately after tm > treg"

    node warmup -int out
    prop check warmup::check
    prop write stdSct::complete
    prop enum off,warmup,htroff,settle
    default 0
  }
}

proc warmup::check {} {
  if {[sct target]} {
    if {![hvali [sct]]} {
      warmup::on
    }
  } else {
    if {[hvali [sct]]} {
      warmup::off
    }
  } 
}

proc warmup::write {} {
  if {[sct target]} {
    if {![hvali [sct]]} {
      warmup::off
    }
  } elseif {[hvali [sct]/warmup]} {
    warmup::off
  }
  hsetprop /tt/dout reset_value 1
  hsetprop /tt/dout reset_item "heater switch"
  sct update [sct target]
  return idle
}

proc warmup::on {} {
  hupdate [sct objectPath]/warmup 1
  nv autoflow/suspended 1
  hsetprop /tt dblctrl_sleep [expr [DoubleTime] + 10]
}

proc warmup::htroff {} {
  clientput "warmup: htr off"
  hupdate [sct objectPath]/warmup 2
  sct start [DoubleTime]
  tt set/mode 0
  tt dblctrl/tshift 0
}

proc warmup::settle {} {
  clientput "warmup: autoflow off"
  hupdate [sct objectPath]/warmup 3
  tt dout 1
  tt set/resist 50
# volodia wants to use ~55 Volts
  tt set/maxheater 2A
  # tt dblctrl/tshift [expr [hvali /tt/tm] - [hvali /tt/target]]
  tt set/mode 1
  # hsetprop /tt  dblctrl_sleep 0
  nv autoflow/suspended 1
  sct start [DoubleTime]
}

proc warmup::off {} {
  clientput "warmup: normal reg"
  hupdate [sct objectPath]/warmup 0
  nv autoflow/suspended 0
  hsetprop /tt dblctrl_sleep 0
}

proc warmup::poll {} {
#  if {[silent 0 sct setoff]} {
#    tt set/mode 1
#    sct setoff 0
#    warmup::off
#  }
  if {[hvali [sct]] == 0} {
    sct update 0
    if {[silent 0 hgetpropval /tt/dout target] != 1} {
      tt dout 1
    }
    return idle
  }
  set trig [hvali [sct]/trig]
  set weight [hvali [sct]/weight]
  set limit [hvali [sct]/limit]
  set ts [hvali /tt/ts]
  set tm [hvali /tt/tm]
  set target [silent 0 hgetpropval tt target]
  set d [expr ($ts - $target) * $weight]
  switch -- [hvali [sct]/warmup] {
    0 { # off
      if {$ts < $target - $trig && $tm < $target + $d && $tm < $target && $target >= $limit} {
        warmup::on
      }
      if {[silent 0 hgetpropval /tt/dout target] != 1} {
        tt dout 1
      }
    }
    1 { # warmup
      set setp [expr $target + $d]
      set now [DoubleTime]
      if {[silent 0 hgetpropval /tt/dout target] != 2} {
        tt dout 2
        clientput "warmup: sample heater on $target $d"
        tt set/resist 25
        tt set/maxheater 2A
        sct lasttm $tm
      }
      # dout will be reset to 1 when reset_time expires
      hsetprop /tt/dout reset_time [expr [DoubleTime] + 10]
      hupdate /tt/dblctrl/tshift $d
      set setlimit [hvali /tt/set/limit]
      if {$target <= $setlimit && $setp > $setlimit} {
        set setp $setlimit
      }
      internalset /tt/set $setp
      if {$ts >= $target || ([hvali [sct]/abruptstop] && $tm >= $setp)} {
        if {[hvali [sct]/abruptstop]} {
          warmup::htroff
        } else {
          warmup::settle
        }
      } elseif {$tm < $setp || $tm > [silent 0 sct lasttm]} {
        sct lastinc $now
        sct lasttm $tm
        hsetprop /tt dblctrl_sleep [expr $now + 10]
      } elseif {$now > [silent 0 sct lastinc] + 12} {
        clientput tm_decrease
        warmup::settle
      }
    }
    2 { # htroff
      hsetprop /tt dblctrl_sleep [expr [DoubleTime] + 10]
      if {[DoubleTime] > [sct start] + 10} {
        warmup::settle
      }
    }
    3 { # settle
      # hsetprop /tt dblctrl_sleep [expr [DoubleTime] + 10]
      set tr [hvali /tt/set/reg]
      set int2 [hvali /tt/dblctrl/int2]
      set now [DoubleTime]
      if {$ts > $target ||
          [DoubleTime] > [sct start] + $int2 * [hvali [sct]/timef]} {
        tt dblctrl/tshift 0
        warmup::off
      }
    }
  }
  sct update [hvali [sct]]
  return idle
}

