esrf

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

#%TITLE% dac_and_relay_magnet_ps.mac
#%NAME%
# Macros to change a dac output together with a relay which changes the polarity on a
# special box borrowed from ID24.
#%DESCRIPTION%
# Change a dac output together with a relay which changes the polarity on a special box
# borrowed from ID24.
# %BR% %BR%
# In the config, place yourself on the motor.%BR%
# The DAC needs defining in the config, (hit "p",
# enter the word %B%"dac"%B% to the left and the taco name to the
# right.%BR%
# Type `a`! Then enter the %B%relay%B% name entering relay to the left and the relay
# taco name to the right.%BR%
# Type `a`! For the config value %B%factor%B% enter the word "factor" to the
# left and the value to the lefts.
#%SETUP%
# In the config editor in the "Motor and Counter Device Configuration" page (hit "D") create a motor
# controller like follows: 
# %BR%
#MOTORS\0\0\0\0\0\0\0\0\0\0DEVICE\0\0\0\0\0\0\0\0\0\0ADDR\0\0<>MODE\0\0NUM\0\0\0\0\0\0\0\0\0\0\0\0\0<>TYPE%BR%
#\0\0\0YES\0\0\0\0\0\0\0\0\0\0\0DACREL\0\0\0\0\0\0\0\0\0\0\0\0-\0\0\0\0\0\0\0\0\0\0\0\01\0\0\0\0\0\0\0Macro Motors
# %BR%
#Then create the macro motor:
#%PRE%
#Number:\0<>Controller\0\0\0\0\0\0\0\0\0\0\00:\0MAC_MOT
#%BR%
#Unit/[Module/]Channel\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00/0 (first num is index num of controller)
#%BR%
#Name\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0current
#%BR%
#Mnemonic\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0iout
#%BR%
#Steps per degree/mm\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\04096
#%BR%
#Sign of user * dial\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\01
#%BR%
#Backlash [steps]\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00
#%BR%
#Steady-state rate [Hz]\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\01
#%BR%
#Base rate [Hz]\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\01
#%BR%
#Acceleration time [msec]\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\01
#%BR%
#Motor accumulator\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00
#%BR%
#Restrictions <>\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0NONE
#%BR%
#
#%BR%
#Dial = accumulator / steps
#%BR%
#\0\0High limit\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\05.0000
#%BR%
#\0\0Current\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00.0000
#%BR%
#\0\0Low limit\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00.0000
#%BR%
#User = sign * dial + offset
#%BR%
#\0\0Offset\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00.0000
#%BR%
#\0\0`High' limit\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\050.0000
#%BR%
#\0\0Current\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00.0000
#%BR%
#\0\0`Low' limit\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0-50.0000
#%PRE%
#%BR%
# It is advisable to set the backlash for the macro motor to 0. 
#%ATTENTION%
# After a fresh start the macros needed for the macro motor are most likely not
# available, which necessitates a reconfig first thing.
#%BR%
#%B%The\0macros\0are\0not\0conceived\0for\0more\0than\0one\0motor.%B%
#%END%
# Modifications history:
# 16/11/2009 Creation 

#%IU%
#%MDESC%
# Called by spec
def DACREL_config(mnum,type,unit,mod,chan) '{
  local dac, arnam
  if ( mnum != ".." && type == "mot" ) {
    TACO_ERR = 0; TACO_ERR_MSG = ""
    arnam = "__DACREL_"
    global @arnam
    @arnam["opiomser"]   = motor_par(mnum, "opiomserial")
    @arnam["dac"]        = motor_par(mnum, "dac")
    x                    = motor_par(mnum, "factor")
    @arnam["factor"]     = x ? x : 1
    __dacreldebug "opiom", @arnam["opiom"]
    __dacreldebug "dac",   @arnam["dac"]
    local answer
    if (!__DACREL_SIMU) {
      ser_put(@arnam["opiomser"], "?O\r")
      __dacreldebug "sss DACREL opiom: ", @arnam["opiomser"], "?O"
      answer = ser_get(@arnam["opiomser"], "\r\n")
      if (answer == ""){
        eprint "Problem with opiom state:", @arnam["opiomser"]
        eprint "Can`t seem to talk to opiom!"
        return ".error."
      }
      @arnam["opstat"] = answer & 0x80 ? 1 : 0
    }
    # There should be a first change on the opiom, as the "ID24 field direction
    # change box" is in an undefined state, when switched on! 
    if (!__DACREL_SIMU) {
      ser_put(@arnam["opiomser"], "im 0 0x80\r")
      __dacreldebug "sss DACREL opiom: ", @arnam["opiomser"], "im 0 0x80"
    }
    
    # check on the dac
    if (!__DACREL_SIMU) {
      taco_io(@arnam["dac"], "DevState")
    }
    if (TACO_ERR){
      eprint "Problem with DAC (DevState):", @arnam["opiomser"], TACO_ERR_MSG
      return ".error."
    }
    __dacreldebug "ARRAY", arnam, @arnam
  }
  return(0)
}
'

