esrf

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

#%TITLE% ID.MAC
#%NAME%
#        ESRF Insertion Devices
#%CATEGORY%
#        Accelerator
#
#%DESCRIPTION%
#%PRE%
#   This macro set allows to access axes on insertion devices as motors in SPEC.
#
#   Since version 4.0 (Jul 2006) this macro file allows also to
#   define new style macro motors on an insertion device.
#
#   To define new style macro motors you must define:
#
#   an id controller in config:
#
#   MOTORS       DEVICE    ADDR   <>MODE      NUM               <>TYPE
#      YES       id        //aries/id/id/28     4         Macro Motors
#
#   motors in config referring to that controller. Channel assignment
#   will decide on the motor role as follow:
#
#   Channel
#     0   -   GAP
#     1   -   TAPER
#     2   -   REVOLVER GAP 1 (Not Implemented yet)
#     3   -   REVOLVER GAP 2 (Not Implemented yet)
#
#   Module holds the "mechanics" number starting from 1.
#   Example: gap and taper motors on first undulator should
#      share the same module=1... and channel=0 for gap
#      channel=1 for taper)
#
#%PRE%

#%SETUP%
# In the current setup your computer must have access to aries (where the
# data base is running) The macros will only work for authorized users.
# You need to ask for permission to the machine group
#
# For getting id parameters. Type idsetup once to get information
# then define motors in setup file and in config as you can see below
# in example (not necessary if using macro motors)
#
#%EXAMPLE%
#   %DL%
#   %DT%idsetup%DD% Without parameters returns the list of axes found
#        in the beamline frontend
#%PRE%
#   Devname:  //aries/id/id/61   for  2 carriages
#   2 axes in the system
#    1 -      U46 :     carriage: id/meca/61m1 ; type: TAPER
#    2 -      U48 :     carriage: id/meca/61m2 ; type: TAPER
#
#%PRE%
#   %DT%idsetup u46 1 gap t48 2 taper%DD% defines two motors u46 and
#                t48 (that should be defined in config) to move axes
#                1 and 2 (as shown by idsetup without parameters). The
#                first one will do movements on the gap of the first axis
#                the second one on the taper of the second axis.
#                  active axes and move to the desired one.
#   %DT%mv u46 23%DD%  Will move u46 gap to position 23
#   %DT%mv t48 0.2%DD%  Will move taper t48 to position 0.2
#   %XDL%



#%UU% [parma]
#%MDESC%
#    
def id_config (mne, type, unit, module, channel) '{

  if (mne == "..") {

    print "Using ID Macros Motor on", id_ADDR, "(ctrl unit", unit, ")"

    global IDDEV IDAXIS
    global IDALLPOS IDMOVE IDERROR
    global IDMOVEPOS IDMOVETAPPOS
    global IDMECA IDMECADEV IDNOMECA

    local _id_

    if (split(SPECBL, _id_, "id") != 2 && split(SPECBL, _id_, "ID") != 2 ) {
        printf("ID Error: Not ID beamline or Wrong SPECBL variable.\n")
        return ".error."
    }

    IDDEV = id_ADDR

    list_init IDAXIS

    if (id_getallinfo(id_ADDR) != 0 ) {
        printf("ID Error getting info from Front End device server\n")
        return ".error."
    }

  }
  else {
    if (type == "mot") {

      local type[]

      type[0]="gap"
      type[1]="taper"
      type[2]="revolver1"
      type[3]="revolver2"

      if (channel>1) {
        printf("ID Warning: revolver type ID not supported yet.\n")
        return ".error."
      }

      if (module < 1 || module > list_n(IDAXIS)) {
        printf("ID Error: Wrong axis (%d) selected\n",module)
        return ".error."
      }
    }
  }
}
'


