esrf

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

#$Log: tab3.mac,v $
#Revision 1.6  2012/03/20 09:03:39  papillon
#* update from master repository xrme
#( new geo for id21 added )
#
#Revision 1.5  2004/01/21 10:32:42  rey
#Bug with index in hgtmove corrected
#
#Revision 1.4  2003/12/09 16:56:55  papillon
#add bm25 geometry (7)
#
#Revision 1.3  2003/06/10 13:42:04  rey
#Bug corrected in t3_geo switch
#
#Revision 1.2  2003/02/27 08:20:38  rey
#*** empty log message ***
#
#Revision 1.1  2003/02/25 09:09:13  rey
#Initial revision
#
#Revision 1.3  2003/01/31 20:01:54  ahoms
#Fixed bug in position calc.: old z variable
#
#Revision 1.2  2002/03/07 17:52:45  beteva
#added id29 (geometry 5).
#
#%TITLE% NTAB3.MAC
#%NAME%
#  Macros to control three leg table(s) with logical motors
#             xtilt, ytilt and height
#%DESCRIPTION%
#  A table with three legs in triangle. One in the front and two in the
#  back is a common positioning element in ESRF beamlines. This macros
#  implement tilts and height for this kind of table as pseudomotors.
#  This macros can use different geometries.
#  More than one table can be defined in this way in the same spec 
#  application.%BR%
#
#  For geometry 0 (standard):%BR%
#     Xtilt is the angle defined by the two back legs. 
#     Fixed a middle point B between the two back legs. The height in the 
#     middle point between B and the front leg gives the value for the
#     motor height. The motor Ytilt is defined as the angle existing 
#     between B and front leg. 
#  
#     Two parameters must be input to the system: the distance between the
#     two back legs and the distance between B and the front leg.
#     In this geometry distances are given in mm. Angles in mrad.%BR%
#  For geometry 1 (side front leg):%BR%
#     The front leg is on the same side and aligned with the first motor.
#     The fixed point is in the middle of the mirror. For positive x tilt 
#     is motor 1 higher up then motor 2. For positive y tilt is the 
#     front motor higher up then the two back motors.%BR%
#  For geometry 2 (ID22 mirror):%BR%
#     Xtilt is the angle defined by the two back legs, but only leg2 moves
#     when a xtilt is requested. Ytilt and Height are defined in the line
#     defined by leg1 and front. For the two movements leg2 follows leg1.%BR%
#  For geometry 3 (ID21 mirror):%BR%
#     Xtilt is the angle defined by the two back legs. 
#     Fixed a middle point B between the two back legs. The value of this 
#     point gives the value for the motor Height. The motor Ytilt is 
#     defined as the angle existing between B and front leg. 
#     Two parameters must be input to the system: the distance between the
#     two back legs and the distance between B and the front leg.
#     In this geometry distances are given in mm. Angles in mrad.%BR%
#  For geometry 4 (ID20):%BR%
#  For geometry 5 (ID29 mirror):%BR%
#     Xtilt is the angle defined by the two back legs. 
#     B is the middle distance point between the two back legs. C is at
#     fixed distance between B and the front leg, used to calculate the
#     height. The Ytilt is defined as the angle between B and the front leg. 
#     Three parameters needed: the distance between the two back legs,
#     between B and the front leg and between C and the front leg (all
#     given in mm). Calculated angles in mrad.%BR%
#  For geometry 6 (ID30):%BR%
#  For geometry 7 (????????):%BR%
#  For geometry 8 (ID21 KB):%BR%
#     l1 and l2 are the 2 back leg. lf is the front leg
#     the angle between (l1-l2) and (l1-lf) is orthogonal
#     B is the mildle of (l1-l2).
#     C is the middle of (l1-lf).
#     YTilt rotation axis pass by B and is parallel to (l1-lf)
#     XTilt rotation axis paas by C and is parallel to (l1-l2)
#     Height is defined by the intersection of the 2 rotation axis
#  
#  All motors must be defined in config.
#
#%EXAMPLE%
#%DL%
#%DT% tab3setup table1 0 122 422 tab1 tab2 tabf xti yti hgt 
#  Defines a table named "table1", geometry 0, distances 122 and 422 and 
#  motor names. To define other tables call tab3setup again changing the
#  table name
#
#%DT% mvr hgt 3
#  Moves relative height 3 mm. this will move all tab motors up 3 mm.
#%DT% ascan xti 0 3 10 1
#  Will scan on angles xti between 0 and 3 stopping in 10 intermediate
#  points and counting for one second at each point
#%XDL%
#%END%
#  
#

#%UU%
#%MDESC%  Setup one table in the system
#
def tab3setup '{
  global TAB3PAR
  local t3_mne t3_geo t3_bl1 t3_bl2 t3_fro t3_xti t3_yti t3_hgt
  local t3_d1 t3_d2 t3_d3
  local t3_trm t3_trl

  list_test TAB3PAR

