esrf

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

#%TITLE% MSTATE.MAC 
#%NAME%
#  Reads motor parameters (MAXE and SPEC) and checks vpap CY550 chip parameters.
#
#%CATEGORY% Positioning
#
#%DESCRIPTION%
#  These macros read the actual parameters of motors configured in SPEC, 
#  or installed on a MAXE device. They eventually check whether these 
#  parameters fit the CY550 vpap board chip stepping algorithm. %BR%
#  You can choose what to read, compute and list out of SPEC, 
#  MAXE and CY550 parameters. 
#%PRE%
#Parameters read and listed from SPEC for a given motor are :
#	motor	as motor mnemonic in SPEC
#	ctrllr  as motor controller name
#	fstepr  as first step rate  
#	velo    as velocity
#	acc ms  as acceleration time in ms
#	accel   as acceleration value eventually sent to MAXE server
#	backl   as backlash
#	hslewr  as home slew rate
#	step    as stepping mode (Full or Half step)
#
#Parameters read and listed from MAXE for a given device and axis number or 
#for  a given SPEC motor are:
#	devices names list 
#	axis	as axis number
#	units	as current unit 
#	mstate	as motor state
#	mpos	as motor position
#	estate  as encoder state
#	epos	as encoder position
#	backl   as backlash
#	hslewr  as home slew rate
#	stepr   as first step rate
#	velo  	as velocity
#	accel   as acceleration value
#	limits  as limits switches
#
#CY550 parameters are the following, computed from MAXE parameters for a given 
#device and axis number or for a given SPEC motor, or from given SPEC motors 
#parameters, or from the base rate, velocity and acceleration parameters input
#by the user:
#	Fstepr  as first rate parameter
#   	  min      
#   	  max      
#	slewR   as slew rate parameter
#	  min      
# 	  max     
#	accel   as acceleration value 
# 	  min  
# 	  max  
#	Slop    as slope parameter 
#	Rdyn    as step rate dynamic
# 	  min   
# 	  max   
#	acctms  as corresponding SPEC acceleration time in ms
# 	  min   
# 	  max   
#The values out of range in CY550 part are highlighted.
#%PRE%
#%UL%%B%vpaptst%B% os9 program connection:
#%LI% Slop is the value to be given to command S 
#%LI% Fstepr is the value to scan through the CY550 step rate table to find out the index to give to the command F 
#%LI% slewR is the value to scan through the CY550 step rate table to find out the index to give to the command R 
#%XUL%
#%ATTENTION%
#The CY550 calculations stand as a general guide for the choice of the stepping parameters for Vpap boards equipped with the CY550 chip at 12 MHz clock frequency. Be aware that due to the complex nature of the CY550 stepping algorithm, it is difficult to provide an exact formula concerning its acceleration behaviour. The formula used in these macros is an aproximate formula. This should be used as a general guide only, with actual timing and acceleration values best determined experimentally. 
#%END%

