esrf

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

#%TITLE% ELMETER.MAC
#$Revision: 2.17 $
#%NAME%
#  %B%ELMETER.MAC%B% - Macros for %B%electrometer%B% control.
#
#%DESCRIPTION%
#   This macro set provides the possibility to read electrometers
#   with automatic gain adujustement.
#
#%PRE%
#
#Three types of electrometers are supported for the moment:
#
#%UL%
#%LI%Type 0: ADC reading with three input lines with all bit combinations for gain adjustment. Eight posible gain values are posible.
#
#%LI%Type 1: ADC reading with three input lines with exclusive values. Only three gain values are posible.
#
#%LI%Type 2: Other type. The macros do not read the counter value but other macros or SPEC itself take care of that. The min/max thresholds are normalized with counting time. For the moment, in this case only three mutually exclusive input lines are used for gain adjustment.
#
#Electrometers are seen in SPEC as counters and must be defined as such in SPEC config.
#
#%LI%Type 3: ID11 electrometers. Like type 1 only that the gains can vary in elmeteradd you need to supply ( not the min gain ) but the gains for the three relay positions.
#%LI%Type 4: Like type 3  but with a vmeadc linux device server madc
#%LI%Type 5: Novelec on a WAGO box. First trial 25.1.2005
#%LI%Type 6: Novelec on a WAGO box. Value is read with icv150 (petitdem).
#%LI%Type 7: gain + adc control by wago (petitdem).
#%XUL%
#
#%BR%

#%UL%
#%SETUP%
#Use the setup command:
#%LI%Start electrometer definition with a line containing %B%elmeterinit%B%
#Use %B%elmeteradd%B% to configure a new electrometer.
#%LI%To setup several electrometers, use %B%elmeteradd%B% several times.
#Without parameters elmeteradd allows keyboard entry for setup.
#
#%XUL%
#
#%END%

#%HISTORY%
#$Log: elmeter.mac,v $
#Revision 2.17  2017/03/09 15:18:09  ohlsson
#Just a small bug in the debug - the wago readout was not displayed
#
#Revision 2.16  2017/02/10 15:44:21  witsch
#between version 2.15 and 2.16, only the order of the elmeter gain cells
#were reversed. version 2.15 has been deleted from the packages, as they
#can't work correctly.
#
#Revision 2.15  2017/01/19 15:26:30  witsch
#and beautify the code a little.
#
#Revision 2.14  2016/11/18 13:48:46  witsch
#Adapt type 5 to the use of wagocore macros, avoid esrf_io(), so that
#both tango and taco device servers can be used.
#
#Also arguments 3, 4 and 5 have been eliminated from the arguments
#treatment, as they are not needed for type 5 electrometers.
#
#
#Revision 2.13  2012/05/03 16:24:27  petitdem
#add type 7 gain + adc control by wago
#
#Revision 2.12  2011/07/28 13:00:44  beteva
#added channel to be read in elmeteradd; type 6 to be madc
#
#Revision 2.11  2011/07/25 14:18:30  beteva
#Change type 4 to read MADC instead of Icvadc
#
#Revision 2.10  2011/02/22 15:46:23  witsch
#instead of count_em use tcount, in order to avoid prepcount to call a
#
#all the other devices' prepcount.
#
#Revision 2.9  2010/09/17 11:29:54  petitdem
#correct some bugs for type 6 (Wagi + IcvADC)
#
#Revision 2.8  2010/09/01 15:13:08  petitdem
#add type 6 it's a mix with type 5 and type 3: gain is control with Wago and value is read with icv150
#
#Revision 2.5  2005/03/31 14:36:37  witsch
#Added type 5 quite similar to type 2 for the use with a Wago box for the gain
#whereas the electrometer is still read through the VCT6.
#
#Revision 2.4  2004/08/27 11:31:33  claustre
#Added type 4 quit similar to type 3 but has to be used with Linux IcvADC and  Relay device server
#
#Revision 2.3  2003/02/10 10:51:28  witsch
#take out the cdef for user_pollcount, as it causes a loop at execution.
#
#Revision 2.2  2002/04/29 15:33:21  witsch
#Enter changes made by Laurent to make sure that the data collector
#entry is present when the first elmeter_set() is done. Apart from that
#a few cosmetic changes.
#
#Revision 2.1  2002/04/11 15:29:19  witsch
#The macro elmeteradd now accepts an argument more, which decides on the
#use of the data collector for storing the gain. The argument must be true
#to use the DC and false to omit the DC use.
#
#revision 2.0
#date: 2002/02/27 08:26:35;  author: witsch;  state: Exp;  lines: +27 -18
#After a long time of searching, a bug in elmeter_mread was found. The
#COUNT_TIME wasn't taken into account when using type 2 kind of elmeters.
#This made that for short counting times the count was low and the automatic
#gain adjustment didn't work.
#Apart from that we have a little cosmetic work..
#----------------------------
#revision 1.2
#date: 2002/02/27 08:14:29;  author: witsch;  state: Exp;  lines: +30 -28
#branches:  1.2.1;
#Move saved gain value from data base to the associative array
#which holds all the info about the elmeters.
#----------------------------
#revision 1.1
#date: 2002/02/27 08:10:45;  author: rey;  state: Exp;
#Initial revision
#%END%

