"""
#%TITLE% ATTRIBUTES.MAC
#%NAME% ATTRIBUTES.MAC - TANGO attribute macro counters.
#
#%DESCRIPTION%
# The macro set offers the possibility to set-up a TANGO attribute
# as macro motor or as macro counter.
# Only read/write TANGO attributes can be used as macro motor.
# The macro motor controller defined is called "attr_mot" and
# The macro counter controller defined is called "attr_ct".
#
#%SETUP%
#Motor and Counter Device Configuration (Not CAMAC)%BR%
#SCALERS\0\0\0\0\0\0\0\0DEVICE\0\0\0ADDR\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0<>MODE\0\0NUM\0\0\0\0\0\0\0\0\0\0\0\0\\0\0\0<>TYPE%BR%
#\0\0\0\0YES\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\0\0\0\0\0\0\0\0\0POLL\0\0\0\01\0\0\0\0\0\0\0\0Software\0Timer%BR%
#\0\0\0\0YES\0\0\0\0\0\0\0attr_ct\0\0\0IDXX/wcidxx/tg\0\0\0\0\0\0\0\0\0\0\0\0\0\0\02\0\0\0\0\0\0\0\0\0Macro\0Counter%BR%
#
# Make sure to set the ADDR field with the device name.%BR%
# Make sure to set the NUM field to the good number of macro_counters you need.%BR%
# If you read from an array of scalars, i.e. a name that was defined multiple
#times, make sure to set the channel number as the array index.
#
# One must set (type p, when on counter) the Custom Parameters "attr_name".
# If the Custom Parameters "channel" is set, the macro assumes, that the signal name is used multiple times and
# that the channel is the index in the array of returned values.
#%EXAMPLE%
#%DL%
#
#
#%DT% attr_mot_setup tilt id14/eh3-motor/mono_tile/Position %DD%
# Set-up the TANGO attribute macro motor with the mnemonic "tilt"
#
#
#%XDL%
#
#%END%
# Even disabled, attr_ct counters consume (small) counting time ( ~0.5 ms ?)
# to read 3 scalars : ~3 ms overhead ?
"""
# for color printing :)
need spec_utils
# Macro-COUNTERS parameters.
global ATTR_CT
list_test ATTR_CT
# ATTR_CT[mne]["dev_name"]
# ATTR_CT[mne]["attr_name"]
# Macro-MOTORS parameters.
global ATTR_MOT
list_test ATTR_MOT
# ATTR_MOT[mne]["dev_name"]
# ATTR_MOT[mne]["attr_name"]
"""
######################################################################
############################## #############################
############################## General #############################
############################## #############################
######################################################################
"""
#%UU%
#%MDESC%
# Removes everything about attributes.mac
def attr_unsetup '{
local ii _arr_name
unglobal ATTR_MOT
unglobal ATTR_CT
}'
#%UU%
#%MDESC%
# Displays information about counters managed by attributes macros.
def attr_show '{
attr_ct_show
print ""
attr_mot_show
}'
#%IU%
#%MDESC%
# Cosmetics.
def attr_error_head '{
tty_cntl("md")
#printf("ERROR:attribute.mac : ")
printf("ERROR : ")
tty_cntl("me")
}'
"""
######################################################################
####################### ######################
####################### Scalar Macro counters ######################
####################### ######################
######################################################################
"""
#%UU%
#%MDESC%
# Displays informations about macro counters.
def attr_ct_show '{
local _mne
print "-------=== macro counters ===------------"
print "mnemonic device attribute "
print "-----------------------------------------"
for (i=0; i< list_n(ATTR_CT); i++){
_mne = ATTR_CT[i+1]
# print ATTR_CT[i+1]" " ATTR_CT[_mne]["dev_name"]" "\
# ATTR_CT[_mne]["attr_name"]
printf("ATTR_CT : Counter %10s linked to %s/%s\n", \
_mne, ATTR_CT[_mne]["dev_name"], ATTR_CT[_mne]["attr_name"])
}
print "-----------------------------------------"
}'
#%IU%
#%MDESC%
#Called on reconfig.
def attr_ct_config(cntnum, what, p1, p2) '{
global ATTR_CT
if((cntnum == "..") && (what == "ctrl")) {
# Check that the Tango DS is running
if(ds_is_tango(attr_ct_ADDR) != 1) {
attr_error_head
printf("device %s is unresponsive -> disabling it. \n", attr_ct_ADDR)
return ".error."
}
return
}
if(what == "cnt") {
local _mne, _attr, _info[], _arrname
_mne = cnt_mne(cntnum)
list_test ATTR_CT
list_add(ATTR_CT, _mne)
if((_attr = counter_par(cntnum,"attr_name")) == 0) {
attr_error_head
printf("missing \"attr_name\" for counter \"%s\"\n", _mne)
return ".error."
}
tango_get(attr_ct_ADDR, "?", _attr, _info)
if (TANGO_ERR != "0"){
tty_cntl("md")
print "\n" ATTR_CT_ERROR " " _cntr_mne
printf ("TANGO_ERR_MSG = \"%s\" \n\n", TANGO_ERR)
print TANGO_ERR_STACK
tty_cntl("me")
return ".error."
}
list_setpar(ATTR_CT, _mne, "dev_name", attr_ct_ADDR)
list_setpar(ATTR_CT, _mne, "attr_name", _attr)
if (_info["max_dim_x"] > 1) { # this is not a scalar but an array of values
_arr_name = "ATTR_CT_" attr_ct_ADDR "_" _attr
list_setpar(ATTR_CT, _mne, "array", _arr_name)
if (! index(ATTR_CT[attr_ct_ADDR], _attr)) {
ATTR_CT[attr_ct_ADDR] = ATTR_CT[attr_ct_ADDR] " " _attr
}
}
}
}'
#%IU%
#%MDESC%
# Main function for macro counter.
def attr_ct_cmd(cntnum, what, p1, p2) '{
local _cntr _dev _attr _ans _attr_name _cntr_mne
local _sname _arr_name ii
if (cntnum == "..") {
if (what == "prestart_all") {
local _aux[], numele, i
numele = split(ATTR_CT[attr_ct_ADDR], _aux)
for (i = 0; i < numele; i++) {
_arr_name = "ATTR_CT_" attr_ct_ADDR "_" _aux[i]
# get all values in the array
tango_get(attr_ct_ADDR, _aux[i], @_arr_name)
if (TANGO_ERR != "0"){
tty_cntl("md")
print "\n" ATTR_CT_ERROR " " _cntr_mne
printf ("TANGO_ERR_MSG = \"%s\" \n\n", TANGO_ERR)
print TANGO_ERR_STACK
tty_cntl("me")
return ".error."
}
}
}
} else
if (cntnum != "..") {
if (what == "counts") {
local _ans, _num, _dev, _attr, _ret_val, _arr_name
_cntr_mne = cnt_mne(cntnum)
# Tests if _cntr_mne is an attr_ct macro counter.
if (list_check(ATTR_CT, _cntr_mne)) {
_dev = list_getpar(ATTR_CT, _cntr_mne, "dev_name")
_attr = list_getpar(ATTR_CT, _cntr_mne, "attr_name")
_arr_name = list_getpar(ATTR_CT, _cntr_mne, "array")
if (_arr_name != -1) { # this must be an array of scalars
# just grab the value from the already existing array
# for that we need the channel number
local chan
chan = counter_par(cntnum, "channel")
return @_arr_name[chan]
}
else {
# print " reading attribute scalar... "
_ans = tango_get(_dev, _attr)
_ret_val = _ans
if (TANGO_ERR != "0"){
tty_cntl("md")
print "\n" ATTR_CT_ERROR " " _cntr_mne
printf ("TANGO_ERR_MSG = \"%s\" \n\n", TANGO_ERR)
print TANGO_ERR_STACK
tty_cntl("me")
return ".error."
}
return (_ret_val)
}
}
else {
# print "Counter \"" _cntr_mne "\" not set up in ATTR_CT."
return (-1)
}
}
}
}'
"""
########################################################################
########################################################################
########################################################################
####################### #######################
####################### Spectrum Macro Counter #######################
####################### #######################
########################################################################
########################################################################
########################################################################
# SETUP FREE : use config only.
# !!! can be time-consuming even with single read. ??
# bench ct 0.00001 : 13.25 msec. for 2 spectrums (soft timer / POLL)
# bench ct 0.00001 : 4.12 msec. for 2 spectrums (soft timer / INTR)
"""
constant __Attr_macfname "attributes.mac"
def __attr_tango_catch_error '{
if (TANGO_ERR != "0") {
tty_cntl("md")
__errstr = __Attr_macfname " - " func " - ERROR: " what \
"(\"" addr "\", \"" attr "\"" add ")\n" \
TANGO_ERR_STACK["0"]["desc"] "\n"
eprint __errstr
__Attr_debug TANGO_ERR_STACK
tty_cntl("me")
return ".error."
}
}
'
if (!(whatis("__Attr_debug") & 2)) rdef __Attr_debug \'#$*\'
#%UU%
#%MDESC% toggle debug mode for the present macros.
def Attr_debug '{
if ((whatis("__Attr_debug") >> 16) <= 5) { # just a # sign -> off
rdef __Attr_debug "eprintf(\"%s: \", __Attr_macfname);eprint "
print "Attributes debug is ON"
} else {
rdef __Attr_debug \'#$*\'
print "Attributes debug is OFF"
}
}
'
#%MDESC%
#Macro counter and motor config
#%IU%
def attr_spectrum_config(num, type, unit, nb_chan, channel) '{
__Attr_debug "attr_spectrum_config:", num, type, unit, nb_chan, channel
local _idx _arr_name
local _ds_name
local _taa[]
split(attr_spectrum_ADDR, _taa, "/")
_ds_name = sprintf("%s/%s/%s", _taa[0], _taa[1], _taa[2])
__Attr_debug "attr_spectrum_config: _ds_name", _ds_name, _taa[3]
if(ds_is_tango(_ds_name)) {
if (num == "..") {
# Creates a global associative array to cache tango
# attribute reading.
# Its name is forged using mac cnt name and unit number.
_arr_name = sprintf("attr_spectrum_%s", _taa[3])
global @_arr_name
@arr_name[0] = 0
__Attr_debug "attr_spectrum_config: _arr_name", _arr_name
}
else {
_arr_name = sprintf("attr_spectrum_%s", _taa[3])
local str, parcmd, mnecmd, showstr
if (type == "mot") {
parcmd = "motor_par"
mnecmd = "motor_mne"
showstr = "Motor "
} else
if (type == "cnt") {
parcmd = "counter_par"
mnecmd = "cnt_mne"
showstr = "Counter "
}
str = parcmd "("num", \"spectrum\", \"" attr_spectrum_ADDR "\", \"add\")"
eval(str)
#counter_par(num, "spectrum", attr_spectrum_ADDR , "add")
str = parcmd "("num", \"temp_arr\", \"" _arr_name "\", \"add\")"
eval(str)
#counter_par(num, "temp_arr", _arr_name , "add")
str = parcmd "("num", \"channel\")"
_idx = eval(str)
#_idx = counter_par(num, "channel")
__Attr_debug " spectrum = " attr_spectrum_ADDR
__Attr_debug " temp_arr = " _arr_name
str = mnecmd "(" num ")"
local mne
mne = eval(str)
mne = showstr mne
printf("ATTR_SPECTRUM : %10s linked to %s[%d]\n", \
mne, attr_spectrum_ADDR, _idx)
}
}
else {
attr_error_head
printf("device %s is unresponsive -> disabling it.\n", _ds_name)
return ".error."
}
}'
#%IU%
#%MDESC%
# Macro motor/counter to read TANGO SPECTRUM ATTRIBUTES.
def attr_spectrum_cmd(num, key, p1, p2, unit) '{
__Attr_debug "attr_spectrum_cmd:", num, key, p1, p2, unit
local _read_at_end
local func, attr, what, __errstr
func = "attr_spectrum_cmd"
local _dev _arr_name
#printf ("attr_spectrum_cmd; cnum=\"%2s\" prestart_all p1=\"%2s\" p2=\"%2s\" unit=\"%2s\"\n", \
# num, p1, p2, unit)
split (attr_spectrum_ADDR, _attr_fields, "/")
_dev = sprintf("%s/%s/%s", _attr_fields[0], _attr_fields[1], _attr_fields[2])
attr = _attr_fields[3]
_arr_name = sprintf("attr_spectrum_%s", attr)
if (num == "..") {
if ((key == "prestart_all") || (key == "preread_all")) {
what = "tango_get"
TANGO_ERR = -1
tango_get(_dev, attr, @_arr_name)
__attr_tango_catch_error
__Attr_debug func ": _array", @_arr_name
}
}
else { # mot or cnt, not ".."
if (key == "start_one") {
if (p2 != 0) { # this must be a motor, as p2 is the relative movement
local _arr_name _index _ret_val
_arr_name = motor_par(num, "temp_arr")
_index = motor_par(num, "channel")
what = "tango_put"
@_arr_name[_index] = p1
TANGO_ERR = -1
tango_put(_dev, attr, @_arr_name)
__attr_tango_catch_error
__Attr_debug "setting wago resource", attr "[" _index "]", "to", p1
}
}
else if (key == "halt_one") {
local _arr_name _index _ret_val
_arr_name = counter_par(num, "temp_arr")
what = "tango_get"
TANGO_ERR = -1
tango_get(_dev, attr, @_arr_name)
__attr_tango_catch_error
__Attr_debug "getting wago resource", attr, @_arr_name
}
else if (key == "counts") {
local _arr_name _index _ret_val
_arr_name = counter_par(num, "temp_arr")
_index = counter_par(num, "channel")
return @_arr_name[_index]
}
else if (key == "position") {
local _arr_name _index _ret_val
_arr_name = motor_par(num, "temp_arr")
_index = motor_par(num, "channel")
return @_arr_name[_index]
}
}
}
'
def attr_spectrum_read_test '{
# ~ 0.33 ms
global TTT[]
tango_get("sys/database/2", "Timing_average", TTT)
}'
"""
######################################################################
########################### ###########################
########################### Macro motors ###########################
########################### ###########################
######################################################################
##%UU% <mne> <dev> <attribute> | <mne> <dev/attribute>
#%MDESC%
# Configures counter <mne> to read <attribute> of tango device <dev>.
#
# example: attr_mot_setup at1 id22eh2/machin/1 X
# or attr_mot_setup at2 id22eh2/machin/1/X
#
# example 2 attr_mot_setup rft1 id22/refillsim/1 Refill_time
# or attr_mot_setup rft1 id22/refillsim/1/Refill_time
#
"""
def attr_mot_setup '{
local _fields _dev_name _nbarg
local _args_strings _mne
_mne = "$1"
motnum = motor_num(_mne)
list_test ATTR_MOT
list_add(ATTR_MOT, _mne)
_nbarg = $#
# Parses arguments to extract device and attribute names.
# 2 or 3 arguments ?
if (_nbarg == 2){
if(motor_par(motnum,"type") != -1){
list_setpar(ATTR_MOT, _mne, "type", motor_par(motnum,"type"))
}
# print "2 parameters given."
_args_strings[0] = 0
split ("$2", _args_strings, "/")
list_setpar(ATTR_MOT, _mne, "dev_name", \
sprintf("%s/%s/%s", _args_strings[0], \
_args_strings[1], _args_strings[2]))
list_setpar(ATTR_MOT, _mne, "attr_name", _args_strings[3])
}
else if (_nbarg == 3){
if(motor_par(motnum,"type") != -1){
list_setpar(ATTR_MOT, _mne, "type", motor_par(motnum,"type"))
}
# print "3 parameters given."
list_setpar(ATTR_MOT, _mne, "dev_name", "$2")
list_setpar(ATTR_MOT, _mne, "attr_name", "$3")
}
else {
attr_error_head
print "$0 requires 2 or 3 arguments."
print "usage -> $0 <mne> <device> <attribute>"
print " or $0 <mne> <device/attribute>"
exit
}
# Informative message.
printf("Configuring macro motor ")
tty_cntl("md")
printf ("%s", "$1")
tty_cntl("me")
printf (" to reflect attribute ")
tty_cntl("md")
printf ("%s", ATTR_MOT["$1"]["attr_name"])
tty_cntl("me")
printf (" of device ")
tty_cntl("md")
printf ("%s", ATTR_MOT["$1"]["dev_name"])
tty_cntl("me")
print "."
if (motor_num(_mne) < 0){
printf("Warning: motor \"%s\" is not defined\n", _mne)
}
}'
#%UU% <mne>
#%MDESC%
# Removes reading of attribute linked to <mne> motor.
# ex: attr_mot_unsetup at1
def attr_mot_unsetup '{
local _nb_param
_nb_param =$#
if (_nb_param < 1){
print "usage : $0 <motor_mnemonic>"
}
else{
list_remove(ATTR_MOT, "$1")
}
}'
#%UU%
#%MDESC%
# Removes reading of all attributes.
def attr_mot_unsetup_all '{
unglobal ATTR_MOT
}'
#%UU%
#%MDESC%
# Displays informations about attributes macro motors.
def attr_mot_show '{
local _mne
print "--------==== macro motors ====-----------"
print "mnemonic device attribute "
print "-----------------------------------------"
for (i=0; i< list_n(ATTR_MOT); i++){
_mne = ATTR_MOT[i+1]
print ATTR_MOT[i+1]" " ATTR_MOT[_mne]["dev_name"]" " \
ATTR_MOT[_mne]["attr_name"]
}
print "-----------------------------------------"
}'
#%IU%
#%MDESC%
# Called on reconfig.
def attr_mot_config(motnum, what, p1, p2) '{
global ATTR_MOT
local _ds_name
if((motnum == "..") && (what == "ctrl")) {
# Check that the Tango DS is running
if(ds_is_tango(attr_mot_ADDR)) {
# ok
}
else{
attr_error_head
printf("%s unresponsive -> disabling. \n", attr_mot_ADDR)
return ".error."
}
return
}
if(what == "mot") {
local _mne
local _attr
_mne = motor_mne(motnum)
list_test ATTR_MOT
list_add(ATTR_MOT, _mne)
if((_attr=motor_par(motnum,"attr_name")) == 0) {
#attr_error_head
#printf("missing \"attr_name\" for motor \"%s\"\n", _mne)
##return ".error."
#return
# PC: take position as default
_attr = "position"
motor_par(motnum, "attr_name", _attr)
}
_ds_name = attr_mot_ADDR
motor_par(motnum, "dev_name", _ds_name, "add")
list_setpar(ATTR_MOT, _mne, "dev_name", attr_mot_ADDR)
list_setpar(ATTR_MOT, _mne, "attr_name", _attr)
printf("ATTR_MOT : Motor %10s linked to %s/%s\n", \
_mne, ATTR_MOT[_mne]["dev_name"], ATTR_MOT[_mne]["attr_name"])
}
}'
#%IU%
#%MDESC%
#
def attr_mot_cmd(motnum, what, p1, p2) '{
local _mot_mne _dev _attr
_mot_mne = motor_mne(motnum)
# Tests if _mot_mne is really an attr_ macro motor.
if (list_check(ATTR_MOT, _mot_mne)){
_dev = list_getpar(ATTR_MOT, _mot_mne, "dev_name")
_attr = list_getpar(ATTR_MOT, _mot_mne, "attr_name")
_target = _dev "/" _attr
}
else{
# print "Motor \"" _mot_mne "\" not set up in ATTR_MOT."
return (-1)
}
if(motnum == ".."){
# key applying to all motors
# print "--"
}
#-------------------------------------
# "position" must return dial position (in integer steps)
# parameters: none
if (what == "position") {
local _pos
if(motor_par(motnum, "type") == "wago"){
local attr_key
local out[]
# Specific command to read real wago value and not cached one.
attr_key = tango_io(_dev, "DevName2Key", _attr)
tango_io(_dev, "DevReadNoCachePhys", attr_key, out)
_pos = out[0]
}
else {
if (motor_par(motnum, "type") == -1){
cprint_red(sprintf("attr_mot_cmd / position : motor %d is not defined", motnum))
}
else{
_pos = tango_get(_dev, _attr)
}
}
if (TANGO_ERR != "0"){
tty_cntl("md")
print "\n" ATTR_MOT_ERROR " " _mot_mne " " _dev "/" _attr
printf ("TANGO_ERR_MSG = \"%s\" \n\n", TANGO_ERR)
print TANGO_ERR_STACK
tty_cntl("me")
return ".error."
}
return (_pos)
}
"""
#-------------------------------------
# "get_status" called during the motion, must return a bit mask
# bits meaning: 0 if motor idle
# 2 if motor moving
# 4 if negative limit on
# 8 if positive limit on
# parameters: none
"""
if (what == "get_status"){
local _state
local _ret
_state = tango_io(_dev, "State")
if (TANGO_ERR != "0"){
tty_cntl("md")
print "\n" ATTR_MOT_ERROR " " _mot_mne " " _dev "/" _attr
printf ("TANGO_ERR_MSG = \"%s\" \n\n", TANGO_ERR)
print TANGO_ERR_STACK
tty_cntl("me")
return ".error."
}
#
# DEVMOVING
#
if (_state == 6) {
_ret |= 2
return _ret
}
#
# DEVFAULT
#
# PC: problem with SyncAxis, acceleration is wrong; causes Fault State while moving
# We do not care; this is anyway a provisional solution
if (_state == 8) {
_ret |= 2
return _ret
}
return 0
}
#-------------------------------------
# "start_one"
# parameters: p2 is relative motion, p1 is absolute requested position
if (what == "start_one") {
tango_put(_dev, _attr, p1)
if (TANGO_ERR != "0"){
tty_cntl("md")
print "\n" ATTR_MOT_ERROR " " _mot_mne " " _dev "/" _attr
printf ("TANGO_ERR_MSG = \"%s\" \n\n", TANGO_ERR)
print TANGO_ERR_STACK
tty_cntl("me")
return ".error."
}
}
"""
#-------------------------------------
# "set_position" called on "set_dial motor newpos"
# parameters: p1 is the new position (in steps)
#
# PC: this does not change the dial value, it will move to position p1
# We don not want set_dial to be used on Tango motors
"""
if (what == "set_position") {
# tango_put(_dev, _attr, p1)
#
# if (TANGO_ERR != "0"){
# tty_cntl("md")
# print "\n" ATTR_MOT_ERROR " " _mot_mne " " _dev "/" _attr
# printf ("TANGO_ERR_MSG = \"%s\" \n\n", TANGO_ERR)
# print TANGO_ERR_STACK
# tty_cntl("me")
# return ".error."
# }
print "Changing dial value is not allowed"
}
#-------------------------------------
# "abort_one" called on <Ctrl-C>
#
if (what == "abort_one") {
tango_io(_dev, "Abort")
if (TANGO_ERR != "0"){
tty_cntl("md")
print "\n" ATTR_MOT_ERROR " " _mot_mne " " _dev "/" _attr
printf ("TANGO_ERR_MSG = \"%s\" \n\n", TANGO_ERR)
print TANGO_ERR_STACK
tty_cntl("me")
return ".error."
}
}
}'
#%MACROS%
#%IMACROS%
#%AUTHOR% JM CG MP PC AM(a little) HW (Jan 2017)
|