esrf

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

#%TITLE% ICE_PMUX.MAC
#
#%NAME%
# Macros to configure the position signal multiplexer 
# inside an IcePAP system.
#
#%DESCRIPTION%
# Currently, the position signals can be only routed in 
# two directions:
#
# %BR% - from the DB9 SYNCRO connector on the front panel of 
# the MASTER module to any DRIVER module.
#
# %BR% - from any DRIVER module to the DB9 SYNCRO connector on 
# the front panel of the MASTER module.
#
# The DRIVER modules are identified by their corresponding motor 
# that must have been previously configured in the current 
# SPEC session.
#
# The IcePAP checks that the requested signals routing is
# feasible and compatible with already configured routing rules.
#
# All the configured routing rules can be removed at once
# using the macro %B%"pmux_reset"%B%
#
# Currently the two IcePAP internal lines, position and
# auxiliray, are routed. The macros can not select one or the other.
#
# Currently, the axis position source is always the "MEASURE" one.
#
#%END%
#


# Mandatory standard IcePAP macros
need ice


#%UU% hostname | motor
#%MDESC%
# Remove all multiplexing in the given IcePAP system or
# in the system where the given motor is hosted
#
def pmux_reset '{
   local num
   local mne


   if($# == 0) {
      p "Usage: $0 [hostname | motor]"
      exit
   }

   # TODO MP : add multiple argins
   mne = "$1"
   if((num = motor_num(mne)) != -1) {
      if(_pmux_check(mne)) { 
         exit
      }
      _pmux_reset_motor(num)
   } else {
      _pmux_reset_system(mne)
   }

}'


#%IU%(hostname)
#%MDESC%
# Remove all multiplexing in the given IcePAP system
#
def _pmux_reset_system(dev) '{
   local ans
   local slt

   slt = 1
   ans = _icepap_query(dev, "#", "PMUX REMOVE", slt)
   if(index(ans,"ERROR") && !index(ans,"No PMUX rule found"))
   {
      _icepap_err
      printf("unable to remove pos mux on IcePAP: \"%s\"\n", dev)
      return(-1)
   }

}'


#%IU%(motor_mne)
#%MDESC%
# Remove all multiplexing in the system where 
# the given motor is hosted
#
def _pmux_reset_motor(mne) '{
   local dev

   dev =  motor_par(mne, "address")
   _pmux_reset_system(dev)

}'


#%UU% motor
#%MDESC%
# Send the given motor position to IcePAP controller 
# "SYNCRO" output (DB9 on controller front panel)
#
def pmux_mot2sync '{
   local num
   local mne


   if($# == 0) {
      p "Usage: $0 motor"
      exit
   }

   mne = "$1"
   if(_pmux_check(mne)) { 
      exit
   }

   _pmux_mot2sync(mne)
}'


#%IU%(motor_mne)
#%MDESC%
# Send the given motor position to IcePAP controller 
# "SYNCRO" output (DB9 on controller front panel)
#
def _pmux_mot2sync(mne) '{
   local dev
   local adr
   local ans
   local slt

   dev  = motor_par(mne, "address")
   adr  = motor_par(mne, "module")*10
   adr += motor_par(mne, "channel")

   slt  = 1
   ans  = _icepap_query(dev, "#", sprintf("PMUX HARD B%d", adr), slt)
   if(index(ans,"ERROR") && !index(ans,"Useless PMUX rule"))
   {
      _icepap_err
      printf("unable to send to syncro output the pos of motor: \"%s\"\n", mne)
      printf("Hint: use \"pmux_reset\" first\n")
      printf("Internal error: \"%s\"\n", ans)
      return(-1)
   }

   # ask to the DRIVER to send the position its internal multiplexed output
   # TODO: add the inverted posibility if the sense of the motor is
   # not the wanted one
   ans  = _icepap_query(dev, "#" adr, sprintf("SYNCPOS MEASURE", adr), slt)
   if(index(ans,"ERROR"))
   {
      _icepap_err
      printf("unable configure output position for motor: \"%s\"\n", mne)
      printf("Internal error: \"%s\"\n", ans)
      return(-1)
   }

   # TODO: check that the routing rule has been well taken into account
   return(0)
}'


#%UU% motor [ motor ... ]
#%MDESC%
# Send the IcePAP controller "SYNCRO" input (DB9 on controller 
# front panel) to the given motors
#
def pmux_sync2mot '{
   local tt[] axes[] n 
   local i

   if($# == 0) {
      p "Usage: $0 motor [ motor ... ]"
      exit
   }

   # Minimum checks on arguments
   n = split("$*", tt)
   for(i=0;i<n;i++) {
      mne = tt[i]
      if(_pmux_check(mne)) { exit }
      axes[i] = mne
   }

   for(i=0;i<n;i++) {
      if(_pmux_sync2mot(axes[i])) { exit }
   }
}'


#%IU%(motor_mne)
#%MDESC%
# Send the IcePAP controller "SYNCRO" input (DB9 on controller 
# front panel) to the given motors
#
def _pmux_sync2mot(mne) '{
   local dev
   local adr
   local ans
   local slt

   dev  = motor_par(mne, "address")
   adr  = motor_par(mne, "module")*10
   adr += motor_par(mne, "channel")

   slt  = 1
   ans  = _icepap_query(dev, "#", sprintf("PMUX HARD E0 B%d", adr), slt)
   if(index(ans,"ERROR") && !index(ans,"Useless PMUX rule"))
   {
      _icepap_err
      printf("unable to send the syncro input to pos of motor: \"%s\"\n", mne)
      printf("Hint: use \"pmux_reset\" first\n")
      printf("Internal error: \"%s\"\n", ans)
      return(-1)
   }

   # TODO: check that the routing rule has been well taken into account
   return(0)
}'


#%IU%_pmux_check(motor_mne)
#%MDESC%
# Returns non null if the given axis mnemonic is not a valid 
# IcePAP motor
# 
def _pmux_check(mne, silent) '{
   local num

   if((num = motor_num(mne)) == -1) {
      _icepap_err
      print "invalid motor \""mne"\", not configured" 
      return(-1)
   }

   if(motor_par(num, "device_id") != "icepap") {
     if(!silent) {
        _icepap_err
        print "invalid motor \""mne"\", not an IcePAP motor"
     }
     return(-1)
   }

   return(0)
}'


#%MACROS%
#%IMACROS%
#%AUTHOR% MP BLISS (Original 11/2014).
# %BR%$Revision: 1.0 $ / $Date: 2014/11/25 10:23:14 $
#%TOC%