#%IU%
#%MDESC%
# Called by spec
def DACREL_cmd(mnum, cmd, sp1, sp2, p3) '{
  local arnam, sign, factor, value, p1, p2
  if (mnum == "..") {
    return
  }
  arnam = "__DACREL_"
  factor = @arnam["factor"]
  # for some reason, I get sth in TACO_ERR, even with this line in place.
  # TACO_ERR = 0; TACO_ERR_MSG = ""
  # set TACO_ERR before each taco_io
  p1 = sp1 * factor
  p2 = sp2 * factor
  __dacreldebug mnum, cmd, p1, p2, unit
  if ((cmd == "start_one") || (cmd == "set_position")) {
    local i, sleept, x, y, steps
    # make a move
    # sp1 is new position
    # sp2 is the magnitude 
    # sp1 - p2 is the old position
    # check for sign change
    steps = motor_par(mnum, "step_size")
    if ((!((p1 >= 0) && ((p1 - p2) >= 0))) && \
        (!((p1 <  0) && ((p1 - p2) <  0)))) { # YES!
      __dacreldebug "sss Sign change needed --> move to zero"
      # step down to zero to acoid damage to the ps
      x = ((p2 == fabs(p2)) * 2) - 1 # up or down
      for (i = 0; i < fabs(p1 - p2) > 0; i++) {
        # values to set are 
        y = (p1 - p2) + x * i
        TACO_ERR = 0; TACO_ERR_MSG = ""
        if (!__DACREL_SIMU) {
          if (taco_io(@arnam["dac"], "DevSetValue", fabs(y)) == -1) {
            eprintf(\
              "DACREL dac: taco_io(\"%s\", \"%s\",%s) failed! 0x%x - %s\n", \
              @arnam["dac"], "DevSetValue", y, TACO_ERR, TACO_ERR_MSG)
            return ".error."
          }
        }
        else {
          __DACREL_SIMU_VALUE = y
          __dacreldebug "sss value", __DACREL_SIMU_VALUE
        }
        # wait for an appropriate amount of time!!!
        sleept = 1 / 4
        sleep(sleept)
      }
      # now to go to zero
      TACO_ERR = 0; TACO_ERR_MSG = ""
      if (!__DACREL_SIMU) {
        if (taco_io(@arnam["dac"], "DevSetValue", 0) == -1) {
          eprintf(\
            "DACREL dac: taco_io(\"%s\", \"%s\",%s) failed! 0x%x - %s\n", \
            @arnam["dac"], "DevSetValue", 0, TACO_ERR, TACO_ERR_MSG)
          return ".error."
        }
      }
      else {
        __DACREL_SIMU_VALUE = 0
        __dacreldebug "sss value", __DACREL_SIMU_VALUE
      }
      # when debug off that gives an error when multiline
      __dacreldebug sprintf("sss DACREL dac: taco_io(\"%s\", \"%s\",%s) succeeded\n", @arnam["dac"], "DevSetValue", 0)
      sign    = (p1 == fabs(p1))
      __dacreldebug "sss Sign is ", sign, "use", sign * 0x80
      if (!__DACREL_SIMU) {
        local str
        str = "im " sign * 0x80 " " 0x80 "\r"
        ser_put(@arnam["opiomser"], str)
        __dacreldebug "DACREL opiom: ", @arnam["opiomser"], str
      }
      else {
        __DACREL_SIMU_SIGN *= -1
        __dacreldebug "sss  sign", __DACREL_SIMU_SIGN
      }
      p2 = p2 + (p1 - p2)
    }
    x = ((p2 == fabs(p2)) * 2) - 1 # up or down
    for (i = 0; i < fabs(p2); i++) {
      # values to set are 
      y = (p1 - p2) + x * i
      if (fabs(y) < 1 / steps) { # sometimes values could be rounding problems
        __dacreldebug "sss value", y, "too small"
        continue
      }
      TACO_ERR = 0; TACO_ERR_MSG = ""
      if (!__DACREL_SIMU) {
        if (taco_io(@arnam["dac"], "DevSetValue", fabs(y)) == -1) {
          eprintf(\
            "DACREL dac: taco_io(\"%s\", \"%s\",%s) failed! 0x%x - %s\n", \
            @arnam["dac"], "DevSetValue", y, TACO_ERR, TACO_ERR_MSG)
          return ".error."
        }
      }
      else {
        __DACREL_SIMU_VALUE = y
        __dacreldebug "sss value", __DACREL_SIMU_VALUE
      }
      # wait for an appropriate amount of time!!!
      sleept = 1 / 4
      sleep(sleept)
    }
    TACO_ERR = 0; TACO_ERR_MSG = ""
    if (!__DACREL_SIMU) {
      if (taco_io(@arnam["dac"], "DevSetValue", fabs(p1)) == -1) {
        eprintf(\
          "DACREL dac: taco_io(\"%s\", \"%s\",%s) failed! 0x%x - %s\n", \
          @arnam["dac"], "DevSetValue", fabs(p1), TACO_ERR, TACO_ERR_MSG)
        return ".error."
      }
      __dacreldebug sprintf("sss DACREL dac: taco_io(\"%s\", \"%s\",%s) succeeded!\n", @arnam["dac"], "DevSetValue", fabs(p1))
    }
    else {
      __DACREL_SIMU_VALUE = fabs(p1)
      __dacreldebug "sss value", __DACREL_SIMU_VALUE
    }
    return 0
  }
  else if (cmd == "position") {
    # get angle
    if (!__DACREL_SIMU) {
      ser_put(@arnam["opiomser"], "?O\r")
      answer = ser_get(@arnam["opiomser"], "\r\n")
      __dacreldebug "DACREL opiom: ", @arnam["opiomser"], "?O", "answer", answer
      if (answer == ""){
        eprint "Problem with opiom state:", @arnam["opiomser"]
        eprint "Can`t seem to talk to opiom!"
        return ".error."
      }
      __dacreldebug "DACREL opiom answer: ", answer
      sign = @arnam["opstat"] = answer & 0x80 ? 1 : -1
      __dacreldebug "DACREL opiom sign: ", sign
    }
    TACO_ERR = 0; TACO_ERR_MSG = ""
    if (!__DACREL_SIMU) {
      value = taco_io(@arnam["dac"], "DevReadValue")
    }
    else {
      value = __DACREL_SIMU_VALUE
      __dacreldebug "ppp position return", value
    }
    if (TACO_ERR){
      eprintf(\
        "DACREL dac: taco_io(\"%s\", \"%s\") failed! 0x%x - %s\n", \
        @arnam["dac"], "DevReadValue", TACO_ERR, TACO_ERR_MSG)
      return ".error."
    }
    __dacreldebug "ppp position return", sign, value, factor, sign * value / factor
    return(sign * value / factor)
  }
}
'