#
# Set values.
  if (($# < 10) || ($# > 12)) {
    t3_mne=getval("Name for the table (no space)",sprintf("%d",list_n(TAB3PAR)))
    if (index(t3_mne, " ") != 0) {
      p "Name for table must not contain any space character"
      exit
    }
    if (t3_mne == 1) {
        t3_mne = "tab3_1"
    }

    if (list_check(TAB3PAR, t3_mne)) {
      t3_geo  = list_getpar(TAB3PAR, t3_mne, "geo")
      t3_d1   = list_getpar(TAB3PAR, t3_mne, "d1")
      t3_d2   = list_getpar(TAB3PAR, t3_mne, "d2")
      t3_d3   = list_getpar(TAB3PAR, t3_mne, "a")
      t3_bl1  = list_getpar(TAB3PAR, t3_mne, "bl1")
      t3_bl2  = list_getpar(TAB3PAR, t3_mne, "bl2")
      t3_fro  = list_getpar(TAB3PAR, t3_mne, "fro")
      t3_xti  = list_getpar(TAB3PAR, t3_mne, "xti")
      t3_yti  = list_getpar(TAB3PAR, t3_mne, "yti")
      t3_hgt  = list_getpar(TAB3PAR, t3_mne, "hgt")
      t3_trm  = list_getpar(TAB3PAR, t3_mne, "trm")
      t3_trl  = list_getpar(TAB3PAR, t3_mne, "trl")
    } else {
      t3_geo = 0
      t3_d1  = 0
      t3_d2  = 0
      t3_d3  = 0
      t3_bl1 = ""
      t3_bl2 = ""
      t3_fro = ""
      t3_xti = ""
      t3_yti = ""
      t3_hgt = ""
      t3_trm = ""
      t3_trl = 0
    }
  
    t3_geo = getval("Geometry for table(0=standard,see help for others)",t3_geo)
    t3_d1 = getval("\tDistance between the two back legs",t3_d1)
    t3_d2 = getval("\tDistance between the front leg and the back",t3_d2)
    if (t3_geo == 5) 
      t3_d3  = getval("\tDistance between front leg and center of rotation",t3_d3)

    printf("  Motor names\n")

    t3_bl1 = getval("\tBack leg 1",t3_bl1)
    t3_bl2 = getval("\tBack leg 2",t3_bl2)
    t3_fro = getval("\tFront leg",t3_fro)
    t3_xti = getval("\tX Tilt(angle between back legs)",t3_xti)
    t3_yti = getval("\tY Tilt(angle between front and back)",t3_yti)
    t3_hgt = getval("\tHeight",t3_hgt)

    if (t3_geo == 7) {
	     printf("  Table Translation\n")
	     t3_trm = getval("\tTranslation motor", t3_trm)
	     t3_trl = getval("\tTranslation limit", t3_trl)
    }
   }
   else {
    t3_mne = "$1"
    if (t3_mne == 1) {
        t3_mne = "tab3_1"
    }
    t3_geo = $2
    t3_d1  = $3
    t3_d2  = $4
    if (t3_geo == 5) {
      t3_d3   = $5
      t3_bl1 = "$6"
      t3_bl2 = "$7"
      t3_fro = "$8"
      t3_xti = "$9"
      t3_yti = "$10"
      t3_hgt = "$11"
    } else {
      t3_d3   = 0
      t3_bl1 = "$5"
      t3_bl2 = "$6"
      t3_fro = "$7"
      t3_xti = "$8"
      t3_yti = "$9"
      t3_hgt = "$10"
    }
    if (t3_geo==7) {
      t3_trm = "$11"
      t3_trl = $12
    }
  }

  if (index(t3_mne, " ") != 0) {
    p "Name for table must not contain any space character"
    exit
  }
  if ((t3_geo != 0)&&\
      (t3_geo!=1)&&\
      (t3_geo!=2)&&\
      (t3_geo!=3)&&\
      (t3_geo!=4)&&\
      (t3_geo!=5)&&\
      (t3_geo!=6)&&\
      (t3_geo!=7)&&\
      (t3_geo!=8)) {
    printf("This geometry is not implemented yet\n")
    exit
  }
  if (motor_num(t3_bl1) == -1) {
    printf("motor \"%s\" does not exist\n", t3_bl1)
    exit
  }
  if (motor_num(t3_bl2) == -1) {
    printf("motor \"%s\" does not exist\n", t3_bl2)
    exit
  }
  if (motor_num(t3_fro) == -1) {
    printf("motor \"%s\" does not exist\n", t3_fro)
    exit
  }
  if (motor_num(t3_xti) == -1) {
    printf("motor \"%s\" does not exist\n", t3_xti)
    exit
  }
  if (motor_num(t3_yti) == -1) {
    printf("motor \"%s\" does not exist\n", t3_yti)
    exit
  }
  if (motor_num(t3_hgt) == -1) {
    printf("motor \"%s\" does not exist\n", t3_hgt)
    exit
  }

  _tab3off(t3_mne)
  list_add(TAB3PAR, t3_mne)
  list_setpar(TAB3PAR, t3_mne, "geo", t3_geo)
  list_setpar(TAB3PAR, t3_mne, "d1" , t3_d1)
  list_setpar(TAB3PAR, t3_mne, "d2" , t3_d2)
  list_setpar(TAB3PAR, t3_mne, "a"  , t3_d3)
  list_setpar(TAB3PAR, t3_mne, "bl1", t3_bl1)
  list_setpar(TAB3PAR, t3_mne, "bl2", t3_bl2)
  list_setpar(TAB3PAR, t3_mne, "fro", t3_fro)
  list_setpar(TAB3PAR, t3_mne, "xti", t3_xti)
  list_setpar(TAB3PAR, t3_mne, "yti", t3_yti)
  list_setpar(TAB3PAR, t3_mne, "hgt", t3_hgt)
  list_setpar(TAB3PAR, t3_mne, "mne", t3_mne)
  if (t3_geo==7) {
    list_setpar(TAB3PAR, t3_mne, "trm", t3_trm)
    list_setpar(TAB3PAR, t3_mne, "trl", t3_trl)
  }

  _tab3on(t3_mne)

  setup_tail("tab3", t3_mne)
}'

#%UU% (table-mnemonic)
#%MDESC%
#   Delete definitions for one table
#
def tab3unsetup '{
  local t3_mne

  t3_mne = "$1"
  _tab3off(t3_mne)
  list_remove(TAB3PAR, t3_mne)
}'

