esrf

Beamline Instrument Software Support
SPEC Macro documentation: [ Macro Index | BCU Home ]

#%TITLE% NHQ.mac
#%NAME%
#  Support for the NHQ high voltage powersupply
#
#%CATEGORY% Other hardware
#
#%DESCRIPTION%
#  The following set of macros allow the user to interrogate the state,
# read and change the voltage setting on an NHQ high voltage powersupply.
#
# It has been tested on NHQ204M; NHQ???
# It should work with NHQ : 102M 103M 104M 105M 106L 202M 203M 204M 205M 206L.
#
#%SETUP%
#The %B%RS232%B%  serial line parameters are:%BR%
#   - 8 bits%BR%
#   - no parity%BR%
#   - 1 stop bit%BR%
#   - 9600 bauds%BR%
#
#  9600 raw in SPEC.
#
#%END%

# To be able to remotely control the NHQ device(s), make sure that the [contr.] switch is in DAC position.

# DONE:
# -change NHQ204M* by NHQ_PAR["*"].
# -extend for multiple devices.

# TODO :
# -check to generalize to all NHQ devices.
# -independant (des)activation of pseudos...
# -affichage dans l-orde
# -tjrs verifier l-etat ?  (LHE)
# -units
# -make hardware macro motors instead of pseudo motors.

# polarity ???


#  WTF ????
#
# 18408 - 2014_Dec_12_18h40m00s    V=3
# 18409 - 2014_Dec_12_18h40m01s    V=3
# 18410 - 2014_Dec_12_18h40m01s    V=0
# 18411 - 2014_Dec_12_18h40m02s    V=1
# 18412 - 2014_Dec_12_18h40m03s    V=3
# OOOOOOOOOOOOOOOO NHQ ERROR 1 : ?WCN received
# I repeat the command...
# NHQ : _nhq_write : Invalid mnemonic : U1
# 
# 398.CYRIL>



need spec_utils
need hg

global NHQ_SLEEP_COEF
NHQ_SLEEP_COEF = 0.01

global NHQ_ERROR_NB

######################################################################
##########################                  ##########################
##########################  INFO AND DEBUG  ##########################
##########################                  ##########################
######################################################################

need hg
# configure info_style, debug_style, error_style
hg_config_style("nhq", 0, 2, 3)

# configure info_indent, debug_indent, error_indent
hg_config_indent("nhq","","\t","")

# generate nhq_msg nhq_err nhq_dbg macros
hg_generate("nhq")


######################################################################
###############################         ##############################
###############################  SETUP  ##############################
###############################         ##############################
######################################################################

