esrf

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

#%TITLE% ATTE.MAC
#%NAME% Attenuator Macros
#%CATEGORY% other hardware
#%DESCRIPTION%
#   This file provides a set of macros for controlling and monitoring 
#   attenuators from spec. There is a menu to easily access the different 
#   axes together with a complete macro set for combining attenuator with
#   other equipment or macros inside spec.  %BR%
#
#%OVERVIEW%
#   Basic commands are:
#   %DL%
#   %DT%atteconfig%DD% Configures the system from a file or interactively.
#   %DT%attemenu%DD% Shows main attenuator menu. From there you can see
#                  active axes and move to the desired one.
#   %DT%atteset%DD%  Sets active a certain filter/axis combination
#   %DT%attestatus%DD%  Returns a report on every axis position 
#   %DT%attepos%DD%  Reduced version of attestatus 
#   %XDL%
#%BR%
#
#
#%EXAMPLE%
#   %DL%
#   %DT% %B% attemenu%B%  %DD% (Opens the menu)
#   %DT% %B% atteset%B% %B% 2 %B% %B% 3 %B% %DD% 
#             (Sets active the filter number three on axis two )
#   %DT% %B% attepos%B%  %DD% (Shows the current position of the axes)
#   %DT% %B% atteconfig %B% %B% atte.dat%B% %B% %DD%
#             ( Configure the system from file atte.dat)
#   %XDL%
#%BR%
#
#%SETUP%
#
#   The macro atteconfig with no arguments will prompt for all
#   configuration parameters. %DD%
#   The configuration can be done from a configuration file too. 
#   The syntax for this file can be seen in the following example:
#%PRE%
#---
# #
# # Axe 1
# #
# Axe id01/atte011_1/1 0
# {
#	filter 1 1.2 Carbon Carbon_1.2
#	filter 2 0.8 Aluminium Poroto
#	filter 3 2.0 Silicon Tururu
# }
# 
# #
# # Axe 2
# #
# Axe id01/atte011_1/1 1
# {
#	filter 3 2 Carbon Carbon1 
#	filter 5 1 Carbon Carbon2
#	filter 2 0.5 Carbon Carbon3
#	filter 1 0.25 Carbon Carbon4
# }
#--- 
#%PRE%
# Three kind of lines are understood by atteconfig macros:
#  
# %UL%
# %LI% Comments: any line starting with the # character
# %LI% Axis lines; keyword "Axe" plus two parameters:device-name 
#   and axenumber
# %LI% Filter lines:  Keyword is "filter", four fields must follow: position 
#   of the filter in its axis, thickness, attenuation file-name and label 
#   to be identify the filter in the menu.
# %XUL%
#
#   Each group of filter lines belonging to the same axis must be surrounded
#   by curly brackets.
#
# %END%
#

##
#  atteconfig
##
#%UU% [config-file]
#%MDESC%
#
#   Configure the system for axes and filters... get the configuration
#   data from the file given as first argument or interactively asks
#   for data.
#
#   For an example of a configuration file see above.
#
def atteconfig '
global ATTE_NAXES ATTE_ACTIVE
global ATTE_SELEC ATTE_GUI_AXE
global ATTE_DEV ATTE_BLK ATTE_NFILT ATTE_FIRST ATTE_LAST
global ATTE_FILTNO ATTE_LABEL ATTE_FPOS ATTE_THICK ATTE_CALF
global ATTE_YOFF
global ATTE_Y ATTE_FRIEND ATTE_ERROR
global ATTE_OUTPUT
global ATTE_STATE_STR
global ATTE_WAS_MOVING

    if ($# > 1) {
       printf("Usage: atteconfig [config-file]")
       exit
    }

    if ($# == 1) {
       ATTE_NAXES=0
       ATTE_FILTNO=0
       _atte_read_file "$1" 
    } else {
       ATTE_NAXES=getval("Number of axes for ATTE",ATTE_NAXES)
       ATTE_FILTNO=0
       for(i=0;i<ATTE_NAXES;i++) {
          printf("\nAxis %d\n",i+1)
          ATTE_DEV[i]=getval("- Device name ",ATTE_DEV[i])
          ATTE_BLK[i]=getval("- Block ",ATTE_BLK[i])
          ATTE_NFILT[i]=getval("- Number of filters",ATTE_NFILT[i])
          ATTE_FIRST[i]=ATTE_FILTNO
          ATTE_LAST[i] =ATTE_FILTNO+ATTE_NFILT[i]-1
          for(j=ATTE_FIRST[i];j<ATTE_FIRST[i]+ATTE_NFILT[i];)
          {
            printf("\n\t-filter %d:\n",j+1-ATTE_FIRST[i])
            ATTE_FPOS[j]  =getval("\t  Position ",        ATTE_FPOS[j])
            ATTE_LABEL[j] =getval("\t  Name ",            ATTE_LABEL[j])
            ATTE_THICK[j] =getval("\t  Thickness ",       ATTE_THICK[j])
            ATTE_CALF[j]  =getval("\t  Calibration file ",ATTE_CALF[j])
            ATTE_LAST[i]=j
            ATTE_FILTNO=++j
          }
       
       }
    }