#%UU% [<+|->MAXE] [<+|->CY] [<+|->SPEC] [maxe_device|motor_mne_list] [axis_number] [axis_number] ...
#%MDESC% 
#%UL% USAGE:
#%LI% %B%options%B%: By default, only the MAXE parameters are listed, unless the input does not make any sense for the MAXE (stepping parameters, or not MAXE motor). You have to play with the %B%+CY +SPEC +MAXE -CY -SPEC -MAXE%B% options to change the listing. The latest options set is memorized untill next change. You can change one or several options at a time. The macro adapts options also itself if it happens that your input does not make any sense to the current options set.%BR%
#%LI% %B%arguments%B%
#%UL%
#%LI% %B%none%B%: macro asks for a %B%MAXE device %B%name or %B%motor mnemonics%B%. If you want to test cy550 chip paramters, answer "0", then it asks for %B%base-rate%B%, %B%velocity%B% (steps/sec), and %B%acceleration time%B% (ms). If you are not happy with the acceleration time, give it "0", then it asks for the %B%acceleration%B% (steps/sec/sec).%BR%
#%LI% %B%maxe device%B%: all the axes installed on that device, or the ones specified on command line are listed.%BR% 
#%LI% %B%list of motor mnemonics%B%: mnemonics are separated by spaces, or "-". "-" indicates the group of motors configured between both specified ones.%BR% 
#%XUL% 
#%XUL%
def mstate '
{
global MS_ACC MS_VEL MS_BAS MS_TIM
global MS_DEV MS_1ST MS_LST MS_CY MS_M 
global ESRF_ERR
global MS_MODE
local str i n arr

for (i=0;i<16;i++) MS_CY[i]="";
for (i=0;i<14;i++) MS_M[i]="";

str="$*"
n=split(str,arr)
for (i=0,str="";i<n;i++) {
  if (arr[i]=="ALL") MS_MODE=0x07
  else if (arr[i]=="+MAXE") MS_MODE|=0x02
  else if (arr[i]=="-MAXE") MS_MODE&=~0x02
  else if (arr[i]=="+SPEC") MS_MODE|=0x01
  else if (arr[i]=="-SPEC") MS_MODE&=~0x01
  else if (arr[i]=="+CY") MS_MODE|=0x04
  else if (arr[i]=="-CY") MS_MODE&=~0x04
  else str=sprintf("%s %s",str,arr[i])
}      

if (!str) {
  if (MS_DEV=getval("Device server name or motor mnemonics:", MS_DEV)) { 
    if (!MS_MODE) MS_MODE=0x02
    ms_parse \'"MS_DEV"\'
  } else {
    MS_BAS = getval("base_rate in Hz",MS_BAS)
    MS_VEL = getval("velocity in Hz",MS_VEL)
    MS_TIM = getval("acceleration time in msec ",MS_TIM)
    if (!MS_TIM) MS_ACC = getval("acceleration in steps/sec/sec ",MS_ACC)
    else MS_ACC=0
    MS_MODE|=0x04
    ms_cy550 MS_BAS MS_VEL MS_ACC MS_TIM/1000
    ms_pr_cy550
  }    
} else {
  if (!MS_MODE) MS_MODE=0x02
  while(substr(str,1,1)==" ") str=substr(str,2)
  ms_parse \'"str"\'
} 
}'

#%IU% <mstate_input_argument_line>
#%MDESC% Parses the %B%mstate %B%input arguments to figure out if they are SPEC motor mnemonics or MAXE device names.
def ms_parse '
{
local _out 
print "Parsing the input arguments:"

MS_DEV="$1"
esrf_io(MS_DEV, "DevReadState", 0, _out)
MS_DEV="$*"
if (ESRF_ERR) {
  printf("%s not a known device server\n",MS_DEV)
  ms_spec \'"MS_DEV"\' 
} else {
  ms_pr_endmsg
  ms_maxe \'"MS_DEV"\' 
  if (MS_1ST<=MS_LST) { 
    ms_pr_maxe
    ms_pr_cy550 
  }
}
}'

def ms_pr_endmsg '
  clscreen()
'