#%UU%  [mot_mnemonic] [serial line] [channel]
#%MDESC%
#   setup NHQ mnemonic, channel and serial_line number.
# * mot_mnemonic + "_c" will be used for the counter mnemonic
# * The #%B%serial line%B% parameter is the ordinal number of the serial
#   line device (starting from 0), as assigned in the %B%config%B% file
# * channel is 1 or 2.
def nhq_setup '{

    NHQ_ERROR_NB = 0

    # list -> 500 0004 (ass + global )
    if (whatis("NHQ_PAR") == 0x5000004){
        # print "NHQ_PAR already exists"
    }
    else{
        nhq_msg("initializing NHQ_PAR")
        global NHQ_PAR
        list_init NHQ_PAR
    }

    #          mne     param
    # NHQ_PAR["nhq1"]["serial"]          serial number in spec session
    ### NHQ_PAR["nhq1"]["model"]         to add if needed ???
    # NHQ_PAR["nhq1"]["channel"]         1 or 2
    # NHQ_PAR["nhq1"]["pseudo_cnt_mne"]  mne+"_c"
    # NHQ_PAR["nhq1"]["pseudo_cnt_on"]
    # NHQ_PAR["nhq1"]["pseudo_mot_mne"]
    # NHQ_PAR["nhq1"]["pseudo_mot_on"]
    # NHQ_PAR["nhq1"]["pos"]
    # NHQ_PAR["nhq1"]["polarity"]        "POSITIVE" or "NEGATIVE"

    local _junk _nb_param _mne _mne_c _ch
    local _mne_i

    _nb_param = $#

    if (_nb_param > 3) {
        print "Usage: nhq_setup <motor mne> <serial line> <channel>"
        print "   will use <motor mne>_i as counter mne for current"
        print "   will use <motor mne>_c or _u as counter mne for voltage"
        exit
    }

    # ARRRG.... _mne must be 5 letters long maximum !!!!!!!!!
    if (_nb_param < 1){
        _mne = getval("NHQ : Mnemonic tu use for pseudo counter / pseudo motor", 0)
    }
    else{
        _mne = "$1"
    }

    _mne_c = _mne"_c"
    _mne_i = _mne"_i"

    if (!cnt_exists(_mne_c)){
        _mne_c = _mne"_u"
        if (!cnt_exists(_mne_c)){
            nhq_err(sprintf("Invalid counter mnemonic for voltage \"%s\"", _mne_c))
        }
    }

    if (!cnt_exists(_mne_i)){
        nhq_err(sprintf("Invalid counter mnemonic for current \"%s\"", _mne_i))
    }

    if (motor_num(_mne) < 0){
        nhq_err(sprintf("Invalid motor mnemonic \"%s\"", _mne))
        exit
    }

    # add _mne as a NHQ.
    list_add(NHQ_PAR, _mne)

    # add mnemonic of pseudo counter.
    list_setpar(NHQ_PAR, _mne, "pseudo_cnt_mne",   _mne_c)

    if (cnt_exists(_mne_i)){
        list_setpar(NHQ_PAR, _mne, "pseudo_cnt_mne_i", _mne_i)
    }

    list_setpar(NHQ_PAR, _mne, "pseudo_cnt_on", 0)

    # add mnemonic of pseudo motor.
    list_setpar(NHQ_PAR, _mne, "pseudo_mot_mne", _mne)
    list_setpar(NHQ_PAR, _mne, "pseudo_mot_on", 0)

    # setup pseudos
    nhq_dbg(sprintf("pseudo_setup(%s)", _mne))
    nhq_pseudo_setup(_mne)

    if (_nb_param < 2){
        _serial = getval("NHQ : Serial line number (starting form 0):", 0)
        list_setpar(NHQ_PAR, _mne, "serial", _serial)
    }
    else{
        list_setpar(NHQ_PAR, _mne, "serial", $2)
    }

    if (_nb_param < 3){
        _ch = 0
        while ((_ch != "1") && (_ch != "2")){
            _ch = getval("NHQ : Channel to use (1/2):", 1)
        }
        list_setpar(NHQ_PAR, _mne, "channel", _ch)
    }
    else{
        list_setpar(NHQ_PAR, _mne, "channel", $3)
    }

    if ( _nb_param == 3){
        nhq_msg(sprintf("channel=%d motor=\"%s\" counters=\"%s\",\"%s\"", \
                NHQ_PAR[_mne]["channel"], \
                NHQ_PAR[_mne]["pseudo_mot_mne"], \
                NHQ_PAR[_mne]["pseudo_cnt_mne"], \
                NHQ_PAR[_mne]["pseudo_cnt_mne_i"]))
    }

    NHQ_PAR[mne]["minVoltage"] = 0
    NHQ_PAR[mne]["maxVoltage"] = 100


    # empty serial line buffer of any junk characters
    nhq_dbg("flushing serial line")
    ser_par(NHQ_PAR[_mne]["serial"], "flush")
}'


#%UU% [mne]
#%MDESC%
#    Removes globals and cdefs for 1 mne or for all if no mnemonic is given.
def nhq_unsetup '{
    local nb_param

    nb_param = $#

    if(nb_param > 0) {
        _mne = "$1"

        nhq_off _mne

        cdef ("", "", "nhqps_c", "delete")
        cdef ("", "", "nhqps_m", "delete")

        list_remove(NHQ_PAR, NHQ_PAR[_mne])
        list_remove(NHQ_PAR, _mne)
    }
    else{
        nhq_off

        cdef ("", "", "nhqps_c", "delete")
        cdef ("", "", "nhqps_m", "delete")

        unglobal NHQ_PAR
    }
}'



######################################################################
#############################            #############################
#############################  COMMANDS  #############################
#############################            #############################
######################################################################


#%UU% [<mne>]
#%MDESC%
#    Prints Status, Voltage, Ramp of NHQ for 1 or all NHQ Devices.
def nhq_info '{

  local _nb ii mne

    if ($# < 1){
        print "----------------- NHQ -----------------------"
        for (ii = 0 ; ii < NHQ_PAR["0"] ;  ii++){
            _nhq_info(NHQ_PAR[ii+1])
        }
    }
    else{
        mne = "$1"

        if (!list_check(NHQ_PAR, mne)) {
            print "Invalid mnemonic : " mne
            exit
        }
        _nhq_info(mne)
    }
}'