'

##
#  attepos
##
#%UU% [axis]
#%MDESC%
#  Fully checks the status of the system and gives a report if ATTE_FRIEND 
#  is not set
def attepos '
   if ($# > 1){
      printf("Usage: $0 [axis]\n")
      exit
   }
   ATTE_FRIEND = -1
   attestatus $*
   ATTE_FRIEND = 0
'

##
#  attestatus
##
#%UU% [axis]
#%MDESC%
#  Fully checks the status of the system and gives a report if ATTE_FRIEND 
#  is not set
def attestatus '
   if ($# > 1){
      printf("Usage: $0 [axis]\n")
      exit
   }
   if ($# == 0)
      for ( i = 0;i<ATTE_NAXES;i++) {
         _attepos i
      }
   else  _attepos $1 - 1
'

##
#  _attepos
##
#%IU% axis
#%MDESC%
#  Fully checks the status of one axis and gives a report if ATTE_FRIEND
#  is not set.
def _attepos '
{
   local axis filt devstat 
   local state 

   axis = $1

   devstat = esrf_io(ATTE_DEV[axis],"DevState",ATTE_OUTPUT)
   if (devstat == -1 ) {
      printf("Cannot communicate with attenuator device server\n")
      exit
   }

   filt  = ATTE_OUTPUT[2*ATTE_BLK[axis] + 1]
   state = ATTE_OUTPUT[2*ATTE_BLK[axis]]
   if (state == 9) ATTE_STATE_STR[axis]="Moving" 
   else if (state == 2) ATTE_STATE_STR[axis]="On"
        else ATTE_STATE_STR[axis] = "Fault"

   #
   # Check which filter correspond to this position.
   #
   for (j=ATTE_FIRST[axis]; j<ATTE_LAST[axis]+1;j++) {
      if (filt == ATTE_FPOS[j]) {
          ATTE_ACTIVE[axis] = j
          break
      }
   }

   if (j > ATTE_LAST[axis] ) ATTE_ACTIVE[axis] = -1

   if (ATTE_FRIEND < 1) {
      printf("\tAxis %d:",axis+1)
      if (!ATTE_FRIEND){
        printf("\n\t  Device %s, block %d is \"%s\"\n", \
                ATTE_DEV[axis],ATTE_BLK[axis],ATTE_STATE_STR[axis])
      }
      if (ATTE_ACTIVE[axis] >= 0)
         printf("\t  Current position is %d (%s)\n", \
                ATTE_ACTIVE[axis]-ATTE_FIRST[axis]+1,ATTE_LABEL[ATTE_ACTIVE[axis]])
      else 
         printf("  Current position is unknown\n")

      printf("\n")
   }

}
'

##
#  attemenu
##
#%UU%
#%MDESC%
#  Starts the interactive menu.
def attemenu '
{
  local  _atteopt 
  local  _attemaxe _attemfilt
  local  attereading

  ATTE_FRIEND=1
  ATTE_ERROR=""

  for(;;) {
    atte_update_menu

    inloop=1
    _atteopt=""
    attereading=0

    while(inloop) {
        local ch
        
        ch = input(-1)
        if (ch == "\n") {
           input(0);inloop=0
        } else {
           if (ch != "\0" && ch != "\004") {
              if(!attereading) attereading=1
              _atteopt=sprintf("%s%s",_atteopt,ch)
              printf("%s",ch)
           } else {
              sleep(0.5)
           }
        }
        if (!attereading) atte_update_state 
       
    }

    if (_atteopt == "0" ) break

    sscanf(_atteopt,"%1d%d",_attemaxe,_attemfilt) 
  
    atteset _attemaxe _attemfilt
  } 

  ATTE_FRIEND=0
  input(0)
}
'

##
# atte_update_state
##
#%IU%
#
def atte_update_state '{
    local iax x mul newstate 

    print
    newstate="On"

    attestatus
    if (ATTE_ERROR != "") 
       tty_move(3,ATTE_Y,ATTE_ERROR)
    for (iax=0;iax<ATTE_NAXES;iax++) {
       if (ATTE_NAXES==2) {xdist = 22} else {xdist = 30} 
       if (ATTE_NAXES>2) { mul = iax - 1}
       else if (ATTE_NAXES==2) {
            if (iax==0) {mul=-1} else {mul=1}
       } else {mul = 0}
       ix = 40 + xdist*mul - 5

       tty_move(ix,ATTE_Y+1,sprintf("%7s",ATTE_STATE_STR[iax]))

       if (ATTE_STATE_STR[iax] == "Moving") newstate="Moving"        
    }

    if (newstate == "Moving") 
        ATTE_WAS_MOVING = 1
    else {
        if (ATTE_WAS_MOVING) {
               inloop=0
        }
        ATTE_WAS_MOVING = 0
    }

    printf("\n\n Choose filter number or 0 to exit: ")
}'