#%IU% <motor_mnemonic_list>
#%MDESC% For each motor of the list, extracts parameters from SPEC;  if a motor is controlled by MAXE, parameters are read from MAXE server as well and cy550 stepping parameters computed; %BR%
#Lists parameters out according to the options set.
def ms_spec '
{
local  i j k l m _n1 _n2 
local _mne _list
local _ctr _chn _vel _tim _fil _lin _dev
local _actr _amot _abas _avel _atim _aacc _fid _abkl _ahsr _aspm
global MS_M

  _n1=split("$*",_list)
  for (i=0;i<_n1;i++) {
    _n2=split(_list[i],_mne,"-")
    j=motor_num(_mne[0])
    if (j<0) {
      printf("%s not a motor mnemonic\n",_mne[0]) 
      continue
    } else {
      k=motor_num(_mne[_n2-1])
      if (k<0) {
        printf("%s not a motor mnemonic\n",_mne[_n2-1]) 
        continue
      } else {
        if (k<j) {l=k;k=j;j=l}
        for (;j<=k;j++) {
          _ctr=motor_par(j,"controller")
          _actr=sprintf("%s%9s",_actr,_ctr)
          _amot=sprintf("%s%9s",_amot,motor_mne(j))
          _abas=sprintf("%s%9.f",_abas,motor_par(j,"base_rate"))
          _vel=motor_par(j,"velocity")
          _avel=sprintf("%s%9.f",_avel,_vel)
          _tim=motor_par(j,"acceleration")/1000
          _atim=sprintf("%s%9.f",_atim,_tim*1000)
          if (_tim) _aacc=sprintf("%s%9.f",_aacc,_vel/_tim)          
          else _aacc=sprintf("%s%9.f",_aacc,0) 
	  _abkl=sprintf("%s%9.f",_abkl,motor_par(j,"backlash"))
          _ahsr=sprintf("%s%9.f",_ahsr,motor_par(j,"home_slew_rate"))
          _aspm=sprintf("%s%9s",_aspm,motor_par(j,"step_mode")?"HALFSTEP":"FULLSTEP")
          if (index(_ctr,"MAXE")) {
#            _unt = motor_par(j,"unit")
            _chn = motor_par(j,"channel")
	    _dev = motor_par(j,"device_id")     # NEW
            ms_maxe \'"_dev"\' \'"_chn"\'
          } else {
            for (m=1;m<14;m++) {MS_M[m]=sprintf("%s%9s",MS_M[m],"-")}
            for (m=0;m<16;m++) {MS_CY[m]=sprintf("%s%9s",MS_CY[m],"-")}
          }
        }
      }
    }
  }

if (_actr) {
  if (!_dev||MS_MODE&0x01) {
    _actr=sprintf("\n%-6s %s","ctrllr",_actr)
    _amot=sprintf("\n%-6s %s","motor",_amot)
    _abas=sprintf("\n%-6s %s","fstepr",_abas)
    _avel=sprintf("\n%-6s %s","velo",_avel)
    _atim=sprintf("\n%-6s %s","acc ms",_atim)
    _aacc=sprintf("\n%-6s %s","accel",_aacc)
    _abkl=sprintf("\n%-6s %s","backl",_abkl)
    _ahsr=sprintf("\n%-6s %s","hslewr",_ahsr)
    _aspm=sprintf("\n%-6s %s","step",_aspm)
    ms_pr_endmsg 
    print "\nSPEC PARAMETERS:"
    print _amot,_actr,_abas,_avel,_atim,_aacc,_abkl,_ahsr,_aspm
  }
  if (_dev) {
    if (!(MS_MODE&1)) { ms_pr_endmsg }
    ms_pr_maxe 
    ms_pr_cy550
  }
}
}'


#%IU% <device_name [axis] ...>
#%MDESC% Reads parameters from MAXE server and computes the cy550 stepping parameters.
def ms_maxe '
{
local _n _arg i_mot _arg_out 
global _arr_motst _arr_encst _arr_motpos _arr_encpos \
     _arr_units _arr_velo _arr_acc _arr_fstepr _arr_hslewr   \
     _arr_backl _arr_brak _arr_sw 

_n=split("$*",_arg)
MS_DEV=_arg[0]
if (_n>1) {
  MS_1ST=MS_LST=_arg[1]
} else {
  MS_1ST=0;MS_LST=7
} 
 

for (i_mot = MS_1ST; i_mot <= MS_LST;i_mot++) {
    esrf_io(MS_DEV, "DevReadState", i_mot, _arg_out)
    if (ESRF_ERR==54) {
      if (MS_1ST!=MS_LST) printf("                         %d motors installed!\n", i_mot)
      else printf("                         Motor %d not installed!\n", i_mot)
      MS_LST = i_mot-1
      break
    }
    _arr_motst[i_mot] = _arg_out[0]
    _arr_encst[i_mot] = _arg_out[1]

    _arr_units[i_mot]   = esrf_io(MS_DEV,"DevReadUnits",i_mot)
    _arr_motpos[i_mot] = esrf_io(MS_DEV,"DevReadPosition",i_mot)
    _arr_encpos[i_mot] = esrf_io(MS_DEV,"DevReadEncPos",i_mot)
    _arr_sw[i_mot]  = esrf_io(MS_DEV,"DevReadSwitches",i_mot)
    _arr_velo[i_mot]    = esrf_io(MS_DEV,"DevReadVelocity",i_mot)
    _arr_acc[i_mot]     = esrf_io(MS_DEV,"DevReadAcceleration",i_mot)
    _arr_fstepr[i_mot]  = esrf_io(MS_DEV,"DevReadFStepRate",i_mot)
    _arr_hslewr[i_mot]  = esrf_io(MS_DEV,"DevReadHomeSlewRate",i_mot)
    _arr_backl[i_mot]   = esrf_io(MS_DEV,"DevReadBacklash",i_mot)

    ms_assign_M 
    ms_cy550 _arr_fstepr[i_mot] _arr_velo[i_mot] _arr_acc[i_mot] 
}
}'