if (!(whatis("__elmeterdebug")  & 2)) rdef __elmeterdebug \'#$*\'

#%UU%
#%MDESC% toggle debug mode for the present macros.
def elmeter_debug '{
  if ((whatis("__elmeterdebug")>>16) <= 5) { # just a # sign -> off
    rdef __elmeterdebug "eprint"
    print "elmeter debug is ON"
  } else {
    rdef __elmeterdebug \'#$*\'
    print "elmeter debug is OFF"
  }
}
'



#%UU% mne type icv150name icv150channel icv196name icv1596channel lowthresh highthresh [gain1 gain2 gain3|lowgain] usedatacoll
#%MDESC% Attention: different number of arguments for different types of electrometers.
def elmeteradd '{
    local mne adcdev channel reldev relfirst type
    local vmin vmax gmin
    gmin = 1; dcaccess = 0

    if (!(whatis("ELM_LIST") & 0x01000000)) elmeterinit

    if (!$#) {
        mne         = getval("Mnemonic for Electrometer counter", "")
        type        = getval("\tElectrometer type (0=ADC 3bit/1= ADC 3bit excl/2=Other/3=ID11/4=Linux ADCds/5=Wago Novelec)", 0)
        if (type == 1 || type == 3) {
            adcdev    = getval("\tICV150 Device name", "")
            channel   = getval("\tICV150 Channel", 0)
            reldev    = getval("\tICV196 Device root name", "")
            relfirst  = getval("\tICV196 First channel", 0)
        } else if (type == 4) {
            adcdev    = getval("\tLinux ICV150 Device name", "")
            reldev    = getval("\tICV196 Device root name", "")
            relfirst  = getval("\tICV196 First channel", 0)
        } else if (type == 5 || type == 6 || type == 7) {
            # reldev    = getval("\tWAGO device name", "")
            reldev    = getval("\tWago signal name for gain", "")
            if(type == 6)
            {
                adcdev    = getval("\tICV150 Device name", "")
                channel   = getval("\tICV150 Channel", 0)
            }
            else if(type == 7)
            {
                adcdev = getval("\tWago device name", "")
                channel = getval("\tWago signal name to read adc value", "")
            }
        }
        vmin        = getval("\tLow value threshold ", 0.8)
        vmax        = getval("\tHigh value threshold", 9)
        if (type == 3 || type == 4) {
            gain1    = getval("\t1st gain", 7)
            gain2    = getval("\t2nd gain", 8)
            gain3    = getval("\t3rd gain", 9)
        } else {
            gmin     = getval("\tLower gain", 4)
        }
        dcaccess    = yesno("\tUse the data collector to store the gain", "")
    } else {
        mne         = "$1"
        type        = $2
        if (type == 1 || type ==3 || type ==4 || type == 6 || type == 7) {
            adcdev   = "$3"
            channel  = "$4"
        } else if (type == 2) {
            adcdev   = "bidon"
            channel  = 0
        }
        reldev      = "$5"
        relfirst    = $6
        if (type == 5 || type == 6 || type == 7) {
            # skipt arguments 3 and 4, they`re not needed
            # reldev    = "$5" # wago resource name, set above
            vmin        = $7
            vmax        = $8
            gmin        = $9
            dcaccess    = "$10"
        } else {
            vmin        = $7
            vmax        = $8
            if (type == 3 ||type == 4) {
                gain1   = $9
                gain2   = $10
                gain3   = $11
                dcaccess= $12
            } else {
                gmin    = $9
                dcaccess= $10
            }
        }
    }

    #
    # Init and dccsetup
    #

    list_add(ELM_LIST, mne)
    list_setpar(ELM_LIST, mne, "adcdev", adcdev)
    list_setpar(ELM_LIST, mne, "channel", channel)
    list_setpar(ELM_LIST, mne, "reldev", reldev)
    list_setpar(ELM_LIST, mne, "relfirst", relfirst)
    list_setpar(ELM_LIST, mne, "type", type)
    list_setpar(ELM_LIST, mne, "cntnum", cnt_num(mne))
    list_setpar(ELM_LIST, mne, "vmin", vmin)
    list_setpar(ELM_LIST, mne, "vmax", vmax)
    list_setpar(ELM_LIST, mne, "gmin", gmin)

    if (dcaccess) {
        local dname
        dname = sprintf("%s/elmeter/%s", SPECBL, mne)
        list_setpar(ELM_LIST, mne, "dcaccess", dname)
        esrf_dc(dname, "create", "DevRead", "D_LONG_TYPE")
    } else {
        list_setpar(ELM_LIST, mne, "dcaccess", 0)
    }

    if (type == 3 || type == 4) {
        list_setpar(ELM_LIST, mne, "gain1", gain1)
        list_setpar(ELM_LIST, mne, "gain2", gain2)
        list_setpar(ELM_LIST, mne, "gain3", gain3)
        list_setpar(ELM_LIST, mne, "gmin", gain1)
        gain = list_getpar(ELM_LIST, mne, "gain")
        if (gain == 0 ) {
            list_setpar(ELM_LIST, mne, "gain", gain1)
        }
        elmeter_set(mne, gain1)
    if (type == 5) {
        local gain
        gain = _wago_elmeter_read(mne)
        list_setpar(ELM_LIST, mne, "gain", gain)
    } else {
        list_setpar(ELM_LIST, mne, "gain", gmin)
    }

    setup_tail("elmeter", "$1")
}'

