esrf

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

#%TITLE% OSCIL.MAC
#%NAME%
#   Macros for synchronisation beam shutter/Phi spindle
#
#%CATEGORY% Obsolete
#%DESCRIPTION%
# The macros allow the Phi spindle motion of the
# diffractometer  and the  control of the beam shutter to be synchronized . This macros 
#should be not directly used and are called from other macros (see ccd.mac
#  and mar.mac files)
#
#%LOG%
# $Log: oscil.mac,v $
# Revision 1.3  2012/05/04 14:06:53  guilloud
# *changed MI_PAR for a good function to read SR current
#
# Revision 1.2  2008/08/12 15:21:01  rey
# documentation changes
#
# Revision 1.1  2002/04/29 13:23:00  claustre
# Initial revision
#
# initial: 10.95
# author: L. claustre
# Modified:
#	copy to the ICNTL master dir. and split into oscil.mac and bac24.mac
#	15/09/2000	
#	Now we can "oscillate" 2 axis the PX phi and omega spindle !!
#	04/06/98 L.C.
######################################################################
#%END%
#####################################################################

global OSCIL_P1 OSCIL_P2 OSCIL_P3 OSCIL_DEFVELOCITY OSCIL_MOTOR_NUM OSCIL_DEFVELOCITY OSCIL_SER_NUM 
global OSCIL_MOTOR_NAME
global OSCIL_SY_MODE OSCIL_PREDELAY OSCIL_POSTDELAY
global DS_VCT6_NAME  OSCIL_STEP_MARGIN

#####################################################################
#%UU% ["name of the PHI rotation motor"] ["name of the OMEGA rotation motor"] ["shutter-pre-delay"] ["shutter-post-delay"] ["synchro type"]
# %MDESC%
# has to be called first for initialisation of the goniostat axis control
# and synchronisation setting up. 
#####################################################################
def oscilsetup'
{
#~~~~~~~~~~~~~~~~~~~~~~

spec_par("modify_step_size",1)

 if ($#){
	OSCIL_MOTOR_NAME = "$1"
	OSCIL_PREDELAY = $2
	OSCIL_POSTDELAY = $3
	OSCIL_STEP_MARGIN = $4
	OSCIL_SY_MODE= "$5"
	DS_VCT6_NAME= "$6"

 }
 else {
	OSCIL_MOTOR_NAME = sprintf("%s",getval("Name of axis",  OSCIL_MOTOR_NAME))
	OSCIL_PREDELAY = getval ("Pre Delay of the shutter to be used (ms)", OSCIL_PREDELAY)
	OSCIL_POSTDELAY = getval ("Post Delay of the shutter to be used (ms)", OSCIL_POSTDELAY)
 	OSCIL_STEP_MARGIN = getval ("Delay before/after shutter open/close positions (steps))", OSCIL_STEP_MARGIN)
 	OSCIL_SY_MODE = sprintf("%s", getval ("Synchro hardware (bac24 / vct6)", OSCIL_SY_MODE))
	if (OSCIL_SY_MODE == "vct6"){
	  DS_VCT6_NAME= sprintf("%s",getval("Name of the VCT6 device server",DS_VCT6_NAME))
	} else if (OSCIL_SY_MODE == "bac24") {
	}else {
	  print "Wrong synchro hardware type"
	}
 }
 if((OSCIL_MOTOR_NUM = motor_num(OSCIL_MOTOR_NAME)) == -1) {
  printf ("Error:  Motor %s doesn\'t exist\n", OSCIL_MOTOR_NAME)
  fprintf ("pipe","[B]abort_from_spec %s[E]",sprintf("Motor %s doesn\'t exist\n",OSCIL_MOTOR_NAME))
  exit
 }

 if (OSCIL_SY_MODE != "bac24" && OSCIL_SY_MODE != "vct6") {
   printf ("wrong Synchro. type (%s), allowed are vct6 or bac24",OSCIL_SY_MODE)
   exit
 }
#
# Back up the  default velocity of the axis
#
 OSCIL_DEFVELOCITY = motor_par(OSCIL_MOTOR_NUM,"velocity")
}'



#####################################################################
#%IU%
#%MDESC%
# clean up macro called when spec received the INT signal (by typing Ctrl-C)
# allows to stop the current command (e.g. a scan command), restores
# the defaults motor parameters (speed ..)
######################################################################
def oscil_cleanup '
{
 rdef cleanup \'
  
  undef cleanup
  printf("Restore default configuration\n")
  motor_par(OSCIL_MOTOR_NUM,"velocity", OSCIL_DEFVELOCITY)

  if (OSCIL_SY_MODE == "vct6") {
   vct6_clear
  } else {
   bac24_stop
  }
 \'
}'