#%IU% 
#%MDESC% Prepares MAXE parameters display output.
def ms_assign_M '
{
local _mstat_units _mstat_switches _mstat_dev

   _mstat_units[1]    = "STEPS"		
   _mstat_units[2]    = "MM"
   _mstat_units[3]    = "MICRON"
   _mstat_units[4]    = "ROTATION"
   _mstat_units[5]    = "DEGREE"
   _mstat_units[6]    = "ARCSEC"
   _mstat_units[20]   = "USER"
   
   _mstat_switches[0] = "NOLIM"
   _mstat_switches[1] = "NEGLIM"
   _mstat_switches[2] = "POSLIM"
   _mstat_switches[3] = "NEGPOS"
   
   _mstat_dev[2]      = "OK"
   _mstat_dev[3]      = "CLOSED"
   _mstat_dev[9]      = "MOVING"
   _mstat_dev[23]     = "ERROR"
   _mstat_dev[111]    = "NOBRAKE"
  
   MS_M[0]=sprintf("%s  axis %d: %s\n",MS_M[0],i_mot,MS_DEV)
   MS_M[1]=sprintf("%s%9s",MS_M[1],i_mot)
   MS_M[2]=sprintf("%s%9s",MS_M[2],_mstat_units[_arr_units[i_mot]])
   MS_M[3]=sprintf("%s%9s",MS_M[3],_mstat_dev[_arr_motst[i_mot]])
   MS_M[4]=sprintf("%s%9.f",MS_M[4],_arr_motpos[i_mot])
   MS_M[5]=sprintf("%s%9s",MS_M[5], _mstat_dev[_arr_encst[i_mot]])
   MS_M[6]=sprintf("%s%9.f",MS_M[6], _arr_encpos[i_mot])
   MS_M[7]=sprintf("%s%9.f",MS_M[7], _arr_backl[i_mot])
   MS_M[8]=sprintf("%s%9.f",MS_M[8], _arr_hslewr[i_mot])       
   MS_M[9]=sprintf("%s%9.f",MS_M[9], _arr_fstepr[i_mot])
   MS_M[10]=sprintf("%s%9.f",MS_M[10], _arr_velo[i_mot])
   MS_M[11]=sprintf("%s%9.f",MS_M[11], _arr_acc[i_mot])
   MS_M[12]=sprintf("%s%9s",MS_M[12], _mstat_switches[_arr_sw_[i_mot]])
#  MS_M[13]=sprintf("%s%9s",MS_M[13], _mstat_dev[_arr_brak[i_mot]])
}'