#%UU%
#%MDESC%
# Sets all electrometers to minimum gain
#
def elmetermin '{
    local gain
    for (i=0;i<ELM_LIST[0];i++) {
        mne = ELM_LIST[i+1]
        type = list_getpar(ELM_LIST, mne, "type")
        if (type == 3 || type == 4) {
            gain = list_getpar(ELM_LIST, mne, "gain1")
        } else {
            gain = list_getpar(ELM_LIST, mne, "gmin")
        }
        elmeter_set(mne, gain)
    }
}'

#%IU%
#%MDESC%
# Use with blmenu
#
def elmeterbody(mode) '{
    if (mode == 1) {
        if (ELM_ON)  {
            elmeteroff
        } else {
            elmeteron
        }
    }

    if (mode == 2) {
        elmetershow
    }

    return(ELM_ON?"On":"Off")
}'


#%IU%
#%MDESC%
#
def elmeterinit '{
    global ELM_LIST

    list_init ELM_LIST
    blmenuadd("Electrometers", "Elmeter show", "elmeterbody", "_elmeter_")
    if (whatis("ELM_ON") & 0x8000000 ) elmeteron
}'

#%IU%
#%MDESC%
#
def elmeterunsetup '{
    elmeterdel("$1")
}'

#%UU% <counter mne>
#%MDESC% deletes from setup an electrometer.
#
def elmeterdel(mne) '{
    list_remove(ELM_LIST, mne)
}'