#%UU%
#%MDESC% Shows a list with the actual configuration in this system
#
def tab3show '{
  local t3_n

  t3_n = list_n(TAB3PAR)
  printf("%d Three leg tables defined in this system:", t3_n)
  printf("\n\n")

  for (i=1;i<=t3_n;i++) {
    printf("   Table \"%s\" :\n", list_getpar(TAB3PAR, i, "mne"))
    printf("      bl1: %5s          xti: %5s\n",list_getpar(TAB3PAR,i,"bl1"),list_getpar(TAB3PAR,i,"xti"))
    printf("      bl2: %5s          yti: %5s\n",list_getpar(TAB3PAR,i,"bl2"),list_getpar(TAB3PAR,i,"yti"))
    printf("      fro: %5s          hgt: %5s\n\n",list_getpar(TAB3PAR,i,"fro"),list_getpar(TAB3PAR,i,"hgt"))
  }
}'

#%IU%
#%MDESC%
# === Use only in geometry 7 ===
# Read translation motor to determine which geometry to use
# Use parameter \"a\" to set a flag
#
def tab3_trmset '{
  local trmnum trmval
  trmnum= motor_num(list_getpar(TAB3PAR, $1, "trm"))
  if (A[trmnum]>list_getpar(TAB3PAR, $1, "trl")) {
	list_setpar(TAB3PAR, $1, "a", 1)
  } else {
	list_setpar(TAB3PAR, $1, "a", 0)
  }
}'

#%IU%
#%MDESC%
#
# Read position from controller for bl1.
#
def tab3_bl1get '{
  list_setpar(TAB3PAR, "$2", "bl1oldpos", A[$1])
}'

#%IU%
#%MDESC%
#
# Read position from controller for bl2.
#
def tab3_bl2get '{
  list_setpar(TAB3PAR, "$2", "bl2oldpos", A[$1])
}'

#%IU%
#%MDESC%
#
# Read position from controller for fro.
#
def tab3_froget '{
  list_setpar(TAB3PAR, "$2", "frooldpos", A[$1])
}'

#%IU%
#%MDESC%
#  Calculates xti from tab1, tab2, tabf
#
def tab3_xtiget '{
  local t3_bl1 t3_bl2 t3_fro t3_xti t3_yti t3_hgt 
  local t3_geo t3_d1 t3_d2 t3_tabmne t3_motmne t3_d3

  t3_motmne = $1
  t3_tabmne = "$2"

  t3_geo = list_getpar(TAB3PAR, t3_tabmne, "geo")
  t3_d1 = list_getpar(TAB3PAR, t3_tabmne, "d1")
  t3_d2 = list_getpar(TAB3PAR, t3_tabmne, "d2")
  if (t3_geo==7) {
    tab3_trmset t3_tabmne
  }
  t3_d3  = list_getpar(TAB3PAR, t3_tabmne, "a")
  t3_bl1 = motor_num(list_getpar(TAB3PAR, t3_tabmne, "bl1"))
  t3_bl2 = motor_num(list_getpar(TAB3PAR, t3_tabmne, "bl2"))
  t3_fro = motor_num(list_getpar(TAB3PAR, t3_tabmne, "fro"))
  t3_xti = motor_num(list_getpar(TAB3PAR, t3_tabmne, "xti"))
  t3_yti = motor_num(list_getpar(TAB3PAR, t3_tabmne, "yti"))
  t3_hgt = motor_num(list_getpar(TAB3PAR, t3_tabmne, "hgt"))

  A[t3_motmne] = tab3_tf(3,A[t3_bl1],A[t3_bl2],A[t3_fro], A[t3_xti],\
			 A[t3_yti],A[t3_hgt],t3_geo,t3_d1,t3_d2, t3_d3)

  list_setpar(TAB3PAR, t3_tabmne, "xtioldpos", A[t3_motmne])
}'

#%IU%
#%MDESC%
#  Calculates yti from tab1, tab2, tabf
#
def tab3_ytiget '{
  local t3_bl1 t3_bl2 t3_fro t3_xti t3_yti t3_hgt 
  local t3_geo t3_d1 t3_d2 t3_tabmne t3_motmne t3_d3

  t3_motmne = $1
  t3_tabmne = "$2"

  t3_geo = list_getpar(TAB3PAR, t3_tabmne, "geo")
  t3_d1 = list_getpar(TAB3PAR, t3_tabmne, "d1")
  t3_d2 = list_getpar(TAB3PAR, t3_tabmne, "d2")
  if (t3_geo==7) {
    tab3_trmset t3_tabmne
  }
  t3_d3  = list_getpar(TAB3PAR, t3_tabmne, "a")
  t3_bl1 = motor_num(list_getpar(TAB3PAR, t3_tabmne, "bl1"))
  t3_bl2 = motor_num(list_getpar(TAB3PAR, t3_tabmne, "bl2"))
  t3_fro = motor_num(list_getpar(TAB3PAR, t3_tabmne, "fro"))
  t3_xti = motor_num(list_getpar(TAB3PAR, t3_tabmne, "xti"))
  t3_yti = motor_num(list_getpar(TAB3PAR, t3_tabmne, "yti"))
  t3_hgt = motor_num(list_getpar(TAB3PAR, t3_tabmne, "hgt"))

  A[t3_motmne] = tab3_tf(4,A[t3_bl1],A[t3_bl2],A[t3_fro],\
			 A[t3_xti],A[t3_yti],A[t3_hgt],t3_geo,t3_d1,t3_d2, t3_d3)
  list_setpar(TAB3PAR, t3_tabmne, "ytioldpos", A[t3_motmne])
}'