##
# atte_update_menu
##
#%IU%
#
def atte_update_menu '{
   attestatus
   _atte_showmenu
}'

##
# attegui
##
def attegui '
{
    ATTE_GUI_AXE = 1
    ATTE_FRIEND = 1
    if ($1 != 0) {
       ATTE_SELEC = $1
       atteset ATTE_GUI_AXE ATTE_SELEC
    }
    ATTE_FRIEND = 0
}
'

##
# Xatte
##
def Xatte '
    for (i=0;i<ATTE_NAXES;i++) {
       bpipe updateval 
       fprintf("pipe","Xlistval%d %d ",i,ATTE_ACTIVE[i])
       epipe
    }
'

##
#  atteset
##
#%UU% axis filter
#%MDESC%
#  Moves axis to the desired filter
def atteset '
{
  local axis filt option nax nfi errflag

  if ($# != 2 )
  {
     printf("Usage: atteset axis filt")
     exit
  }

  errflag=0

  axis  = $1 - 1
  filt = $2  - 1
  filtabs = filt + ATTE_FIRST[axis]
  #
  # Checking
  #
  if (axis < 0 || axis > ATTE_NAXES - 1) {
     ATTE_ERROR=sprintf("Bad axis selection")
     errflag = 1
  } else if ( filtabs < ATTE_FIRST[axis] || filtabs > ATTE_LAST[axis]) {
     ATTE_ERROR=sprintf("Bad filter number")
     errflag = 1
  } else { ATTE_ACTIVE[axis]=filt;ATTE_ERROR="" }

  if (!ATTE_FRIEND) {print ATTE_ERROR}

  if (!errflag) {
    devstat = esrf_io(ATTE_DEV[axis],"DevGotoFilter",ATTE_BLK[axis],ATTE_FPOS[filtabs])
    if (devstat == -1 ) {
        printf("Cannot communicate with attenuator device server\n")
        exit
    }
  }

  if (GUI_RUN) Xatte
}
'

##
#  _atte_showmenu
##
#%IU%
#%MDESC%
#  Macro that prepares and shows the menu on the screen.
def _atte_showmenu '
{
  local xoff attex attey axmax nfil str 

  AXE_PER_LINE=ATTE_NAXES>3?3:ATTE_NAXES
  if (ATTE_NAXES==2) {xdist = 22} else {xdist = 30} 
  axmax=0
  ATTE_YOFF = 0 
  axis  = 0

  clscreen()
  printf("\n              *********** ")
  tty_cntl("us")
  printf(" ATTE Attenuator MENU " )
  tty_cntl("ue")
  printf(" ***********\n")

  for ( i=0;i<ATTE_NAXES;i++)
  {
    axis++;
    # 
    # Axis Header.
    attey = 3 + ATTE_YOFF 
    xoff = 5 
    if (ATTE_NAXES>2) { mul = axis - 2}
    else if (ATTE_NAXES==2) {
            if (axis==1) {mul=-1} else {mul=1}
         } else {mul = 0}
    attex = 40 + xdist*mul - xoff

    str= sprintf(" Axis %d ",i+1)
    tty_cntl("us")
    tty_move(attex,attey,str)
    tty_cntl("ue")

    #
    # Filters
    nfil=ATTE_NFILT[i]
    if (nfil>axmax) {axmax=nfil;ATTE_Y= ATTE_YOFF + axmax + 5}
    for(j=0;j<nfil;j++)
    {
        jabs = j + ATTE_FIRST[i]
        xoff=10
        attey = 4 + ATTE_YOFF + j
        attex = 40 + xdist*mul - xoff
        if (ATTE_ACTIVE[i]==jabs)
        {
           str= sprintf(" %s ",100*(i+1)+j+1)
           tty_cntl("md")
           tty_move(attex,attey,str)
           str= sprintf("%s", ATTE_LABEL[jabs])
           tty_cntl("mr")
           tty_move(attex+5,attey,str)
           tty_cntl("me")
        } else {
           str= sprintf(" %s ",100*(i+1)+j+1)
           tty_cntl("md")
           tty_move(attex,attey,str)
           str= sprintf("%s", ATTE_LABEL[jabs])
           tty_cntl("me")
           tty_move(attex+5,attey,str)
        }
    }

    if (axis%AXE_PER_LINE==0) {ATTE_YOFF += axmax + 2;axmax=0;axis=0}
  }
 
}
'

##
#  _atte_read_file
##
#%IU%
#%MDESC%
#  Reads information from configuration file
def _atte_read_file '
{
    
     local str out_of_data file_open axe_no file_name

     axe_no=ATTE_NAXES
     file_name="$1"

     # 
     # first search for first Axe or axe or AXE str:
     #
     if (getline("$1","open") != 0)
     {
         printf("Error opening ATTE config file %s\n",file_name)
         file_open=0
     } else { file_open = 1}

     while(file_open)
     {
         str = getline("$1")
         if (str == "-1")  { 
              file_open=0
              getline("$1","close")
         }

         if ((a=index(str,"Axe")) != 0 || (a=index(str,"axe")) != 0 || (a=index(str,"AXE")) != 0) {
             dd=index(str,"#")
             if (dd==0 || dd > a)
             {
             nn=sscanf(str,"Axe %s %d",atte_arg1,atte_arg2)
             if (nn!=2) {
                 p "Syntax error on file " file_name " " str
                 getline("$1","close")
                 file_open=0
                 break 
             } else {
                ATTE_DEV[axe_no]=atte_arg1
                ATTE_BLK[axe_no]=atte_arg2
             }
             _atte_read_filter "$1"
             ATTE_NAXES=++axe_no
             }
         }
     }
     
}
'


##
#  _atte_read_filter
##
#%IU%
#%MDESC%
#  Reads from configuration file information concerning an axis.
def _atte_read_filter '
{
    local file_name reading 

    file_name = "$1"
    reading = 1
    ATTE_FIRST[ATTE_NAXES]=j=ATTE_FILTNO
    while(reading)  {
       str = getline(file_name)
       if (index(str,"}")) reading=0
       if (str == "-1")  { 
           printf("end of file encountered unexpectedly\n")
           getline("$1","close")
           reading=0
       }

       if (a=index(str,"filter") != 0 ) {
          # Could be a filter or a comment. 
          dd=index(str,"#")
          if (dd == 0 || dd > a) {    # it is not a comment
              nn=sscanf(str," filter %d %f %s %s", \
                        atte_arg1,atte_arg2,atte_arg3,atte_arg4)
              if (nn !=4) {p "Syntax error in file " file_name " " str}
              else {
                  ATTE_FPOS[j]=atte_arg1
                  ATTE_THICK[j]=atte_arg2
                  ATTE_CALF[j]=atte_arg3
                  ATTE_LABEL[j]=atte_arg4
                  j++
              }
          }
      }
      ATTE_LAST[ATTE_NAXES]=j-1
      ATTE_FILTNO=j
      ATTE_NFILT[ATTE_NAXES] = ATTE_LAST[ATTE_NAXES] - ATTE_FIRST[ATTE_NAXES]+1
     }
}
'

##
# attestop
##
#%UU%
#%MDESC% 
#  Stops all movement in attenuator system 
#
def attestop '{
   for (i=0;i< ATTE_NAXES;i++) {
       esrf_io(ATTE_DEV[i],"DevAbortCommand")
   }
}'

##
# attewait
##
#%IU%
#%MDESC% 
# Waits until the attenuator system is not moving.
#
def attewait '{
   local ismov no_axes val

   _ismov=1

   while(_ismov) {
       _ismov = 0
       sleep(0.2)
       for (i=0;i< ATTE_NAXES;i++) {
           val = esrf_io(ATTE_DEV[i],"DevState",ATTE_OUTPUT)
           no_axes = val/2
           for ( j=0;j< no_axes;j++) if (ATTE_OUTPUT[2*j]==9) _ismov++
       }
   }
     
}'

#%MACROS%
#%IMACROS%
#%AUTHOR% Vicente Rey 27 Feb. 1996
#%TOC%