esrf

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

#%TITLE% SLIT_MH.MAC
#%NAME% %B%slit_mh.mac%B%#  Macros for operating slits (gap/offset)
#%DESCRIPTION%
#This macro set allows you to define calculation motors on slits.
#You must define:
#%PRE%
#   a slit controller in config (one controller will work on one or
#   two pair of blades):
#   MOTORS       DEVICE    ADDR   <>MODE      NUM               <>TYPE
#      YES       slit                           4         Macro Motors
#   motors in config referring to that controller. Channel assignment
#   will decide on the motor role as follow:
#   Channel
#     0   -   gap    
#     1   -   offset 
#
#   Different pairs of slits can be defined by using additional
#   module numbers in the motor unit/module/channel assignment.
#
#   Config file
#     The following motor parameters have to be associated in config
#     file to the channel 0 of the controller/module. 
#
#     Example:
#
#     MOT000 = MAXE:0/0 [...]   psu
#     MOT001 = MAXE:0/1 [...]   psd
#     MOT002 = MAXE:0/2 [...]   psl
#     MOT003 = MAXE:0/3 [...]   psr
#     MOT004 = MAXE:0/4 [...]   ssu
#     MOT005 = MAXE:0/5 [...]   ssd
#     MOT004 = MAXE:0/4 [...]   ssl
#     MOT005 = MAXE:0/5 [...]   ssr
#
#     MOT006 = MAC_MOT:0/0/0 [....]         psvg
#     MOTPAR:blade1 = psu
#     MOTPAR:blade2 = psd
#     MOT007 = MAC_MOT:0/0/1 [....]         psvo
#     MOT008 = MAC_MOT:0/1/0 [....]         pshg
#     MOTPAR:blade1 = psl
#     MOTPAR:blade2 = psr
#     MOT009 = MAC_MOT:0/1/1 [....]         psho
#
#     MOT010 = MAC_MOT:0/2/0 [....]         ssvg
#     MOTPAR:blade1 = ssu
#     MOTPAR:blade2 = ssd
#     MOT011 = MAC_MOT:0/2/1 [....]         ssvo
#     MOT012 = MAC_MOT:0/3/0 [....]         sshg
#     MOTPAR:blade1 = ssl
#     MOTPAR:blade2 = ssr
#     MOT013 = MAC_MOT:0/3/1 [....]         ssho
#%PRE%
#There is a possibility to set a scale factor on the gap or offset, so that
#the resulting gap or offset original value is multiplied by this scale factor.
#%BR%This is implemented when the %B%scale%B% property is defined for a
#gap/pffset motor:
#%BR%     MOTPAR:scale = <a value>
#%BR%This is useful in particular when moving the gap executes a rotational
#movement on the plate and we want the gap to reflect the angular rotation.
#%END%

#%IU% (mne, type, unit, module, chan)
#%MDESC% Called after reading the config file. If return the string ".error.",
#spec will consider the channel unusable.
def slit_config(mne,type,unit,module,chan) '{

  if (type == "ctrl") return

  
  master = motor_par(mne,"chan0")
  chan   = motor_par(mne,"channel")

  blade1 = motor_par(master,"blade1")
  blade2 = motor_par(master,"blade2")

  if (motor_num(blade1) == -1 || motor_num(blade2) == -1) {  
    return ".error."
  }

  motor_par(mne, "master",  master, "add")

  if (chan == 0) {
    motor_par(mne,    "role",   "slitgap","add")
    motor_par(mne,    "locked",   0,       "add")
    motor_par(mne,    "setp",    -999,       "add")
    motor_par(mne,    "oldpos",  -999,       "add")
    local myscale
    myscale = motor_par(mne,    "scale")
    if (myscale < 1.0e-8) {
      myscale = 1
    }
    motor_par(mne,    "scalefactor",  myscale,   "add")
    motor_par(master, "slitgap", motor_mne(mne), "add")

    motor_par(blade1, "master",  mne, "add")
    motor_par(blade2, "master",  mne, "add")
    motor_par(blade1, "oldpos",  -999, "add")
    motor_par(blade2, "oldpos",  -999, "add")

    motor_par(blade1, "role",  "blade1", "add")
    motor_par(blade2, "role",  "blade2", "add")
  } else if (chan == 1) {
    motor_par(mne,    "role",   "slitoff",  "add")
    motor_par(mne,    "locked",  0,          "add")
    motor_par(mne,    "setp",   -999,       "add")
    motor_par(mne,    "oldpos",  -999,       "add")
    motor_par(master, "slitoff", motor_mne(mne), "add")
    local myscale
    myscale = motor_par(mne,    "scale")
    if (myscale < 1.0e-8) {
      myscale = 1
    }
    motor_par(mne,    "scalefactor",  myscale,       "add")
  } else {
    printf ("Wrong channel assignment for slit motor. Only 0 or 1 accepted\n")
    return ".error."
  }
  
  cdef("user_checkall",sprintf("slit_checkmove(%s)\n",master),motor_mne(master),0x01)

  return sprintf("%s %s", blade1, blade2)
}'