#%IU%
#%MDESC%
#  Calculates hgt from tab1, tab2, tabf
#
def tab3_hgtget '{
  local t3_bl1 t3_bl2 t3_fro t3_xti t3_yti t3_hgt 
  local t3_geo t3_d1 t3_d2 t3_tabmne t3_motmne t3_d3

  t3_motmne = $1
  t3_tabmne = "$2"

  t3_geo = list_getpar(TAB3PAR, t3_tabmne, "geo")
  t3_d1 = list_getpar(TAB3PAR, t3_tabmne, "d1")
  t3_d2 = list_getpar(TAB3PAR, t3_tabmne, "d2")
  if (t3_geo==7) {
    tab3_trmset t3_tabmne
  }
  t3_d3  = list_getpar(TAB3PAR, t3_tabmne, "a")
  t3_bl1 = motor_num(list_getpar(TAB3PAR, t3_tabmne, "bl1"))
  t3_bl2 = motor_num(list_getpar(TAB3PAR, t3_tabmne, "bl2"))
  t3_fro = motor_num(list_getpar(TAB3PAR, t3_tabmne, "fro"))
  t3_xti = motor_num(list_getpar(TAB3PAR, t3_tabmne, "xti"))
  t3_yti = motor_num(list_getpar(TAB3PAR, t3_tabmne, "yti"))
  t3_hgt = motor_num(list_getpar(TAB3PAR, t3_tabmne, "hgt"))

  A[t3_motmne] = tab3_tf(5,A[t3_bl1],A[t3_bl2],A[t3_fro],\
			 A[t3_xti],A[t3_yti],A[t3_hgt], t3_geo,t3_d1,t3_d2,t3_d3)
  list_setpar(TAB3PAR, t3_tabmne, "hgtoldpos", A[t3_motmne])
}'

#%IU%
#%MDESC%
#  Moves tab1 when xti, yti or hgt change
#
def tab3_bl1move '{
  local t3_bl1 t3_bl2 t3_fro t3_xti t3_yti t3_hgt 
  local t3_geo t3_d1 t3_d2 t3_tabmne t3_motmne t3_d3

  t3_motmne = $1
  t3_tabmne = "$2"
  t3_xti = motor_num(list_getpar(TAB3PAR, t3_tabmne, "xti"))
  t3_yti = motor_num(list_getpar(TAB3PAR, t3_tabmne, "yti"))
  t3_hgt = motor_num(list_getpar(TAB3PAR, t3_tabmne, "hgt"))

  if ((list_getpar(TAB3PAR, t3_tabmne, "xtioldpos") != A[t3_xti]) ||\
      (list_getpar(TAB3PAR, t3_tabmne, "ytioldpos") != A[t3_yti]) ||\
      (list_getpar(TAB3PAR, t3_tabmne, "hgtoldpos") != A[t3_hgt])) {
    t3_geo = list_getpar(TAB3PAR, t3_tabmne, "geo")
    t3_d1 = list_getpar(TAB3PAR, t3_tabmne, "d1")
    t3_d2 = list_getpar(TAB3PAR, t3_tabmne, "d2")
    t3_d3  = list_getpar(TAB3PAR, t3_tabmne, "a")
    t3_bl1 = motor_num(list_getpar(TAB3PAR, t3_tabmne, "bl1"))
    t3_bl2 = motor_num(list_getpar(TAB3PAR, t3_tabmne, "bl2"))
    t3_fro = motor_num(list_getpar(TAB3PAR, t3_tabmne, "fro"))
 
    A[t3_motmne] = tab3_tf(0,A[t3_bl1],A[t3_bl2],A[t3_fro],\
			   A[t3_xti],A[t3_yti],A[t3_hgt],\
                           t3_geo,t3_d1,t3_d2,t3_d3)
    list_setpar(TAB3PAR, t3_tabmne, "bl1oldpos", A[t3_motmne])
  }
}'

#%IU%
#%MDESC%
#  Moves tab2 when xti, yti or hgt change
#
def tab3_bl2move '{
  local t3_bl1 t3_bl2 t3_fro t3_xti t3_yti t3_hgt 
  local t3_geo t3_d1 t3_d2 t3_tabmne t3_motmne t3_d3

  t3_motmne = $1
  t3_tabmne = "$2"
  t3_xti = motor_num(list_getpar(TAB3PAR, t3_tabmne, "xti"))
  t3_yti = motor_num(list_getpar(TAB3PAR, t3_tabmne, "yti"))
  t3_hgt = motor_num(list_getpar(TAB3PAR, t3_tabmne, "hgt"))

  if ((list_getpar(TAB3PAR, t3_tabmne, "xtioldpos") != A[t3_xti]) ||\
      (list_getpar(TAB3PAR, t3_tabmne, "ytioldpos") != A[t3_yti]) ||\
      (list_getpar(TAB3PAR, t3_tabmne, "hgtoldpos") != A[t3_hgt])) {
    t3_geo = list_getpar(TAB3PAR, t3_tabmne, "geo")
    t3_d1 = list_getpar(TAB3PAR, t3_tabmne, "d1")
    t3_d2 = list_getpar(TAB3PAR, t3_tabmne, "d2")
    t3_d3  = list_getpar(TAB3PAR, t3_tabmne, "a")
    t3_bl1 = motor_num(list_getpar(TAB3PAR, t3_tabmne, "bl1"))
    t3_bl2 = motor_num(list_getpar(TAB3PAR, t3_tabmne, "bl2"))
    t3_fro = motor_num(list_getpar(TAB3PAR, t3_tabmne, "fro"))

    A[t3_motmne] = tab3_tf(1,A[t3_bl1],A[t3_bl2],A[t3_fro],\
			   A[t3_xti],A[t3_yti],A[t3_hgt], \
                           t3_geo,t3_d1,t3_d2,t3_d3)
    list_setpar(TAB3PAR, t3_tabmne, "bl2oldpos", A[t3_motmne])
  }
}'