#%IU% (<mne>, <cmd>, <p1>, <p2>)
#%MDESC%
#    Macro motor main macro.
def id_cmd (mne, cmd, p1, p2) '{

  if (mne == "..") {
    if (cmd == "preread_all") {
      if (esrf_io(IDDEV, "DevRead", IDALLPOS) == -1) {
           IDERROR = 1
      }

    }
    else if (cmd == "prestart_all") {
       for (i=0 ; i<list_n(IDAXIS) ; i++) {
           IDMOVE[i] = 0
       }
    }
    else if (cmd == "start_all") {
      local i axis argin argout

      for (i in IDMOVE) {
        if (IDMOVE[i] != 0) {

          IDMOVE[i]--

          axis=i+1

          argin[0] = list_getpar(IDAXIS, axis, "dev")
          argin[1] = list_getpar(IDAXIS, axis, "ident")
          argin[2] = IDMOVE[i]
          argin[3] = IDMOVEPOS[i]
          argin[4] = IDMOVETAPPOS[i]

          esrf_io(IDDEV,"DevWrite",argin,argout)
        }
      }
    }
  }
  else {
    local iddev axis channel mecadev

    iddev   = motor_par(mne, "address")
    axis    = motor_par(mne, "module")
    channel = motor_par(mne, "channel")
    mecadev = list_getpar (IDAXIS, axis, "dev")

    if (cmd == "get_status") {

      local idstat

      idstat  = esrf_io(IDDEV, "DevTrigMotion", mecadev)

      if (idstat == 2 ) {
          id_getallpos()
          return 0x02
      }
      else {
          return 0
      }
    }
    else if (cmd == "start_one") {
       # p1 : target position in dial units for absolute motion.
       # p2 : magnitude in dial units for relative motion.



       if (channel == 0 ) {
               IDMOVE[axis-1]    |= 0x1
               IDMOVEPOS[axis-1] = p1
       }

       if (channel == 1) {
              IDMOVE[axis-1]    |= 0x2
              IDMOVETAPPOS[axis-1] = p1
       }


    }
    else if (cmd == "position") {

       local pos

       pos = IDALLPOS[(axis-1)*2+channel+0]

       return pos
    }
  }
}
'



#%UU% [mnemonic axe-number gap/taper [mnemonic2 axe-number2 gap/taper ...]]
#%MDESC%
#  Macro to setup the insertion device parameters. It uses the
#  SPECBL variable to get information from the frontend device
#  server
#  If called with no parameters it will get information from frontend
#  device server and show to the user info about: present axes ant types.
#  It can then be called with parameters to configure pseudo motors.
#
def idsetup '{

  global ID_ON
  global IDDEV
  global IDNOMECA    IDMECA    IDMECADEV
  global IDAXIS
  global IDALLPOS    ID_OLDPOS
  global ID_ARGIN    ID_ARGOUT
  global ID_MOVETHIS ID_NOTREAD
  global IDMOVE      IDMOVEPOS IDMOVETAPPOS ID_MOVINGANY
  global ID_TIMEOUT

  local _idno param _onoff idno idhost idroot isid
  local i

  ID_TIMEOUT=15

  # Checks if you are in a BM or ID.
  if (split(SPECBL,_idno,"id") != 2 && split(SPECBL,_idno,"ID")!=2) {
    if (split(SPECBL,_idno,"d") != 2 && split(SPECBL,_idno,"D")!=2) {
      printf("Wrong SPECBL variable\n")
      printf("Sorry")
      exit
    } else {
      isid = 0
    }
  } else {
    isid = 1
  }

  # Setup IDDEV: names of insertion device and front end
  # device servers.
  if (whatis("IDDEV") & 0x8000000) {

    sscanf(_idno[1],"%d",idno)

    idhost = "aries"

    if ( isid ) {
       IDDEV    = sprintf("//%s/id/id/%d",idhost,idno)
    }
  }

  if ( isid ) {
      list_init IDAXIS

      if (id_getallinfo(IDDEV) != 0 ) {
          printf("***********************************************\n")
          printf("Error getting info from Front End device server\n")
          printf("***********************************************\n")
      }
      else {
          # No arguments -> display infos.
          if (!$#) {
              id_showinfo()
          }
          else if ("$1" != "silent") {
              _onoff = ID_ON
              idoff
              nmot = split("$*", param)/3

              for (i=0 ; i<list_n(IDAXIS) ; i++) {
                  list_setpar(IDAXIS, i+1, "tapmne", "")
                  list_setpar(IDAXIS, i+1, "gapmne", "")
                  list_setpar(IDAXIS, i+1, "def", 0)
              }

              for (i=0 ; i<nmot ; i++) {
                  local axis idmne tapergap

                  idmne    = param[i*3]
                  axis     = param[i*3 + 1] - 1
                  tapergap = param[i*3 + 2]

                  if (axis < 0 || axis >= list_n(IDAXIS)) {
                      printf("Wrong axis (%d) selected\n", axis + 1)
                  } else {
                      id_axedef(axis, idmne, tapergap)
                  }
              }

              if (whatis("ID_ON") & 0x8000000) idon
              if (_onoff) idon
              setup_tail("id")
          }
      }
  }
}
'


