esrf

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

#%TITLE% MATT.MAC
#%NAME%
#  Monochromatic beam attenuators
#
#%CATEGORY% Other hardware
#
#%DESCRIPTION%
# A set of rellays allows the remote control of the attenuators.
#%SETUP% The relays are driven auther using the
#digital I/O card (ivc196) in the VME crate controls OUTPUT relays or
#a WAGO digital input/output module.
#
#%END%

#%IU%
#%MDESC% Initialise the different control types.
def mattinit '{
global MATT_LIST

  MATT_LIST[1]["name"] = "ICV196 - obsolete"
  MATT_LIST[2]["name"] = "WAGO - security"
  MATT_LIST[3]["name"] = "WAGO - simple"
  MATT_LIST[4]["name"] = "WAGO - alternate bits "
  MATT_LIST[5]["name"] = "User Defined"
}'

#%UU% <type> <other_parametres>
#%MDESC% set the attenuators up. The %B%other_parameters%B% depend on the
#control unit %B%type%B% (WAGO or other).
def mattsetup '{
global MATT_PARS[]
local i inp[] nb

  mattinit

  if ($# == 0) {
    tty_cntl("md")
    printf ("Choose the attenuators control type:\n")
    for (i=2; i<= asso_len(MATT_LIST) ; i++)
      printf ("  %d (%s)", i, MATT_LIST[i]["name"])
    MATT_PARS["type"] = getval ("",MATT_PARS["type"])
    if (MATT_PARS["type"] != 5) {
      matt_wago_setup $*
    } else {
      printf("user setup\n")
    }
    tty_cntl("me")
  } else {
    MATT_PARS["type"] = $1
    if ((MATT_PARS["type"] != 5) && (MATT_PARS["type"] > 1)) {
       matt_wago_setup $*
    } else {
      nb = split("$*",inp) -1
      _setup(inp[0],inp[1],inp[2],inp[3],inp[4])
    }
  }

  #get the initial attenuation
  matt_get()
}'

#%IU% (nb,root,fin,fout)
#%MDESC% set up attenuator box for %B%nb%B% filters, controlled by
#a devices with root name %B%root%B%. The %B%fin%B% is the first
#reading the state (input) channel, while the %B%fout%B% is the first
#control (output) channel.
def _setup(type, nb,root,fin,fout) '{
global MATT_PARS[]
global MATT_STATE MATT_SAVSTATE

  if (type != 5) {
    MATT_PARS["type"]      = type
    MATT_PARS["nb_filt"]   = nb
    MATT_PARS["root"]      = root
    MATT_PARS["first_in"]  = fin
    MATT_PARS["first_out"] = fout
  } else {
    printf("user setup\n")
  }
}'

#%UU% <nb> <root> <firstin> <firstout>
#%MDESC% set up attenuator box for %B%nb%B% filters, controlled by
#wago devices with root name %B%root%B%. The %B%firstin%B% is the
#firs reading the state (input) channel, while the %B%firstout%B% is the
#first control (output) channel.
def matt_wago_setup '{
global MATT_STATE MATT_SAVSTATE
global MATT_PARS[] MATT_NUMBER

  if ($# < 2) {
    tty_cntl("md")
    MATT_PARS["nb_filt"] = getval("Number of filters    :", \
	MATT_PARS["nb_filt"])
    MATT_PARS["root"] = getval("Root name (e.g. att) :", \
	MATT_PARS["root"])
    MATT_PARS["first_in"] = getval("First read channel   :", \
	MATT_PARS["first_in"])
    MATT_PARS["first_out"] = getval("First control channel:", \
	MATT_PARS["first_out"])

  } else {
    MATT_PARS["nb_filt"] = int($2)
    MATT_PARS["root"] = "$3"
    MATT_PARS["first_in"] = int($4)
    MATT_PARS["first_out"] = int($5)
  }
  tty_cntl("me")
  MATT_NUMBER = MATT_PARS["nb_filt"]
}'