#####################################################################
#%IU% ["Edge value"] ["gate value"]
#%MDESC%
#Set up parameters of the the VCT6 channel to get a gate generation 
#according to the parameters.
#
#####################################################################
def vct6_set '
{
  # Initialize the vct6 channels to the desired mode ( GateGen)
  vct6_devname[0] = sprintf("%s/1", DS_VCT6_NAME) 
  vct6_devname[2] = sprintf("%s/3", DS_VCT6_NAME)
  vct6_init[0] = 0 # Master
  vct6_init[1] = 0 # No gate
  vct6_init[2] = 1 # External clock
  vct6_init[3] = 0 # Clock Frequency, Not used
  vct6_init[4] = 0 # No free run mode
  vct6_init[5] = 1 # External Start counting signal
  vct6_init[6] = 0 # Internal stop counting
  vct6_init[7] = 0 # Desabled divider mode 
  vct6_init[8] = 0 # Desabled autoclear of counting value 
  vct6_init[9] = 0 # 
  vct6_init[10] = 1 # External precount clock

  esrf_io(vct6_devname[0], "DevCntInit", vct6_init)
  # Test time
  vct6_init[0] = 1 # Slave
  vct6_init[1] = 0 # No gate
  vct6_init[2] = 0 # Internal clock
  vct6_init[3] = 1 # Clock Frequency of 1MHz
  vct6_init[4] = 0 # No free run mode
  vct6_init[5] = 0 # External Start counting signal
  vct6_init[6] = 0 # Internal stop counting
  vct6_init[7] = 0 # Desabled divider mode 
  vct6_init[8] = 0 # Desabled autoclear of counting value 
  vct6_init[9] = 0 # 
  vct6_init[10] = 0 # Internal precount clock

  esrf_io(vct6_devname[2], "DevCntInit", vct6_init)
 

  esrf_io(vct6_devname[0] ,"DevCntStop")
  esrf_io(vct6_devname[0], "DevCntClear")
  esrf_io(vct6_devname[0], "DevCntEdgeSet", $1)
  esrf_io(vct6_devname[0], "DevCntPresetValue", $2)
 
  esrf_io(vct6_devname[0], "DevCntStart")

  esrf_io(vct6_devname[2], "DevCntStart")
}'

#####################################################################
#%IU%
#%MDESC%
# Stop the vct6 Master timer (channel 1)
#
#####################################################################
def vct6_stop '{
   vct6_devname[0] = sprintf("%s/1", DS_VCT6_NAME)
   esrf_io(vct6_devname[0] ,"DevCntStop")
   esrf_io(vct6_devname[0], "DevCntClear")
}'

#####################################################################
#%IU% ["start angle"] ["stop angle"] ["time"]
#%MDESC%
# According to the motor parameters, the angle positions  and the
# Oscillation time, performs the motor motion and the synchronisation
# with the fast beam shutter (by using the maxcount2 box or the VCT6 board).
##
#####################################################################
def phi_oscillation '
{
  oscillation_prepare $*
  oscillation
}'