#%IU% 
#%MDESC% Prints out MAXE parameters if MAXE option is set.
def ms_pr_maxe '
{
local n i _dv _ax _oo _fmt
if (MS_MODE&0x02) {
    MS_M[0]=sprintf("devices:\n%s",MS_M[0]) 
    MS_M[1]=sprintf("%-6s %s\n", "axis",MS_M[1]) 
    MS_M[2]=sprintf("%-6s %s\n", "units",MS_M[2])
    MS_M[3]=sprintf("%-6s %s\n", "mstate",MS_M[3])
    MS_M[4]=sprintf("%-6s %s\n", "mpos",MS_M[4])
    MS_M[5]=sprintf("%-6s %s\n", "estate",MS_M[5])
    MS_M[6]=sprintf("%-6s %s\n", "epos",MS_M[6])
    MS_M[7]=sprintf("%-6s %s\n", "backl",MS_M[7])
    MS_M[8]=sprintf("%-6s %s\n", "hslewr",MS_M[8])
    MS_M[9]=sprintf("%-6s %s\n", "fstepr",MS_M[9])
    MS_M[10]=sprintf("%-6s %s\n", "velo",MS_M[10])
    MS_M[11]=sprintf("%-6s %s\n", "accel",MS_M[11])
    MS_M[12]=sprintf("%-6s %s\n", "limits",MS_M[12])
#   MS_M[13]=sprintf("%-6s %s\n", "brakes",MS_M[13])
    print "\nMAXE PARAMETERS:"
    for (m=0;m<13;m++) printf("%s", MS_M[m])
print
}
}'

#%IU% <base_rate> <velocity> <0|acceleration> <acceleration_time|0>
#%MDESC% Calculates the CY550 parameters and their limits out of the input arguments arguments, and prepares the display output.
def ms_cy550 '
{
global MS_CY
local _t _bas _vel _acc _min _max _tms _dyn _slp

_bas=$1;_vel=$2;_acc=$3;_tms=$4
_dyn=_vel-_bas

if (_acc) _tms=_dyn/_acc
else if (_tms) _acc=_dyn/_tms

if (_acc) {
  _slp=256-(135000/_acc)
  _t=_tms
}

#bas #vel

MS_CY[0]=sprintf("%s%s%9.f%s",MS_CY[0],((_bas<15)||(_bas>4950))?CP_ONB:CP_OFS,_bas,CP_OFS)
MS_CY[1]=sprintf("%s%s%9.f%s",MS_CY[1],(_bas<15)?CP_ONB:CP_OFS,15,CP_OFS)
MS_CY[2]=sprintf("%s%s%9.f%s",MS_CY[2],(_bas>4950)?CP_ONB:CP_OFS,4950,CP_OFS)
_min=530*_tms;_max=135000*_tms
_min=(_min<15)?15:(_min>14950)?14950:_min;_max=(_max>14925)?14925:(_max<15)?15:_max
MS_CY[3]=sprintf("%s%s%9.f%s",MS_CY[3],((_vel<_min)||(_vel>_max))?CP_ONB:CP_OFS,_vel,CP_OFS)
MS_CY[4]=sprintf("%s%s%9.f%s",MS_CY[4],(_vel<_min)?CP_ONB:CP_OFS,_min,CP_OFS)
MS_CY[5]=sprintf("%s%s%9.f%s",MS_CY[5],(_vel>_max)?CP_ONB:CP_OFS,_max,CP_OFS)

#acc
MS_CY[6]=sprintf("%s%s%9.f%s",MS_CY[6],((_acc<530)||(_acc>135000))?CP_ONB:CP_OFS,_acc,CP_OFS)
MS_CY[7]=sprintf("%s%s%9.f%s",MS_CY[7],(_acc<530)?CP_ONB:CP_OFS,530,CP_OFS)
MS_CY[8]=sprintf("%s%s%9.f%s",MS_CY[8],(_acc>135000)?CP_ONB:CP_OFS,135000,CP_OFS)

#slop
MS_CY[9]=sprintf("%s%s%9s%s",MS_CY[9],((_slp<1)||(_slp>255))?CP_ONB:CP_OFS,((_slp<1)||(_slp>255))?"???":int(_slp),CP_OFS)

#dyn range
if (_t>0) {_min=530*_t;_max=135000*_t}
else _min=_max=0
MS_CY[10]=sprintf("%s%s%9.f%s",MS_CY[10],((_dyn<_min)||(_dyn>_max))?CP_ONB:CP_OFS,_dyn,CP_OFS)
MS_CY[11]=sprintf("%s%s%9.f%s",MS_CY[11],(_dyn<_min)?CP_ONB:CP_OFS,_min,CP_OFS)
MS_CY[12]=sprintf("%s%s%9.f%s",MS_CY[12],(_dyn>_max)?CP_ONB:CP_OFS,_max,CP_OFS)

#timespec range
_min=_vel/135;_max=_vel/530*1000
MS_CY[13]=sprintf("%s%s%9.f%s",MS_CY[13],((_tms<_min/1000)||(_tms>_max/1000))?CP_ONB:CP_OFS,_tms*1000,CP_OFS)
MS_CY[14]=sprintf("%s%s%9.f%s",MS_CY[14],(_tms<_min/1000)?CP_ONB:CP_OFS,_min,CP_OFS)
MS_CY[15]=sprintf("%s%s%9.f%s",MS_CY[15],(_tms>_max/1000)?CP_ONB:CP_OFS,_max,CP_OFS)

}'