#%UU% ()
#%MDESC% Get the attenuation.
def matt_get() '{
  MATT_STATE = _matt_get()
  MATT_SAVSTATE = MATT_STATE
}'

#%UU% ()
#%MDESC% Set the attenuation to 0 (all the available filters out).
def mattset0() '{
  MATT_STATE = _matt_get()
  MATT_SAVSTATE = MATT_STATE
  _mattset(0)
}'

#%UU% ()
#%MDESC% Reset the attenuation to its initial value.
def mattreset() '{
  _mattset(MATT_SAVSTATE)
}'

#%UU% ()
#%MDESC% Set the attenuation to the max value (all the available filters in).
def mattsetmax() '{
  MATT_STATE = _matt_get()
  MATT_SAVSTATE = MATT_STATE
  _mattset((1<<MATT_PARS["nb_filt"]) - 1)
}'

#%IU% ()
#%MDESC% Read attenuator status.
def _matt_get() '{
local ret

  ret = _matt_read()
  if (ret == -1) {
    eprintf ("Cannot read the attenuators hardware, exiting...\n")
    return(-1)
  }

  if (MATT_PARS["type"] == 2)
    ret = _matt_wagoget_2posbit()
  else if (MATT_PARS["type"] == 3)
    ret =  _matt_wagoget_1posbit()
  else if (MATT_PARS["type"] == 4)
    ret = _matt_wagoget_alternate()

  return(ret)
}'

#%IU% ()
#%MDESC% Get the wago attenuator value (double/security cabling).
def _matt_wagoget_2posbit() '{
global MATT_WAGOREAD[]
local i ret

  ret = 0
  for (i = 0; i < MATT_PARS["nb_filt"]; i++) {
    pos = MATT_WAGOREAD[2*i+1] * (1<<i)
    ret += pos
  }

  return(ret)
}'

#%IU% ()
#%MDESC% Get the wago attenuator value (simple cabling).
def _matt_wagoget_1posbit() '{
local i ret

  ret = 0
  for (i = 0; i < MATT_PARS["nb_filt"]; i++) {
    ret += MATT_WAGOREAD[i]<<i
  }
  return(ret)
}'

#%IU% ()
#%MDESC% Get the wago attenuator value - alternate cabling.
def _matt_wagoget_alternate()  '{
local gidx groupno idx
local i ret

  ret = 0
  for (i = 0; i < MATT_PARS["nb_filt"]; i++) {
    gidx    = i % 4
    groupno = int (i / 4)
    idx     = groupno * 8 + 4  + gidx

    ret += MATT_WAGOREAD[idx] << i
  }
  return(ret)
}'

#%IU% ()
#%MDESC% Read the wago module. Return the number of channels red if OK, -1 if
#error.
def _matt_read() '{
local ch
unglobal MATT_WAGOREAD
global MATT_WAGOREAD[]

  ch = sprintf ("%sin",MATT_PARS["root"])
  return(wago_readch(ch, MATT_WAGOREAD))

}'

#%IU% (value)
#%MDESC% set the attenuator to %B%value%B%
def _matt_put(value) '{
local i valarr[]

  #printf ("%x\n", value)
  for (i = 0; i < MATT_PARS["nb_filt"]; i++) {
    valarr[i] = (value&(1<<i)) ? 1: 0
  }
  return(wago_writech(sprintf ("%sout", MATT_PARS["root"]), valarr))
}'

#%UU% (val)
#%MDESC% set attenuator, where %B%val%B% is a hexadecimal representation
#of the desired blades in. Insert needed blades first, then retract the
#unwanted ones to avoid exposure of detector while moving. Verify the
#result of the operation. Return the attenuator status.
def _mattset(val) '{
local newvalue oldvalue

  oldvalue = _matt_get()

  if (oldvalue == val)
    return(oldvalue)

  if ((~val & oldvalue) && (val & ~oldvalue)) {
    _matt_put(val | oldvalue)
    sleep(0.25)
  }
  _matt_put(val)
  sleep(0.25)

  MATT_STATE = _matt_get()
  return (MATT_STATE)
}'