#%UU%
#%MDESC% shows the currently defined electrometers in setup.
#
def pindiode 'elmetershow '
def elmetershow '{
    local i j elmno mne
    local adcdev channel reldev relfirst type dcaccess
    local cntnum cntstate tmpgainNow gainnow vmin vmax gmin gmax cnum

    elmno = ELM_LIST[0]

    if (elmno) {
        for (i=0; i<elmno; i++) {
            mne[i]         = ELM_LIST[i+1]
            type[i]        = list_getpar(ELM_LIST, ELM_LIST[i+1], "type")
            if (type[i] != 2) {
                adcdev[i]    = list_getpar(ELM_LIST, ELM_LIST[i+1], "adcdev")
                channel[i]   = list_getpar(ELM_LIST, ELM_LIST[i+1], "channel")
            } else {
                cnum         = cnt_num(mne[i])
                if (cnum != -1 ) {
                    adcdev[i]    = counter_par(cnum, "controller")
                    channel[i]   = counter_par(cnum, "channel")
                } else {
                    adcdev[i]    = "Not config"
                    channel[i]   = 0
                }
            }
            reldev[i]    = list_getpar(ELM_LIST, ELM_LIST[i+1], "reldev")
            relfirst[i]  = list_getpar(ELM_LIST, ELM_LIST[i+1], "relfirst")
            cntnum[i]    = list_getpar(ELM_LIST, ELM_LIST[i+1], "cntnum")
            cntstate[i]  = (cntnum[i]==-1)?"No":"Yes"
            vmin[i]      = list_getpar(ELM_LIST, ELM_LIST[i+1], "vmin")
            vmax[i]      = list_getpar(ELM_LIST, ELM_LIST[i+1], "vmax")
            if ( type[i] == 3 ) {
                gmin[i]      = list_getpar(ELM_LIST, ELM_LIST[i+1], "gain1")
                gmax[i]      = list_getpar(ELM_LIST, ELM_LIST[i+1], "gain3")
            } else {
                gmin[i]      = list_getpar(ELM_LIST, ELM_LIST[i+1], "gmin")
                gmax[i]      = (type[i])?(gmin[i]+2):(gmin[i]+7)
            }
            gainnow[i]   = list_getpar(ELM_LIST, ELM_LIST[i+1], "gain")
            if (type[i] == 5) {     # read real value from wago
                gainnow[i] = _wago_elmeter_read(ELM_LIST[i+1])
            }
#~          if(tmpgainNow < gmin[i])
#~              tmpgainNow += 6 #~ not sure, what that was for !
            dcaccess[i]  = list_getpar(ELM_LIST, ELM_LIST[i+1], "dcaccess")
            __elmeterdebug "wago_readch:", mne[i], gainnow[i], x[0], x[1], x[2]
        }
        elmpr("Mnemonic", mne, elmno)
        elmpr("Defined", cntstate, elmno)
        elmpr("Type", type, elmno)
        printf("GAIN:\n")
        elmpr("Min", gmin, elmno)
        elmpr("Set", gainnow, elmno)
        elmpr("Max", gmax, elmno)
        printf("THRES:\n")
        elmpr("Low", vmin, elmno)
        elmpr("High", vmax, elmno)
        printf("DEV:\n")
        elmpr("CTRL", adcdev, elmno)
        elmpr("Channel", channel, elmno)
        elmpr("Relay", reldev, elmno)
        elmpr("R.1st Ch", relfirst, elmno)
        printf("DC:\n")
        elmpr("dcaccess", dcaccess, elmno)

    } else {
        printf("No electrometer defined\n")
    }
}'


#%IU%
#%MDESC%
#
def elmpr(label, var, n) '{
    local j

    printf("%10s: ", label)
    for (j=0;j<n;j++) {
        printf(" %12.12s", var[j])
    }
    printf("\n")
}'

#%IU%
#%MDESC% Enables all electrometer counters
#
def elmeteron '{
    global ELM_AVER ELM_NOREAD ELM_ON ELM_GAIN
    global ELM_UPDATING

    local i elmno

    ELM_ON = 1

    cdef("user_prepcount",  "elmeter_prepcount;", "elmeter")
    cdef("user_getcounts",  "elmeter_getcounts;", "elmeter")

    elmno = ELM_LIST[0]

    for (i=0; i<elmno; i++) {
        local num mne

        mne = ELM_LIST[i+1]
        num = cnt_num(mne)

        if (num != -1) counter_par (num, "disable", 0)
    }
}'


#%UU%
#%MDESC% Disables all electrometer counters
#
def elmeteroff '{
    local elmno i

    ELM_ON = 0
    cdef("", "", "elmeter", "delete")

    elmno = ELM_LIST[0]

    for (i=0; i<elmno; i++) {
        local num mne

        mne = ELM_LIST[i+1]
        num = cnt_num(mne)

        if (num != -1) counter_par(num, "disable", 1)
    }
}'