#%IU%
#%MDESC% Prints out the CY550 parameters if the CY option is set.
def ms_pr_cy550 '
{
if (MS_MODE&0x04) {
  MS_CY[0]=sprintf("%-6s %s\n","Fstepr",MS_CY[0])
  MS_CY[1]=sprintf("%6s %s\n","min",MS_CY[1])
  MS_CY[2]=sprintf("%6s %s\n","max",MS_CY[2])
  MS_CY[3]=sprintf("%-6s %s\n","slewR",MS_CY[3])
  MS_CY[4]=sprintf("%6s %s\n","min",MS_CY[4])
  MS_CY[5]=sprintf("%6s %s\n","max",MS_CY[5])
  MS_CY[6]=sprintf("%-6s %s\n","accel",MS_CY[6])
  MS_CY[7]=sprintf("%6s %s\n","min",MS_CY[7])
  MS_CY[8]=sprintf("%6s %s\n","max",MS_CY[8])
  MS_CY[9]=sprintf("%-6s %s\n","Slop",MS_CY[9])
  MS_CY[10]=sprintf("%-6s %s\n","Rdyn",MS_CY[10])
  MS_CY[11]=sprintf("%6s %s\n","min",MS_CY[11])
  MS_CY[12]=sprintf("%6s %s\n","max",MS_CY[12])
  MS_CY[13]=sprintf("%-6s %s\n","acctms",MS_CY[13])
  MS_CY[14]=sprintf("%6s %s\n","min",MS_CY[14])
  MS_CY[15]=sprintf("%6s %s\n","max",MS_CY[15])
 
  print "\nCY550 PARAMETERS:"

  for (i=0;i<16;i++) printf("%s",MS_CY[i])
}
}'



#%IU% 
#%MDESC% Sets some characters processing up. (Bold,Underlined,...)
def utilsetup '{

global UTIL_CTRLEN UTIL_CLR UTIL_OFS UTIL_ONB UTIL_ONR UTIL_ONU

if (TERM == "vt100"|| TERM=="xterm" || TERM=="xterms") {
  UTIL_CLR=""
  UTIL_OFS=sprintf("%c[m",27); UTIL_ONB=sprintf("%c[1m",27) ;
  UTIL_ONU=sprintf("%c[4m",27); UTIL_ONR=sprintf("%c[7m",27) ;
} else if (TERM =="hpterm" || TERM == "hp") { 
  UTIL_CLR="&a0y0CJ"
  UTIL_OFS=sprintf("%c&d@",27); UTIL_ONB=sprintf("%c&d@",27) ;
  UTIL_ONU=sprintf("%c&dD",27); UTIL_ONR=sprintf("%c&dF",27) ;
}

UTIL_CTRLEN = 4

}'

utilsetup

#%MACROS%
#%IMACROS%
#%AUTHOR%
#  Elke RAABE 01/95, Marie-Claire LAGIER 1994
#%TOC%















#            _fil=sprintf("%s/%s/config",SPECD,SPEC)
#            getline(_fil,"open")
#            l=0
#            while ((_lin=getline(_fil))!=-1) {
#              split(_lin,_fid)
#              if (index(_fid[0],"VM_MAXE")) {
#                if (l++==_unt) {
#                  _dev=_fid[2]
#                  break
#                }
#              }
#            }
#            getline(_fil,"close")