#%UU% (mne)
#%MDESC%
#    Prints Status, Voltage, Ramp of NHQ (bench -> ~1.8s / channel)
def _nhq_info(mne) '{

    printf( "ask status of NHQ module ")
    cprint_bold(mne)
    print ""

    printf("Id (unit nb; software version; U max ; Imax) :")
    cprint_bold(_nhq_id(mne))
    print ""

    print "SerialLine   :", NHQ_PAR[mne]["serial"]  "    \tChannel :", NHQ_PAR[mne]["channel"]
    printf( "Status       : ")
    cprint_bold(_nhq_status(mne))
    print ""

    printf("module status :")
    cprint_bold( _nhq_mod_status(mne))
    print ""

    print "Voltage      :", _nhq_get_voltage(mne)" V"  "   \tU limit : " _nhq_get_voltage_limit(mne)"%"
    print "Polarity     :", NHQ_PAR[mne]["polarity"]
    print "Current      :", _nhq_get_current(mne)" uA"  "   \tI limit : " _nhq_get_current_limit(mne)"%", \
        "     Current Trip :", _nhq_get_current_trip(mne)
    print "Ramp speed   :", _nhq_get_ramp(mne) " V/s"
    print "Break time   :", _nhq_get_break_time(mne) "ms"
    print ""

}'



######################################################################
###########################                 ##########################
###########################  COMMUNICATION  ##########################
###########################                 ##########################
######################################################################


#%IU% (mne, str)
#%MDESC%
#    Writes string charcter by character to NHQ serial line. (c by c ???)
# The commands are transmitted in ASCII. All commands are terminated
# by the sequence <CR> <LF> ( 0x0D 0x0A , 13 10 respectively). Leading
# zeroes can be omitted on input, output is in fixed format.
def _nhq_write(mne, str) '{

    local _str_len  ch  ii

    _str_len = length(str)

    if (!list_check(NHQ_PAR, mne)) {
        nhq_err(sprintf("_nhq_write : Invalid mnemonic : \"%s\"", mne))
        exit
    }

    ser_par(NHQ_PAR[mne]["serial"], "flush", 2)

    nhq_dbg(sprintf( "write string : %s", str))

    # Code to write character by character to NHQ serial line.
    for (ii=1; ii < _str_len+1; ii++) {
       ch = substr(str, ii, 1)
#       nhq_dbg(sprintf("_nhq_write(serial%d; char%d): put %s", NHQ_PAR[mne]["serial"], ii, ch))
       ser_put(NHQ_PAR[mne]["serial"], ch)
       ch = ser_get(NHQ_PAR[mne]["serial"], 1)
#       nhq_dbg(sprintf("_nhq_write(serial%d; char%d): get %s", NHQ_PAR[mne]["serial"], ii, ch))
    }

    # Each command must ends by "\r\n"
    ser_put(NHQ_PAR[mne]["serial"], sprintf("%c%c", 13, 10))

    # ? ?? check ???
    ch = ser_get(NHQ_PAR[mne]["serial"], 2)

    # sleep _str_len + 2 * 0.05 seconds - to give powersupply time to think !
    sleep((_str_len + 2)*NHQ_SLEEP_COEF)
}'


def _nhq_read(mne) '{
    local _ans

    _ans = ser_get(NHQ_PAR[mne]["serial"], 0)
    _ans = removeEndingChar(_ans, "\n")
    _ans = removeEndingChar(_ans, "\r")

    nhq_dbg(sprintf( "read string : %s", _ans))

    return _ans
}'


def _nhq_send_no_ans(mne, cmd) '{
    _nhq_write(mne, cmd)
}'

def _nhq_send(mne, cmd) '{
    local _ans  _repeat_idx  _repeat_count

    _nhq_write(mne, cmd)
    _ans = _nhq_read(mne)

    # Repeats 3 times the command in case of error.
    for (_repeat_idx = 0 ; _repeat_idx < _repeat_count ; _repeat_idx++){
        if (_ans == "?WCN"  || _ans == "?TOT" || _ans == "????"){
            NHQ_ERROR_NB++
            nhq_err(sprintf("OOOOOOOOOOOOOOOO NHQ ERROR %d : %s received\n", \
                            NHQ_ERROR_NB,  _ans))
            nhq_err(sprintf("I repeat (%d/%d) the command (%s) ", _repeat_idx, cmd))
            _nhq_write(mne, cmd)
            _ans = _nhq_read(mne)
        }
        else{
            return _ans
        }
    }

    return _ans
}'