# some programmer help
if (!(whatis("__dacreldebug")  & 2)) rdef __dacreldebug \'#$*\'
#%UU%
#%MDESC% toggle debug mode for the present macros.
def dacrel_debug '{
  if ((whatis("__dacreldebug")>>16) <= 2) { # just a # sign -> off
    rdef __dacreldebug "eprint"
    print "dacrel debug is ON"
  } else {
    rdef __dacreldebug \'#$*\'
    print "dacrel debug is OFF"
  }
}
'

# some programmer help
#%UU%
#%MDESC% toggle debug mode for the present macros.
def dacrel_simu '{
  if (__DACREL_SIMU) { # if present should be true
    unglobal __DACREL_SIMU __DACREL_SIMU_VALUE __DACREL_SIMU_SIGN
    print "dacrel simulation is OFF"
  } else {
    global __DACREL_SIMU __DACREL_SIMU_VALUE __DACREL_SIMU_SIGN
    __DACREL_SIMU      = 1
    __DACREL_SIMU_SIGN = 1
    print "dacrel simulation is ON"
  }
}
'

#%MACROS%
#%IMACROS%
#%DEPENDENCIES%
#The file dac_and_relay_magnet_ps.mac has to be read in. When read in by the IDXXsetup.mac
# or the private setup of a particular spec, the fresh start has no access to
# the _config function. Here, a reconfig is needed before the motors work!
#%AUTHOR% BLISS - ESRF, H. Witsch%BR%
#$Revision: 1.4 $, $Date: 2009/12/11 05:09:40 $
#%TOC%