#####################################################################
#%IU%  ["start angle"] ["stop angle"] ["time"]
#%MDESC%
# According to the motor parameters, the angle positions  and the 
# Oscillation time, performs the motor motion and the synchronisation
# with the fast beam shutter (by using the maxcount2 box or the VCT6 board).
##
#####################################################################
def oscillation_prepare '
{
global SENSI42_
#
# D. Spruce
# controlling variables to switch on diagnostic mode or not
# the vct6 setup is done in the macro diag_rot_image which controls
# this variable
global DO_DIAGNOSTIC
#
# D. Spruce
# keep a record of the diode counts while collecting an image
#
global EXPOSURE_COUNTS START_COUNTS curr_intensity

global step_size enco_step_size velocity  acceleration deceleration slew_rate
global dslope slope shutter_gate init_angle final_angle enco_step_time step_time predelay
global postdelay
global shutter_edge

# Added by D. Spruce
global nflux42
#
# Added by D. Spruce to return if in simulation mode 11/3/98
#
if ( set_sim(-1) ) {
  fprintf("pipe","[B]finished[E]")
  return
}
#
# Install the cleanup macro
#
 oscil_cleanup

 OSCIL_DEFVELOCITY= motor_par(OSCIL_MOTOR_NUM,"velocity") 
 acceleration   = (2 * motor_par(OSCIL_MOTOR_NUM,"acceleration"))
 enco_step_size = fabs(motor_par(OSCIL_MOTOR_NUM,"encoder_step_size"))
 step_size      = motor_par(OSCIL_MOTOR_NUM,"step_size")
 velocity  	= fabs ($2 - $1) / ($3)
 slew_rate  	= velocity * step_size

 if (OSCIL_SY_MODE == "bac24") { # Bac24 
   enco_step_time	= (1/(velocity *enco_step_size)) * 1000 # in ms 
   predelay	= fabs(int(OSCIL_PREDELAY / enco_step_time))
   postdelay	= fabs(int(OSCIL_POSTDELAY / enco_step_time))
 }
 if (OSCIL_SY_MODE == "vct6"){ # VCT6
   step_time	= (1/(velocity * step_size)) * 1000     # in ms
   predelay	= fabs(int(OSCIL_PREDELAY / step_time))
   postdelay	= fabs(int(OSCIL_POSTDELAY / step_time))
 }
  
 if (MARDEBUG) { 
  if (OSCIL_SY_MODE =="bac24")
   printf("enco. step time = %f ms\n", enco_step_time)
  else
   printf("motor step time = %f ms\n", step_time)
  
  printf("sh. predelay	= %d steps\n", predelay)
  printf("sh. postdelay	= %d steps\n", postdelay)
 }

 # VPAP has no deceleration parameter, slope=dslope 
 slope  	= (velocity * (acceleration / 1000)) + (OSCIL_STEP_MARGIN/step_size) # Slope in degree
 dslope  	= slope

 if (OSCIL_SY_MODE == "bac24") { # BAC24
  shutter_gate	= int(fabs($2 - $1) * enco_step_size)-  postdelay
 }
 if (OSCIL_SY_MODE == "vct6") { # VCT6
  shutter_gate	= int(fabs($2 - $1) * step_size)-  postdelay
 }

 if($1 > $2){ 
  init_angle = $1 + slope
  final_angle = $2 - dslope 
 } else {
  init_angle = $1 - slope
  final_angle = $2 + dslope
 }
 if (MARDEBUG) {
  printf("velocity  	= %f deg./s (%d steps/s)\n", velocity, velocity * enco_step_size)
  printf("calc. slope	= %f deg.(s) (%d steps)\n", slope, slope* enco_step_size)
  printf("shutter gate	= %d step(s)\n", shutter_gate)
 }

  A[OSCIL_MOTOR_NUM] = init_angle
  move_em;waitmove;get_angles
  printf("Moving %s to %f \(- %f\)\n",OSCIL_MOTOR_NAME,init_angle+dslope,dslope)
  
  #
  # Get the real encoder position to calculate the P1 and P2 
  # Bac24 (Box), or the VCT6 counter values.
  #
  slope = fabs($1 - A[OSCIL_MOTOR_NUM]) 
  
  if (OSCIL_SY_MODE == "bac24") { # Bac24
   OSCIL_P1 = int(slope * enco_step_size)- predelay
   OSCIL_P2 = OSCIL_P1 + shutter_gate + predelay

   if (MARDEBUG) {
    printf(" real slope	= %f degree (%d steps)\n", slope, slope*enco_step_size)
    printf("BAC24 P1		= %d steps\n", OSCIL_P1)
    printf("BAC24 P2		= %d steps\n", OSCIL_P2)
   }
   bac24_2pos (OSCIL_P1, OSCIL_P2)
 }
 if (OSCIL_SY_MODE == "vct6") { # VCT6
  shutter_edge =  int(slope * step_size)- predelay
  if (MARDEBUG) {
    printf(" real slope	= %f degree (%d steps)\n", slope, slope*step_size)
    printf("SHUTTER EDGE	= %d steps\n", shutter_edge)
    printf("SHUTTER GATE	= %d steps\n", shutter_gate)
  }
  vct6_set shutter_edge shutter_gate
 }
}'