#%IU% (mne, mode, master0)
#%MDESC% Calculate the gap/offset as function of the real motors (mode=0)
#or the real motor positions as function of the gap/offset(mode=1).
#Apply the scale factor if defined.
def slit_calc(mne,mode,master0) '{
   local role master motnum
   local blade1 blade2 slitoff slitgap
   local bl1num bl2num offnum gapnum

   if (mne == "..") {
         return
   }

   motnum = motor_num(mne)
   role   = motor_par(mne,"role")
   master = motor_par(mne,"master")

   if ( mode == 0) {
      blade1 = motor_par(master, "blade1")
      blade2 = motor_par(master, "blade2")
      bl1num = motor_num(blade1)
      bl2num = motor_num(blade2)
      local scale      
      scale = motor_par(mne,"scalefactor")
      if (scale  < 1.0e-8)
        scale = 1

      if (role == "slitoff") {
        A[motnum] = ((A[bl1num] - A[bl2num]) / 2.0) * scale
      } else if ( role == "slitgap") {  # role = gap
        A[motnum] = (A[bl1num] + A[bl2num]) * scale
      }

   } else {

      slitoff = motor_par(master, "slitoff")
      slitgap = motor_par(master, "slitgap")
      offnum  = motor_num(slitoff)
      gapnum  = motor_num(slitgap)

      offpos = A[offnum]
      gappos = A[gapnum]

      if ( motor_par(offnum,"locked") ) {
          offpos = motor_par(offnum,"setp")
      }
      if ( motor_par(gapnum,"locked") ) {
          gappos = motor_par(gapnum,"setp")
      }
           
      if (role == "blade1") {
         A[motnum] = (gappos/2.0)/motor_par(gapnum,"scalefactor") + offpos/motor_par(offnum,"scalefactor")
      } else if (role == "blade2") {  # role = blade2
         A[motnum] = gappos/2.0/motor_par(gapnum,"scalefactor")- offpos/motor_par(offnum,"scalefactor")
      }
   }

   motor_par( motnum,"oldpos", A[motnum])
   
}'

#%IU% (master)
#%MDESC% Check if the motors, attached to the %B%master%B% one can move.
def slit_checkmove(master) '{
local slitmots 
local diff mot motnum
     
  slitmots["gap"] = motor_num( motor_par(master,"slitgap") )
  slitmots["off"] = motor_num( motor_par(master,"slitoff") )
  slitmots["bl1"] = motor_num( motor_par(master,"blade1") )
  slitmots["bl2"] = motor_num( motor_par(master,"blade2") )

  offnum = slitmots["off"]
  gapnum = slitmots["gap"]

  for (mot in slitmots) {
    motnum = slitmots[mot]
    diff   = fabs( A[motnum] - motor_par(motnum,"oldpos") )

    if (diff > 1.0 / motor_par(motnum, "step_size")) {
      if (mot == "bl1" || mot == "bl2") {
        motor_par(slitmots["gap"], "locked", 0)
        motor_par(slitmots["off"], "locked", 0)
      } else {
        if (mot == "off") {  #offset - fix gap
          if (motor_par(gapnum,"locked") == 0) {
            motor_par(gapnum,"setp",A[gapnum])
            motor_par(gapnum,"locked",1)
          }
        } else {  #gap - fix offset
          if (motor_par(offnum,"locked") == 0) {
            motor_par(offnum,"setp",A[offnum])
            motor_par(offnum,"locked",1)
          }
        }
        motor_par(motnum,"locked",0)
      }
    }    
  }
}'