#%UU%
#%MDESC%
def idunsetup 'idoff'


#%UU%
#%MDESC%
# This macro undefines all macros related with the beamline
# insertion device.
#
def idoff '{
    local i
    ID_ON = 0
    for(i=0;i<list_n(IDAXIS);i++) {
        cdef("","",list_getpar(IDAXIS,i+1,"gapmne"),"delete")
        cdef("","",list_getpar(IDAXIS,i+1,"tapmne"),"delete")
    }
    cdef("","","_id","delete")
    cdef("","","_id2","delete")
}
'


#%UU%
#%MDESC%
# Makes all the definitions active
#
def idon '{
  local idmne i

  ID_ON = 1

  cdef("_id_prompt")
  cdef("prompt_mac",     "id_prompt()\n",   "_id")
  cdef("user_getpangles","id_getallpos()\n","_id",0x10)
  cdef("user_checkall",  "id_premove()\n",  "_id",0x10)
  cdef("user_checkall",  "id_moveall()\n",  "_id2",0x20)
  cdef("user_motorsrun", "id_poll\n",       "_id2",0x20)

  for(i=0;i<list_n(IDAXIS);i++) {
      local _def

      _def = list_getpar(IDAXIS,i+1,"def")

      if (_def & 0x1) {
          idmne = list_getpar(IDAXIS,i+1,"gapmne")
          cdef("user_getpangles",sprintf("id_getpos(%d,%s,1)\n",i,idmne),idmne,0x01)
          cdef("_id_prompt",sprintf("id_getpos(%d,%s,1)\n",i,idmne),idmne,0x21)
          cdef("user_checkall",sprintf("id_moveone(%d,%s,1)\n",i,idmne),idmne,0x01)
      }

      if (_def & 0x2) {
          idmne = list_getpar(IDAXIS,i+1,"tapmne")
          cdef("user_getpangles",sprintf("id_getpos(%d,%s,2)\n",i,idmne),idmne,0x01)
          cdef("_id_prompt",sprintf("id_getpos(%d,%s,2)\n",i,idmne),idmne,0x21)
          cdef("user_checkall",sprintf("id_moveone(%d,%s,2)\n",i,idmne),idmne,0x01)
       }
  }

  if (whatis("blmenu") & 0x2){
      blmenuadd("Insertion Device motors","ID info","idbody","_idblmenu_")
  }
}
'


#%IU%
#%MDESC%
def idbody(mode) '{
  if (mode == 1) {
     if (ID_ON) {
         idoff
     } else {
         idon
     }
  }

  if (mode == 2) {
     idsetup
  }

  return(sprintf("%s",ID_ON?"On":"Off"))
}
'


#%IU%
#%MDESC%
# Polls in the state of the front end
#
def id_poll '{
   local idstat argin moving
   moving = 0

   for (i=0;i<IDNOMECA;i++) {
       if (ID_MOVETHIS[i]) {
           idstat=esrf_io(IDDEV,"DevTrigMotion",IDMECADEV[i])
           if (idstat == 2 ) {
               err_accum=0
               moving=1
           }
           else {
               if (!ESRF_ERR) {
                   ID_MOVETHIS[i] = 0
               }
               else {
                   if ( (err_accum++) > 3 ) {
                       print "Error on polling insertion device.Giving up"
                       ID_MOVETHIS[i] = 0
                   }
               }
           }
       }
   }

   if (moving)  return(1)
}
'