#%IU%
#%MDESC%
#  Moves tabf when xti, yti or hgt change
#
def tab3_fromove '{
  local t3_bl1 t3_bl2 t3_fro t3_xti t3_yti t3_hgt 
  local t3_geo t3_d1 t3_d2 t3_tabmne t3_motmne t3_d3

  t3_motmne = $1
  t3_tabmne = "$2"
  t3_xti = motor_num(list_getpar(TAB3PAR, t3_tabmne, "xti"))
  t3_yti = motor_num(list_getpar(TAB3PAR, t3_tabmne, "yti"))
  t3_hgt = motor_num(list_getpar(TAB3PAR, t3_tabmne, "hgt"))

  if ((list_getpar(TAB3PAR, t3_tabmne, "xtioldpos") != A[t3_xti]) ||\
      (list_getpar(TAB3PAR, t3_tabmne, "ytioldpos") != A[t3_yti]) ||\
      (list_getpar(TAB3PAR, t3_tabmne, "hgtoldpos") != A[t3_hgt])) {
    t3_geo = list_getpar(TAB3PAR, t3_tabmne, "geo")
    t3_d1 = list_getpar(TAB3PAR, t3_tabmne, "d1")
    t3_d2 = list_getpar(TAB3PAR, t3_tabmne, "d2")
    t3_d3  = list_getpar(TAB3PAR, t3_tabmne, "a")
    t3_bl1 = motor_num(list_getpar(TAB3PAR, t3_tabmne, "bl1"))
    t3_bl2 = motor_num(list_getpar(TAB3PAR, t3_tabmne, "bl2"))
    t3_fro = motor_num(list_getpar(TAB3PAR, t3_tabmne, "fro"))

    A[t3_motmne] = tab3_tf(2,A[t3_bl1],A[t3_bl2],A[t3_fro],\
			   A[t3_xti],A[t3_yti],A[t3_hgt],\
                           t3_geo,t3_d1,t3_d2,t3_d3)
    list_setpar(TAB3PAR, t3_tabmne, "frooldpos", A[t3_motmne])
  }
}'

#%IU%
#%MDESC%
#
def tab3_xtimove '{
  local t3_bl1 t3_bl2 t3_fro t3_xti t3_yti t3_hgt 
  local t3_geo t3_d1 t3_d2 t3_tabmne t3_motmne t3_d3

  t3_motmne = $1
  t3_tabmne = "$2"
  t3_bl1 = motor_num(list_getpar(TAB3PAR, t3_tabmne, "bl1"))
  t3_bl2 = motor_num(list_getpar(TAB3PAR, t3_tabmne, "bl2"))
  t3_fro = motor_num(list_getpar(TAB3PAR, t3_tabmne, "fro"))

  if ((list_getpar(TAB3PAR, t3_tabmne, "bl1oldpos") != A[t3_bl1]) ||\
      (list_getpar(TAB3PAR, t3_tabmne, "bl2oldpos") != A[t3_bl2]) ||\
      (list_getpar(TAB3PAR, t3_tabmne, "frooldpos") != A[t3_fro])) {
    t3_geo = list_getpar(TAB3PAR, t3_tabmne, "geo")
    t3_d1 = list_getpar(TAB3PAR, t3_tabmne, "d1")
    t3_d2 = list_getpar(TAB3PAR, t3_tabmne, "d2")
    t3_d3  = list_getpar(TAB3PAR, t3_tabmne, "a")
    t3_xti = motor_num(list_getpar(TAB3PAR, t3_tabmne, "xti"))
    t3_yti = motor_num(list_getpar(TAB3PAR, t3_tabmne, "yti"))
    t3_hgt = motor_num(list_getpar(TAB3PAR, t3_tabmne, "hgt"))

    A[t3_motmne] = tab3_tf(3,A[t3_bl1],A[t3_bl2],A[t3_fro],\
			   A[t3_xti],A[t3_yti],A[t3_hgt],\
                           t3_geo,t3_d1,t3_d2,t3_d3)
    list_setpar(TAB3PAR, t3_tabmne, "xtioldpos", A[t3_motmne])
  }
}'

#%IU%
#%MDESC%
#
def tab3_ytimove '{
  local t3_bl1 t3_bl2 t3_fro t3_xti t3_yti t3_hgt 
  local t3_geo t3_d1 t3_d2 t3_tabmne t3_motmne t3_d3

  t3_motmne = $1
  t3_tabmne = "$2"
  t3_bl1 = motor_num(list_getpar(TAB3PAR, t3_tabmne, "bl1"))
  t3_bl2 = motor_num(list_getpar(TAB3PAR, t3_tabmne, "bl2"))
  t3_fro = motor_num(list_getpar(TAB3PAR, t3_tabmne, "fro"))

  if ((list_getpar(TAB3PAR, t3_tabmne, "bl1oldpos") != A[t3_bl1]) ||\
      (list_getpar(TAB3PAR, t3_tabmne, "bl2oldpos") != A[t3_bl2]) ||\
      (list_getpar(TAB3PAR, t3_tabmne, "frooldpos") != A[t3_fro])) {
    t3_geo = list_getpar(TAB3PAR, t3_tabmne, "geo")
    t3_d1 = list_getpar(TAB3PAR, t3_tabmne, "d1")
    t3_d2 = list_getpar(TAB3PAR, t3_tabmne, "d2")
    t3_d3  = list_getpar(TAB3PAR, t3_tabmne, "a")
    t3_xti = motor_num(list_getpar(TAB3PAR, t3_tabmne, "xti"))
    t3_yti = motor_num(list_getpar(TAB3PAR, t3_tabmne, "yti"))
    t3_hgt = motor_num(list_getpar(TAB3PAR, t3_tabmne, "hgt"))

    A[t3_motmne] = tab3_tf(4,A[t3_bl1],A[t3_bl2],A[t3_fro],\
			   A[t3_xti],A[t3_yti],A[t3_hgt],\
                           t3_geo,t3_d1,t3_d2,t3_d3)
    list_setpar(TAB3PAR, t3_tabmne, "ytioldpos", A[t3_motmne])
  }
}'

