#%TITLE% XLENS_tango.mac
#$Revision: 1.2 $
#%NAME% Macros for CRL lenses tango device servers.
#%DESCRIPTION%
# The macros provide users with an interface between SPEC and CRL lenses tango
# device servers.
#%SETUP%
#When doing the config, declare a %B%motor\0controller%B%.
#%BR%
#%PRE%
#MOTORS\0\0\0\0DEVICE\0\0\0ADDR\0\0\0\0\0\0\0\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<>TYPE%BR%
#\0\0\0YES\0\0\0__XLENS\0\0\0//orion:10000/fe/xlens-mot/id18\0\0\0\0\02\0\0Macro\0Motors%BR%
# %BR%%B%Please\0note,%B% that the "-x" and "-z" parts of the tango domain name will added in the macros, depending on the channel number! %BR%
# Channel 0 will be "-x", %BR%
# channel 1 will be "-z" !
#%PRE%
#%BR% %BR%
#%BR% %BR%
#Then create %B%macro\0motors%B% in a similar manner. Unit is index number of the controller.
#%PRE%
#Number:\0<>Controller\0\0\0\0\0\0\0\00:\0MAC_MOT\0\0\01:\0MAC_MOT
#Unit/[Module/]Channel\0\0\0\0\0\0\0\0\0\0\0\0\0\0x/0\0\0\0\0\0\0\0\0\0\0x/1
#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\0FE_L_Y\0\0\0\0\0\0\0FE_L_Z
#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\0fly\0\0\0\0\0\0\0\0\0\0flz
#
#Steps\0per\0degree/mm\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0160\0\0\0\0\0\0\0\0\02000
#Sign\0of\0user\0*\0dial\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\01\0\0\0\0\0\0\0\0\0\0\0\01
#Backlash\0[steps]\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00\0\0\0\0\0\0\0\0\0\0\0\00
#Steady-state\0rate\0[Hz]\0\0\0\0\0\0\0\0\0\0\0\01000\0\0\0\0\0\0\0\0\01000
#Base\0rate\0[Hz]\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0200\0\0\0\0\0\0\0\0\0\0\015
#Acceleration\0time\0[msec]\0\0\0\0\0\0\0\0\0\02000\0\0\0\0\0\0\0\0\0\0500
#Motor\0accumulator\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00\0\0\0\0\0\0\0\0\0\0\0\00
#Restrictions\0<>\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0NONE\0\0\0\0\0\0\0\0\0NONE
#
#Dial\0=\0accumulator\0/\0steps
#\0\0High\0limit\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\07.0000\0\0\0\0\0\0\06.8755
#\0\0Current\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00.0000\0\0\0\0\0\0\00.0000
#\0\0Low\0limit\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0-6.4000\0\0\0\0\0\0-6.5265
#User\0=\0sign\0*\0dial\0+\0offset
#\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\00.0000\0\0\0\0\0\0\00.0000
#\0\0`High'\0limit\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\07.0000\0\0\0\0\0\0\06.8755
#\0\0Current\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00.0000\0\0\0\0\0\0\00.0000
#\0\0`Low'\0limit\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0-6.4000\0\0\0\0\0\0-6.5265
#%PRE%
# Please note, that step size and rates are not taken into account!
#%END%
#%BR%
# Then hit 'm' twice. Set the following for your motor:
#%PRE%
#Hardware\0read\0mode\0<>\0\0\0\0\0\0\0\0%B%NO\0QUERY\0=NQ%B%
#%PRE%
# If you miss this, you will be asked to confirm motor positions after each
# change on a revolver.
#%END%
#%HISTORY%
#$Log: XLENS_tango.mac,v $
#Revision 1.2 2016/12/02 12:05:51 guilloud
#changed TANGO_ERR test.
#
#Revision 1.1 2012/03/07 14:59:56 witsch
#Initial revision
#
need spec_utils
if (!(whatis("__xlens_debug") & 2)) rdef __xlens_debug \'#$*\'
if (SPEC == "holg") {
if (!(whatis("__xlens_verbose") & 2)) rdef __xlens_verbose \'eprint "XLENS >>> "\'
} else {
if (!(whatis("__xlens_verbose") & 2)) rdef __xlens_verbose \'#$*\'
}
#%UU%
#%MDESC% toggle debug mode for the present macros.
def XLENS_debug '{
if ((whatis("__xlens_debug") >> 16) <= 5) { # just a # sign -> off
rdef __xlens_debug "eprint \"XLENS: \", "
eprint "XLENS debug is ON"
} else {
rdef __xlens_debug \'#$*\'
eprint "XLENS debug is OFF"
}
}
'
#%IU%
#%MDESC% called after each tango_[get|io] call. Checks for errors.
def __XLENS_tango_catch_error '{
if (TANGO_ERR != "0") {
tty_cntl("md")
#__errstr = what "(\"" addr "\", \"" attr "\")"
__errstr = __XLENS["macfname"] " - " func " - ERROR: " what \
"(\"" addr "\", \"" attr "\") " add "\n"
__XLENS_error(__errstr)
__xlens_debug TANGO_ERR_STACK
tty_cntl("me")
return ".error."
}
}
'
#%IU%(mnum, type, unit, mod, chan)
#%MDESC%
# The macro motor configuration function
def __XLENS_config(mnum, type, unit, mod, chan) '{
# chan will be used for counters to designate the tag address. Leave alone.
__xlens_debug "Configuring XLENS", mnum, type, unit, mod, chan
local func, attr, what, __errstr
func = "__XLENS_config()"
addr = __XLENS_ADDR
what = "tango_get"
if (type == "ctrl") {
# delete all the associative arrays to do a clean job.
global __XLENS[]
local x
__XLENS["savedir"] = SPECD "/../../../local/spec/userconf"
__XLENS["macfname"] = "XLENS_tango.mac"
__XLENS["unit"] = __XLENS_ADDR # saving for the spec bug in _par
}
else if (type == "mot") {
motor_par(mnum, "backlash", 0) # is handled by server
__xlens_verbose "Motor", motor_name(mnum), "(mne", motor_mne(mnum) ")"
}
}
'
#%IU%(mnum, cmd, p1, p2, p3)
#%MDESC%
# The macro motor command function
def __XLENS_cmd(mnum, cmd, p1, p2, p3) '{
local unit, chan, retval
__xlens_debug "Command XLENS", mnum, cmd, p1, p2, p3, "(" __XLENS["unit"] ")"
local func, attr, what, __errstr
func = "__XLENS_cmd()"
addr = __XLENS["unit"]
if (!addr) { # when macro has just been loaded and a reconfig is performed
addr = __XLENS_ADDR
}
what = "tango_io"
if (mnum != "..") {
unit = motor_par(mnum, "unit")
chan = motor_par(mnum, "channel") # 0 -> x / 1 -> z
if (chan == 0) {
addr = addr "-x"
}
else if (chan == 1) {
addr = addr "-z"
}
else {
__XLENS_error("Channel must be 0 for x and 1 for z!")
return ".error."
}
if (cmd == "start_one") {
local state, position
attr = "Position"
state = __XLENS_state(addr)
what = "tango_put"
__xlens_debug "tango_put(\"" addr "\", \"" attr "\", " p1 ")"
tango_put(addr, attr, p1)
__XLENS_tango_catch_error
}
else if (cmd == "position") {
local state, position
state = __XLENS_state(addr)
__xlens_debug "position:", chan, "state is", state
what = "tango_get"
attr = "Position"
__xlens_debug "get_status:", chan, addr, "state is", state
retval = tango_get(addr, attr)
__XLENS_tango_catch_error
return retval
}
else if (cmd == "get_status") {
local state, xtra[]
attr = "Position"
state = __XLENS_state(addr)
__xlens_debug "get_status:", chan, addr, "state is", state
if (state == "ALARM") {
__xlens_debug "get_status: in ALARM state"
attr = "HardLimitLow"
retval = tango_get(addr, attr)
__XLENS_tango_catch_error
if (retval == 1) {
return 0x04
} else {
attr = "HardLimitHigh"
retval = tango_get(addr, attr)
__XLENS_tango_catch_error
if (retval == 1) {
return 0x08
}
}
} else
if (state == "MOVING") {
return 2
} else
if (state == "ON") { # all good
return 0
} else { # anything else is bad
return 0x20
}
}
else if (cmd == "abort_one") {
attr = "Abort"
__xlens_debug "tango_io(\"" addr "\", \"" attr "\")"
tango_io(addr, attr)
__XLENS_tango_catch_error
}
}
}
'
#%IU%(und)
#%MDESC%Get state of xlens motor%BR%
#%END%
# Info from J. Meyer 12/12/11 on states%BR%
# Von ON = 0 bis UNKNOWN=13%BR%
# enum DevState { ON, OFF, CLOSE, OPEN, INSERT, EXTRACT, MOVING,%BR%
# STANDBY, FAULT, INIT, RUNNING, ALARM, DISABLE,%BR%
# UNKNOWN };
def __XLENS_state(addr) '{
__xlens_debug "state from", addr
local state, aux[], stenum[], str
str = "ON OFF CLOSE OPEN INSERT EXTRACT MOVING STANDBY FAULT INIT
RUNNING ALARM DISABLE UNKNOWN"
if (!addr) { # when macro has just been loaded and a reconfig is performed
return "UNKNOWN"
}
split(str, stenum)
local func, attr, what, __errstr
func = "__XLENS_state()"
what = "tango_get"
attr = "State"
__xlens_debug "tango_get(\"" addr "\", \"" attr "\", aux)"
state = tango_get(addr, attr)
__XLENS_tango_catch_error
return stenum[state]
}
'
#%IU%(mesg)
#%MDESC% Writes indentical error message only once in a while.
def __XLENS_error(errstr) '{
global __XLENSERR[]
local expiry, now, str
str = "XLENS: " errstr
expiry = 5 # seconds before message is redisplayed
now = time()
if (errstr in __XLENSERR) {
if ((time() - __XLENSERR[errstr]) > expiry) {
__XLENSERR[errstr] = now
cprint(str, 3, 1, 1)
}
} else {
__XLENSERR[errstr] = now
cprint(str, 3, 1, 1)
}
local x
for (x in __XLENSERR) {
if ((time() - __XLENSERR[x]) > 20) {
delete __XLENSERR[x]
}
}
}
'
#%MACROS%
#%IMACROS%
#%INTERNALS%
#%AUTHOR% H. Witsch, BLISS - ESRF
#$Revision: 1.2 $, $Date: 2016/12/02 12:05:51 $
#%TOC%
|