esrf

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

#%TITLE% SAFSHUT.MAC
#%NAME%
#  Macros for operating the secondary safety shutters.
#
#%OVERVIEW%

#  These macros give access from %B%spec%B% to the safety beam
#  shutters that are controlled by Taco or Tango device servers
#  through the beamline PLC's. An arbitrary name is given to each
#  shutter in the %B%safshutsetup%B% macro. A particular shutter can
#  be identified by means of its name or its number. The number of a
#  shutter corresponds to the relative position, starting from 0,
#  where it appears in the %B%safshutsetup%B% line. %BR% Whenever a
#  shutter action (%B%shopen%B%, %B%shclose%B% or %B%shosh%B%) is
#  invoked whithout especifying a name or a number, the action affects
#  the active shutter. The active shutter is the one that was most
#  recently accessed or selected with %B%shsel%B%.


#%EXAMPLE%
#
#  %DL%
#  %DT%Taco  : safshutsetup exp1 ID03/BSH/1 exp2 ID03/BSH/2
#  %DT%Tango : safshutsetup exp1 id03/v-bsh/1 exp2 id03/v-bsh/2
#  %DD%Configures two shutters, ID03/BSH/1 and ID03/BSH/2, with the names
#  `exp1' and `exp2'.
#  %DT%shopen exp1
#  %DD%Opens the shutter `exp1'.
#  %DT%shclose
#  %DD%Closes the active shutter.
#  %DT%shsel
#  %DD%Lets the user select the active shutter.
#  %XDL%


##############  STATES #############
#
# TACO STATES :
# -1 : FAULT
#  3 : CLOSED
#  4 : OPEN
#  9 : MOVING
# 23 : EXTERNALLY DISABLED
# 46 : EXTERNALLY DISABLED
#
# TANGO STATES:
# 0:  'ON',
# 1:  'OFF',
# 2:  'CLOSED',
# 3:  'OPENED',
# 4:  'INSERT',
# 5:  'EXTRACT',
# 6:  'MOVING',
# 7:  'STANDBY',
# 8:  'FAULT',
# 9:  'INIT',
# 10: 'RUNNING',
# 11: 'ALARM',
# 12: 'DISABLED',
# 13: 'UNKNOWN',
# -1: 'FAULT' 


# For ds_is_tango and tango_cprint_state and tango_str_to_state
need spec_utils


#%UU% [<shutter-name> <shutter-device>]+
#%MDESC%
#  Defines the shutters to be accessed. Each shutter is described
#  by an arbitrary single-word name <shutter-name>
#  and by the name of the device <shutter-device> that the
#  corresponding device server uses to identify this particular shutter.%BR%
#  This macro doesnt check if the device names are valid or if they
#  correspond to properly configured devices.%BR%
#
#  If %B%safshutsetup%B% is called without parameters, the control of
#  safety shutters from %B%spec%B% is disabled.  ???
#
# ex :  safshutsetup eh1 id22/bsh/1 eh2 id22/bsh/2
# ex :  safshutsetup eh1 id22/v-bsh/1 eh2 id22/v-bsh/2
#
def safshutsetup '{
    # SHUTTER parameters
    unglobal SHUTTER
    global SHUTTER

    # Shutter State.
    global _SS

    local i list

    SHUTTER["_CURRENT"] = ""

    # Number of shutters : half of args number.
    SHUTTER["_N"] = split("$*", list)/2

    if (SHUTTER["_N"] != int(SHUTTER["_N"])){
        if (SETUP){
            print "Error in setup, line: $0 $*"
        }

        print "safshutsetup: Wrong parameter list "
        print " -> disabling shutter control from SPEC."
        unglobal SHUTTER
    }
    else {
        # 
        for (i=0; i<SHUTTER["_N"]; i++){
            SHUTTER[i] = SHUTTER[list[2*i]] = list[2*i+1]
            SHUTTER[SHUTTER["_N"]+i] = SHUTTER[list[2*i+1]] = list[2*i]
        }

        # 
        if (SHUTTER["_N"] == 1){
            SHUTTER["_CURRENT"] = SHUTTER[0]
        }
        else{
            SHUTTER["_CURRENT"] = ""
        }

        # Tests if shutter DS are *taco* or *tango* or *unresponding*.
        for (i=0; i<SHUTTER["_N"]; i++){

            if(ds_is_tango(SHUTTER[i])){
                SHUTTER[i]["tango"] = 1
                SHUTTER[SHUTTER[i]]["tango"] = 1
            }
            else{
                SHUTTER[i]["tango"] = 0
                SHUTTER[SHUTTER[i]]["tango"] = 0
            }

            printf("Configuring shutter %s (", SHUTTER[i])
            cprint_ok_bad(SHUTTER[i]["tango"], "TANGO", "TACO or unresponding")
            print ")"
        }

        setup_tail("safshut")
    }
}'