#%IU%
#%MDESC%
#
def elmeter_prepcount '{
    local i elmno gain, type
    elmno = ELM_LIST[0]

    elmupdate

    for (i=0; i<elmno; i++) {
        ELM_AVER[i]    = 0
        ELM_NOREADS[i] = 0
    }

    ELM_UPDATING=0

    if (COUNT_TIME < 0) {
        if (cnt_mne(MON) > 0) {
            gain  = list_getpar(ELM_LIST, cnt_mne(MON), "gain")
            type  = list_getpar(ELM_LIST, cnt_mne(MON), "type")
            if (type == 5) {
                gain = _wago_elmeter_read(cnt_mne(MON))
                list_setpar(ELM_LIST, mne, "gain", gain)
            }
            COUNT_TIME = COUNT_TIME * exp10(gain)
            COUNT_TIME /= exp10(10)
        }
    }

}'

#%IU%
#%MDESC%
#
def elmeter_getcounts '{
    local i elmno type

    elmno = ELM_LIST[0]

    # next macro OK for type 0 and 1 also after count
    # for type 2 exit is done from elmeter_mread
    # for type 2 get counts automatically?

    elmeter_mread

    for (i=0; i<elmno; i++) {
        local num mne

        mne = ELM_LIST[i+1]
        num = cnt_num(mne)

        if (num == -1 || counter_par(num, "disable") == 1) continue

        # for type 2 exit is done here
        type = list_getpar(ELM_LIST, mne, "type")

        #
        # For type 0 and 1. Just show average.
        #
        if (type != 2 && type != 5) {
            if (num != -1 ) {
                S[num] = ELM_AVER[i] * counter_par(num, "scale") / ((ELM_NOREADS[i]==0)?1:ELM_NOREADS[i]);
            } else {
                printf("Wrong counter number. Internal macro error\n")
            }
        } else {
            if (!ELM_UPDATING) {
                gain  = list_getpar(ELM_LIST, mne, "gain")
                # type 5, gain has been read in user_prepcount
                __elmeterdebug "original value", mne, S[num], "to be devided with exp10(" gain - 1 ")", exp10(gain - 1)

                S[num] /= exp10(gain - 1)
            }
        }
    }
}'


#%IU%
#%MDESC% For ADC type electrometers (type 0 and 1), since read/gain corrected
#        during counting
#
def elmeter_mread '{
    local val i ell elmno iter num

    elmno = ELM_LIST[0]
    for (ell=0; ell<elmno; ell++) {
        local inloop mne chan adcdev
        local vmin vmax gmin gmax type
        local gain num

        mne     = ELM_LIST[ell+1]
        num = cnt_num(mne)

        if (num == -1 || counter_par(num, "disable") == 1) continue

        vmin    = list_getpar(ELM_LIST, mne, "vmin")
        vmax    = list_getpar(ELM_LIST, mne, "vmax")
        type    = list_getpar(ELM_LIST, mne, "type")
        if (type == 3 || type == 4) {
            gmin    = list_getpar(ELM_LIST, mne, "gain1")
            gain2   = list_getpar(ELM_LIST, mne, "gain2")
            gmax    = list_getpar(ELM_LIST, mne, "gain3")
        } else if(type == 6 || type == 7){
            gmin = 1
            gmax = 3
        } else {
            gmin    = list_getpar(ELM_LIST, mne, "gmin")
            gmax    = (type)?(gmin+2):(gmin+7)
        }
        gain    = list_getpar(ELM_LIST, mne, "gain")
        if (type == 5) {
            gain = _wago_elmeter_read(mne)
        }

        if ((num = cnt_num(mne)) == -1) continue

        inloop = 1
        iter   = 0

        while (inloop) {


            if (type == 2 || type == 5)  {
                # HW20020214 begin
                # The counter will deliver a count, which already takes
                # the scaling factor into account. To get the real value, we
                # have to multiply the given value with the scaling factor.
                # However the longer you read the more counts you get!
                # Devide by count_time
                # HW20020214 end
                val=S[num] * counter_par(num, "scale")
                val /= COUNT_TIME
            } else {
              val = _adc_read(mne)
              if (val == -1) { break }
            }

            if (ELM_FIXED) { break }

            if ( fabs(val) < vmin ) {
                if ( gain  < gmax ) {
                    if ( type == 3 || type == 4) {
                        if ( gain == gmin ) {
                            gain = gain2
                        } else if ( gain != gmin ) {
                            gain = gmax
                        }
                    } else {
                        gain++
                    }
                    elmeter_set( mne , gain)
                } else {
                    inloop = 0
                }
            } else {
                if ( fabs(val) > vmax ) {
                    if ( gain > gmin ) {
                        if ( type == 3 || type == 4) {
                            if ( gain == gmax ) {
                                gain = gain2
                            } else if ( gain != gmax ) {
                                gain = gmin
                            }
                        } else {
                            gain--
                        }
                        elmeter_set(mne, gain)
                    } else {
                        inloop = 0
                    }
                } else {
                    inloop = 0
                }
            }
            if (iter++ > 10) inloop = 0

            if (inloop == 1 && (type == 2 || type == 5)) {
                __elmeterdebug "inloop elmeter_mread"
                elmeter_prepcount
                tcount(COUNT_TIME)
                # -- count_em COUNT_TIME
                waitcount
                getcounts
            }
        }

        gain  = list_getpar(ELM_LIST, mne, "gain")

        if ( type == 3 || type == 4) {
            coeff = 9  - gain
            val *= exp10(coeff)
        } else if(type == 6 || type == 7) {
            coeff = (6 + gain) * -1
            val *= exp10(coeff)
        } else {
            val /= exp10(gain)
            val *= exp10(9)
            val /= 2.0
        }

        # 258199 = overflow
        if (ESRF_ERR == 0 || ESRF_ERR == 258199) {
            if (type != 2 && type != 5) {
                ELM_AVER[ell]   += val
                ELM_NOREADS[ell]++;
            }
        }

        if (type == 2 || type == 5) {
            ELM_AVER[ell]    == val;
            ELM_NOREADS[ell] == 1;
        }

    }
}'