#%IU%
#%MDESC%
#
def tab3_hgtmove '{
  local t3_bl1 t3_bl2 t3_fro t3_xti t3_yti t3_hgt 
  local t3_geo t3_d1 t3_d2 t3_tabmne t3_motmne t3_d3

  t3_motmne = $1
  t3_tabmne = "$2"
  t3_bl1 = motor_num(list_getpar(TAB3PAR, t3_tabmne, "bl1"))
  t3_bl2 = motor_num(list_getpar(TAB3PAR, t3_tabmne, "bl2"))
  t3_fro = motor_num(list_getpar(TAB3PAR, t3_tabmne, "fro"))

  if ((list_getpar(TAB3PAR, t3_tabmne, "bl1oldpos") != A[t3_bl1]) ||\
      (list_getpar(TAB3PAR, t3_tabmne, "bl2oldpos") != A[t3_bl2]) ||\
      (list_getpar(TAB3PAR, t3_tabmne, "frooldpos") != A[t3_fro])) {
    t3_geo = list_getpar(TAB3PAR, t3_tabmne, "geo")
    t3_d1 = list_getpar(TAB3PAR, t3_tabmne, "d1")
    t3_d2 = list_getpar(TAB3PAR, t3_tabmne, "d2")
    t3_d3  = list_getpar(TAB3PAR, t3_tabmne, "a")
    t3_xti = motor_num(list_getpar(TAB3PAR, t3_tabmne, "xti"))
    t3_yti = motor_num(list_getpar(TAB3PAR, t3_tabmne, "yti"))
    t3_hgt = motor_num(list_getpar(TAB3PAR, t3_tabmne, "hgt"))

    A[t3_motmne] = tab3_tf(5,A[t3_bl1],A[t3_bl2],A[t3_fro],\
			   A[t3_xti],A[t3_yti],A[t3_hgt],\
                           t3_geo,t3_d1,t3_d2,t3_d3)
    list_setpar(TAB3PAR, t3_tabmne, "hgtoldpos", A[t3_motmne])
  }
}'