#%IU% motor_mne
#%MDESC% Print the configuration of a slit, where %B%motor_mne%B% is a gap or
#offset mnemonic.
def slit '{
   local mne master
   mne    = "$1"
   master = motor_par(mne,"chan0")

   printf ("Gap    : %s\n", motor_par(master,"slitgap"))
   printf ("Offset : %s\n", motor_par(master,"slitoff"))
   printf ("Blade1 : %s\n", motor_par(master,"blade1"))
   printf ("Blade2 : %s\n", motor_par(master,"blade2"))
}'

#%IU%  (<format>, <label>, <offs>, <gap>, <bld1>, <bld2>)
#%MDESC% Formated print of a slit configuration.
def slit_disp(format, label, offs, gap, bld1, bld2) '{
local _offset _gap _blade1 _blade2

  _offset = sprintf("Offset(%s)", motor_mne(offs))
  _gap = sprintf("Gap(%s)", motor_mne(gap))
  _blade1 = sprintf("Blade(%s)", motor_mne(bld1))
  _blade2 = sprintf("Blade(%s)", motor_mne(bld2))
  printf("%10s: %12s %12s %12s %12s\n",label,_offset,_gap,_blade1,_blade2)
  if (format == 1) {
    printf("           %12.4f %12.4f %12.4f %12.4f    High\n",         \
	user(offs, get_lim(offs, 1)), user(gap, get_lim(gap, 1)), \
        user(bld1, get_lim(bld1, 1)), user(bld2, get_lim(bld2, 1)))
  }
  printf("%10s %12.4f %12.4f %12.4f %12.4f   (User)\n", "", \
	A[offs], A[gap], A[bld1], A[bld2])
  if (format == 1) {
    printf("           %12.4f %12.4f %12.4f %12.4f    Low\n", \
	user(offs, get_lim(offs,-1)), user(gap, get_lim(gap,-1)), \
	user(bld1, get_lim(bld1,-1)), user(bld2, get_lim(bld2,-1)))
    printf("           %12.4f %12.4f %12.4f %12.4f    High\n",  \
	get_lim(offs,1),get_lim(gap,1),get_lim(bld1,1),get_lim(bld2,1))
    printf("%10s %12.4f %12.4f %12.4f %12.4f   (Dial)\n", "", \
	dial(offs,A[offs]),dial(gap,A[gap]),dial(bld1,A[bld1]), \
	dial(bld2,A[bld2]))
    printf("           %12.4f %12.4f %12.4f %12.4f    Low\n",  \
	get_lim(offs,-1),get_lim(gap,-1),get_lim(bld1,-1),get_lim(bld2,-1))
  }
}'

#%IU% (mot)
#%MDESC%
# Returns true if %B%mot%B% is protected.
def mot_prot(mot) '{
   local stat
   stat = motor_par(mot, "status")
   return (!((stat & 0x0040) && (stat & 0x0080)))
}'

#%MACROS%
#%IMACROS%
#%AUTHOR% %BR%
#%TOC%
#$Revision: 1.1 $, $Date: 2013/07/22 10:47:20 $
#%END%
#%LOG%
#$Log: slit_mh.mac,v $
#Revision 1.1  2013/07/22 10:47:20  beteva
#Initial revision
#