#%UU%
#%MDESC%
#    For interactive use
#
def elmeterfix '{
    global ELM_FIXED

    printf("Electrometer gains were ")
    tty_cntl("md")
    printf("%s", ELM_FIXED?"Fixed":"Not fixed")
    tty_cntl("me")
    printf(". Now they are ")
    if (ELM_FIXED) {
        ELM_FIXED=0
    } else {
        ELM_FIXED=1
    }
    tty_cntl("md")
    printf("%s\n", ELM_FIXED?"Fixed":"Not fixed")
    tty_cntl("me")
}'

#%IU%
#%MDESC%
#    For interactive use
#
def elmetergain '{
    if ($# == 2) {
        elmeter_set("$1", $2)
    } else  if ($# == 1) {
        local gain mne, type
        mne = cnt_mne($1)
        type = list_getpar(ELM_LIST, mne, "type")
        gain = list_getpar(ELM_LIST, mne, "gain")
        if (type == 5) {
            gain = _wago_elmeter_read(mne)
        }
        print "Elmeter gain for counter", mne, "is", gain
    } else
        elmetershow
}'

#%IU%
#%MDESC%
#
def elmeter_set(mne, gain) '{
    printf("counter %s: gain -> %d\n", mne, gain)
    local k el_old dcaccess
    local type gmin gmax reldev relroot relfst

    #  print " <ELMETER> Setting gain on " cnt_mne(mne) " to " gain
    type    = list_getpar(ELM_LIST, mne, "type")
    if (type == 3 || type == 4) {
        gain1    = list_getpar(ELM_LIST, mne, "gain1")
        gain2    = list_getpar(ELM_LIST, mne, "gain2")
        gain3    = list_getpar(ELM_LIST, mne, "gain3")
    } else {
        gmin    = list_getpar(ELM_LIST, mne, "gmin")
    }
    relroot = reldev = list_getpar(ELM_LIST, mne, "reldev")
    relfst  = list_getpar(ELM_LIST, mne, "relfirst")

    if ( type == 0) {
        setval = gmin - gain + 7

        for (k=0;k<3;k++) {
            reldev = sprintf("%s/%.2d", relroot, relfst+k)
            esrf_io(reldev , setval&(1<<k)?"DevClose":"DevOpen")
        }
    }

    if (type == 1 || type == 2) {
        setval = gmin - gain + 2

        for (k=0;k<3;k++) {
            reldev = sprintf("%s/%.2d", relroot, relfst+k)
            esrf_io(reldev, (setval == k)?"DevClose":"DevOpen")
        }
    } else if ( type == 3 || type == 4) {
        if ( gain == gain1 ) {
            setval = 0
        } else if ( gain == gain2 ) {
            setval = 1
        } else if ( gain == gain3 ) {
            setval = 2
        } else {
            print "    Wrong gain for type 3"
            print "      Only values " gain1", " gain2 " and " gain3 " are allowed."
            notok=1
        }
        if (!notok) {
            for (k=0;k<3;k++) {
                if (type == 4)
                reldev = sprintf("%s%.2d", relroot, relfst+k)
                else
                reldev = sprintf("%s/%.2d", relroot, relfst+k)
                esrf_io(reldev, (setval == k)?"DevOpen":"DevClose")
            }
        }
    } else if (type == 5 || type == 6 || type == 7) {
        if ( gain >= 1 && gain <= 3 )
        {
            local x[]
            x[0] = x[1] = x[2] = 0  # set all zero
            x[3 - gain] = 1         # set the one element
            __elmeterdebug "wago_writech:", mne, gain, x[0], x[1], x[2]
            wago_writech(reldev, x)
        }
        else
            eprint "Values for wago gain must be (1, 2 or 3)"
    }

    list_setpar(ELM_LIST, mne, "gain", gain)

    dcaccess= list_getpar(ELM_LIST, mne, "dcaccess")

    if (dcaccess) {
        esrf_dc(dcaccess, "put", gain)
    }

}'