#%IU%
#%MDESC%
#   Undoes the setup
#
def safshutunsetup '{
    unglobal SHUTTER
}'


#%UU% [<shutter-name> | <shutter-number>]
#%MDESC%
#  Opens a safety shutter.
#  Without parameters : opens the active shutter.
#
def shopen '{
    printf ("Opening Safety Shutter...\n")
    shset 1 $*
}'


#%UU% [<shutter-name> | <shutter-number>]
#%MDESC%
#  Closes a safety shutter.
#  Without parameters : closes the active shutter.
#
def shclose '{
    printf ("Closing Safety Shutter...\n")
    shset 0 $*
}'


#%IU% [ <state> ] [<shutter-name> | <shutter-number>]
#%MDESC%
#  Changes the state of a safety shutter. If <state> is "OPEN",
#  "open" or 1, the shutter is open, otherwise it is closed.%BR%
#  If no shutter is specified it affects the active shutter.
#  Without parameters : it closes the active shutter.
#
def shset '{
    local _shutter _state _comm _shut t0

    # set _shut to 88 which is always the current shutter. The current shutter
    # will be changed if the input argument is not the current shutter.
    _shut = 88
    if ($# > 1) {
        shsel $2
    }
    else if (SHUTTER["_CURRENT"] == "") {
        shsel
    }

    _shutter = SHUTTER["_CURRENT"]
    _SS = _bshstate(_shutter)

    # 46 = "EXTERNALLY DISABLED"
    if ((_SS == -1) || (_SS == 46) || (_SS == 12)) {
        printf ("Safety shutter %s, exiting...\n", _bshstatus(_SS))
        SHUTTER[SHUTTER[_shutter]]["laststate"]  = _SS
        SHUTTER[SHUTTER[_shutter]]["laststatus"] = _bshstatus(_SS)

    }
    else {
        _state = $1
        if (_state == "OPEN" || _state == "open" || _state == 1) {
          _comm = 1

          if(ds_is_tango(_shutter)){
              # tango
              _state = 3
          }
          else{
              # taco
              _state = 4
          }

        }
        else {
          _comm = 0

          if(ds_is_tango(_shutter)){
              # tango
              _state = 2
          }
          else{
              # taco
              _state = 3
          }
        }

        printf("Beam shutter \`%s\' was %s, ",SHUTTER[_shutter], _bshstatus(_SS))
        # ?
        ESRF_ERR = -1
        _shset(_comm,_shut)
        _SS = _bshstate(_shutter)

        t0 = time()

        while ((_SS != _state) && (_SS <= 17) && (_SS > 0)) {
            sleep(1)
            _SS = _bshstate(_shutter)
            # timeout
            if ((time()-t0) > 10) break;
        }

        SHUTTER[SHUTTER[_shutter]]["laststate"] = _SS
        SHUTTER[SHUTTER[_shutter]]["laststatus"] = _bshstatus(_SS)

        printf("now is %s\n", _bshstatus(_SS))
    }
}'