#####################################################################
#%IU%
#%MDESC%
# According to the motor parameters, the angle positions  and the 
# Oscillation time, performs the motor motion and the synchronisation
# with the fast beam shutter (by using the maxcount2 box or the VCT6 board).
# HAS TO BE CALLED AFTER A CALL OF oscillation_prepare
##
#####################################################################
def oscillation '
{

local _sr_current

#
# Now, start the oscillation
#
 waitmove; get_angles
 motor_par(OSCIL_MOTOR_NUM,"velocity", slew_rate)
 A[OSCIL_MOTOR_NUM] = final_angle
 printf("Moving %s to %f \(+ %f\)\n",OSCIL_MOTOR_NAME,final_angle-dslope,dslope)
#
# kludge to tell ProDC that the fast shutter is open
# (until its possible to really read the value, i.e its cabled
# D.Spruce 18/06/97
# added reading of pin42 (D.Spruce) 10/2/98
#
 fprintf("pipe","[B]fast_shutter OPEN[E]")
#
# 17/5/99 count for the length of the exposure and normalise to 1 sec
# store the relevant pin diode counts to gice to prodc
# the pin diode name is really specific to the beamline
#
# Count for longer (proportional to the extra distance moved by phi)
# This is only necessary if the diode is AFTER the fast shutter so we
# make sure that the full exposure is captured while counting
# other wise we only need to count for the normal count time
# i.e 1 second

 # time_to_count = (final_angle - init_angle) / ($2 - $1) * $3
 # p "count for " time_to_count " seconds"
 count_em 1
 #
 # put zap scan commands here to remove timing of all other movements
 # D.Spruce
 if ( DO_DIAGNOSTIC == 1) {
   zapvct6start
 }
 move_em; waitmove
 if ( DO_DIAGNOSTIC == 1) {
   zapvct6stop
 }
 get_angles
 get_counts
 fprintf("pipe","[B]fast_shutter CLOSED[E]")
 # Only normalise for the real time the shutter was open
 global norm_factor
 EXPOSURE_COUNTS = S[peh1]
 p "got " EXPOSURE_COUNTS " counts"
 mach_current = esrf_dc("sys/mach/current","DevRead")
 if ( norm_factor == 0 ) { norm_factor = 5.43 }
 if ( mach_current > 0 ) {
   # curr_intensity = EXPOSURE_COUNTS /mach_current * norm_factor
   curr_intensity = EXPOSURE_COUNTS
   fprintf("pipe","[B]dc_msg %s[E]",sprintf("\tIntensity is %6.1f\n ",curr_intensity))
 }
 #
 # Make sure there can be no errors here
 #
 # calculate the normalised flux for pin42 (ProDC has recently got current)
 #

 _sr_current = mi_SR_Current()

 if ( MI_PAR["CURR"] != 0 ) {
   nflux42 = flux42/(_sr_current/100)
 }
 else {
   nflux42 = 0
 }

 Xval("pd42",sprintf("%7.2g",nflux42))
 Xval("pd42c",sprintf("%d",S[cntti23]))
 waitcount

#
# Restore the defaults motor velocity
#
 undef cleanup
 motor_par(OSCIL_MOTOR_NUM,"velocity", OSCIL_DEFVELOCITY)
 
 if (OSCIL_SY_MODE == "bac24") {  # Bac24
  # Make the BAC24 I box inactive (for the shutter)
  bac24_stop
   
 }
 fprintf("pipe","[B]finished[E]")
}'


#####################################################################
#%IU% ["channel-num"] ["gate-time"]
#%MDESC%
# allows us to generate from the VCT6 card a gate on the %B%channel-num%B%
# channel (1 to 2) of duration %B%gate-time%B% in seconds.
#####################################################################
def sy_test '
{
local vct6_devname vct6_init chan_num sy_time

 if ($#) {
	chan_num = $1
	sy_time  = $2
 }
 else {
	chan_num = getval("GateGen channel number (1-2)", 1)
	sy_time = getval("Time (s)", 1)
 }

#
# Initialize the vct6 channels to the desired mode ( GateGen)
#
 vct6_devname = sprintf("%s/%d", DS_VCT6_NAME, chan_num) 
 vct6_init[0] = 0 # Master
 vct6_init[1] = 0 # No gate
 vct6_init[2] = 0 # Internal clock
 vct6_init[3] = 1 # Clock Frequency, 1 MHz 
 vct6_init[4] = 0 # No free run mode
 vct6_init[5] = 0 # InternaL Start counting signal
 vct6_init[6] = 0 # Internal stop counting


 esrf_io(vct6_devname, "DevCntInit", vct6_init)

 esrf_io(vct6_devname ,"DevCntStop")
 esrf_io(vct6_devname, "DevCntClear")
 esrf_io(vct6_devname, "DevCntPresetTime", sy_time)
 
 esrf_io(vct6_devname, "DevCntStart")
 esrf_io(vct6_devname, "DevCntStart")
}'

### +SW

def XHuberFinished '
{
 on("pipe")
 offt
 printf("[B]Huber_finished[E]")
 off("pipe")
 ont
}'
### -SW


#%MACROS%

#%IMACROS%

#%DEPENDENCIES%
# The files oscil.mac and bac24.mac have to be read in ! done by: startup script
#%AUTHOR% Laurent Claustre, 15/09/2000 
# $Revision: 1.3 $, $Date: 2012/05/04 14:06:53 $
#%TOC%