#%IU% (mne)
#%MDESC%
#    Returns status of one NHQ channel.   "S" command
def _nhq_status(mne) '{
   local str

   #             "S1"
   str = sprintf("S%1d", NHQ_PAR[mne]["channel"])

   str = _nhq_send(mne, str)

   if (str=="?WCN"){
       return("Wrong Channel")
   }
   else if(str == "????"){
       return "Syntax error"
   }
   else if(str == "?TOT"){
       return "Timeout error"
   }
   else{
       return str
   }
}'


#%IU% (mne)
#%MDESC%
#    Returns Module Status of one NHQ module.      "T" command
def _nhq_mod_status(mne) '{
   local str _s val

   #             "T1"
   str = sprintf("T%1d", NHQ_PAR[mne]["channel"])

   val = nhq_send(str)

   nhq_dbg(sprintf("val = %d  --->", val))
   _s = ""

   if (val >> 8){
       # Quality of output voltage not given at present
       _s = "QUA"
   }
   if (val >> 7){
       # Vmax or Imax is / was exceeded
       _s = _s " ERR"
   }
   if (val >> 6){
       # INHIBIT signal was/ is active
       _s = _s " INH"
   }
   if (val >> 5){
       # KILL-ENABLE  is on
       _s = _s " KILL_ENA"
   }
   if (val >> 4){
       # Front panel HV-ON is OFF
       _s = _s " OFF"
   }
   if (val >> 3){
       # Polarity set to positive
       _s = _s " POL"
   }
   if (val >> 2){
       # control is manual
       _s = _s " MAN"
   }
   if (val >> 1){
       _s = _s " T?"
   }

   return (_s)
}'





#%IU% (mne)
#%MDESC%
#    Returns Module Status of one NHQ module.      "T" command
def _nhq_mod_status(mne) '{
   local str _s val

   #             "T1"
   str = sprintf("T%1d", NHQ_PAR[mne]["channel"])
   val = _nhq_send(mne, str)

   nhq_dbg(sprintf("val = %d  --->", val))
   _s = ""

   if (val & 0x80){
       # Quality of output voltage not given at present
       _s = "\n QUA : Quality of output voltage not given at present"
   }
   if (val & 0x40){
       # Vmax or Imax is / was exceeded
       _s = _s "\n ERR : Vmax or Imax is / was exceeded"
   }
   if (val & 0x20){
       # INHIBIT signal was/ is active
       _s = _s "\n INH : INHIBIT signal was/ is active"
   }
   if (val & 0x10){
       # KILL-ENABLE  is on
       _s = _s "\n KILL_ENA : KILL-ENABLE  is on"
   }
   if (val & 0x08){
       # Front panel HV-ON is OFF
       _s = _s "\n OFF : Front panel HV-ON is OFF"
   }
   if (val & 0x04){
       # Polarity set to positive
       _s = _s "\n POL : Polarity set to positive"
   }
   if (val & 0x02){
       # control is manual
       _s = _s "\n MAN : control is manual"
   }
   if (val & 0x00){
       _s = _s " "
   }

   return (_s)
}'

#%IU% (mne)
#%MDESC%
#    Returns ID of one NHQ channel.
def _nhq_id(mne) '{
    local str

   str = _nhq_send(mne, "#")

   return (str)
}'

######################################################################
########################                      ########################
########################  Voltage Operations  ########################
########################                      ########################
######################################################################

