# simulate a ramping device
#

namespace eval simramp {} {
}

proc stdConfig::simramp {{initvalue 0} {minvalue 0} {maxvalue 100} {time_const 60} {ramp 1e10} } {
  variable name
  
  controller syncedprot 30
  prop write stdSct::complete
  
  pollperiod 6 6

  obj SIMRAMP_$name rd
  default $initvalue
  prop read simramp::poll
  prop lasttime 0
  prop minvalue $minvalue
  prop time_const $time_const
  
  kids $name {
    node set out
    default $initvalue
    prop check simramp::check_set
    
    node limit par $maxvalue
    
    node reg upd

    node ramp par $ramp

    node command par -text noop
  }
}

proc simramp::check_set {} {
  if {[sct target] > [hval [sct parent]/limit]} {
    error "[sct] [sct target] is above limit ([hval [sct parent]/limit])"
  }
  sct update [sct target]
}

proc simramp::poll {{step 0}} {
  set now [doubleTime]
  set delay [expr $now - [sct lasttime]]
  sct lasttime $now
  set weight [expr 1.0 - exp(-$delay / double([sct time_const]))]
  putIntoLimits delay 0 10
  
  get_values [sct] set reg ramp
  set meas [hvali [sct]]
  
  if {$set > $reg} {
    set reg [expr $reg + $delay * $ramp]
    putIntoLimits reg [sct minvalue] $set
  } else {
    set reg [expr $reg - $delay * $ramp]
    putIntoLimits reg $set 1e10
  }
  update_values [sct] reg

  putIntoLimits reg [sct minvalue] $reg
  set meas [expr $meas + $weight * ($reg - $meas)]
  sct update $meas
  eval "[hval [sct]/command] $meas"
  return idle
}

proc noop {value} {
}