def elmget '{
    if ($#) {
        elmeter_gainadj($1)
    }  else {
        elmeter_gainadj(1)
    }

}'

#%IU%
#%MDESC%
#    Adjusts the gains for all electrometers
#
def elmeter_gainadj(ctime) '{

    local i elmno
    local mne
    local k el_old
    local type gmin gmax vmin vmax
    local inloop


    elmno = list_n(ELM_LIST)

    #
    # Now take care of type 2 electrometers
    #
    iter   = 0
    inloop = 1

    while(inloop) {

        iter++

        #
        # Count and wait for "ctime" seconds
        #
        count_em ctime
        waitcount; ELM_UPDATING=1; get_counts

        elm2no = 0
        elmok  = 0

        for (i=0; i<elmno; i++) {
            local num ctnorm

            mne  = list_item(ELM_LIST, i+1)
            type = list_getpar(ELM_LIST, mne, "type")

            if (type == 5) {
                gain = _wago_elmeter_read(mne)
                list_setpar(ELM_LIST, mne, "gain", gain)
            }

            if (type != 2 && type != 5) continue


            vmin = list_getpar(ELM_LIST, mne, "vmin")
            vmax = list_getpar(ELM_LIST, mne, "vmax")
            gmin = list_getpar(ELM_LIST, mne, "gmin")
            gain = list_getpar(ELM_LIST, mne, "gain")
            gmax = gmin + 2

            num  = cnt_num(mne)
            if ( num == -1 ) continue

            elm2no++

            ctnorm = S[num]/ctime

            if ( fabs(ctnorm) < vmin ) {
                if ( gain  < gmax ) {
                    gain++
                    elmeter_set(mne , gain )
                } else {
                    elmok++
                }
            } else if ( fabs(ctnorm) > vmax ) {
                if ( gain > gmin ) {
                    gain--
                    elmeter_set( mne, gain )
                } else {
                    elmok++
                }
            } else {
                elmok++
            }
        }

        if (elmok == elm2no) { inloop = 0 }

        if (iter > 10) inloop = 0
    }

}'


# this is an enigma. What`s that for? Reading the data collector and
# writing it into the array ?
def elmupdate '{

    elmno = list_n(ELM_LIST)

    for (i=0; i<elmno; i++) {
        local num mne ctnorm

        mne  = list_item(ELM_LIST, i+1)
        num = cnt_num(mne)

        if (num == -1 || counter_par(num, "disable") == 1) continue

        dcaccess= list_getpar(ELM_LIST, mne, "dcaccess")
        if (dcaccess) {
            gain = esrf_dc(dcaccess, "DevRead")
            if (gain != -1 ) {
                list_setpar(ELM_LIST, mne, "gain", gain)
            }
        }

    }
}'