#%UU% [<mne>] [<voltage>]
#%MDESC%
#    Sets voltage of NHQ.
def nhq_set_voltage '{
    local _vvalue _nb_param _msg  _mne
    local _delta_voltage   _current_voltage   _ramp  _wait_time

    _nb_param = $#

    if ( _nb_param == 2){
        _mne = "$1"

        if (!motor_valid(_mne)){
            nhq_err(sprintf( "Invalid motor mne : \"%s\"  \n ->exit", _mne))
            exit
        }

        _vvalue = "$2"

        if(!is_number_in_range(_vvalue,  NHQ_PAR[mne]["minVoltage"], NHQ_PAR[mne]["maxVoltage"])){
            nhq_err(sprintf("Invalid voltage \"%s\"", _vvalue))
            nhq_err(sprintf("Voltage range is  [%g ; %g]",  NHQ_PAR[mne]["minVoltage"], NHQ_PAR[mne]["maxVoltage"]))
            exit
        }
    }
    else if(_nb_param == 1) {
        _mne = "$1"

        if (!motor_valid(_mne)){
            nhq_err(sprintf( "Invalid motor mne : \"%s\"  \n ->exit", _mne))
            exit
        }

        _vvalue = getval_number_interval("Voltage to set for NHQ", NHQ_PAR["nhq"]["last_voltage"], 0 , 1000)
    }
    else{
        print "Usage:  nhq_set_voltage [<mne>] [<voltage>]"
        exit
    }

    NHQ_PAR["nhq"]["last_voltage"] = _vvalue


    if (NHQ_PAR["secure"]){
        nhq_msg(sprintf("current voltage = %g ", _current_voltage = _nhq_get_voltage(_mne)))
        nhq_msg(sprintf("delta voltage = %g", _delta_voltage = fabs(_current_voltage - _vvalue)))
        nhq_msg(sprintf( "ramp = %g ", _ramp = _nhq_get_ramp(_mne)))

        if (_ramp > 0){
            nhq_msg(sprintf("wait time = %g", _wait_time  = _delta_voltage / _ramp))
        }
        else{
            nhq_err("ramp is <= 0 !?!")
            exit
        }
    }

    nhq_dbg(sprintf("I will require %g Volts for NHQ \"%s\"", _vvalue, _mne))
    _nhq_set_voltage(_mne, _vvalue)

    if (NHQ_PAR["secure"]){
        local _time_to_wait  _waited_time _time0

        # waits time for NHQ to reach requiered voltage + 10%

        _time0 = time()
        _time_to_wait = _wait_time*1.1+1

        _waited_time  = time() - _time0
        nhq_msg(sprintf("_waited_time =%g  _time_to_wait=%g", _waited_time, _time_to_wait))

        while (_time_to_wait > _waited_time ){
            sleep(1)
            _waited_time  = time() - _time0
            nhq_msg(sprintf("current voltage = %g ", _current_voltage = _nhq_get_voltage(_mne)))
        }

        # Checks that current voltage is aroud requiered voltage.
        nhq_msg(sprintf("current voltage = %g ", _current_voltage = _nhq_get_voltage(_mne)))
        if (is_aprox(_vvalue, _current_voltage, 1)){
            nhq_msg("ok")
        }
        else{
            nhq_err("OULALA")
            nhq_msg(sprintf("current voltage = %g ", _current_voltage = _nhq_get_voltage(_mne)))
        }
    }
}'



#%IU% (mne, voltage)
#%MDESC%
#    Sets voltage of NHQ.
def _nhq_set_voltage(mne, voltage) '{
   local str

   if (voltage < 0) {
        nhq_err("--NHQ error _nhq_set_voltage : voltage must be positive")
   }
   else{
       # send command "D1=xxx" : Set voltage for channel 1
       str = sprintf("D%1d=%d", NHQ_PAR[mne]["channel"], voltage)
       # print "str = " str
       str = _nhq_send(mne, str)
       # get ???
       # printf("nhq_set_voltage(): get %s\n", str)

       # send command "G1" : Start Voltage change for channel 1
       str = sprintf("G%1d", NHQ_PAR[mne]["channel"])
       str = _nhq_send(mne, str)
       # ???
       # printf("nhq_set_voltage(): get %s\n",str)
   }
}'



#  Extract a number from <str> string.
# <str> is like : "+00001-0"
def _nhq_get_float(str) '{
    local float_str  idx
    local value

    float_str = str

    if(idx = index(substr(float_str, 2),"-")) {
        idx += 1
        float_str = substr(str, 0, idx-1) "e" substr(str,idx)
    }

    if (sscanf(float_str, "%f", value) == 0) {
        nhq_err(sprintf ("Error on _nhq_get_float, got %s\n", str))
        global TTT[]
        TTT[0]=str
        print TTT
        return("get_float_error")
    }

    return value

}'

#%IU% (mne)
#%MDESC%
#    Returns voltage of NHQ   "U" command
#
#    Returns an ABSOLUTE value (???)
#
def _nhq_get_voltage(mne) '{
   local str ii value


   str = sprintf("U%1d", NHQ_PAR[mne]["channel"])

   str = _nhq_send(mne, str)

   value = _nhq_get_float(str)

   if (value < 0 ){
       NHQ_PAR[mne]["polarity"] = "NEGATIVE"
   }
   else{
       NHQ_PAR[mne]["polarity"] = "POSITIVE"
   }
   return fabs(value)
}'