#%UU% <value>
#%MDESC% set attenuator, where %B%value%B% is a hexadecimal representation
#of the desired blades in. Insert needed blades first, then retract the
#unwanted ones to avoid exposure of detector while moving. Verify the
#result of the operation and print new attenuator status.
def mattset '{
local newvalue getvalue notset

  notset = 1

  if ($# != 1) {
    print "Usage: mattset value"
    exit
  }
  newvalue = ($1)
  getvalue = _mattset(newvalue)

  printf("Set: %2d  Got: %2d\n",newvalue,getvalue)
  if (getvalue == newvalue) { 
    notset=0;
  }

  if (notset)
    printf("It appears the attenuators could not be set.\n")
  else
    MATT_STATE = getvalue
}'

#%UU%
#%MDESC% Read attenuator status and print to screen.
# If an argument is given, the macro repeats until interupted by ^C.
def mattstatus '{
global MATT_PARS[]
local i value

  printf("   #\t")
  for (i=1; i<=MATT_PARS["nb_filt"]; i++) {
    if (i<10)
      printf("F%d  ",i)
    else
      printf("F%d ",i)
  }
  printf("\n")
  for (;;) {
    value = _matt_get() 
    printf ("%4d\t", value)
    for (i=0;i<MATT_PARS["nb_filt"];i++) {
      printf ("%s ",(value&(1<<i))?"IN ":"OUT")
    }
    if ($# == 0) {
      printf("\n");
      break
    } else {
      printf ("\r");
    }
  }
}'

#%UU%
#%MDESC% read/set attenuators
def att '{
   if($# != 0) {
      att_set $*
   }
   mattstatus
}'

#%UU% <value>
#%MDESC%
# just a common typo...
def att_Set 'att_set $*'
#
#%UU% <forever>
#%MDESC% 
# ...and another one...
def att_State 'mattstatus $*'
#

#%UU% <number of repetitions>
#%MDESC% test the attenuators - puts them in and out and leaves them
# in their original state.
def matt_test '{
local ii
  current_value = _matt_get()
  for (ii=0;ii<$1;ii++) {
    mattsetmax()
    sleep(1)
  }
  _matt_put(current_value)
}'

#%UU% (args)
#%MDESC% Set the table with sequence of attenuation values. 
def matt_table_setup(args) '{
global MATT_TABLE NR_MATT
local auxlist  i

  list_init auxlist
  NR_MATT = list_splitadd(auxlist,args)
  for (i=1; i <= NR_MATT; i++) {
    MATT_TABLE[i-1] = auxlist[i]
  }
}'

#%MACROS%
#%IMACROS%
#%TOC%
#%DEPENDENCIES% wagocore.mac
#%AUTHOR% J.Klora, A.Beteva, V.Rey%BR%
#$Revision: 1.6 $,$Date: 2012/03/14 10:42:38 $
#%END%
#%LOG%
#$Log: matt.mac,v $
#Revision 1.6  2012/03/14 10:42:38  beteva
#Removed the obsolete hardware (icv196)
#Changed the WAGO reading from using directly Device Server or old modbus
#macros to the wagocore.mac commands
#
#Revision 1.5  2008/08/12 13:26:46  rey
#documentation changes
#
#Revision 1.4  2005/04/01 14:11:09  beteva
#added MATT_STATE for the attenuators brick
#
#Revision 1.3  2004/07/21 15:48:36  beteva
#added WAGO device server and alternate type (VR, AB)
#
#Revision 1.2  2003/08/20 14:42:51  beteva
#added the _mattset function (AB)
#
#Revision 1.1  2003/07/25 15:18:11  beteva
#Initial revision