#%IU%
#%MDESC%
#    Adjusts the gain for ONLY ONE electrometer
#
def elmetergainadj1 '{

    local mne num ctime
    local type gmin gmax vmin vmax ctnorm
    local inloop iter

    if ($# != 2) {
        print "Usage: elmtergainadj1 elmeter-mnemonics counting-time-in-seconds"
        exit
    }

    mne   = "$1"
    ctime = $2
    num = cnt_num(mne)

    if (num == -1) {
        printf("Mnemonics %s does not correspond to any of electrometers\n", mne)
        exit
    }

    # get electrometer type
    type = list_getpar(ELM_LIST, mne, "type")

    if ((type == 0) || (type == 1)) {
        # for elmeters type 0 and 1 (read in ADC), all is done in
        # elmeter_mread inside user_pollcounts and user_getcounts
        count_em ctime
        waitcount; get_counts

    } else if (type == 2 || type == 5) {
        iter   = 0
        inloop = 1

        while(inloop) {
            iter++
            # Count and wait for "ctime" seconds
            count_em ctime
            waitcount
            ELM_UPDATING=1
            get_counts
            vmin = list_getpar(ELM_LIST, mne, "vmin")
            vmax = list_getpar(ELM_LIST, mne, "vmax")
            gmin = list_getpar(ELM_LIST, mne, "gmin")
            gain = list_getpar(ELM_LIST, mne, "gain")
            if (type == 5) {
                gain = _wago_elmeter_read(mne)
                list_setpar(ELM_LIST, mne, "gain", gain)
            }
            gmax = gmin + 2
            ctnorm = S[num]/ctime

            if ( fabs(ctnorm) < vmin ) {
                if ( gain  < gmax ) {
                    gain++
                    elmeter_set( mne , gain )
                } else {
                    inloop = 0
                }
            } else if ( fabs(ctnorm) > vmax ) {
                if ( gain > gmin ) {
                    gain--
                    elmeter_set( mne, gain )
                } else {
                    inloop = 0
                }
            } else {
                inloop = 0
            }
            if (iter > 10) inloop = 0
        }  # end of while loop
    } else {
        print "Unkown type of electrometer"
        exit
    } # end of cases over elmeter types

}'

#%IU% (mne)
#%MDESC% Read the appropriate adc device.
def _adc_read(mne) '{
local adcdev chan val adc_data adctype key

  chan = list_getpar(ELM_LIST, mne, "channel")
  adcdev = list_getpar(ELM_LIST, mne, "adcdev")
  adctype = list_getpar(ELM_LIST, mne, "type")

  if (adctype == 1) {
    val = esrf_io(adcdev, "DevReadChannel", chan)
  } else if (adctype == 2){
    val = esrf_io(adcdev, "DevReadValue")
  } else if ((adctype == 4) || (adctype == 6)) {
    val = esrf_io(adcdev, "DevReadSigValues", adc_data)
    if (val > 0)
      val = adc_data[chan]
  } else {
    if(adctype == 7)
    {
     local id
     id = esrf_io(adcdev, "DevName2Key", chan)
     chan = id
    }
    val = esrf_io(adcdev, "DevReadNoCachePhys", chan, adc_data)
    if(val == 1) {
      val = adc_data[0]
    }
  }
  return (val)
}'


#%IU% (mne)
#%MDESC% Read the appropriate adc device.
def _wago_elmeter_read(mne) '{
    local tmpgainNow, type, reldev, j, x[]
    type        = list_getpar(ELM_LIST, ELM_LIST[mne], "type")
    reldev      = list_getpar(ELM_LIST, ELM_LIST[mne], "reldev")
    tmpgainNow = 0
    wago_readch(reldev, x)
    for (j = 0; j < 3; j++) {
        tmpgainNow += x[2 - j]? j+1: 0
    }
    return tmpgainNow
}
'


#%MACROS%
#%IMACROS%
#%AUTHOR% V. Rey to start, H. Witsch recently
#  ELMETER.MAC - ICNTL - 10/96
#$Revision: 2.17 $, $Date: 2017/03/09 15:18:09 $
#%TOC%