#%IU% (mne)
#%MDESC%
#    Returns Voltage limit of NHQ ;  "M" command
#
#    Returns an ABSOLUTE value ###
#
def _nhq_get_voltage_limit(mne) '{
   local str ii value


   str = sprintf("M%1d", NHQ_PAR[mne]["channel"])

   str = _nhq_send(mne, str)

   if (sscanf(str, "%f", value) == 0) {
       nhq_err(sprintf ("Error on _nhq_get_voltage_limit, got %s\n", str))
       global TTT[]
       TTT[0]=str
       print TTT
   }
   else {
       return fabs(value)
   }

   return (-1)
}'



#######################################################################
#########################                      ########################
#########################  CURRENT OPERATIONS  ########################
#########################                      ########################
#######################################################################

#%IU% (mne)
#%MDESC%
#    Returns current of NHQ   "I" command
def _nhq_get_current(mne) '{
   local str ii value

   for (ii=0 ; ii<3 ; ii++) {

       str = sprintf("I%1d", NHQ_PAR[mne]["channel"])
       str = _nhq_send(mne, str)

       value = _nhq_get_float(str)
       return (value)
   }
   return (-1)
}'


#%IU% (mne)
#%MDESC%
#    Returns Current limit of NHQ ;  "N" command
def _nhq_get_current_limit(mne) '{
   local str ii value

   str = sprintf("M%1d", NHQ_PAR[mne]["channel"])
   str = _nhq_send(mne, str)

   if (sscanf(str, "%f", value) == 0) {
       nhq_err(sprintf ("Error on _nhq_get_current_limit, got %s\n", str))
       global TTT[]
       TTT[0]=str
       print TTT

   }
   else{
       return (value)
   }

}'


#%IU% (mne)
#%MDESC%
#    Returns Current Trip of NHQ ;  "L" command
def  _nhq_get_current_trip(mne)'{
   local str ii value

   str = sprintf("L%1d", NHQ_PAR[mne]["channel"])
   str = _nhq_send(mne, str)

   if (sscanf(str, "%f", value) == 0) {
       nhq_err(sprintf ("Error on _nhq_get_current_trip, got %s\n", str))
       global TTT[]
       TTT[0]=str
       print TTT

       return (-1)
   }
   else {
       return (value)
   }
}'


#%IU% (mne)
#%MDESC%
#    Returns Current Trip of NHQ ;  "L" command
def  _nhq_set_current_trip(mne, wert)'{
   local str ii value


   str = sprintf("L%1d=%g", NHQ_PAR[mne]["channel"], wert)

   str = _nhq_send(mne, str)

   if (sscanf(str, "%f", value) == 0) {
       nhq_err(sprintf ("Error on _nhq_get_current_trip, got %s\n", str))
       global TTT[]
       TTT[0]=str
       print TTT

   }
   else{
       return (value)
   }
}'

######################################################################
#########################                    #########################
#########################  Ramps Operations  #########################
#########################                    #########################
######################################################################


#%UU% mne [ramp_speed]
#%MDESC%
#    Sets ramp speed of NHQ
def nhq_ramp '{
    local _value _mne

    if ($#<1 || $#>2) {
        print "Usage: nhq_ramp mne [ramp_speed in V/sec]"
        exit
    }

    _mne   = "$1"

    if ($#>1) {
        _value = "$2" + 0.00

        if (list_item(NHQ_PAR, _mne)==-1){
            nhq_err("_nhq_ramp error : invalid motor mnemonic")
            exit
        }
    
        _nhq_set_ramp(_mne, _value)
    }

    # always print out the current ramp speed
    _value = _nhq_get_ramp(_mne)
    nhq_msg(sprintf("Ramp speed: %d V/s", _value))
}'


#%IU% (mne, ramp)
#%MDESC%
#    Sets ramp speed of NHQ.     "Vn=xxxx" command
def _nhq_set_ramp(mne, ramp) '{
    local str

    str = sprintf("V%1d=%d", NHQ_PAR[mne]["channel"] , ramp)
    _nhq_write(mne, str)
    sleep(1)

}'

