#driver for hcp high voltage power supply

namespace eval hcp {
}

proc stdConfig::hcp {} {

  controller std
  prop startcmd "*IDN?"
  prop read hcp::read
  prop write hcp::write
  prop update hcp::update
  prop complete hcp::complete

  obj hcp rd
  prop reg M0
  kids "high voltage" {

    node set wr
    prop read hcp::setread
    prop write hcp::setwrite
    prop reg S0

    node on wr -int
    prop complete hcp::oncomplete
    prop label "voltage on"
    prop enum 1
    prop reg BON  

    node setcurrent wr
    prop label "max. current (absolute)"
    prop reg S1

    node ramp wr
    prop reg S0R
    prop label "ramp \[V/sec\]"

    node rampmode wr -int
    prop label "ramp mode"
    prop enum "no ramp,always ramp,ramp up only"
    prop reg S0B

    node workset upd

    node current rd
    prop update hcp::currentupdate
    prop reg M1

    node currentlimit par 1e-3
  }

  return "HCP High Voltage Supply"
}


proc hcp::read {} {
  sct send ">[sct reg]?"
  return update
}

proc hcp::setread {} {
  sct send ">BX?"
  return hcp::setread2
}

proc hcp::setread2 {} {
  set res [split [sct result] :]
  sct negative [lindex $res 1]
  sct send ">[sct reg]?"
  return hcp::setupdate
}

proc hcp::setupdate {} {
  set res [split [sct result] :]
  if {! [string equal [sct reg] [lindex $res 0]]} {
    error "illegal response to [sct send]: [sct result]"
  }
  if {[sct negative]} {
    sct update [expr -[lindex $res 1]]
  } else {
    sct update [lindex $res 1]
  }
  sct send >S0A?
  return hcp::setupdate2
}

proc hcp::setupdate2 {} {
  set res [split [sct result] :]
  set res [lindex $res 1]
  if {[sct negative]} {
    set res [expr -$res]
  }
  hupdate [sct objectPath]/workset $res
  if {$res == 0 && [silent 0 sct newtarget] != 0} {
    if {[sct newtarget] < 0} {
# switch to negative
      clientput "switch to negative voltage"
      sct send ">BX 1"
      hset [sct] [sct newtarget]
      sct newtarget 0
      sct negative 1
      return hcp::complete
    }
# switch to positive
    clientput "switch to positive voltage"
    sct send ">BX 0"
    hset [sct] [sct newtarget]
    sct newtarget 0
    sct negative 0
    return hcp::complete
  }
  return idle
}
  
proc hcp::update {} {
  set res [split [sct result] :]
  if {! [string equal [sct reg] [lindex $res 0]]} {
    error "illegal response to [sct send]: [sct result]"
  }
  sct update [lindex $res 1]
  return idle
}

proc hcp::write {} {
  sct send ">[sct reg] [sct target]"
  return complete
}

proc hcp::complete {} {
  if {! [string equal E0 [sct result]]} {
    error "illegal response to [sct send]: [sct result]"
  }
  sct send ">[sct reg]?"
  return update
}

proc hcp::worksetupdate {} {
  
}

proc hcp::currentupdate {} {
  hcp::update
  if {abs([hvali [sct]]) > [hvali [sct objectPath]/currentlimit]} {
    hset [sct objectPath]/on 0
    if {[hvali [sct objectPath]/on]} {
      clientput "ERROR: Overcurrent"
      hupdate [sct objectPath]/status "Overcurrent: Voltage switched off"
    }
  }
  return idle
}

proc hcp::setwrite {} {
  if {[sct negative] != ([sct target] < 0) && [sct target] != 0} {
  clientput "newtarget [sct target]"
    sct send ">[sct reg] 0"
    sct newtarget [sct target]
  } else {
    sct send ">[sct reg] [expr abs([sct target])]"
    sct newtarget 0
  }
  return read
}

proc hcp::oncomplete {} {
  if {[sct target]} {
    clientput "clear hcp status"
    hupdate [sct objectPath]/status ""
  }
  return [hcp::complete]
}