#%IU% (<axis>, <idmne>, <tapergap>)
#%MDESC%
#    Sets the "def" and "tapmne" or "gapmne" fields in IDAXIS.
# <axis>     : axis number.
# <idmne>    : ID motor mnemonic.
# <tapergap> : can be {"1"|"TAPER"|"taper"|"t"|"Taper"}
#
def id_axedef(axis, idmne, tapergap) '{
    local _def

    _def = list_getpar(IDAXIS, axis+1, "def")

    if (tapergap == "1" || tapergap == "TAPER" || tapergap == "taper" || tapergap == "t" || tapergap == "Taper") {
        list_setpar(IDAXIS, axis+1, "tapmne", idmne)
        list_setpar(IDAXIS, axis+1, "def", _def |= 0x2)
    }
    else {
        list_setpar(IDAXIS, axis+1, "gapmne", idmne)
        list_setpar(IDAXIS, axis+1, "def", _def |= 0x1)
    }

}
'


#%IU% (<devname>)
#%MDESC%
#    Gets all info from frontend device server
# Fills IDNOMECA  IDMECA  IDMECADEV
def id_getallinfo(devname) '{
    local helloval configval

    if (esrf_io(devname,"tcp")  == -1 ) {
            return(-1)
    }

    if (esrf_io(devname,"DevHello",helloval)  == -1 ) {
            return(-1)
    }

    if (esrf_io(devname,"DevReadConfig",configval) == -1) {
        return(-1)
    }

    IDNOMECA = helloval[2]

    axis     = 0
    mecaix   = 0

    for (i=0;i<IDNOMECA;i++) {
         local mecaname
         IDMECA[i]    = helloval[3+i]
         IDMECADEV[i] = configval[mecaix]

         mecaname = configval[mecaix+1]
         mecaix  += 2
         for (j=0;j<IDMECA[i];j++) {
              list_add(IDAXIS,sprintf("_%d",axis+1))
              list_setpar(IDAXIS,axis+1,"dev",IDMECADEV[i])
              list_setpar(IDAXIS,axis+1,"meca",mecaname)
              list_setpar(IDAXIS,axis+1,"title",configval[mecaix + 1])
              list_setpar(IDAXIS,axis+1,"type",configval[mecaix + 2])
              list_setpar(IDAXIS,axis+1,"num",j+1)
              list_setpar(IDAXIS,axis+1,"ident",configval[mecaix])
              mecaix += 5
              axis++
         }

    }

}
'


#%IU% ()
#%MDESC%
# Print out main info from frontend device server
#
def id_showinfo() '{
    printf("Devname:  %s   for  %d carriage\n",IDDEV,IDNOMECA)

    printf("%d axes in the system\n",list_n(IDAXIS))
    for (i=0;i<list_n(IDAXIS);i++) {
       printf("%2d - %8s :",i+1,list_getpar(IDAXIS,i+1,"meca"))
       printf("     carriage: %s ; type: %s \n", list_getpar(IDAXIS,i+1,"dev"), list_getpar(IDAXIS,i+1,"title"))
    }
}'


#%IU% ()
#%MDESC%
#  Reads position for all axes
#
def id_getallpos() '{
    global IDERROR

    if (ID_NOTREAD) return(0)

    if (esrf_io(IDDEV,"DevRead",IDALLPOS) == -1) {
           IDERROR=1
           return(-1)
    } else {
           IDERROR=0
    }
}
'


#%IU% (axis,idmne,gaptap)
#%MDESC%
#  Assigns position to each motor
#
def id_getpos(axis,idmne,gaptap) '{

    local motnum

    if (IDERROR)
      return(-1);

    if (ID_NOTREAD) return(0)

    motnum = motor_num(idmne)

    if (motnum == -1 ) {
        printf("Internal macro error on \"id\" macros.\n")
        printf("Contact your spec administrator!\n")
        return(-1)
    }

    if (gaptap == 1) {
       A[motnum] = IDALLPOS[axis*2]
    }

    if (gaptap == 2) {
       A[motnum] = IDALLPOS[axis*2+1]
    }

    if (ID_ATPROMPT) {
      chg_dial(motnum,A[motnum])
      chg_offset(motnum,A[motnum])
    }

    ID_OLDPOS[motnum] = A[motnum]

    return(0)
}
'