#%IU% (calcidx , tbl1, tbl2, front, xti, yti, z, mode , d1, d2,d3)
#%MDESC% calcidx gives the index of the value to be calculated. Indexes are 
# starting from 0 (tbl1) and go to 5 (z). The 3 leg motors and the 3 pseudo
# motors are all the time given. Depending on calcidx only 3 of them are used
# in the calculation. The mode allows for different geometries. d1 and d2 are
# the distances between the legs. d3 is the distance between the front leg
#and the center of the rotation.
def tab3_tf(calcidx,t3_bl1,t3_bl2,t3_fro,t3_xti,t3_yti,t3_hgt,mode,d1,d2,d3) '{
  local reverse res
  if (calcidx > 2 )
    reverse = 1

  if (mode == 0) {
    if (reverse) {
      res[3] = 1000*atan( (t3_bl2 - t3_bl1) / d1 ) # xti 
      res[4] = 1000*atan( ( (t3_bl1 + t3_bl2)/2 - t3_fro) / d2) # yti
      res[5] = (t3_bl1 + t3_bl2 + 2*t3_fro)/4 # z
    } else {
      res[0] = t3_hgt - d1 * tan(t3_xti/1000) / 2+d2*tan(t3_yti/1000)/2 # tbl 1
      res[1] = t3_hgt + d1 * tan(t3_xti/1000) / 2+d2*tan(t3_yti/1000)/2 # tbl 2
      res[2] = t3_hgt - d2 * tan(t3_yti/1000) / 2  # front 
    }
  }
  if (mode == 1) {
    if (reverse) {
      res[3] = 1000*atan( (t3_bl2 - t3_bl1) / d1 ) # xti
      res[4] = 1000*atan( (t3_fro - t3_bl1) / d2 ) # yti
      res[5] = (t3_bl2 + t3_fro)/2 # z
    } else {
      res[0] = t3_hgt - d1 * tan(t3_xti/1000) / 2 - d2*tan(t3_yti/1000) / 2  # tbl 1
      res[1] = t3_hgt + d1 * tan(t3_xti/1000) / 2 - d2*tan(t3_yti/1000) / 2  # tbl 2
      res[2] = t3_hgt + d2 * tan(t3_yti/1000) / 2 - d1*tan(t3_xti/1000) / 2  # front 
    }
  }
  if (mode == 2) {
    if (reverse) {
      res[3] = deg(atan( (t3_bl2 - t3_bl1) / d1 ))  # xti
      res[4] = deg(atan( (t3_bl1 - t3_fro) / d2 )) # yti
      res[5] = (t3_bl1 + t3_fro)/2            # z
    } else {
      res[0] = t3_hgt + d2 * tan(rad(t3_yti))/2                 # tbl 1
      res[1] = t3_hgt + d2 * tan(rad(t3_yti))/2 + d1 * tan(rad(t3_xti)) # tbl 2
      res[2] = t3_hgt - d2 * tan(rad(t3_yti))/2                 # front 
    }
  }
  if (mode == 3) {
    if (reverse) {
      res[3] = 1000*atan( (t3_bl2 - t3_bl1) / d1 ) # xti 
      res[4] = 1000*atan( ( (t3_bl1 + t3_bl2)/2 - t3_fro) / d2) # yti
      res[5] = (t3_bl1 + t3_bl2)/2 # z
    } else {
      res[0] = t3_hgt - d1 * tan(t3_xti/1000) / 2 # tbl 1
      res[1] = t3_hgt + d1 * tan(t3_xti/1000) / 2 # tbl 2
      res[2] = t3_hgt - d2 * tan(t3_yti/1000) # front 
    }
  }

  if (mode == 4) {
    if (reverse) {
      res[3] = 1000*atan( (t3_bl2 - t3_bl1) / d1 )               # xti
      res[4] = 1000*atan( ( t3_fro - (t3_bl1 + t3_bl2)/2 ) / d2) # yti
      res[5] = (t3_bl1 + t3_bl2 + 2*t3_fro)/4                    # hgt
    } else {
      res[0] = t3_hgt - d1 * tan(t3_xti/1000) / 2 - d2 * tan(t3_yti/1000) / 2 # tbl 1
      res[1] = t3_hgt + d1 * tan(t3_xti/1000) / 2 - d2 * tan(t3_yti/1000) / 2 # tbl 2
      res[2] = t3_hgt + d2 * tan(t3_yti/1000) / 2                             # front
    }
  }
  if (mode == 5) {
    if (reverse) {
      res[3] = 1000*atan( (t3_bl2 - t3_bl1) / d1 ) # xti 
      res[4] = 1000*atan( ( (t3_bl1 + t3_bl2)/2 - t3_fro) / d2) # yti
      res[5] = t3_fro + ( (t3_bl1 + t3_bl2)/2 - t3_fro) * (d3/d2) #z
    } else {
      res[0] = t3_hgt - d1 * tan(t3_xti/1000) / 2 + (d2 - d3)*tan(t3_yti/1000)  #tbl 1
      res[1] = t3_hgt + d1 * tan(t3_xti/1000) / 2 + (d2 - d3)*tan(t3_yti/1000)  #tbl 2
      res[2] = t3_hgt - d3 * tan(t3_yti/1000) #front 
    }
  }
  if (mode == 6) {
    if (reverse) {
      res[3] = deg( atan( (t3_bl2 - t3_bl1) / d1 ) )              # xti
      res[4] = deg( atan( ( (t3_bl1 + t3_bl2)/2 - t3_fro) / d2) ) # yti
      res[5] = (t3_bl1 + t3_bl2) / 2                              # z
    } else {
      res[0] = t3_hgt - d1 * tan( rad(t3_xti) ) / 2  # tbl 1
      res[1] = t3_hgt + d1 * tan( rad(t3_xti) ) / 2  # tbl 2
      res[2] = t3_hgt - d2 * tan( rad(t3_yti) )      # front
    }
  }
  if (mode == 7) {
    if (d3==0) {
      if (reverse) {
        res[3] = 1000*atan((t3_bl2 - t3_bl1)/d1) # xti 
        res[4] = 1000*atan( ( (3*t3_bl1 + t3_bl2)/4 - t3_fro) / d2) # yti
        res[5] = ((3*t3_bl1 + t3_bl2)/4 + t3_fro)/2 # z
      } else {
        res[0] = t3_hgt + d2*tan(t3_yti/1000)/2 - d1*tan(t3_xti/1000)/4
        res[1] = t3_hgt + d2*tan(t3_yti/1000)/2 + 3*d1*tan(t3_xti/1000)/4
        res[2] = t3_hgt - d2*tan(t3_yti/1000)/2
      }
    } else {
      if (reverse) {
        res[3] = 1000*atan((t3_bl1 - t3_bl2)/d1)	# xti
	      res[4] = 1000*atan(((t3_bl1+3*t3_bl2)/4 - t3_fro)/d2)	# yti
	      res[5] = ((t3_bl1 + 3*t3_bl2)/4 + t3_fro)/2 	# z
      } else {
	      res[0] = t3_hgt + d2*tan(t3_yti/1000)/2 + 3*d1*tan(t3_xti/1000)/4
        res[1] = t3_hgt + d2*tan(t3_yti/1000)/2 - d1*tan(t3_xti/1000)/4
	      res[2] = t3_hgt - d2*tan(t3_yti/1000)/2
      }
    }
  }
  if (mode == 8) {
    #print reverse, d1, d2, t3_hgt, t3_xti, t3_yti
    if (reverse) {
      res[3] = 1000*atan( (t3_bl2 - t3_bl1) / d1 ) # xti
      res[4] = -1000*atan((t3_fro - t3_bl1) / d2) # yti
      res[5] = t3_fro + (t3_bl1 - t3_fro)/2 + (t3_bl2 - t3_bl1)/2 # z
    } else {
      res[0] = t3_hgt - d1*tan(t3_xti/1000)/2 + d2*tan(t3_yti/1000)/2 # tbl 1
      res[1] = t3_hgt + d1*tan(t3_xti/1000)/2 + d2*tan(t3_yti/1000)/2 # tbl 2
      res[2] = t3_hgt - d1*tan(t3_xti/1000)/2 - d2*tan(t3_yti/1000)/2 # front 
    }
  }
  return res[calcidx];
}'