#%IU% (val,shut)
#%MDESC% Changes the state of a safety shutter. If %B%val%B% is 1, the
#shutter %B%shut%B% is open, otherwise it is closed. Returns the state of the
#shutter, -1 if shutter not defined.
def _shset(val, shut) '{
    local _shutter _state cmd

    if (shut == 88){
        _shutter = SHUTTER["_CURRENT"]
    }
    else {
        _shutter = _shsel(shut)
        if (_shutter == -1){
            return (_shutter)
        }
    }

    if (val == 1){
        _SS = _bshstate(_shutter)

        if(ds_is_tango(_shutter)){
            # tango
            if (_SS == 2){
                _SS = _bshopen (_shutter)
            }
        }
        else{
            #taco
            if (_SS == 3){
                _SS = _bshopen (_shutter)
            }
        }

    }
    else {
        _SS = _bshstate(_shutter)

        if(ds_is_tango(_shutter)){
            # tango
            if (_SS == 3){
                _SS = _bshclose (_shutter)
            }
        }
        else{
            # taco
            if (_SS == 4){
                _SS = _bshclose (_shutter)
            }
        }
    }

    return (_SS)
}'


#%IU% (shut)
#%MDESC% Set %B%shut%B% as active shutter. Return the device name or -1, if
#the shutter is not defined.
def _shsel(shut) '{
    local nb

    nb = SHUTTER["_N"]

    if (nb == 0) {
        printf ("There are no shutters defined (use \`safshutsetup\').\n")
        return (-1)
    }
    else if (shut >= nb) {
        printf ("%d is more than the number of shutters defined, command ignored\n", shut)
        return (-1)
    }
    else{
        _shutter = ((shut + 0) >= SHUTTER["_N"])?"":SHUTTER[shut]
    }

    SHUTTER["_CURRENT"] = _shutter
    return (_shutter)
}'


#%UU% [<shutter-name> | <shutter-number> | all]
#%MDESC%
#  Shows the state of a safety shutter.
#  Without parameters shows the current state of the active shutter.%BR%
#  With the literal string `all' as parameter, this macro shows the state of
#  all the shutters defined with %B%safshutsetup%B%.
#
def shosh '{
    local _shutter _ss i

    if ("$1" != "all" || SHUTTER["_N"] == 0) {
        if ($# > 0 || SHUTTER["_CURRENT"] == ""){
            shsel $*
        }

        _shutter = SHUTTER["_CURRENT"]
        _SS = _bshstate(_shutter)
        SHUTTER[SHUTTER[_shutter]]["laststate"]  = _SS
        SHUTTER[SHUTTER[_shutter]]["laststatus"] = _bshstatus(_SS)
        printf("Beam shutter \`%s\' is %s.", SHUTTER[_shutter], _bshstatus(_SS))
    }
    else {
        print "\nCurrently configured safety shutters:"
        for (i=0; i<SHUTTER["_N"]; i++) {
            _shutter = SHUTTER[i]
            _SS = _bshstate(_shutter)
            SHUTTER[SHUTTER[_shutter]]["laststate"] = _SS
            SHUTTER[SHUTTER[_shutter]]["laststatus"] = _bshstatus(_SS)
            if(COLOR){
                printf("%8d) %15s - ", i, SHUTTER[_shutter])
                # print "_bshstatus(_SS)="_bshstatus(_SS)
                tango_cprint_state(tango_str_to_state(_bshstatus(_SS)))
                print ""
            }
            else{
                printf("%8d) %15s - %s\n", i, SHUTTER[_shutter], _bshstatus(_SS))
            }
        }
    }

    print ""
}'


#%IU% (state)
#%MDESC% If not in simulation mode, returns the state of the shutter.
#If in simulation mode, returns the %B%state%B% value.
def shstate(state) '{
    local st cmd _shutter

    _shutter = SHUTTER["_CURRENT"]

    if (set_sim(-1) == 0) {
        st = _bshstate(_shutter)
    }
    else{
        st = state
    }

    _SS = st

    SHUTTER[SHUTTER[_shutter]]["laststate"]  = _SS
    SHUTTER[SHUTTER[_shutter]]["laststatus"] = _bshstatus(_SS)

    return (st)
}'

}'