#%IU% (<axis>, <idmne>, <gaptap>)
#%MDESC%
#  Flags whether axes should be moved or not.
#
def id_moveone(axis, idmne, gaptap) '{
    local idnum

    idnum = motor_num(idmne)

    if (fabs(A[idnum] - ID_OLDPOS[idnum]) > (1.0 / motor_par(idnum,"step_size"))) {
        _bad_lim = 0
        _chk_lim idnum A[idnum]

        if (!_bad_lim) {
            if (gaptap == 1 ) {
                IDMOVE[axis] |= 0x1
                IDMOVEPOS[axis] = A[idnum]
            }

            if (gaptap == 2) {
                IDMOVE[axis] |= 0x2
                IDMOVETAPPOS[axis] = A[idnum]
            }

            ID_MOVINGANY  = 1
            ID_NOTREAD    = 0
        }
        else {
            A[idnum] = ID_OLDPOS[idnum]
        }
    } 
    else {
        # movement too small
    }
}
'


#%IU% ()
#%MDESC%
#
def id_prompt() '{
   global ID_ATPROMPT

   ID_ATPROMPT=1
   id_getallpos()
   _id_prompt
   ID_ATPROMPT=0

   ID_NOTREAD=0
}
'


#%IU% ()
#%MDESC%
#
def id_premove() '{
    local ii

    ID_MOVINGANY = 0
    ID_NOTREAD   = 1

    for (ii=0 ; ii<list_n(IDAXIS) ; ii++) {
        local _def

        IDMOVE[ii] = 0

        _def = list_getpar(IDAXIS, ii+1, "def")

        if (_def & 0x1) {
            mnum = motor_num(list_getpar(IDAXIS, ii+1, "gapmne"))
            if (mnum != -1 ) {
                IDMOVEPOS[mnum] = ID_OLDPOS[mnum]
            }
        }

        if (_def & 0x2) {
            mnum = motor_num(list_getpar(IDAXIS, ii+1, "tapmne"))
            if (mnum != -1 ) {
                IDMOVETAPPOS[mnum] = ID_OLDPOS[mnum]
            }
        }
    }
}
'


#%IU% ()
#%MDESC%
# Move all axes that were previously flagged to move
#
def id_moveall() '{
    local i axis j

    if (ID_MOVINGANY) {

        axis = 0
        for (i=0;i<IDNOMECA;i++) {

            ID_MOVETHIS[i]=0
            ID_ARGIN[3] = 0
            ID_ARGIN[4] = 0

            for (j=0;j<IDMECA[i];j++) {
                if (IDMOVE[axis]) {
                    local _def

                    _def = list_getpar(IDAXIS,axis+1,"def")

                    ID_MOVETHIS[i]++
                    ID_ARGIN[0] = IDMECADEV[i]
                    ID_ARGIN[1] = list_getpar(IDAXIS,axis+1,"ident")

                    if (IDMOVE[axis] == 3) {   # both
                        ID_ARGIN[2] = 2
                        ID_ARGIN[3] = IDMOVEPOS[axis]
                        ID_ARGIN[4] = IDMOVETAPPOS[axis]
                    }

                    if (IDMOVE[axis] == 2) {   # only taper
                        ID_ARGIN[2] = 1
                        ID_ARGIN[4] = IDMOVETAPPOS[axis]
                    }

                    if (IDMOVE[axis] == 1) {   # only gap
                        ID_ARGIN[2] = 0
                        ID_ARGIN[3] = IDMOVEPOS[axis]
                    }
                }
                axis++
            }
            if (ID_MOVETHIS[i]) {
                esrf_io(IDDEV,"DevWrite",ID_ARGIN,ID_ARGOUT)
            }
        }
    }
}
'


#%MACROS%
#%IMACROS%
#%AUTHOR% V.Rey - BLISS - (Original 11/1996)
#  $Revision: 5.0 $ / $Date: 2012/05/03 12:33:32 $
#%TOC%