#%IU% (mne)
#%MDESC%
#    Gets ramp speed of NHQ.          "V" command
def _nhq_get_ramp(mne) '{
   local _str_cmd  _str_ans  value

   _str_cmd = sprintf("V%1d", NHQ_PAR[mne]["channel"])

   _str_ans = _nhq_send(mne, _str_cmd)


   if (sscanf(_str_ans, "%d", value)==0) {
       nhq_err(sprintf("Error on _nhq_get_ramp, got %s\n", _str_ans))
       global TTT[]
       TTT[0]=str
       print TTT

       return (-1)
   }
   else{
       return (value)
   }

}'


#%IU% <mne>
#%MDESC%
#    Read "break time" from NHQ device ("W" commad)
def _nhq_get_break_time(mne)'{
    local _str_cmd  _str_ans  value

    _str_cmd = sprintf("W")

    _str_ans = _nhq_send(mne, _str_cmd)

    if (sscanf(_str_ans, "%d", value)==0) {
        nhq_err(sprintf("Error on _nhq_get_break_time, got %s\n", _str_ans))
        global TTT[]
        TTT[0]=str
        print TTT

        return (-1)
    }
    else {
        return(value)
    }
}'


#%IU% <mne> , <break_time>
#%MDESC%
#    Write "break time" from NHQ device ("W" commad)
# <break_time> : 2..255 ms
def _nhq_write_break_time(mne, break_time)'{
    local _str_cmd  _str_ans  value

    _str_cmd = sprintf("W=%d", break_time)
    _str_ans = _nhq_send(mne, _str_cmd)

    if (sscanf(_str_ans, "%d", value)==0) {
        nhq_err(sprintf("Error on _nhq_get_break_time, got %s\n", _str_ans))
        global TTT[]
        TTT[0]=str
        print TTT
        return (-1)
    }
    else {
        return(value)
    }
}'



######################################################################
#######################                         ######################
#######################  Pseudos counter/motor  ######################
#######################                         ######################
######################################################################

#%UU% (mne)
#%MDESC%
#    Defines the nhq mne as pseudo c(ounter) and pseudo m(otor)%BR%
#    Pseudo names are: "mne"_c for counter, "mne" for motor
def nhq_pseudo_setup(mne) '{
    global NHQ_PAR[]

    local ps_type ps_mne _cnt_mne _mot_mne _key

    _cnt_mne =  NHQ_PAR[mne]["pseudo_cnt_mne"]
    _mot_mne =  NHQ_PAR[mne]["pseudo_mot_mne"]

    nhq_dbg(sprintf("Setting up pseudos for \"%s\"",mne))

    # Pseudo counter.
    _cnt_num = cnt_num(_cnt_mne)
    if (_cnt_num != -1) {
        S[_cnt_num]= 0
    }

    cdef ("user_getcounts", sprintf( "\n_nhq_getcounts(\"%s\");", mne), _cnt_mne, 0x02)

    # Pseudo motor.
    _mot_num = motor_num(_mot_mne)
    if (_mot_num != -1) {
        A[_mot_num] = 0
    }

    cdef ("user_getpangles", sprintf("\n _nhq_getpangles(\"%s\");",mne), _mot_mne, 0x01)
    cdef ("user_checkall",   sprintf("\n _nhq_checkall(\"%s\");",  mne), _mot_mne, 0x01)
}'


#%UU%
#%MDESC%
#    Undefines the nhq mne as pseudo c(ounter) and pseudo m(otor)
def nhq_pseudo_unsetup '{
    for (ii = 0;  ii< list_n(NHQ_PAR) ; ii++){
        _mne = NHQ_PAR[ii+1]
        _cnt_mne =  NHQ_PAR[_mne]["pseudo_cnt_mne"]
        _mot_mne =  NHQ_PAR[_mne]["pseudo_mot_mne"]

        nhq_dbg(sprintf("Desactivating pseudos for \"%s\"",_mne))
        cdef ("user_checkall",   "", _mot_mne, "delete")
        cdef ("user_getpangles", "", _mot_mne, "delete")
        cdef ("user_getcounts",  "", _cnt_mne, "delete")
    }
}'


#%IU% (mne)
#%MDESC%
#
def _nhq_getpangles(mne) '{
    local _mne_m _mot_num

    if (NHQ_PAR[mne]["pseudo_mot_on"]){
        _mne_m = mne

        if (motor_num(_mne_m) < 0){
            nhq_err("_nhq_getpangles error : invalid motor mnemonic")
            exit
        }

        _mot_num = motor_num(_mne_m)

        A[_mot_num]=_nhq_get_voltage(mne)
        NHQ_PAR[mne]["pos"] = A[_mot_num]
    }
}'