#%IU% (device)
#%MDESC%
#    Reads and returns the state (number) of the shutter <device>.
def _bshstate(device) '{

    if(SHUTTER[device]["tango"]){
        return (tango_io(device, "State"))
    }
    else{
        return (esrf_io(device, "DevState"))
    }
}'


#%IU% (_ss)
#%MDESC% Return the string value corresponding to the <_ss> state value.
def _bshstatus(_ss) '{
    local _strs  _current_sh


    _current_sh = SHUTTER["_CURRENT"]

        # tango_state_to_str is in spec_utils.mac
        _strs = tango_state_to_str(_ss)
        # TANGO
        _strs = tango_shstate_to_str(_ss)
    }
    else{
        # TACO
        if (_ss == -1)
            _strs="FAULT"
        else if(_ss == 9)
            _strs="MOVING"
        else if(_ss == 3)
            _strs="CLOSED"
        else if(_ss == 4)
            _strs="OPEN"
        else if(_ss == 46 || _ss == 23 || _ss == 12 )
            _strs="EXTERNALLY DISABLED"
        else
            _strs="????"
    }

    return (_strs)
}'


#%IU% (<device>)
#%MDESC% Opens the <device> shutter.
def _bshopen(device) '{

    if(SHUTTER[device]["tango"]){
        if (tango_io(device, "Open") == 0)
            return (4)
    }
    else{
        if (esrf_io(device, "DevOpen") == 0)
            return (4)
    }

    return(-1)
}'


#%IU% (device)
#%MDESC% Close the %B%device%B% shutter.
def _bshclose (device) '{

    if(SHUTTER[device]["tango"]){
        if (tango_io(device, "Close") == 0){
            return (3)
        }
    }
    else{
        if (esrf_io(device, "DevClose") == 0){
            return (3)
        }
    }

    return (-1)
}'


#%UU% [shutter-name | shutter-number]
#%MDESC%
#  Lets the user select the active shutter. This macro is also internally
#  called from %B%shopen%B%, %B%shclose%B% and %B%shosh%B%. If the macro is
#  called without parameter or the parameter doesnt correpond to a valid
#  shutter, %B%shsel%B% lists the currently defined shutters and prompts
#  the user for a selection.
#
def shsel '{
    local _shutter

    if (SHUTTER["_N"]==0) {
        print "There are no shutters defined (use \`safshutsetup\')."
        exit
    }
    else if($# > 1) {
            print "Too many parameters"
            exit
    }
    else if ($# == 0) {
             _shutter = ""
    }
    else {
      _shutter = (("$1" + 0) >= SHUTTER["_N"])?"":SHUTTER["$1"]
    }

    if (_shutter == "" || _shutter == 0) {
        local i answer

        print "\nThe safety shutters currently defined are:"
        for (i = 0; i < SHUTTER["_N"]; i++){
            printf("%8d) %s\n", i, SHUTTER[SHUTTER[i]])
        }

        answer = getval("\nWhich one", SHUTTER[SHUTTER["_CURRENT"]])
        _shutter = ((answer + 0) >= SHUTTER["_N"])?"":SHUTTER[answer]

        if (_shutter == "" || _shutter == 0) {
            printf("\`%s\' is not a valid shutter.", answer)
            exit
        }
    }

    SHUTTER["_CURRENT"] = _shutter
}'


#%MACROS%
#%IMACROS%
#%SETUP%
#  The %B%safshutsetup%B% macro has to be executed with the proper parameters.
#
#%DEPENDENCIES%
#  This macro set relies on the proper installation and configuration of
#  the device servers that control the safety shutters.
#
#%ATTENTION%
#  These macros only affect the safety beam shutters, and have nothing to
#  do with the control of auxiliary shutters implemented in `shut.mac'.
#  $Revision: 3.14 $ / $Date: 2012/05/03 07:57:00 $
#%AUTHOR% P. Fajardo, (Original 4/94).
#  $Revision: 3.14 $ / $Date: 2012/05/03 07:57:00 $
#%TOC%