#%UU% table-number
#%MDESC%
#
# Sets on the track between table and logical motors
#
def tab3on '{
  local t3_tabmne

  t3_tabmne = "$1"

  if (list_check(TAB3PAR, t3_tabmne)) {
    _tab3on(t3_tabmne)
  } else {
    printf("tab3 \"%s\" does not exist\n", t3_tabmne)
  }
}'

def _tab3on(t3_tabmne) '{
  local t3_bl1 t3_bl2 t3_fro t3_xti t3_yti t3_hgt 
  local t3_geo

  t3_geo = list_getpar(TAB3PAR, t3_tabmne, "geo")
  t3_bl1 = list_getpar(TAB3PAR, t3_tabmne, "bl1")
  t3_bl2 = list_getpar(TAB3PAR, t3_tabmne, "bl2")
  t3_fro = list_getpar(TAB3PAR, t3_tabmne, "fro")
  t3_xti = list_getpar(TAB3PAR, t3_tabmne, "xti")
  t3_yti = list_getpar(TAB3PAR, t3_tabmne, "yti")
  t3_hgt = list_getpar(TAB3PAR, t3_tabmne, "hgt")

  cdef("user_getpangles", sprintf("tab3_bl1get %d %s\n", motor_num(t3_bl1), \
       t3_tabmne), t3_bl1, 0x01)
  cdef("user_checkall",   sprintf("tab3_bl1move %d %s\n",motor_num(t3_bl1), \
       t3_tabmne), t3_bl1, 0x01)

  cdef("user_getpangles", sprintf("tab3_bl2get %d %s\n", motor_num(t3_bl2), \
       t3_tabmne), t3_bl2, 0x01)
  cdef("user_checkall",   sprintf("tab3_bl2move %d %s\n",motor_num(t3_bl2), \
       t3_tabmne), t3_bl2, 0x01)

  cdef("user_getpangles", sprintf("tab3_froget %d %s\n", motor_num(t3_fro), \
       t3_tabmne), t3_fro, 0x01)
  cdef("user_checkall",   sprintf("tab3_fromove %d %s\n",motor_num(t3_fro), \
       t3_tabmne) , t3_fro, 0x01)

  cdef("user_getpangles", sprintf("tab3_xtiget %d %s\n", motor_num(t3_xti), \
       t3_tabmne), t3_xti, 0x01)
  cdef("user_checkall",   sprintf("tab3_xtimove %d %s\n",motor_num(t3_xti), \
       t3_tabmne) , t3_xti, 0x01)

  cdef("user_getpangles", sprintf("tab3_ytiget %d %s\n", motor_num(t3_yti), \
       t3_tabmne), t3_yti, 0x01)
  cdef("user_checkall",   sprintf("tab3_ytimove %d %s\n",motor_num(t3_yti), \
       t3_tabmne) , t3_yti, 0x01)

  cdef("user_getpangles", sprintf("tab3_hgtget %d %s\n", motor_num(t3_hgt), \
       t3_tabmne), t3_hgt, 0x01)
  cdef("user_checkall",   sprintf("tab3_hgtmove %d %s\n",motor_num(t3_hgt), \
       t3_tabmne) , t3_hgt, 0x01)
  list_setpar(TAB3PAR, t3_tabmne, "state", 1)
}'

#%UU% table-number
#%MDESC% 
#
# Sets off the track between table and logical motors
#
def tab3off '{
  local t3_tabmne

  if ($# == 0) {
    t3_tabmne=getval("table mnemonic to set off",list_getpar(TAB3PAR,1,"mne"))
  } else if ($# == 1) {
    t3_tabmne = "$1"
  } else {
    p "Usage : tab3off [table mnemonic]"
    exit
  }

  if (list_check(TAB3PAR, t3_tabmne)) {
    _tab3off(t3_tabmne)
  } else {
    printf("tab3 \"%s\" does not exist\n", t3_tabmne)
  }
}'

def _tab3off(t3_tabmne) '{
  local t3_bl1 t3_bl2 t3_fro t3_xti t3_yti y3_hgt
  local t3_geo

  t3_geo  = list_getpar(TAB3PAR, t3_tabmne, "geo")
  t3_bl1  = list_getpar(TAB3PAR, t3_tabmne, "bl1")
  t3_bl2  = list_getpar(TAB3PAR, t3_tabmne, "bl2")
  t3_fro  = list_getpar(TAB3PAR, t3_tabmne, "fro")
  t3_xti  = list_getpar(TAB3PAR, t3_tabmne, "xti")
  t3_yti  = list_getpar(TAB3PAR, t3_tabmne, "yti")
  t3_hgt  = list_getpar(TAB3PAR, t3_tabmne, "hgt")
  cdef("", "", t3_bl1, "delete")
  cdef("", "", t3_bl2, "delete")
  cdef("", "", t3_fro, "delete")
  cdef("", "", t3_xti, "delete")
  cdef("", "", t3_yti, "delete")
  cdef("", "", t3_hgt, "delete")
  list_setpar(TAB3PAR, t3_tabmne, "state", 0)
}'

#%MACROS%
#%IMACROS%
#%DEPENDENCIES%
#  To use the table with its pseudomotors the following must be done
#%UL%
#%LI% The file tab3.mac has to be read in               done by: startup s.
#    (this file needs: pseudo.mac , stchanges.mac)
#%LI% the piezo motors have to be configured            done by: SPECADM
#       (Controller NONE, mnemonic as in startupscript)
#%LI% setup the table ( with tab3setup )                done by: startup s.
#%XUL%
#%AUTHOR% Vicente Rey. June 1995
#$Revision: 1.6 $, $Date: 2012/03/20 09:03:39 $
#%TOC%