#%IU% (mne)
#%MDESC%
#
def _nhq_checkall(mne) '{
    local _mne_m _mot_num

    if (NHQ_PAR[mne]["pseudo_mot_on"]){
        _mne_m = mne

        if (motor_num(_mne_m) < 0){
            nhq_err("_nhq_checkall error : invalid motor mnemonic")
            exit
        }

        _mot_num = motor_num(_mne_m)

        NHQ_PAR[mne]["pos"] = A[_mot_num]
        _nhq_set_voltage(mne, A[_mot_num])
    }
}'


#%IU% (mne)
#%MDESC%
#    Reads voltage and places it in S array.
def _nhq_getcounts(mne) '{
    global NHQ_PAR[]

    local _mne_c _mne_i

    if (NHQ_PAR[mne]["pseudo_cnt_on"]){
        _mne_c = NHQ_PAR[mne]["pseudo_cnt_mne"]
        _mne_i = NHQ_PAR[mne]["pseudo_cnt_mne_i"]

        if ((cnt_num(_mne_c)<0) || (cnt_num(_mne_i)<0)){
            nhq_err("_nhq_getcounts error : invalid counter mnemonic")
            exit
        }

        if (NHQ_PAR[mne]["polarity"] == "NEGATIVE"){
            S[cnt_num(NHQ_PAR[mne]["pseudo_cnt_mne"])] = -_nhq_get_voltage(mne)
        }
        else{
            S[cnt_num(NHQ_PAR[mne]["pseudo_cnt_mne"])] = _nhq_get_voltage(mne)
        }

        if (cnt_exists(_mne_i)){
            S[cnt_num(NHQ_PAR[mne]["pseudo_cnt_mne_i"])] = _nhq_get_current(mne)
        }
    }
}'


#%UU% [mne]
#%MDESC%
#    Activates pseudo counter/motor for NHQ given its mnemonic.
def nhq_on '{
    local nb_param ii

    nb_param = $#

    if (nb_param >0 ){
        list_setpar(NHQ_PAR, mne, "pseudo_cnt_on", 1)
        list_setpar(NHQ_PAR, mne, "pseudo_mot_on", 1)
    }
    else{
        for (ii=0 ; ii<list_n(NHQ_PAR) ; ii++){
            list_setpar(NHQ_PAR, NHQ_PAR[ii+1], "pseudo_cnt_on", 1)
            list_setpar(NHQ_PAR, NHQ_PAR[ii+1], "pseudo_mot_on", 1)
        }
    }
}'

#%UU% [mne]
#%MDESC%
#    Undefines pseudo counter/motor for NHQ given its mnemonic.
def nhq_off '{
    global NHQ_PAR[]

    local nb_param

    nb_param = $#

    if (nb_param >0){
        # OFF for device mne.
        list_setpar(NHQ_PAR, mne, "pseudo_cnt_on", 0)
        list_setpar(NHQ_PAR, mne, "pseudo_mot_on", 0)

        if (cnt_num(NHQ_PAR[mne]["pseudo_cnt_mne"]) != -1) {
            S[NHQ_PAR[mne]["pseudo_cnt_mne"]]= 0
        }

        if (motor_num(NHQ_PAR[mne]["pseudo_mot_mne"]) != -1) {
            A[NHQ_PAR[mne]["pseudo_mot_mne"]]= 0
        }
    }
    else{
        # OFF for all devices.

        for (ii=0 ; ii<list_n(NHQ_PAR) ; ii++){
            list_setpar(NHQ_PAR, NHQ_PAR[ii+1], "pseudo_cnt_on", 0)
            list_setpar(NHQ_PAR, NHQ_PAR[ii+1], "pseudo_mot_on", 0)
        }
    }
}'


def nhq_test_R '{
    local ii
    ii = 0

    while(1)  {  printf("%d:V.=%g    ", ii, _nhq_get_voltage("nhq")) ; ii++}
}'

def nhq_test_WR '{
    local  vv  ii
    ii = 0
    vv = 1

    while(1)  {
        if(vv >20){
            vv = 0
        }
        _nhq_set_voltage("nhq", vv)
        vv += 0.2
        printf("%d:V.=%5g    ", ii, _nhq_get_voltage("nhq")) ; ii++
    }
}'


#%MACROS%
#%IMACROS%
#%AUTHOR%
#  NHQ204M.MAC  AG 2.98 EP 3.03  CG X.2008
#%TOC%