#%TITLE% ICE.MAC
#
#%NAME%
# Macros to control ISG ICEPAP motor controller as a macro motor
# and to configure macro counters to read DRIVERs temperatures.
# Replacing the old "icepap.mac" set of macros.
#
#%CATEGORY% Positioning, Isg
#
#%DESCRIPTION%
#%DL%
#%DT%Configuring macro motors %DD%
# %DL%
# %DT% 1)
# You must have an entry in "MOTORS" table for each icepap MASTER
# %DL%
# %DT% -
# The "DEVICE" field must be set to string "icepap"
# %DT% -
# The "ADDR" must be set to the MASTER network name.
# The communication port can optionaly be specified also
# (ex: "isgtmp5:5000")
# %DT% -
# The "NUM" should be set to 159
# %DT% -
# The "TYPE" field must be set to "Macro Motors"
# %XDL%
# %DT% 2)
# For each axis you must define a motor with:
# %DL%
# %DT% -
# The "Controller" field set to "MAC_MOT"
# %DT% -
# The "Unit" field, numbered from 0,
# must be set to the MOTORS entry.
# %DT% -
# The "Module" field, numbered from 0,
# must be set to the ICEPAP rack number (seen on
# the red 7 segments display of the left hand of each rack)
# %DT% -
# The "Chan" field, numbered from 1,
# must be set to the DRIVER address
# %DT% -
# Example: "0/1/2" refers to the first icepap controller declared,
# the rack having the number "1" on its display,
# the 2nd DRIVER of this rack
# %XDL%
# %XDL%
#
#
#%DT%Configuring macro counters to read a DRIVER ENCODER POSITION%DD%
# %DL%
# %DT% 1)
# You must have a "SCALER" define with "icepapenc" as "DEVICE" and
# "Macro Counter" as "TYPE".
# %DT% 2)
# You must define a counter with "MAC_CNT" as "Device".
# %DL%
# %DT% -
# The "Unit" field must be set to the SCALER entry.
# %DT% -
# The "Chan" field must be set to the DRIVER address (ex: 5 for
# the 5th DRIVER of crate 0 or ex: 23 for the 3rd DRIVER of crate 2)
# %DT% -
# The "encoder" parameter can be set to one of the following values.
# Typically this parameter is set in config "custom parameters"
# screen for a counter. Hint: type "p" to get in.
# %DL%
# %DT% -
# "abs" Read the SSI absolute encoder
# %DT% -
# "absuXX" Read the unsigned SSI XX bits absolute encoder
# %DT% -
# "inc" Read the incremental encoder (DEFAULT)
# %DT% -
# "inpos" Read the DRIVER front panel input
# %DT% -
# "motor" Read the motor phase position
# %XDL%
# %XDL%
# %XDL%
#
#
#%DT%Configuring macro counters to read a single DRIVER TEMPERATURE %DD%
# %DL%
# %DT% 1)
# You must have a "SCALER" define with "icepapcnt" as "DEVICE" and
# "Macro Counter" as "TYPE".
# %DT% 2)
# You must define a counter with "MAC_CNT" as "Device".
# %DL%
# %DT% -
# The "Unit" field must be set to the SCALER entry.
# %DT% -
# The "Chan" field must be set to the DRIVER address (ex: 5 for
# the 5th DRIVER of crate 0 or ex: 23 for the 3rd DRIVER of crate 2)
# %XDL%
# %XDL%
#
#
#%DT%Configuring macro counters to read several DRIVERs TEMPERATUREs %DD%
# %DL%
# %DT% 1)
# You must have a "SCALER" define with "icepapcalc" as "DEVICE" and
# "Macro Counter" as "TYPE"
# %DT% 2)
# For each counter declared:
# %DL%
# %DT% -
# The "Device" field set to "MAC_CNT"
# %DT% -
# The "Unit" field must be set to the SCALER entry.
# %DT% -
# The "Chan" field is not used.
# %DT% -
# The "Misc 1" parameter (type "s" to access it) is the
# crate number (ex: 0)
# %DT% -
# The "Misc 2" parameter is the type of calculation
# done on the DRIVERs temperatures of the crate. Possible values are
# "max", "min", "avg"
# %XDL%
# %XDL%
#
#
#%DT%Configuring macro counters to read a single DRIVER internal parameter %DD%
# %DL%
# %DT% 1)
# You must have an entry in "SCALER" table for each icepap MASTER
# %DL%
# %DT% -
# The "DEVICE" field must be set to string "icepapmeas"
# %DT% -
# The "ADDR" must be set to the MASTER network name.
# The communication port can optionaly be specified also
# (ex: "isgtmp5:5000")
# %DT% -
# The "NUM" should be set to 159
# %DT% -
# The "TYPE" field must be set to "Macro Counter"
# %XDL%
# %DT% 2)
# You must define a counter with "MAC_CNT" as "Device".
# %DL%
# %DT% -
# The "Unit" field must be set to the SCALER entry.
# %DT% -
# The "Chan" field must be set to the DRIVER address (ex: 5 for
# the 5th DRIVER of crate 0 or ex: 23 for the 3rd DRIVER of crate 2)
# %DT% -
# An extra parameter called "cmd" must be set to the command
# to be used to get the DRIVER internal parameter (ex: "meas vm"
# "meas i" etc)
# %XDL%
# %XDL%
#
#
#%DT%Extra motor_par() parameters %DD%
# %DL%
# %DT% motor_par(motor,"power")%DD%
# Return "1" if the power is enabled on the speficied motor
# %DT% motor_par(motor,"power",1)%DD%
# Try to enable the the power the speficied motor and return the result
# %DT% motor_par(motor,"jog_speed")%DD%
# Returns the current speed if the motor is in never ending motion
# or returns "0" if it's stop or in normal operation mode.
# %DT% motor_par(motor,"jog_speed",speed)%DD%
# Sets the speed for the never ending motion. If the motor is
# already moving in this mode, its speed will be changed on the fly.
# If the new speed has not the same sign that the current one, the
# motor will first deccelerate until stopping and then starts rotating
# in the other direction with the new speed.
# %DT% motor_par(motor,"jog_speed",0)%DD%
# Cancel a never ending motion.
# %DT% motor_par(motor,"closed_loop")%DD%
# Returns nonzero if the closed loop is active
# %DT% motor_par(motor,"closed_loop",1)%DD%
# Activate or desactivate the closed loop for the specified motor
# %DT% motor_par(motor,"home_active")%DD%
# Returns nonzero if logical home signal is active
# %DT% motor_par(motor,"high_lim_set")%DD%
# Returns nonzero if positive limitswitch is active
# %DT% motor_par(motor,"low_lim_set")%DD%
# Returns nonzero if negative limitswitch is active
# %DT% motor_par(motor,"keepusable",1)%DD%
# Keep the motor usable even if power could not be switched on during
# reconfig. Typically this parameter is set in config "additional
# optional parameters" screen for a motor. Hint: type "p" to get in
# %XDL%
#
#%XDL%
#
#%END%
#
#
# ----------------------- MACRO MOTOR implementation -----------------------
#
constant ICEPAP_LOCKFILE "/users/blissadm/local/spec/userconf/icepap_lock"
constant ICEPAP_TIMEOUT 3
#%IU% [personal msg]
#%MDESC%
# Switch on or off the print of debug messages
#
def icepapdebug '{
global ICEPAP[]
if(ICEPAP["debug"]) {
rdef icepap__debug \'#\$#\'
print "ICEPAP debug mode is OFF"
ICEPAP["debug"]=0
} else {
rdef icepap__debug \'print "ICEPAP[\"dev\"]: "\'
print "ICEPAP debug mode is ON"
ICEPAP["debug"]=1
}
}'
#%IU%
#%MDESC%
# Reset socket communication and MASTER FIFOs
#
def icepap_fiforst(dev) '{
_icepap_wr(dev,"","_FIFORST")
}'
#%IU%
#%MDESC%
# Called on <Ctrl-C>
#
def icepap_cleanup(dev) '{
# give time to sockets
sleep(.02)
# very dangerous with multiple clients
# icepap_fiforst(dev)
sock_par(dev,"flush")
}'
#%IU%
#%MDESC%
# Needed to initialize debug print out macro the first time the
# file is loaded.
def icepapdebug_init '{
if(!(whatis("ICEPAP") & 0x05000000)) {
global ICEPAP[]
ICEPAP["debug"]=1
icepapdebug
}
}'
icepapdebug_init
#%IU%(string, case)
#%MDESC%
# Convert to lower (case==1) or to upper (case==0) case the string passed
#
def icepap__tocase(str, case) '{
string array str_a[length(str)]
local l
str_a = str
l = length(str)-1
for(;l>=0;l--) {
if(case)
str_a[l]=str_a[l]+(str_a[l]>=asc("A") && str_a[l]<=asc("Z"))*0x20;
else
str_a[l]=str_a[l]-(str_a[l]>=asc("a") && str_a[l]<=asc("z"))*0x20;
}
return(sprintf("%s", str_a))
}'
#%IU%(string)
#%MDESC%
# Return the lower string of the string passed
#
def icepap__tolower(str) '{return((str!="")?icepap__tocase(str, 1):"")}'
#%IU%(string)
#%MDESC%
# Return the upper string of the string passed
#
def icepap__toupper(str) '{return((str!="")?icepap__tocase(str, 0):"")}'
#%IU%(string)
#%MDESC%
#
def icepap_trim(str) '{
string array str_a[length(str)]
local b l
str_a = str
l = length(str)-1
for(;(l>=0)&&(str_a[l]==0x20);l--);
for(b=0;(b<l)&&(str_a[b]==0x20);b++);
return(substr(str,b+1,(l-b)+1))
}'
#%IU%(x)
#%MDESC%
# Return a well rounded integer as opposed to int() which always
# round down
#
def icepap_round(x) '{ if (x>=0) return int(x+0.5); else return int(x-0.5) }'
#%IU%(ans)
#%MDESC%
# Check if the answer given contains an ERROR and if yes
# request the error message
#
def icepap_chkerr(dev,ans) '{
if(index(ans,"ERROR") == 1) {
ans= _icepap_wrrd(dev,0,"?ERR 1")
print ans;
}
}'
#
# ----------------------- IcePAP library access ----------------------------
#
#%IU%()
#%MDESC%
# Check if the IcePAP library can be used through the dedicated TANGO DS.
# Returns non null if usable.
#
def _icepaplib_check() '{
global ICEPAP[]
local ds
# TODO: implement a custom TANGO DS name (cf new controler type?)
ds = sprintf("%s/testicepap/1", SPECBL)
# Check if the DS is out there
TANGO_ERR = "-1"
if(tango_io(ds, "State") == -1) {
printf("ICEPAP WARNING: missing DS \"%s\", using old fashion control\n",\
ds)
return 0
}
# This will force to use the TANGO DS and its library
ICEPAP["ds"] = ds
# Normal end
return 1
}'
#%IU%
#%MDESC%
# Macro to get access to the TANGO DS using the IcePAP library
#
def _icepaplib_access '
if(!(ds = ICEPAP["ds"])) { return -1}
'
#%IU%(group_name)
#%MDESC%
# Creates a group with the specified name.
# If the group already exists, it will be emptied
# WARNING: this implies that groups can not be shared accross different
# SPEC sessions.
#
def _icepaplib_create_group(name) '{
global ICEPAP[]
local ds
# Returns if library is not usable
_icepaplib_access
TANGO_ERR = "-1"
if(tango_io(ds, "CreateGroup", name) == -1) {
if(!index(TANGO_ERR_STACK[0]["desc"],"already defined group name")) {
p TANGO_ERR_STACK["0"]["desc"]
return -1
}
printf("ICEPAP WARNING: emptying existing group \"%s\"\n", name)
tango_io(ds, "EmptyGroup", name)
}
# Update group list
ICEPAP["ds"]["groups"] = sprintf("%s %s", ICEPAP["ds"]["groups"], name)
# Normal end
return 0
}'
#%IU%(mne, flags)
#%MDESC%
# Add a new axis to defaut group or to a given group if motor mne
# has a parameter "group" defined.
# Returns 0 if success otherwise -1
#
def _icepaplib_create_axis(mne, flags) '{
global ICEPAP[]
local ds
local i argin[]
local dev idx
local num grp
# Returns if library is not usable
_icepaplib_access
# Remove host port if any
dev = ICEPAP[mne]["dev"]
if(idx=index(dev,":")) { dev=substr(dev, 0 , idx-1) }
# By default use the session name as group name
num = motor_num(mne)
if(!(grp = motor_par(num,"group"))) {
grp = SPEC
motor_par(num, "group", grp, "add")
}
if(!index(ICEPAP["ds"]["groups"], grp)) {
_icepaplib_create_group(grp)
}
# An axis is identified by: name, group name, hostname, address, flags
argin[i++] = mne
argin[i++] = grp
argin[i++] = dev
argin[i++] = ICEPAP[mne]["addr"]
# The flags are optional
if(flags) { argin[i++] = flags }
# Append the axis
ds = ICEPAP["ds"]
if(tango_io(ds, "AddAxis", argin) == -1) {
p TANGO_ERR_STACK["0"]["desc"]
return -1
}
# Normal end
return 0
}'
#%IU%()
#%MDESC%
#
def _icepaplib_prestart_all() '{
global ICEPAP[]
local ds
local n grps[]
# Returns if library is not usable
_icepaplib_access
ICEPAP["ds"]["tomove"]=""
ICEPAP["ds"]["tostat"]=""
n = split(ICEPAP["ds"]["groups"],grps)
for(;n;n--) {
ICEPAP["ds"][grps[n-1]] = ""
}
# Normal end
return 0
}'
#%IU%(mne, pos_in_steps)
#%MDESC%
#
def _icepaplib_start_one(mne, pos) '{
global ICEPAP[]
local ds
local num grp
# Returns if library is not usable
_icepaplib_access
# Retrieve the group owning this motor
num = motor_num(mne)
grp = motor_par(num, "group")
ICEPAP["ds"][grp] = sprintf("%s %s %d", ICEPAP["ds"][grp], mne, pos)
# Normal end
return 0
}'
#%IU%()
#%MDESC%
#
def _icepaplib_start_all() '{
global ICEPAP[]
local ds
local n grps[]
local i argin[]
# Returns if library is not usable
_icepaplib_access
# Each array element is "group mne pos mne pos..."
# One array element per group to move
n = split(ICEPAP["ds"]["groups"],grps)
for(;n;n--) {
tomove = icepap_trim(ICEPAP["ds"][grps[n-1]])
if(length(tomove)) {
argin[i++] = sprintf("%s:%s",grps[n-1], tomove)
}
}
if(tango_io(ds, "MoveGroup", argin) == -1) {
p TANGO_ERR_STACK["0"]["desc"]
return -1
}
# Normal end
return 0
}'
#%IU%(mne)
#%MDESC%
# Returns the move and limit status of a single motor (bit mask) or
# the string ".error.". If the library can not be used, returns -1
#
def _icepaplib_get_status(mne) '{
global ICEPAP[]
local ds
local num grp
local i argin[] argout[]
local sta
# Returns if library is not usable
_icepaplib_access
# Retrieve the group owning this motor
num = motor_num(mne)
grp = motor_par(num, "group")
# Get the status of a unique motor
argin[i++] = sprintf("%s:%s", grp, mne)
if(tango_io(ds, "IsMovingGroup", argin, argout) == -1) {
p TANGO_ERR_STACK["0"]["desc"]
return ".error."
}
# Get a numerical status as hexa bitmask
sta = 0
if(sscanf(argout[0],"%s %s %x", grp, mne, sta) != 3) {
p "ICEPAP ERROR: unable to parse group status"
return ".error."
}
# The TANGO DS bitmaks is identical to SPEC one (strange ;-)
return sta
}'
#%IU%(mne)
#%MDESC%
# Returns the position single motor or
# the string ".error.". If the library can not be used, returns ".error."
#
def _icepaplib_get_position(mne) '{
global ICEPAP[]
local ds
local num grp
local i argin[] argout[]
local pos
# Returns if library is not usable
if(!(ds = ICEPAP["ds"])) { return ".error."}
# Retrieve the group owning this motor
num = motor_num(mne)
grp = motor_par(num, "group")
# Get the status of a unique motor
argin[i++] = sprintf("%s:%s", grp, mne)
if(tango_io(ds, "PositionGroup", argin, argout) == -1) {
p TANGO_ERR_STACK["0"]["desc"]
return ".error."
}
# Get the position in steps
pos = 0
if(sscanf(argout[0],"%s %s %d", grp, mne, pos) != 3) {
p "ICEPAP ERROR: unable to parse group position"
return ".error."
}
# Returns the position in steps
return pos
}'
#%IU%(mne)
#%MDESC%
# Stops a single motor or
# the string ".error.". If the library can not be used, returns -1
#
def _icepaplib_stop(mne) '{
global ICEPAP[]
local ds
local num grp
local i argin[]
# Returns if library is not usable
_icepaplib_access
# Retrieve the group owning this motor
num = motor_num(mne)
grp = motor_par(num, "group")
# Get the status of a unique motor
argin[i++] = sprintf("%s:%s", grp, mne)
if(tango_io(ds, "StopGroup", argin) == -1) {
p TANGO_ERR_STACK["0"]["desc"]
return ".error."
}
# Normal end
return 0
}'
#%IU%(mne, power)
#%MDESC%
# Change the power of the specified axis. The argument can be "ON" or "OFF".
# Returns 0 if success otherwise -1
#
def _icepaplib_power_axis(mne, power) '{
global ICEPAP[]
local ds
local num grp
local i argin[] argout[]
# Returns if library is not usable
_icepaplib_access
# Retrieve the group owning this motor
num = motor_num(mne)
grp = motor_par(num, "group")
# Let the DS to the check on action string
power = icepap__toupper(power)
# Actuate on a unique motor
argin[i++] = sprintf("%s %s:%s", grp, power, mne)
if(tango_io(ds, "PowerGroup", argin, argout) == -1) {
p TANGO_ERR_STACK["0"]["desc"]
return -1
}
# Check that things went well
if(!index(argout[0], "ON")) {
local dev addr
#TODO: implement diagnostic through library
dev=motor_par(num,"address")
addr=ICEPAP[mne]["addr"]
_icepap_err
printf("unusable motor: \"%s\"\n",mne)
_icepap_print_info(dev,addr,mne)
motor_par(num,"disable",1)
return -1
}
# Normal end
return 0
}'
#
# ----------------------- MACRO MOTOR implementation -----------------------
#
#%IU%
#%MDESC%
# MACRO MOTOR:
# Called by spec after reading the config file
#
def icepap_config(num,type,p1,p2,p3) '{
global ICEPAP[]
global ICEPAP_CAT[]
local dev
local i j
local ans
local hrev lrev
local n tt[]
local m aa[]
local mne
local silent
# p1==controller index p2==number of motors supported
if(type=="ctrl") {
silent = 1
icepap__debug "config(): new controller"
if (p1 == 0) { for(i in ICEPAP) { delete ICEPAP[i] } }
ICEPAP["on"] = 0
ICEPAP["dev"]=""
# Check if a TANGO DS is out there
if (p1 == 0) {
if(_icepaplib_check()) {
# Create a group per spec session.
_icepaplib_create_group(SPEC)
}
}
# get the MASTER
dev=icepap_ADDR
if(dev=="") {
_icepap_err
printf("missing ADDR field\n")
return
}
if(index(dev,":") == 0) { dev=sprintf("%s:5000",dev) }
ICEPAP["dev"][p1]=dev
ICEPAP["dev"]=dev
ICEPAP["on"] = 1
# if the MASTER is switched off, disable all the associated motors
ans=_icepap_query(dev,0,"?ID", silent)
if(ans == "") { return ".error." }
# get the system version
hrev = 0
lrev = 0
ICEPAP[dev]["hrev"]=0
ICEPAP[dev]["lrev"]=0
ans=_icepap_query(dev,"","?VER")
if(sscanf(ans,"%d.%d",hrev,lrev) == 2) {
ICEPAP[dev]["hrev"]=hrev
ICEPAP[dev]["lrev"]=lrev
}
# try to guess if the firmware supports group motions
ICEPAP[dev]["groups"]=(((hrev>=1)&&(lrev >= 22)) || (hrev>=2))?"YES":"NO"
# try to guess if the firmware supports linked axis
ans=_icepap_query(dev,"","?LINKED",silent)
n =split(ans,tt,"\r\n")
ICEPAP[dev]["linked"]=(!index(ans,"ERROR"))?"YES":"NO"
# get linked axis configured if any (expecting a multi-line answer)
if((ICEPAP[dev]["linked"] == "YES") && (n>=3)) {
ICEPAP[dev]["linked_list"]=""
for(i=0;i<n;i++) {
if(tt[i] == "$") {
continue
}
m = split(tt[i],aa)
mne = (m>0)?aa[0]:"???"
if(m<1) {
_icepap_err
printf("bad configured linked axis \"%s\" on \"%s\"\n", \
mne,dev)
continue
}
ICEPAP[dev]["linked_list"]=ICEPAP[dev]["linked_list"] mne " "
for(j=1;j<m;j++) {
ICEPAP[mne]["linked_addr"]=ICEPAP[mne]["linked_addr"] aa[j] " "
}
ICEPAP[mne]["linked_addr"]=icepap_trim(ICEPAP[mne]["linked_addr"])
ICEPAP[mne]["linked"] ="YES"
}
ICEPAP[dev]["linked_list"]=icepap_trim(ICEPAP[dev]["linked_list"])
}
}
# p1==unit p2==module p3==channel
if(type=="mot") {
local mne
local dev
local addr
local i
local ret
local addr
local silent
# If the controller was not well configured then give up
if(ICEPAP["on"] != 1) { return }
# get the motor mnemonic string
mne=motor_mne(num)
# get the MASTER
ICEPAP[mne]["dev"]=""
dev=motor_par(num,"address")
if(dev==0) { return }
if(index(dev,":") == 0) { dev=sprintf("%s:5000",dev) }
ICEPAP[mne]["dev"]=dev
# initialize global settings
ICEPAP[mne]["addr"]=p2*10+p3
addr=ICEPAP[mne]["addr"]
ICEPAP[mne]["jog_velocity"]=0
ICEPAP[mne]["stop_code"]=0
# for a linked axis the mnemonic is used as identification for the DSP
if(addr==0){
ICEPAP[mne]["addr"]=mne
}
# create a new library access and add it to a group
if(!_icepaplib_create_axis(mne, flags)) {
# try to switch on power on motors
_icepaplib_power_axis(mne, "ON")
# if the library is usable, nothing else to do
return
}
# check if it is linked axis (address==0)
if(addr==0) {
if(ICEPAP[mne]["linked"] != "YES") {
_icepap_err
printf("unusable motor: \"%s\"\n",mne)
printf("Hint: change address in config or configure linked axe\n")
motor_par(num,"disable",1)
return ".error."
}
# switch on, at once, the power on all concerned motors
ans=_icepap_query(dev,"#",sprintf("POWER ON %s", mne))
if(index(ans,"ERROR"))
{
_icepap_err
printf("unusable motor: \"%s\"\n",mne)
_icepap_print_info(dev,addr,mne)
motor_par(num,"disable",1)
return ".error."
}
# the afterward commands are not implemented in DSP for linked axis:
# ?ACTIVE
# ?CFG ACTIVE
# ?PCLOOP
return
}
# check if the DRIVER is configured and active
ans=_icepap_query(dev,addr,"?ACTIVE")
if(ans != "NO") {
if (ans != "YES")
{
_icepap_err
printf("unusable motor: \"%s\"\n",mne)
motor_par(num,"disable",1)
return ".error."
}
}
else
{
ans=_icepap_query(dev,addr,"?CFG ACTIVE")
if(ans != "ACTIVE YES") {
_icepap_err
printf("not configured active driver for motor: \"%s\"\n",mne)
printf("Hint: use \"icepapcms\" to activate this driver\n")
} else {
_icepap_err
printf("not active driver for motor: \"%s\"\n",mne)
printf("Hint: probably a hardware problem, crate off/on may help\n")
}
motor_par(num,"disable",1)
return ".error."
}
# check if the DSP will handle a closed loop
ICEPAP[mne]["pcloop"]="OFF"
ans=_icepap_query(dev,addr,"?PCLOOP")
if(index(ans,"ON")) { ICEPAP[mne]["pcloop"]="ON" }
# check if the DC dead band and settling time are well set in the config
if(ICEPAP[mne]["pcloop"]=="ON")
{
if(motor_par(num,"dc_settle_time") != 0)
{
printf("ICEPAP WARNING: settling handled by IcePAP for motor: \"%s\"\n",mne)
printf("ICEPAP WARNING: the \"DC settle time\" should be set to 0\n")
}
if(motor_par(num,"dc_dead_band") != 1)
{
printf("ICEPAP WARNING: settling handled by IcePAP for motor: \"%s\"\n",mne)
printf("ICEPAP WARNING: the \"DC dead band\" should be set to 1\n")
}
}
# switch on the power on the motor, chaud devant
silent = 1
ans=_icepap_query(dev,"#" addr,"POWER ON", silent)
if(index(ans,"ERROR") && motor_par(mne, "keepusable") != 1)
{
_icepap_err
printf("unusable motor: \"%s\"\n",mne)
_icepap_print_info(dev,addr,mne)
motor_par(num,"disable",1)
return ".error."
}
}
}'
#%IU%
#%MDESC%
# MACRO MOTOR:
# Called by spec after reading the config file, after calling _config()
# and only if parameters are set in the config file for a motor.
#
def icepap_par(num,key,todo,p1) '{
global ICEPAP[]
local mne
local ans
local sta
local dev
# get the motor mnemonic string
mne=motor_mne(num)
# get the MASTER
if(!("dev" in ICEPAP[mne])) { return }
dev=ICEPAP[mne]["dev"]
if(dev=="") { return }
# get the address
if(!("addr" in ICEPAP[mne])) return;
addr=ICEPAP[mne]["addr"]
# return new motor_par() argins handled
if (key == "?" && todo == "get") {
return("power, jog_speed, closed_loop")
}
#
#
#
if (key == "power") {
# Change the power on the motor, chaud devant
if(todo == "set") {
if(ICEPAP[mne]["linked"] == "YES") {
ans=_icepap_query(dev,"#",sprintf("POWER %s %s",(p1==1?"ON":"OFF"),addr))
} else {
ans=_icepap_query(dev,"#" addr,sprintf("POWER %s",(p1==1?"ON":"OFF")))
}
if(index(ans,"ERROR"))
{
_icepap_print_info(dev,addr,mne)
_icepap_err
printf("unable to power motor: \"%s\"\n",mne)
return
}
}
# Return the current state in any case
if(ICEPAP[mne]["linked"] == "YES") {
ans=_icepap_query(dev,"",sprintf("?POWER %s",addr))
} else {
ans=_icepap_query(dev,addr,"?POWER")
}
return(index(ans,"ON")?1:0)
}
#
#
#
if (key == "jog_speed") {
if(ICEPAP[mne]["linked"] == "YES") {
_icepap_err
printf("JOG motion no implemented for linked axis\n")
return
}
# Change or start a JOG motion
if(todo == "set")
{
local vel
local acc
local cmd
# Just in case the motor had never been moved previously
acc = motor_par(num,"acceleration")
icepap_cmd(num,"acceleration",acc)
# If the rotation sense changes, we have to stop first the motor
# NOTE MP 15Jul13: with firmware >=2.0 this is no more needed
if(((ICEPAP[mne]["jog_velocity"] * p1) <0) && (ICEPAP[dev]["hrev"]<2))
{
# Stop the motion
ans=_icepap_query(dev,"#" addr,"STOP")
if(index(ans,"ERROR"))
{
_icepap_err
printf("unable to stop JOG on motor: \"%s\"\n",mne)
return
}
# Wait for the end of the motion
while(icepap_cmd(num,"get_status") == 0x02) sleep(.01);
# Give some time to DRIVER to refresh its status
sleep(0.1)
}
# Treat the special case of null velocity
# NOTE MP 15Jul13: with firmware >=2.0 a "JOG 0" will block the motor
# in a never ending loop because the status shows an ongoing motion at
# null velocity.
if(p1 == 0) {
cmd = "STOP"
} else {
cmd = sprintf("JOG %d",p1)
}
# Set the new velocity
ICEPAP[mne]["jog_velocity"]=p1
ans=_icepap_query(dev,"#" addr, cmd)
if(index(ans,"ERROR"))
{
_icepap_err
printf("unable to launch JOG on motor: \"%s\"\n",mne)
return
}
}
# Avoid position discrepancy on motion stopped
if((todo == "set") && (p1 == 0))
{
# NOTE MP 21Jun10: wait for the end of motion before reading position
# can not call wait(0x21) because Spec does not know that we are moving
while(icepap_cmd(num,"get_status") == 0x02) sleep(.01);
# NOTE MP 26Oct09: on users request, clear the position to avoid
# huge position values
icepap_cmd(num,"set_position",0)
# NOTE MP 21Jun10: give time to DSP to update DPM, seen with firmware 1.21
sleep(.1)
# NOTE: from "help motors": position discrepancies between spec and the
# motor hardware will be silently resolved in favor of the hardware
read_motors(0x06)
}
# Return the current jog velocity in any case
# NOTE MP 15Oct09: ?V returns the current instantaneous speed which therefore
# can not be the target one if the motor is still accelerating.
# To avoid confusing the user, we return the target one
if(todo == "set")
return(ICEPAP[mne]["jog_velocity"])
# Return the current instantaneous velocity
ans=_icepap_query(dev,addr,"?JOG")
if(index(ans,"ERROR"))
{
_icepap_err
printf("unable to get speed for motor: \"%s\"\n",mne)
return
}
if(sscanf(ans,"%d",vel) != 1)
{
_icepap_err
printf("unable to read speed for motor: \"%s\"\n",mne)
return
}
# NOTE MP 15Oct09: ?JOG returns positive only values, little work-arround
if(ICEPAP[dev]["hrev"]<2) {
if(ICEPAP[mne]["jog_velocity"]<0)
vel *= -1
}
return(vel)
}
#
#
#
if (key == "closed_loop") {
if(todo == "set") {
ans=_icepap_query(dev,"#" addr,sprintf("PCLOOP %s",(p1==1?"ON":"OFF")))
if(index(ans,"ERROR"))
{
_icepap_err
printf("unable to activate closed loop for: \"%s\"\n",mne)
return
}
}
# Return the current state of closed loop
ans=_icepap_query(dev,addr,"?PCLOOP")
return(index(ans,"ON")?1:0)
}
#
#
#
if (key == "home_active") {
sta = 0
ans=_icepap_query(dev,"",sprintf("?FSTATUS %s",addr))
if(sscanf(ans,"%x", sta) != 1)
{
_icepap_err
printf("unable to get status for: \"%s\"\n",mne)
return ".error."
}
# get home signal status
return((sta & (1<<20))!=0)
}
#
#
#
if (key == "high_lim_set") {
sta = 0
ans=_icepap_query(dev,"",sprintf("?FSTATUS %s",addr))
if(sscanf(ans,"%x", sta) != 1)
{
_icepap_err
printf("unable to get status for: \"%s\"\n",mne)
return ".error."
}
# get limitswtich status
return(sta & (1<<18))
}
#
#
#
if (key == "low_lim_set") {
sta = 0
ans=_icepap_query(dev,"",sprintf("?FSTATUS %s",addr))
if(sscanf(ans,"%x", sta) != 1)
{
_icepap_err
printf("unable to get status for: \"%s\"\n",mne)
return ".error."
}
# get limitswtich status
return(sta & (1<<19))
}
}'
#%IU%
#%MDESC%
# MACRO MOTOR:
#
def _icepap_prestart_all(dev) '{
global ICEPAP
if(ICEPAP[dev]["groups"] != "YES") { return }
ICEPAP[dev]["tomove"]=""
ICEPAP[dev]["tostat"]=""
}'
#%IU%
#%MDESC%
# MACRO MOTOR:
#
def _icepap_start_all(dev) '{
global ICEPAP
local aux[]
if(ICEPAP[dev]["groups"] != "YES") { return }
# NOTE MP 24Jul12: the start_all should not be call if nothing to move
# but SPEC version 5.10.02-16 do this
if(ICEPAP[dev]["tomove"] == "") { return }
# NOTE MP 01Feb11: avoid group motion for single axis motion
cmd=sprintf("MOVE %s %s",\
(split(ICEPAP[dev]["tostat"],aux)>1)?"GROUP":"",\
ICEPAP[dev]["tomove"])
answ = _icepap_query(dev,"#",cmd)
if (answ != "OK")
{
_icepap_err
printf("unable to start grouped motion\n")
return ".error."
}
}'
#%IU%
#%MDESC%
# MACRO MOTOR:
#
def _icepap_start_one(dev, addr, pos) '{
global ICEPAP
if(ICEPAP[dev]["groups"] != "YES")
{
local cmd
# NOTE MP 31Jan11: even if multi-axes motion exists before group motion
# their behavior as drastically changed with group implementation
# therefore it is better to not use them
cmd=sprintf("MOVE %d",pos)
addr = "#" addr
answ = _icepap_query(dev,addr,cmd)
if (answ != "OK")
{
_icepap_err
printf("unable to start motion for: \"%s\"\n",mne)
return ".error."
}
return
}
ICEPAP[dev]["tomove"] = sprintf("%s %s %d",ICEPAP[dev]["tomove"],addr,pos)
ICEPAP[dev]["tostat"] = sprintf("%s %s", ICEPAP[dev]["tostat"],addr)
}'
#%IU%
#%MDESC%
# MACRO MOTOR:
# Called by spec on motor operation.
#
def icepap_cmd(num,key,p1,p2) '{
local dev
local mne
local addr
#
# Handle actions at controller level
#
if(num == "..") {
dev = icepap_ADDR
if(index(dev,":") == 0) { dev=sprintf("%s:5000",dev) }
if ( key == "prestart_all" ) {
if(!_icepaplib_prestart_all(dev)) { return }
return(_icepap_prestart_all(dev))
}
if ( key == "start_all" ) {
if(!_icepaplib_start_all(dev)) { return }
return(_icepap_start_all(dev))
}
return
}
# If the controller was not well configured then give up
if(ICEPAP["on"] != 1) { return }
# get the motor mnemonic string
mne=motor_mne(num)
# get the MASTER
if(!("dev" in ICEPAP[mne])) { return }
dev=ICEPAP[mne]["dev"]
if(dev=="") { return }
# NOTE MP 2Aug05: when starting from fresh, SPEC calls
# icepap_cmd("position") before calling icepap_config() and
# therefore nothing is usable at that moment
if(!("addr" in ICEPAP[mne])) return;
addr=ICEPAP[mne]["addr"]
#
# return the current motor position in mm or deg
#
if (key == "position") {
local pos
local pos_str
local ans
# Try to use the library
if((pos = _icepaplib_get_position(mne)) == ".error.") {
# Oherwise use the direct access
ans= _icepap_query(dev,"",sprintf("?FPOS %s",addr))
if(sscanf(ans,"%d",pos) != 1) {
_icepap_err
printf("unable to get position for: \"%s\"\n",mne)
return ".error."
}
}
pos_str = sprintf("%.15g", pos / motor_par(num,"step_size"))
icepap__debug sprintf("\"%s\": pos %s",mne,pos_str)
return(pos_str)
}
#
# start a motion (p1==abs pos, p2==rel pos, with pos in mm or deg)
#
if (key == "start_one") {
local pos
local cmd
local ans
# Convert position into steps
pos=icepap_round(p1*motor_par(num,"step_size"))
ICEPAP[mne]["target_steps"]=pos
# Erase stop code condition to treat it once
ICEPAP[mne]["stop_code"]=0
# Try to use the library
if(!_icepaplib_start_one(mne, pos)) { return }
# Otherwise use the direct access
# minimum check that motion is possible
sta = 0
ans=_icepap_query(dev,"",sprintf("?FSTATUS %s",addr))
if(sscanf(ans,"%x", sta) != 1)
{
_icepap_err
printf("unable to get status for: \"%s\"\n",mne)
return ".error."
}
# get ready status
if(!(sta & (1<<9)))
{
_icepap_err
printf("driver is not ready for: \"%s\"\n",mne)
# temporary: for debug purpose only
_icepap_print_info(dev,addr,mne)
return ".error."
}
return(_icepap_start_one(dev,addr,pos))
}
#
# Check if the driver is powered and ready to use
#
if (key == "prestart_one") {
local ret
local ans
local i
return(0)
}
#
# return the current motor status
#
if (key == "get_status") {
local ret
local ans
local cms
local sta sta_neg sta_pos
# Try to use the library
if((ret = _icepaplib_get_status(mne)) != -1) { return(ret)}
# Oherwise use the direct access
ret = 0
sta = 0
ans=_icepap_query(dev,"",sprintf("?FSTATUS %s",addr))
if(sscanf(ans,"%x", sta) != 1)
{
_icepap_err
printf("unable to get status for: \"%s\"\n",mne)
return ".error."
}
# get moving status
#
# NOTE MP 07Jun10: check MOVING and SETTLING status bits
# -the MOVING (10) goes down at the end of the trajectory
# -the SETTLING (11) goes down at the end of close loop algorythm
#
# NOTE MP 21Jun10: during a HOMING sequence, several motions take place,
# therefore the MOVING/SETTLING pair can be unset. But the READY remains
# unset during all the HOMING sequence. To distinguish a non READY axis
# due to error condition from moving condition, the POWER bit
# must also be checked
# -the READY (09) goes down on error or moving
# -the POWERON (23) goes down on error
#
if((sta & (1<<10)) || (sta & (1<<11))) ret |= 0x02;
else if(!(sta & (1<<9)) && (sta & (1<<23))) ret |= 0x02;
# get limitswitches status
if(sta & (1<<19)) ret |= 0x04;
if(sta & (1<<18)) ret |= 0x08;
# check stop code if not moving, of course
#
if(!(ret & 0x02)) {
_icepap_stopcode(num, sta)
}
return(ret)
}
#
# verify if settling is OK
#
if (key =="diff_position") {
# the settling is handled by the DSP
if(ICEPAP[mne]["pcloop"]=="ON")
{
local ans
ans=_icepap_query(dev,"",sprintf("?FSTATUS %s",addr))
if(sscanf(ans,"%x", sta) !=1) {
_icepap_err
printf("unable to get status for: \"%s\"\n",mne)
return 0
}
# by default the motion is finished
ret=0
# get settling bit
if(sta & (1<<11)) { ret=motor_par(num,"dc_dead_band") }
return ret
}
# the settling is handled by SPEC
if(ICEPAP[mne]["pcloop"]=="OFF")
{
local pos
local ans
local poubelle
ans= _icepap_query(dev,"",sprintf("?FPOS %s",addr))
if(sscanf(ans,"%f%s",pos,poubelle) != 1) {
_icepap_err
printf("unable to get position for: \"%s\"\n",mne)
return ".error."
}
# must return the position delta in steps
return (pos-ICEPAP[mne]["target_steps"])
}
}
#
# stop a single motor
#
if (key == "abort_one") {
local answ
# Try to use the library
if(_icepaplib_stop(mne) != -1) { return }
# Oherwise use the direct access
cmd=sprintf("STOP %s",addr)
answ = _icepap_query(dev,"#",cmd)
if (answ == "OK")
return;
else
_icepap_wr(dev,"","STOP");
return
}
#
# set position (p1=mm)
#
if (key == "set_position") {
local fpos tbeg
ans = _icepap_query(dev,"#",\
sprintf("POS %s %d", addr, icepap_round(p1*motor_par(num,"step_size"))))
if(index(ans,"ERROR"))
{
_icepap_err
printf("unable set position for: \"%s\"\n",mne)
return ".error."
}
# give time to the DPM update from concerned DRIVER
# sleep(.1)
tbeg = time()
while(((time()-tbeg) < .3)) {
sscanf(icepap_cmd(num,"position"),"%.15g",fpos)
if(fabs(fpos-p1) < 1e-3) { break }
}
return
}
#
# set acceleration (p1=ms p2=steps/sec^2)
#
if (key == "acceleration") {
ans = _icepap_query(dev,"#",sprintf("ACCTIME %s %f",addr,p1/1000))
if(index(ans,"ERROR"))
{
_icepap_err
printf("unable set acceleration for: \"%s\"\n",mne)
return ".error."
}
}
#
# set base_rate (p1=rate in Hz)
#
if (key == "base_rate") {
return
}
#
# set slew_rate (p1=rate in Hz)
#
if (key == "slew_rate") {
ans = _icepap_query(dev,"#",sprintf("VELOCITY %s %d",addr,p1))
if(index(ans,"ERROR"))
{
_icepap_err
printf("unable set velocity for: \"%s\"\n",mne)
return ".error."
}
}
#
# initiate a home or limit search (p1=string with what to search)
#
if (key == "search") {
local lim
local cmd
if(ICEPAP[mne]["linked"]=="YES") {
_icepap_err
printf("limit search not implemented for linked axis\n")
return ".error."
}
if(p1=="lim+") { cmd = "SRCH" ; lim="LIM+" }
else if(p1=="lim-") { cmd = "SRCH" ; lim="LIM-" }
else if(p1=="lim+edge") { cmd = "SRCH" ; lim="LIM+" }
else if(p1=="lim-edge") { cmd = "SRCH" ; lim="LIM-" }
else if(p1=="home+") { cmd = "HOME" ; lim="+1" }
else if(p1=="home-") { cmd = "HOME" ; lim="-1" }
else
{
_icepap_err
printf("un-supported home or limit search\n")
return ".error."
}
# If already at limit, do nothing
#
# NOTE MP 10Nov08: the default behavior of "LIM+" command is to look for
# a transition of positive limitswitch (i.e. the DRIVER will automatically
# change the motor motion sense if the limitswitch is already active)
# This behavior can be used using "lim+edge" argin.
#
if(p1=="lim+") { if(icepap_cmd(num,"get_status") == 0x08) { return } }
if(p1=="lim-") { if(icepap_cmd(num,"get_status") == 0x04) { return } }
# NOTE MP 10Nov08: the local variables are erased by the recursive call
# to icepap_cmd("get_status"). Bug fixed in release 5.08.03-3
mne = motor_mne(num)
dev = ICEPAP[mne]["dev"]
addr= ICEPAP[mne]["addr"]
addr = "#" addr
ans = _icepap_query(dev,addr,sprintf("%s %s",cmd,lim))
if(index(ans,"ERROR"))
{
_icepap_err
printf("unable to start limit search\n")
return ".error."
}
# NOTE MP 07Jun10: do a polling on ?SRCHSTAT ?HOMESTAT to have
# the found/notfound information from the DSP directly and to be
# able to do some usage of the SRCHPOS and HOMEPOS
#
# from here, spec will do the polling on status until the
# end of the motion.
return
}
}'
#%IU%(dev,addr,mne)
#%MDESC%
#
def _icepap_print_info(dev,addr,mne) '{
local n tt[]
# check if linked axe or linked one
if(ICEPAP[mne]["linked"] == "YES") {
n=split(ICEPAP[mne]["linked_addr"],tt)
for(;n;n--) {
_icepap_print_info_driver(dev,tt[n-1],mne)
}
} else {
_icepap_print_info_driver(dev,addr,mne)
}
}'
#%IU%(dev,addr)
#%MDESC%
# TODO: unify with icepap_info macro
#
def _icepap_print_info_driver(dev,addr,mne) '{
local num
local tab
tab="\t|"
print "\t---------------------------------------------------------"
num = motor_num(mne)
print tab"MOTOR : ",mne
print tab"SYSTEM : ",motor_par(num,"address")
print tab"DRIVER : ",sprintf("%02d",addr)
print tab"WARNING: ",_icepap_query(dev,addr,"?warning")
print tab"ALARM : ",_icepap_query(dev,addr,"?alarm")
print tab"PWRINFO: "
_icepap_print_tabbed(tab,_icepap_query(dev,addr,"?isg ?pwrinfo"))
print "\t---------------------------------------------------------"
}'
def _icepap_print_tabbed(tab,str) '{
local lines[]
local i,n
n=split(str,lines,"\n")
for(i=0,ret="";i<n;i++) {
print tab,lines[i]
}
}'
#%UU% [hostname|motor]
#%MDESC%
# Print out information on the specified ICEPAP system or on an
# ICEPAP motor configured in the current SPEC session.
#
def icepap_info '{
local todo
local num
if($# == 0) {
p "Usage: $0 [hostname | motor]"
exit
}
# TODO MP : add multiple argins
todo = "$1"
if((num=motor_num(todo)) != -1) {
_icepap_print_info_mot(num)
} else {
_icepap_print_info_system(todo)
}
}'
#%IU%(motor)
#%MDESC%
#
def _icepap_print_info_mot(num) '{
local mne
local ad sw hn i
sw = 15
mne = motor_mne(num)
if(!("dev" in ICEPAP[mne])) {
p "ERROR: unknown motor"
return
}
printf("%*s : %s\n",sw,"motor name",mne)
hn = ICEPAP[mne]["dev"]
if(i=index(hn,":")) { hn = substr(hn,0,i-1) }
printf("%*s : %s\n",sw,"system",hn)
ad = ICEPAP[mne]["addr"]
printf("%*s : %s\n",sw,"address",ad)
printf("%*s : %s\n",sw,"power",motor_par(num,"power")?"ON":"OFF")
printf("%*s : %s\n",sw,"closed loop",motor_par(num,"closed_loop")?"ON":"OFF")
}'
#%IU%(hostname)
#%MDESC%
#
def _icepap_print_info_system(dev) '{
local sw ans silent
local i nm nums[] ns
silent = 1
ans =_icepap_query(dev,0,"?VER", silent)
if(ans == "") {
p "ERROR: unknown or unreachable system"
return
}
sw = 15
printf("%*s : %s\n",sw,"system",dev)
printf("%*s : %s\n",sw,"version",icepap_trim(ans))
# look for motor from this system configured in the current session
for(i=0,nm=0,ns="";i<MOTORS;i++) {
if(!index(motor_par(i,"address"),dev)) { continue }
nums[nm++] = i
ns = sprintf("%s%s ",ns,motor_mne(i))
}
printf("%*s : %s\n",sw,"motors used",nm?ns:"NONE")
}'
#%UU% [hostname|motor]
#%MDESC%
# Check the firmware version(s) of the specificied ICEPAP system or
# ICEPAP motor configured in the current SPEC session.
#
def icepap_firmware_check '{
local todo
local num
if($# == 0) {
p "Usage: $0 [hostname | motor]"
exit
}
todo = "$1"
if((num=motor_num(todo)) != -1) {
_icepap_fw_check_mot(num)
} else {
_icepap_fw_check_system(todo)
}
}'
#%IU%(motor)
#%MDESC%
#
def _icepap_fw_check_mot(num) '{
p "NOT IMPLEMENTED YET"
}'
#%IU%(hostname)
#%MDESC%
#
def _icepap_fw_check_system(dev) '{
local r_saved
local r_master
local r_drivers[]
local n_drivers
local r_failed_new[]
local r_failed_old[]
local s_failed_new
local s_failed_old
local n_failed
local ans
local addrs
local i n a
local cmp cmp_saved
local sw
#
# Collect information
#
printf("collecting data...\r");
# Get the system revisions
r_master = _icepap_fw_controller(dev)
r_saved = _icepap_fw_saved(dev)
# Get the list of modules
ans = _icepap_get_addrs(dev)
n = split(ans, addrs)
for(i=0,n_drivers=0;i<n;i++) {
a = addrs[i]
if(a==0) { continue }
r_drivers[a] = _icepap_fw_driver(dev,a)
n_drivers++
if(cmp = _icepap_fw_compare(r_master,r_drivers[a])) {
if(cmp == 2) {
r_failed_new[a] = cmp
s_failed_new = sprintf("%s %s",a,s_failed_new)
n_failed_new++
}
if(cmp == 1) {
r_failed_old[a] = cmp ;
s_failed_old = sprintf("%s %s",a,s_failed_old)
n_failed_old++
}
n_failed++
}
}
#
# Display results
#
sw = 21
cmp_saved = _icepap_fw_compare(r_master,r_saved)
printf("%*s : %s\n",sw,"system version",r_master)
printf("%*s : %s\n",sw,"check saved", !cmp_saved?"OK":"FAILED")
ans = sprintf("check %d drivers",n_drivers)
printf("%*s : %s\n",sw, ans, !n_failed?"OK":"FAILED")
if(n_failed) {
printf("%*s : %s\n",sw,"found mismatch on", \
sprintf("%d driver%s",n_failed,n_failed==1?"":"s"))
}
if(n_failed_old) {
#printf("%*s : ",sw, "too old drivers")
#for(a in r_failed_old) { printf("%s ", a) }
printf("%*s : %s",sw, "too old drivers", s_failed_old)
printf("\n")
}
if(n_failed_new) {
printf("%*s : ",sw, "too modern drivers")
for(a in r_failed_new) { printf("%s ", a) }
printf("\n")
}
#
# Actions to take
#
if(cmp_saved) {
p ""
p "WARNING: firmware saved not up to date, giving up"
p "HINT : use the command \"icepap_prog\" with flag \"SAVE\" "
exit
}
if((n_failed_new) && (n_failed_new > (n_drivers/2))) {
p ""
p "WARNING: there are too many drivers with too modern firmware,giving up"
p "HINT : use the command \"icepap_prog\" with flag \"ALL\" "
exit
}
if(n_failed_old) {
p ""
p "WARNING: there are drivers with too old firmware"
if(yesno("Do you agree to upgrade all of them",1)) {
# NOTE MP 26Feb13: according to ICEPAP User Manual, the PROG command
# accepts only on module address, therefore, we have to program
# one after the other
for(a in r_failed_old) {
printf("\n%*s : %s\n",sw, "upgrading driver",a)
_icepap_prog(dev,"",a,"FORCE")
}
}
}
if((n_failed_new) && (n_failed_new < (n_drivers/2))) {
p ""
p "WARNING: there are drivers with too modern firmware"
if(yesno("Do you agree to downgrade all of them",0)) {
# NOTE MP 26Feb13: according to ICEPAP User Manual, the PROG command
# accepts only on module address, therefore, we have to program
# one after the other
for(a in r_failed_new) {
printf("\n%*s : %s\n",sw, "downgrading driver",a)
_icepap_prog(dev,"",a,"FORCE")
}
}
}
}'
#%IU%(rev1, rev2)
#%MDESC%
# Compare deux revisions, given as strings, and returns:
# 0 if rev1 equal rev2
# 1 if rev1 > rev2
# 2 if rev1 < rev2
# -1 if invalid revision numbers
#
def _icepap_fw_compare(rev1, rev2) '{
local hrev1 lrev1
local hrev2 lrev2
local ret
if(sscanf(rev1,"%d.%d",hrev1,lrev1) != 2) { return(-1) }
if(sscanf(rev2,"%d.%d",hrev2,lrev2) != 2) { return(-1) }
if(hrev1>hrev2) { return(1) }
if(hrev1<hrev2) { return(2) }
if(lrev1>lrev2) { return(1) }
if(lrev1<lrev2) { return(2) }
return(0)
}'
#%IU%(hostname)
#%MDESC%
# Returns, for the specified system, the firmware version of the CONTROLLER
#
def _icepap_fw_controller(dev) '{
return(_icepap_fw_driver(dev,0))
}'
#%IU%(hostname, addr)
#%MDESC%
# Returns, for the specified system, the firmware version of the DRIVER
# specified by its address.
#
def _icepap_fw_driver(dev, addr) '{
local rev
local ans
# get the system version
rev="0.0"
ans=_icepap_query(dev,addr,"?VER")
if(index(ans,"ERROR")) { return(rev) }
rev=icepap_trim(ans)
return(rev)
}'
#%IU%(hostname)
#%MDESC%
# Returns, for the specified system, the firmware version saved in flash
#
def _icepap_fw_saved(dev) '{
local rev
local ans
local i n lines[] elts[]
# get the system version
rev="0.0"
ans=_icepap_query(dev,"","?VER SAVED")
if(index(ans,"ERROR")) { return(rev) }
n=split(ans,lines,"\n")
for(i=0;i<n;i++) {
if(!index(lines[i],"SYSTEM")) { continue }
split(lines[i],elts,":")
rev=icepap_trim(elts[1])
break
}
return(rev)
}'
#%UU% [hostname[:port]]
#%MDESC%
# Reset all the racks of the specified ICEPAP MASTER
#
def icepap_reset'{
global ICEPAP[]
local dev
if($# < 1) {
dev=getval("Icepap MASTER network name",ICEPAP["dev"])
} else {
dev="$1"
}
if(!index(dev,":")) { dev = dev":5000" }
ICEPAP["dev"]=dev
_icepap_wr(dev,"","RESET")
}'
#%IU% axis
#%MDESC%
# CONFIG LOCK:
# Add a lock on the specified axis (ex: 0/2)
#
def icepap_lock '{
local a
local u c
local line
if($# != 1) {
print "USAGE: $0 axis"
print " Ex: $0 0/2"
exit
}
a="$1"
_icepap_lock(a,1)
}'
#%IU% axis
#%MDESC%
# CONFIG LOCK:
# Remove a lock on the specified axis (ex: 0/2)
#
def icepap_unlock '{
local a
local u c
local line
if($# != 1) {
print "USAGE: $0 axis"
print " Ex: $0 0/2"
exit
}
a="$1"
_icepap_lock(a,0)
}'
#%IU%
#%MDESC%
# CONFIG LOCK:
# Check that lock file exist and create empty if not
#
def _icepap_islockfile() '{
if(file_info(ICEPAP_LOCKFILE, "-w") == 0){
printf("ICEPAP WARNING: touching \"%s\"\n",ICEPAP_LOCKFILE)
if(unix(sprintf("touch %s",ICEPAP_LOCKFILE)) != 0) {
_icepap_err
print "error creating file "ICEPAP_LOCKFILE
return -1
}
}
close(ICEPAP_LOCKFILE)
if(getline(ICEPAP_LOCKFILE, "open") < 0){
_icepap_err
printf("Can\'t open file \"%s\"\n", ICEPAP_LOCKFILE)
return -1
}
return 0
}'
#%IU%(axis,lock)
#%MDESC%
# CONFIG LOCK:
# Add or remove (lock=1 or 0) a lock on the specified axis (ex: 0/2)
#
def _icepap_lock(arg,lock) '{
local a
local u c
local line
local nline
local found
if(sscanf(arg,"%d/%d",u,c)!=2) {
_icepap_err
print "bad axis syntax (Ex: \"0/2\")"
return -1
}
a=sprintf("%d/%d\n",u,c)
if(_icepap_islockfile() != 0)
return -1;
line =""
nline=""
found=0
while ((line = getline(ICEPAP_LOCKFILE)) != -1)
{
if(lock)
{
if(line == a) {
print "AXIS already locked"
close(ICEPAP_LOCKFILE)
return -1
}
} else {
if(line == a) {
printf("ICEPAP : removing lock on axis %s\n",a)
found=1
} else {
nline=sprintf("%s%s",nline,line)
}
}
}
if(lock) {
printf("ICEPAP : adding lock on axis %s\n",a)
fprintf(ICEPAP_LOCKFILE,"%s",a)
close(ICEPAP_LOCKFILE)
return 0
}
if(found == 0) {
_icepap_err
print "axis was not locked"
close(ICEPAP_LOCKFILE)
return -1
}
unix(sprintf("\\rm -f %s",ICEPAP_LOCKFILE))
unix(sprintf("touch %s",ICEPAP_LOCKFILE))
open(ICEPAP_LOCKFILE)
fprintf(ICEPAP_LOCKFILE,"%s",nline)
close(ICEPAP_LOCKFILE)
return 0
}'
#%IU%(axis)
#%MDESC%
# CONFIG LOCK:
# Return 1 if a lock exist for the specified axis (ex: 0/2)
# Return 0 if there is no lock.
# Return -1 in case of error.
#
def _icepap_islock(arg) '{
local a
local u c
local line
local nline
local found
if(sscanf(arg,"%d/%d",u,c)!=2) {
_icepap_err
print "bad axis syntax (Ex: \"0/2\")"
return -1
}
a=sprintf("%d/%d\n",u,c)
if(_icepap_islockfile() != 0)
return -1;
line =""
found=0
while ((line = getline(ICEPAP_LOCKFILE)) != -1)
{
if(line == a) {
found=1
break
}
}
close(ICEPAP_LOCKFILE)
return(found)
}'
#
# ----------------------- MACRO COUNTER implementation -----------------------
#
#%IU%(hostname:port, address)
#%MDESC%
# MACRO COUNTER:
# Read the temperature on the specified address
# Returns 0 in case of error
#
def _icepapcnt_gettemp(dev,addr) '{
local ans
local t
ans= _icepap_query(dev,addr,"?MEAS T")
if(sscanf(ans,"%d",t) != 1) {
_icepap_err
printf("%s: addr: %s: unable to get temp\n",mne,addr)
icepap_chkerr(dev,ans)
icepap_fiforst(dev)
return(0)
}
return(t)
}'
#%IU%
#%MDESC%
# MACRO COUNTER:
# Called by spec after reading the config file
#
def icepapcnt_config(num,type,p1,p2,p3) '{
global ICEPAP_CNT[]
local mne
local dev
if(type=="ctrl") {
return
}
# p1 is the unit
# p2 is always 0
# p3 is the channel which is the two digits address
if(type=="cnt") {
mne=cnt_mne(num)
ICEPAP_CNT[mne]["addr"]=p3
# get the MASTER
ICEPAP_CNT[mne]["dev"]=""
dev=counter_par(num,"address")
if(dev==0) {
printf("ICEPAPCNT ERROR: missing ADDR field\n")
return
}
if(index(dev,":") == 0) { dev=sprintf("%s:5000",dev) }
ICEPAP_CNT[mne]["dev"]=dev
}
}'
#%IU%
#%MDESC%
# MACRO COUNTER:
# Called by spec on counter operation.
#
def icepapcnt_cmd(num,key,p1,p2) '{
global ICEPAP_CNT[]
local mne
local addr
local dev
if (key == "counts") {
mne=cnt_mne(num)
addr=ICEPAP_CNT[mne]["addr"]
# get the MASTER
if(!("dev" in ICEPAP_CNT[mne])) { return }
dev=ICEPAP_CNT[mne]["dev"]
if(dev=="") { return }
S[num]=_icepapcnt_gettemp(dev,addr)
}
}'
#
# ----------------------- MACRO COUNTER implementation -----------------------
#
#%IU%(<counter_number>, <hostname:port>, <address>)
#%MDESC%
# MACRO COUNTER: ENCODER
# Read the encoder position on the specified address
# Returns 0 in case of error
#
def _icepapenc_getpos(counter_num, dev, addr) '{
local ans
local t
local cmd
local typ
# "encoder" parameter is set to "inc" by default in config.
typ = counter_par(counter_num, "encoder")
cmd = ICEPAP_ENCCMD[typ]
ans = _icepap_query(dev,addr,sprintf("?ENC %s", cmd))
if(sscanf(ans, "%lf", t) != 1) {
_icepap_err
printf("counter \"%s\": addr: \"%s\": unable to get enc pos\n", \
cnt_mne(counter_num), addr)
icepap_chkerr(dev, ans)
icepap_fiforst(dev)
return(0)
}
# handle specific case of unsigned SSI encoders
if(typ == "absu") {
t += ((t<0)?(1<<counter_par(counter_num, "ssi")):0)
}
# normal end
return(t)
}'
#%UU% (<counter_mnemonic>)
#%MDESC%
# Returns value of encoder associated to macro-counter
# <encoder_mnemonic>.
# This function is similar to the previous one but provided to be
# user-callable by beeing more user-friendly.
def icepapenc_read(counter_mne) '{
local _dev _addr _res
if(!("dev" in ICEPAP_ENC[counter_mne])) {
printf("counter %s: unable to read encoder\n", counter_mne)
printf("--> check that your icepap macro counter is defined in SPEC config. \n")
return
}
else{
_dev = ICEPAP_ENC[counter_mne]["dev"]
_addr = ICEPAP_ENC[counter_mne]["addr"]
_res = _icepapenc_getpos(cnt_num(counter_mne), _dev, _addr)
return _res
}
}'
#%IU%(counter, hostname:port, address, pos)
#%MDESC%
# MACRO COUNTER: ENCODER
# Set the encoder position on the specified address
# Returns 0 in case of error
#
def _icepapenc_setpos(num,dev,addr,pos) '{
local ans
local t
local cmd
local typ
typ = counter_par(num,"encoder")
if(index(typ,"abs")) {
_icepap_err
p "no sense to set the position of an absolute encoder"
return
}
cmd = ICEPAP_ENCCMD[typ]
ans = _icepap_wrrd(dev,sprintf("#%s",addr),sprintf("ENC %s %d",cmd,pos))
if(index(ans,"ERROR"))
{
_icepap_err
print ""ans
return
}
}'
#%UU% counter position
#%MDESC%
# MACRO COUNTER: ENCODER
# Force the value of an ICEPAP encoder configured as a SPEC counter
#
def icepap_setenc '{
if($#!=2) {
p "Usage: $0 counter position"
exit
}
_icepap_setenc("$1",$2)
}'
#%IU%(counter_mne, position)
#%MDESC%
# MACRO COUNTER: ENCODER
# Force the value of an ICEPAP encoder configured as a SPEC counter
#
def _icepap_setenc(mne,pos) '{
local addr
local dev
local num
addr=ICEPAP_ENC[mne]["addr"]
dev =ICEPAP_ENC[mne]["dev"]
if(addr == 0) {
_icepap_err
p "\""mne"\" not an ICEPAP encoder counter"
return
}
num = cnt_num(mne)
pos = pos * counter_par(num,"scale")
_icepapenc_setpos(num,dev,addr,pos)
}'
#%IU%
#%MDESC%
# MACRO COUNTER: ENCODER
# Called by spec after reading the config file
#
def icepapenc_config(num,type,p1,p2,p3) '{
global ICEPAP_ENC[]
global ICEPAP_ENCCMD[]
local mne
local dev
if(type=="ctrl") {
ICEPAP_ENCCMD["inc"] = "ENCIN"
ICEPAP_ENCCMD["abs"] = "ABSENC"
ICEPAP_ENCCMD["absu"] = "ABSENC"
ICEPAP_ENCCMD["inpos"] = "INPOS"
ICEPAP_ENCCMD["motor"] = "MOTOR"
dev = icepapenc_ADDR
ans=_icepap_query(dev,0,"?ID", silent)
if(ans == "")
{ return ".error." }
return
}
# p1 is the unit
# p2 is always 0
# p3 is the channel which is the two digits address
if(type=="cnt") {
mne=cnt_mne(num)
ICEPAP_ENC[mne]["addr"]=p3
# get the MASTER
ICEPAP_ENC[mne]["dev"]=""
dev=counter_par(num,"address")
if(dev==0) {
printf("ICEPAPCNT ERROR: missing ADDR field\n")
return ".error."
}
if(index(dev,":") == 0) { dev=sprintf("%s:5000",dev) }
ICEPAP_ENC[mne]["dev"]=dev
# get the type of encoder to read
typ = counter_par(num,"encoder")
if((typ == -1) || (typ == 0)) {
counter_par(num,"encoder","inc","add")
typ = "inc"
}
# minium check
if((index(typ,"abs")!=1)&&(typ!="inc")&&(typ!="inpos")&&(typ!="motor")) {
_icepap_err
printf("invalid \"encoder\" parameter for counter \"%s\"", mne)
return ".error."
}
# handle the specific case of unsigned SSI encoders
if((typ != "abs") && index(typ,"absu")) {
local ssi
if(sscanf(typ,"absu%d",ssi) != 1) {
_icepap_err
printf("invalid \"encoder\" parameter \"absu\" for counter \"%s\"", mne)
return ".error."
}
counter_par(num,"encoder","absu")
counter_par(num,"ssi",ssi,"add")
ICEPAP_ENC[mne]["ssi"]=ssi
}
# normal end
ICEPAP_ENC[mne]["typ"]=typ
}
}'
#%IU%
#%MDESC%
# MACRO COUNTER: ENCODER
# Called by spec on counter operation.
#
def icepapenc_cmd(num,key,p1,p2) '{
global ICEPAP_ENC[]
local mne
local addr
local dev
if (num != "..") {
mne=cnt_mne(num)
addr=ICEPAP_ENC[mne]["addr"]
# get the MASTER
if(!("dev" in ICEPAP_ENC[mne])) { return }
dev=ICEPAP_ENC[mne]["dev"]
if(dev=="") { return }
}
if (key == "start_one") {
icepap_cleanup(dev)
}
if (key == "counts") {
return _icepapenc_getpos(num,dev,addr)
}
if (key == "halt_one") {
icepap_cleanup(dev)
}
}'
#
# ----------------------- MACRO COUNTER implementation -----------------------
#
#%IU%
#%MDESC%
# MACRO COUNTER:
# Called by spec after reading the config file
#
def icepapcalc_config(num,typ,p1,p2,p3) '{
global ICEPAP_CALC[]
local mne
local crate
local type
local dev
if(typ=="ctrl") {
ICEPAP_CALC["min_crate"]=0
ICEPAP_CALC["max_crate"]=0
return
}
# p1 is the unit
# p2 is always 0
# p3 is the channel which is the two digits address
if(typ=="cnt") {
mne =cnt_mne(num)
crate=counter_par(num,"misc_par_1")
if((crate<0) || (crate>16)) {
p "\tERROR: counter "mne" unusable: invalid crate as \"misc_par_1\""
p "\tHINT: type \"help local icepap\""
return
}
type =counter_par(num,"misc_par_2")
if((type!="min") && (type!="max") && (type!="avg")) {
p "\tERROR: counter "mne" unusable: invalid type as \"misc_par_2\""
p "\tmust be \"max\" \"min\" or \"avg\""
p "\tHINT: type \"help local icepap\""
return
}
ICEPAP_CALC[mne]["crate"]=crate
ICEPAP_CALC[mne]["type"] =type
if(crate>ICEPAP_CALC["max_crate"]) { ICEPAP_CALC["max_crate"]=crate }
if(crate<ICEPAP_CALC["min_crate"]) { ICEPAP_CALC["min_crate"]=crate }
# get the MASTER
ICEPAP_CALC["dev"]=""
dev=counter_par(num,"address")
if(dev==0) {
printf("ICEPAPCALC ERROR: missing ADDR field\n")
return
}
if(index(dev,":") == 0) { dev=sprintf("%s:5000",dev) }
ICEPAP_CALC["dev"]=dev
}
}'
#%IU%
#%MDESC%
# MACRO COUNTER:
# Called by spec on counter operation.
#
def icepapcalc_cmd(num,key,p1,p2) '{
global ICEPAP_CALC[]
local mne
local addr
local crate
local type
local t j c
local t_min t_max t_tot t_avg n_tot
local dev
if (key == "prestart_all") {
# get the MASTER
if(!("dev" in ICEPAP_CALC)) { return }
dev=ICEPAP_CALC["dev"]
if(dev=="") { return }
for(crate=ICEPAP_CALC["min_crate"];crate<=ICEPAP_CALC["max_crate"];crate++) {
t_max=0
t_min=0
t_tot=0
n_tot=0
for(j=1;j<=8;j++) {
addr=sprintf("%d%d",crate,j)
t=_icepapcnt_gettemp(dev,addr)
if(!t) { continue }
if(!t_min) { t_min=t }
if(t>t_max) { t_max=t }
if(t<t_min) { t_min=t }
t_tot += t
n_tot++
}
t_avg=t_tot/n_tot
ICEPAP_CALC[crate]["min"]=t_min
ICEPAP_CALC[crate]["max"]=t_max
ICEPAP_CALC[crate]["avg"]=t_avg
ICEPAP_CALC[crate]["n"] =n_tot
}
}
if (key == "counts") {
mne =cnt_mne(num)
type =ICEPAP_CALC[mne]["type"]
crate =ICEPAP_CALC[mne]["crate"]
S[num]=ICEPAP_CALC[crate][type]
}
}'
#
# ----------------------- MACRO COUNTER implementation -----------------------
#
#%IU%
#%MDESC%
# MACRO COUNTER: MEASURE
# Called by spec after reading the config file
#
def icepapmeas_config(num,type,p1,p2,p3) '{
global ICEPAP_MEAS[]
local mne
local dev
local cmd
if(type=="ctrl") {
return
}
# p1 is the unit
# p2 is always 0
# p3 is the channel which is the two digits address
if(type=="cnt") {
mne=cnt_mne(num)
ICEPAP_MEAS[mne]["addr"]=p3
# get the MASTER
ICEPAP_MEAS[mne]["dev"]=""
dev=counter_par(num,"address")
if(dev==0) {
printf("ICEPAPMEAS ERROR: \"%s\": missing ADDR field\n", mne)
return ".error."
}
if(index(dev,":") == 0) { dev=sprintf("%s:5000",dev) }
ICEPAP_MEAS[mne]["dev"]=dev
# get the command to read the DSP internals
cmd=counter_par(num,"cmd")
if(cmd==0) {
printf("ICEPAPMEAS ERROR: \"%s\": missing \"cmd\" parameter\n", mne)
return ".error."
}
ICEPAP_MEAS[mne]["cmd"]=cmd
}
}'
#%IU%
#%MDESC%
# MACRO COUNTER: MEASURE
# Called by spec on counter operation.
#
def icepapmeas_cmd(num,key,p1,p2) '{
global ICEPAP_MEAS[]
local mne
local addr
local dev
local cmd
if (num != "..") {
mne =cnt_mne(num)
addr=ICEPAP_MEAS[mne]["addr"]
dev =ICEPAP_MEAS[mne]["dev"]
cmd =ICEPAP_MEAS[mne]["cmd"]
}
if (key == "start_one") {
icepap_cleanup(dev)
}
if (key == "counts") {
local ans
local t
ans= _icepap_query(dev,addr,"?"cmd)
if(index(ans,"ERROR")) {
printf("ICEPAPMEAS ERROR: \"%s\": unable to get value\n",mne)
return(0)
}
if(sscanf(ans,"%lf",t) != 1) {
printf("ICEPAPMEAS ERROR: \"%s\": addr: %s: unable to get value\n",mne,addr)
icepap_chkerr(dev,ans)
icepap_fiforst(dev)
return(0)
}
return(t)
}
if (key == "halt_one") {
icepap_cleanup(dev)
}
}'
#
# ----------------------- direct accces macros -------------------------
#
#%UU% hostname cmd [args]
#%MDESC%
# Execute the specified command with its args on all
# ICEPAP modules (MASTER, SLAVES and DRIVERS) known by the hostname.
# Note that quotes must be used when cmd includes a hash for the
# acknowledge.
#
def icepap_all '{
local dev
local cmd
# Minimum check
if($# < 2) {
p "Usage: $0 icepap cmd [args]"
p " ex: $0 iceid131 ?ver info"
p " ex: $0 iceid131 \"\#power\" off"
exit
}
# Get args
dev = "$1"
if(!index(dev,":")) { dev = dev":5000" }
ICEPAP["dev"]=dev
# Get args
cmd = "$2"
if($# > 2) { cmd = cmd " $3" }
if($# > 3) { cmd = cmd " $4" }
_icepap_all(dev, cmd)
}'
#%IU%(hostname,cmd)
#%MDESC%
#
def _icepap_all(dev, cmd) '{
local ans
local addrs
local i n a
# Not needed
cmd = icepap__toupper(cmd)
# Just in case
icepap_fiforst(dev)
# Get the list of modules
ans = _icepap_get_addrs(dev)
n = split(ans, addrs)
# Execute the command on each module
for(i=0;i<n;i++) {
a = addrs[i]
if(substr(cmd,1,1)=="?")
p _icepap_wrrd(dev,a,cmd);
else if(substr(cmd,1,1)=="#")
p _icepap_wrrd(dev,"#" a,substr(cmd,2));
else
_icepap_wr(dev,a,cmd);
}
}'
#%IU%(hostname)
#%MDESC%
# Returns the addresses of all ICEPAP modules alive on the
# specficed hostname. The addresses are returned in a single string,
# blank separated.
#
def _icepap_get_addrs(dev) '{
local cmd_ans
local addrs
local rflg
local r
local dflg
local d
local a
addrs = ""
cmd_ans = _icepap_query(dev,"","?SYSSTAT")
if(index(cmd_ans,"ERROR"))
{
printf("ICEPAP: sorry, too old firmware to guess racks present\n")
return(addrs)
}
sscanf(cmd_ans,"%x",rflg)
for(r=0;r<16;r++)
{
if(!(rflg & (1<<r))) { continue }
cmd_ans = _icepap_query(dev,"",sprintf("?SYSSTAT %d",r))
if(index(cmd_ans,"ERROR")) return(addrs)
cmd_ans=substr(cmd_ans,index(cmd_ans," ")+1)
sscanf(cmd_ans,"%x",dflg)
for(d=0;d<=8;d++)
{
if((d!=0) && !(dflg & (1<<(d-1)))) { continue }
a=(d)+(r*10)
addrs = sprintf("%s%d ",addrs,a)
}
}
return(addrs)
}'
#%IU%(bliss_package_name)
#%MDESC%
#
def _is_package_installed(pkg) '{
local ll
local cmd
cmd = "rpm --dbpath ~blissadm/admin/RPM -qa"
cmd = sprintf("%s | grep \"%s\"",cmd, pkg)
unix(cmd,ll)
if(ll=="") {
p "ERROR: missing package \"",pkg,"\""
p "HINT : use \"blissinstaller\""
exit
}
}'
#%IU%(icepap_hostname)
#%MDESC%
#
def _is_same_subnetwork(dev) '{
local ll
local cmd
local dev_ip[]
local host_ip[]
cmd = sprintf("nslookup `hostname`")
cmd = sprintf("%s |grep -i \"address\"|grep -v \"#\"|cut -d\':\' -f2",cmd)
unix(cmd, ll)
if(ll=="") {
p "ERROR: unable to get hostname IP, giving up"
exit
}
split(ll, host_ip, ".")
cmd = sprintf("nslookup %s", dev)
cmd = sprintf("%s |grep -i \"address\"|grep -v \"#\"|cut -d\':\' -f2",cmd)
unix(cmd, ll)
if(ll=="") {
p "ERROR: unable to get \""dev"\" IP, giving up"
exit
}
split(ll, dev_ip, ".")
if(dev_ip[2] != host_ip[2]) {
p "ERROR: not on same sub-network than \""dev"\", giving up"
p "HINT : use spec on another machine"
exit
}
}'
#%IU%(firmwares_list)
#%MDESC%
#
def _is_valid_version(dev, ll) '{
local fw_list[]
local fw_n
local fw_cur
local ans
fw_n = split(ll,fw_list)
ans=_icepap_query(dev, "", "?VER")
if(index(ans,"ERROR"))
{
p "ERROR: unable to get icepap system version, giving up"
p "HINT : switch on \""dev"\""
exit
}
fw_cur=icepap_trim(ans)
for(n in fw_list) {
if(fw_list[n] == fw_cur)
return
}
p "ERROR: wrong current firmware version \""fw_cur"\" on \""dev"\""
p "HINT : must be one of these \""ll"\""
exit
}'
#%IU%(icepap_hostname)
#%MDESC%
#
def _is_alive(dev) '{
local silent
local ans
local cmd
local n
cmd = sprintf("ping -c 1 %s > /dev/null",dev)
for(n=5;n;n--) {
if(!unix(cmd)) {
# Linux is up but give time to the embedded program to start
sleep(1)
# Restore SPEC socket connection
if(!index(dev,":")) { dev = dev":5000" }
sock_par(dev,"close")
sock_par(dev,"connect")
# Check that the embedded program started well
silent = 1
ans=_icepap_query(dev,0,"?ID", silent)
if(ans == "") {
p "ERROR: the embedded program is not running on \""dev"\""
p "HINT : reboot it by cycling its power supply (off/on)"
return ".error."
}
# Normal end
return ""
}
sleep(1)
}
p "ERROR: timeout waiting for \""dev"\" to be alive"
return ".error."
}'
#%IU%(dev, addr_list)
#%MDESC%
# Bypass external disable signal on the list of drivers given.
# (this was done with DISDIS command on old firmwares <2.0)
# Works only on firmware >=2.0
#
def _emulate_alldis(dev, addr_list) '{
local ll
local i
split(addr_list, ll)
for(i in ll) {
_emulate_onedis(dev, ll[i])
}
}'
#%IU%(dev, addr)
#%MDESC%
# Bypass external disable signal on the driver given.
# (this was done with DISDIS command on old firmwares <2.0)
# Works only on firmware >=2.0
#
def _emulate_onedis(dev, addr) '{
local ans
local cmd
local signature
ans = _icepap_query(dev, addr, "?MODE")
if(!index(ans,"OPER"))
{
p "ERROR: driver \""addr"\" not in OPER mode, giving up"
exit
}
ans = _icepap_query(dev, addr, "?CONFIG")
signature = ans
cmd = sprintf("%sCONFIG",spec_par("specwiz")?"BD_":"")
ans = _icepap_query(dev, "#"addr, cmd)
if(index(ans,"ERROR"))
{
p "ERROR: unable to enter CONFIG on driver \""addr"\", giving up"
exit
}
cmd = sprintf("%sCFG EXTDISABLE NONE",spec_par("specwiz")?"BD_":"")
ans = _icepap_query(dev, "#"addr, cmd)
if(index(ans,"ERROR"))
{
p "ERROR: unable to change EXTDISABLE on driver \""addr"\", giving up"
exit
}
cmd = sprintf("%sCONFIG \"%s\"",spec_par("specwiz")?"BD_":"", signature)
ans = _icepap_query(dev, "#"addr, cmd)
if(index(ans,"ERROR"))
{
p "ERROR: unable to change CONFIG on driver \""addr"\", giving up"
exit
}
}'
#%UU% hostname
#%MDESC%
# Upgrade the specified icepap system from firmware 1.22 to 2.0
# If called from SPEC wizard mode, the security of the mandatory
# same subnetwork is bypassed.
#
def upgrade_firmware_1_22 '{
local dev
local fname
local addr
local opt
local dis_list
local msg
local i
# Minimum check
if($# < 1) {
p "Usage: $0 hostname"
p " ex: $0 iceid131"
exit
}
dev = "$1"
# Dangerous macro
p "\nWARNING: this macro will upgrade all the firmwares of \"$1\""
if(!yesno("Do you want to continue",0)) {
p "Giving up"
exit
}
p ""
# Check that packages have been upgarded
_is_package_installed("icepapcms-src-1.28")
_is_package_installed("icepap_firmware-src-2.0")
# Check that the system has firmware version 1.22 or 1.225
_is_valid_version(dev, "1.22 1.225")
# Check that we are on the same subnetwork
if(!spec_par("specwiz")) {
_is_same_subnetwork(dev)
}
# Do an inventory of axis with external signal disabled
p "Collectng list of axis with external disable signal bypassed"
dis_list = _icepap_alldis(dev, 1)
# Keep inventory into a file
# Upgrade firmwares
fname = "/users/blissadm/local/userconf/icepap/icepfw_2.0"
addr = "ALL"
opt = "FORCE"
p "Upgrading FPGA/DSP firmwares"
_icepap_prog(dev,fname,addr,opt)
# Upgrade MCPUx firmwares
addr = "MCPU0"
p "Upgrading embedded Linux firmwares"
_icepap_prog(dev,fname,addr,opt)
addr = "MCPU1"
_icepap_prog(dev,fname,addr,opt)
addr = "MCPU2"
_icepap_prog(dev,fname,addr,opt)
# Save new firmware into the icepap system flash
addr = "NONE"
opt = "SAVE"
p "Saving new firmware package into embedded flash"
_icepap_prog(dev,fname,addr,opt)
# Reboot the icepap system to run the new MCPUx and set RDISPOL
p "Reboot the system and wait for its wake up"
_icepap_query(dev,"#","REBOOT")
sleep(20)
if(_is_alive(dev) != "") {
p "HINT : after the reboot run the following macro:"
p sprintf("_emulate_alldis(\"%s\",\"%s\")",dev, dis_list)
exit
}
# Restore external disable signal
p "Restoring external disable signal bypasses"
_emulate_alldis(dev, dis_list)
# Normal end
p "Bravo\! System should be upgraded"
if(i=index(dev,":")) { dev = substr(dev, 0, i-1) }
msg = sprintf("%s", date())
msg = sprintf("%s\nsystem : %s", msg, dev)
msg = sprintf("%s\nupgraded to : 2.0", msg)
msg = sprintf("%s\nDISDIS kept : %s", msg, dis_list)
_icepap_email(sprintf("%s: UPGRADE", dev), msg)
}'
#%UU% hostname
#%MDESC%
# Will try to guess if the DISDIS parameter is really needed on
# each DRIVER of the specified ICEPAP systerm. If not needed, the
# macro will remove it.
# WARNING: this macro is for temporary usage only.
#
def icepap_alldis '{
local dev
local silent
# Minimum check
if($# < 1) {
p "Usage: $0 icepap"
p " ex: $0 iceid131"
exit
}
# Get args
dev = "$1"
ICEPAP["dev"]=dev
silent = 0
_icepap_alldis(dev, silent)
}'
def _icepap_alldis(dev, silent) '{
global ICEPAP[]
local cmd_ans
local rflg
local r
local dflg
local d
local addr
local was_on
local addr_list
local del_list
local msg
local i
# Just in case
if(!index(dev,":")) { dev = dev":5000" }
icepap_fiforst(dev)
# Check if firmware is a valid one
cmd_ans = _icepap_wrrd(dev,"","?SYSSTAT")
if(index(cmd_ans,"ERROR"))
{
printf("ICEPAP: sorry, too old firmware to guess racks present\n")
exit
}
addr_list = ""
del_list = ""
cmd_ans = _icepap_query(dev,"","?SYSSTAT")
sscanf(cmd_ans,"%x",rflg)
for(r=0;r<16;r++)
{
if(!(rflg & (1<<r))) { continue }
cmd_ans = _icepap_query(dev,"",sprintf("?SYSSTAT %d",r))
if(index(cmd_ans,"ERROR")) exit;
cmd_ans=substr(cmd_ans,index(cmd_ans," ")+1)
sscanf(cmd_ans,"%x",dflg)
# Skip COMM or MASTER modules
for(d=1;d<=8;d++)
{
if((d!=0) && !(dflg & (1<<(d-1)))) { continue }
addr=(d)+(r*10)
cmd_ans = _icepap_query(dev,addr,"?DISDIS")
if(index(cmd_ans,"ERROR")) continue;
if(int(cmd_ans) != 1) { continue }
if(!silent) { printf("Found driver with DISDIS set: %02d\n",addr) }
# Keep a record of the current state in any case
cmd_ans=_icepap_query(dev,addr,"?POWER")
was_on =(index(cmd_ans,"ON")?1:0)
if(!silent) { printf("\tPOWER is %s\n",(was_on?"ON":"OFF")) }
# Try to disable DISDIS
if(was_on)
{
cmd_ans=_icepap_query(dev,"#" addr,"POWER OFF")
if(index(cmd_ans,"ERROR"))
{
printf("ERROR: switching off power\n")
printf("Giving up\n")
continue;
}
}
cmd_ans=_icepap_query(dev,"#" addr,"DISDIS 0")
if(index(cmd_ans,"ERROR"))
{
printf("ERROR: removing DISDIS parameter\n")
printf("Giving up\n")
continue;
}
# Try to guess if DISDIS is really needed
cmd_ans=_icepap_query(dev,addr,"?ISG ?PWRINFO")
if(index(cmd_ans,"axis remote disable signal on"))
{
if(!silent) { printf("\tDISDIS needed\n") }
addr_list = sprintf("%s%s ", addr_list, addr)
cmd_ans=_icepap_query(dev,"#" addr,"DISDIS 1")
if(index(cmd_ans,"ERROR"))
{
printf("ERROR: setting DISDIS parameter\n")
}
}
else
{
del_list = sprintf("%s%s ", del_list, addr)
if(!silent) { printf("\tDISDIS not needed, removed !!!!!!!!!!!!!!\n") }
}
# Put back power if needed
if(was_on)
{
if(!silent) { printf("\tPOWER set %s\n",(was_on?"ON":"OFF")) }
cmd_ans=_icepap_query(dev,"#" addr,"POWER ON")
if(index(cmd_ans,"ERROR"))
{
printf("ERROR: switching on power\n")
printf("Giving up\n")
continue;
}
}
}
}
printf("\tDISDIS kept : \"%s\"\n",addr_list)
printf("\tDISDIS deleted : \"%s\"\n",del_list)
# Normal end, return the list of drivers than need DISDIS
if(i=index(dev,":")) { dev = substr(dev, 0, i-1) }
msg = sprintf("%s", date())
msg = sprintf("%s\n%s", msg, dev)
msg = sprintf("%s\nDISDIS kept : %s", msg, addr_list)
msg = sprintf("%s\nDISDIS deleted: %s", msg, del_list)
_icepap_email(sprintf(" %s: DISDIS", dev), msg)
return addr_list
}'
#%UU% [hostname[:port]]
#%MDESC%
# Console implementation to communicate to icepap MASTER
#
def icepap '{
global ICEPAP[]
global ICEPAP_NCOMM
global ICEPAP_HIST[]
global ICEPAP_NHIST
global ICEPAP_CHIST
local dev
local line c fc
local args[]
if($# < 1) {
dev=getval("Icepap MASTER network name",ICEPAP["dev"])
} else {
dev="$1"
}
if(!index(dev,":")) { dev = dev":5000" }
ICEPAP["dev"]=dev
cdef("cleanup_once",sprintf("_icepap_close(\"%s\")",dev),"ICEPAP")
if(sock_put(dev, "?_help\n") == -1) { exit }
sleep(0.1)
sock_par(dev,"timeout",2)
p "\n" sock_get(dev)
while(1) {
line = ""
printf("\n%d.ICEPAP console> ",ICEPAP_NCOMM);
while(1) {
c = input(-1)
if (c == "\n") {
printf("\n")
tty_cntl("cd")
break
} else if ((c == "\b" || c == "\177") && (line != "")) {
line = substr(line, 0, length(line)-1)
printf("\b \b")
} else if (asc(c) == 27) {
sleep(0.05)
c = input(-1)
sleep(0.01)
c = input(-1)
# left arrow
# if(asc(c) == 0x44)
# right arrow
# if(asc(c) == 0x43)
if(asc(c) == 0x41) {
if(ICEPAP_CHIST) {
line = ICEPAP_HIST[--ICEPAP_CHIST]
printf("\r")
tty_cntl("cd")
printf("%d.ICEPAP console> %s",ICEPAP_NCOMM,line);
}
} else if(asc(c) == 0x42) {
if(ICEPAP_CHIST<ICEPAP_NHIST) {
line = ICEPAP_HIST[++ICEPAP_CHIST]
printf("\r")
tty_cntl("cd")
printf("%d.ICEPAP console> %s",ICEPAP_NCOMM,line);
}
}
} else if (c >= " " && c <= "z") {
line = line c
printf(c)
}
sleep(0.01)
}
if(line) {
ICEPAP_HIST[ICEPAP_NHIST]=line
ICEPAP_NHIST++
ICEPAP_CHIST=ICEPAP_NHIST
}
split(line,args)
if(!args[0]) {
continue
} else if(whatis(args[0]) & 0x00000002) {
eval(line)
continue
}
uline = icepap__toupper(line)
if((uline == "QUIT") || (uline == "CLOSE")) {
sock_par(dev,"close")
exit
}
fc = substr(line,1,1)
if((fc!="#") && (fc!=":")) {
line = "#" line
}
# acknowledge of broadcast commands is forbidden
if(fc==":") {
_icepap_wr(dev,"",line)
} else {
ans = _icepap_query(dev,"",line,1)
p icepap_trim(ans)
}
ICEPAP_NCOMM++
}
}'
#%IU%(string, n)
#%MDESC%
# Parse the string to get the ICEPAP device to talk to.
# Try to get as nth argument (starting from 1) in the string,
# if not prompt the user.
#
def _icepap_getdev(str, i) '{
local args[]
local n
local dev
local sl
n=split(str,args)
if(n < i) {
dev=getval("Icepap MASTER network name or SL",ICEPAP["dev"])
} else {
dev=args[i-1]
}
sl = (dev + 0 == dev)?1:0
if(!sl && !index(dev,":")) { dev = dev":5000" }
ICEPAP["dev"]=dev
return(dev)
}'
#%IU%(string, n)
#%MDESC%
# Parse the string to get the ICEPAP tocho file.
# Try to get as nth argument (starting from 1) in the string,
# if not prompt the user.
#
def _icepap_getfname(str, i) '{
local args[]
local n
local fname
local fdir
local uxcom
local aux
local m
local flist[]
local f
n=split(str,args)
if(n < i) {
fdir=sprintf("%s/%s",BLISSADM,"local/userconf/icepap");
if(!file_info(fdir)) {
print "ERROR: missing icepap_firmware, hint: use \"blissinstaller\""
exit
}
uxcom = "cd " fdir "; ls -rt"
unix(uxcom, aux)
m = split(aux, flist, "\n")
for(m--;m;m--)
{
f=flist[m]
if(f=="") continue;
if(file_info(sprintf("%s/%s",fdir,f),"isdir")) continue;
break;
}
fname=sprintf("%s/%s",fdir,flist[m])
fname=getval("Binary program file",fname)
} else {
fname=args[i-1]
}
if(file_info(fname,"-r") == 0) {
print "ERROR: unable to read file \""fname"\""
exit
}
return(fname)
}'
#%IU%(string, n)
#%MDESC%
# Parse the string to get the addr for programming.
# Try to get as nth argument (starting from 1) in the string,
# if not prompt the user.
#
def _icepap_getaddr(str, i) '{
local args[]
local n
local addr
n=split(str,args)
if(n < i) {
addr=getval("What to program (\"ALL\"|\"DRIVERS\"|\"CONTROLLERS\"|\"NONE\"|addr) ",\
"NONE")
} else {
addr=args[i-1]
}
addr = icepap__toupper(addr)
if(addr=="NONE") { addr="" }
return(addr)
}'
#%IU%(string, n)
#%MDESC%
# Parse the string to get the options for programming.
# Try to get as nth argument (starting from 1) in the string,
# if not prompt the user.
# Any remaining argument is also return as option.
#
def _icepap_getopts(str, i) '{
local args[]
local n
local opt
n=split(str,args)
if(n < i) {
opt=getval("Options (\"SAVE\"|\"SL\"|\"FORCE\"|\"NONE\") ","NONE")
} else {
opt=args[i-1]
for(;i<n;i++) { opt=opt " " args[i] }
}
opt = icepap__toupper(opt)
if(opt =="NONE") { opt ="" }
return(opt)
}'
#%IU%(string, n)
#%MDESC%
# Parse the string to get the rack addresses for programming.
# Try to get as nth argument (starting from 1) in the string,
# if not prompt the user.
# Any remaining argument is also return as option.
#
def _icepap_getracks(str, i) '{
local args[]
local n
local racks
n=split(str,args)
if(n < i) {
racks=getval("List of racks (ex: 0 3)",0)
} else {
racks=args[i-1]
for(;i<n;i++) { racks=racks " " args[i] }
}
racks = icepap__toupper(racks)
return(racks)
}'
#%UU% [hostname[:port] [file] [rack ... ]]
#%MDESC%
# Program a the ICEPAP specified list of racks using the rack back plane
# serial line.
#
def icepap_rprog '{
local dev
local fname
local racks
local sl
local cmd_ans
# Get args or prompt them to the user
dev = _icepap_getdev ("$*", 1)
fname = _icepap_getfname("$*", 2)
racks = _icepap_getracks("$*", 3)
sl = (dev + 0 == dev)?1:0
# Get a connection to ICEPAP
if(!sl) { _icepap_check(dev) }
# Send this with acknowledge to ensure that all DRIVERs mode have changed
cmd = "#MODE PROG"
printf("\tCommand sent : \"%s\"\n", cmd)
if(sl)
{
ser_put(dev,sprintf("%s\n",cmd))
}
else
{
cmd_ans = _icepap_wrrd(dev,"",cmd)
if(!index(cmd_ans,"MODE OK"))
{
_icepap_err
print "unable to switch ICEPAP to programmation mode"
exit
}
}
cmd = sprintf("*RPROG %s",racks)
printf("\tCommand sent : \"%s\"\n", cmd)
if(sl) { ser_put(dev,sprintf("%s\n",cmd)) } else { _icepap_wr(dev,"",cmd) }
# Send the binary data
# _icepap_wrbin(dev,fname)
}'
#%UU% [hostname[:port] [file] [addr] [options]]
#%MDESC%
# Program a the ICEPAP module with the specified binary file
#
def icepap_prog '{
local dev
local fname
local addr
local opt
# Get args or prompt them to the user
dev = _icepap_getdev ("$*", 1)
fname = _icepap_getfname("$*", 2)
addr = _icepap_getaddr ("$*", 3)
opt = _icepap_getopts ("$*", 4)
_icepap_prog(dev,fname,addr,opt)
}'
#%IU%(dev,fname,addr,opt)
#%MDESC%
# Program a the ICEPAP module with the specified arguments.
# If no firmware file name is given, the programmatino will used
# the firmware saved in the controller flash.
#
def _icepap_prog(dev,fname,addr,opt) '{
global ICEPAP[]
local sl
local cmd
local cmd_ans
local dest_mcpu
local dest_none
local use_saved
local dodo
# Get a connection to ICEPAP
sl = (dev + 0 == dev)?1:0
if(!sl && !index(dev,":")) { dev = dev":5000" }
if(!sl) { _icepap_check(dev) }
dest_mcpu=index(addr,"MCPU")
dest_none=(addr=="")?1:0
# Minimum check on parameters validity
if(dest_none && opt == "")
{
_icepap_err
print "nothing to do, giving up"
exit
}
# If no firmware file, then use the saved one
use_saved = (fname=="")
# Skip mode handling if no DSP or FPGA is concerned
if(!dest_none && !dest_mcpu)
{
# Send this with acknowledge to ensure that all DRIVERs mode have changed
cmd = "#MODE PROG"
printf("\tCommand sent : \"%s\"\n", cmd)
if(sl)
{
ser_put(dev,sprintf("%s\n",cmd))
}
else
{
cmd_ans = _icepap_wrrd(dev,"",cmd)
if(!index(cmd_ans,"MODE OK"))
{
_icepap_err
print "unable to switch ICEPAP to programmation mode"
exit
}
}
}
cmd = sprintf("%sPROG %s %s",(use_saved?"":"*"),addr, opt)
printf("\tCommand sent : \"%s\"\n", cmd)
if(sl) { ser_put(dev,sprintf("%s\n",cmd)) } else {
_icepap_wr(dev,"",cmd)
}
# Send the binary data
if(!use_saved) { _icepap_wrbin(dev,fname) }
#Skip mode handling if no DSP or FPGA is concerned
#if(!dest_none && !dest_mcpu)
if(!dest_mcpu)
{
ans="?????"
printf("\tState : %-20s\r",ans)
# NOTE MP 08Apr11: should be replaced by an acknowled on *PROG cmd
sleep(1)
cmd="?_PROG"
if(index((_icepap_wrrd(dev,"",cmd)),"ERROR")) { cmd="?PROG" }
for(;index((ans= _icepap_query(dev,"",cmd)),"ACTIVE");sleep(.5))
printf("\tState : %-20s\r",ans);
printf("\tState : %-20s\n",ans)
sleep(2)
}
else
{
ans=" DONE"
printf("\tState :%-20s\n",ans)
}
if(!dest_none && !dest_mcpu)
{
# Give time to the drivers to come back to life
dodo = 5
printf("\tWait for : %dsecs\n", dodo)
sleep(dodo)
cmd = "#MODE OPER"
printf("\tCommand sent : \"%s\"\n", cmd)
if(sl)
{
ser_put(dev,sprintf("%s\n",cmd))
}
else
{
cmd_ans = _icepap_wrrd(dev,"",cmd)
if(!index(cmd_ans,"MODE OK"))
{
_icepap_err
print "unable to switch ICEPAP to operation mode"
exit
}
}
}
# Check if a reboot is needed
cmd="?VER"
if(index((_icepap_wrrd(dev,"",cmd)),"ERROR Reboot is needed"))
{
cmd = "REBOOT"
printf("\tCommand sent : \"%s\"\n", cmd)
printf("NOTE: the connection to \"%s\" will be unusable during 30s\n",dev)
_icepap_wr(dev,"",cmd)
}
}'
#%IU%(dev,fname)
#%MDESC%
# Send the contain of the file to the ICEPAP using the ISG
# binary transfer protocol.
#
def _icepap_wrbin(dev,fname) '{
local sl
local bin_l
local bin_chksum
sl = (dev + 0 == dev)?1:0
bin_l = (file_info(fname,"size")/2) & 0xffffffff
local ushort array icepapfw[bin_l]
fmt_read(fname,"raw",icepapfw)
# 2 words startup mark (ex: 0xa5aa555a)
local ulong array datal[1]
datal[0]=0xa5aa555a
if(sl) { ser_put(dev, datal) } else { sock_put(dev, datal) }
# 2 words for the binary data length
datal[0]=bin_l
if(sl) { ser_put(dev, datal) } else { sock_put(dev, datal) }
# 2 words for the checksum
bin_chksum = (array_op("sum",icepapfw)) & 0xffffffff
printf("\tCheck sum : 0x%08X\n", bin_chksum)
datal[0]=bin_chksum
if(sl) { ser_put(dev, datal) } else { sock_put(dev, datal) }
# chaud devant !!!
printf("\tTransferring : %d words\n", bin_l)
if(sl) { ser_put(dev, icepapfw) } else { sock_put(dev, icepapfw) }
}'
#%IU% [hostname:port]
#%MDESC%
# Reset the MASTER DSP
#
def icepap_mdspreset '{
global ICEPAP[]
local dev
if($# < 1) {
dev=getval("Icepap MASTER network name",ICEPAP["dev"])
} else {
dev="$1"
}
if(!index(dev,":")) { dev = dev":5000" }
ICEPAP["dev"]=dev
sock_put(dev,"_dsprst\n")
print "MASTER DSP reseted"
}'
#%IU% [hostname:port [driver]]
#%MDESC%
# Program one or all DRIVER DSP numbered from 1 to 8
# using the backplane serial line and the DDSP programm taken
# from MDSP flash (no binary transferred)
#
def icepap_ddsppgm_sl '{
local dev
local board
if($# < 1) {
dev=getval("Icepap MASTER network name","isgtmp5:5000")
} else {
dev="$1"
}
_icepap_check(dev)
# Ya un couillon au clavier ?
board=0
if($# < 2) {
board=getval("Icepap DRIVER to program from 1 to 8 (0 for all)",board)
} else {
board=$2
}
if((board<0) || (board>8))
{
print "ICEPAP: invalid channel/board "board" (valid: 1 to 8 or 0 for all)"
return
}
# ok, on peut bosser
if (board) { p "\tProgramming board: "board }
else { p "\tProgramming all boards" }
sock_put(dev,sprintf("PROG %d\n",board))
p "\tBe patient....."
p "\tHint: check messages on DSP serial line console of MASTER"
}'
#%IU%(hostname:port)
#%MDESC%
# Do not touch, needed by the "raleur"
#
def _icepap_check(dev) '{
local ans
# Allo? Gaston? Tes la?
sock_par(dev,"close")
if(!sock_par(dev,"connect"))
{
_icepap_err
print "communication program not running on MASTER"
print "Hint: reset MASTER or run \"icepap_sock\" on ",dev
exit
}
sock_par(dev,"timeout",ICEPAP_TIMEOUT)
ans=_icepap_query(dev,"","?_SOCKPING")
if(ans != "OK") {
_icepap_err
print "bad response from MASTER"
print "Hint: reset MASTER or run \"icepap_sock\" on ",dev
exit
}
}'
#%IU%(hostname:port)
#%MDESC%
#
def _icepap_close(dev) '{
sock_put(dev,"_SOCKCLOSE\n");
sock_par(dev,"close");
}'
#%IU%
#%MDESC%
#
def _icepap_err '{
tty_cntl("md")
printf("ICEPAP ERROR: ")
tty_cntl("me")
}'
#%IU%
#%MDESC%
#
def _icepap_warn '{
tty_cntl("md")
printf("ICEPAP WARNING: ")
tty_cntl("me")
}'
#%IU%(num, status)
#%MDESC%
# Decode stop reason for the driver status given.
# No action, print only for diagnostic
#
def _icepap_stopcode(num, sta) '{
local stop_code
local mne
# Stop code implemented on bits 14-17
stop_code = (sta & ((1<<14)|(1<<15)|(1<<16)|(1<<17))) >> 14
# Normal case is code 0
if(!stop_code) { return(0) }
# Ignore limitswitches
if((stop_code==3) || (stop_code==4)) { return(0) }
# Treat the stop code only once
mne=motor_mne(num)
if(stop_code == ICEPAP[mne]["stop_code"]) { return(1) }
ICEPAP[mne]["stop_code"]=stop_code
# Abnormal stop case
_icepap_warn
printf("\"%s\": abnormal stop condition: ", mne)
if(stop_code == 1) {p "STOP signal received" ; return(1) }
if(stop_code == 2) {p "ABORT signal received" ; return(1) }
if(stop_code == 3) {p "Limit+ activated" ; return(1) }
if(stop_code == 4) {p "Limit- activated" ; return(1) }
if(stop_code == 5) {p "close loop settling timeout" ; return(1) }
if(stop_code == 6) {p "axis disabled" ; return(1) }
if(stop_code == 8) {p "internal failure" ; return(1) }
if(stop_code == 9) {p "motion failure" ; return(1) }
if(stop_code == 10) {p "power overload" ; return(1) }
if(stop_code == 11) {p "driver overheating" ; return(1) }
if(stop_code == 12) {p "close loop error" ; return(1) }
if(stop_code == 13) {p "control encoder error" ; return(1) }
if(stop_code == 15) {p "external abort" ; return(1) }
}'
#%IU%(dev,addr,cmd)
#%MDESC%
#
def _icepap_wr(dev,addr,cmd) '{
local str
global ICEPAP_HISTORY[]
if(addr != "" && addr != "#") str=addr":"cmd; else str=cmd;
if (addr == "#") str = "#" str
icepap__debug "sending " str
_icepap_hist_add(dev, str)
str=str"\n"
sock_par(dev,"flush")
sock_put(dev,str);
}'
#%IU%(dev,addr,cmd)
#%MDESC%
#
def _icepap_wrrd(dev,addr,cmd) '{
local ret
_icepap_wr(dev,addr,cmd)
ret=sock_get(dev);
icepap__debug "getting " ret
_icepap_hist_append(ret)
return(ret)
}'
#%IU%(dev,addr,cmd,silent)
#%MDESC%
#
def _icepap_query(hn,addr,cmd,silent) '{
local dev
local ans[]
local cmd_ans
local len_ans
local lc
local n
local ret
local i
ret=""
dev=sprintf("%s%s",hn, index(hn,":")?"":":5000")
cmd_ans=_icepap_wrrd(dev,addr,cmd)
for(;;) {
len_ans=length(cmd_ans)
lc = substr(cmd_ans,len_ans,1)
if((lc=="\n") || (lc=="\r")) {
cmd_ans=substr(cmd_ans,0,len_ans-1)
continue
}
break
}
n=split(cmd_ans,ans)
if(n<1) {
if(!silent) {
_icepap_err
printf("bad answer from IcePAP\n")
}
return(cmd_ans)
}
if(index(ans[1],"ERROR")) {
if(!silent) {
_icepap_err
printf("%s\n",cmd_ans)
}
return(cmd_ans)
}
ret=substr(cmd_ans,index(cmd_ans," ")+1)
return(ret)
}'
#%IU%()
#%MDESC%
# Temporary patch
#
def _icepap_patch(dev, addr) '{
local slave
local dest
print "WARNING: icepap ",dev,"MASTER DSP being reset (",addr,")"
# Reset the MASTER DSP only, DRIVERs not affected
_icepap_wr(dev,"","_DSPRST")
# Give a minimum time to DSP to reset (and to DRIVERs to come back)
# or check that it is alive
sleep(3)
# Reaffect a CAN address to the DRIVER
# slave=int(addr/10)*10
# If the DRIVER is in the MASTER rack, the CAN address is already given
# if(slave != 0)
# {
# _icepap_wr(dev,slave,"RESET")
# sleep(10)
# }
}'
#%IU%()
#%MDESC%
# Temporary email after patch
#
def _icepap_patch_email() '{
dest = "perez@esrf.fr jclement@esrf.fr"
unix(sprintf("echo \"%s\" |mailx -s \"ERROR on %s session %s\" %s",\
_icepap_hist_dump(),\
SPECBL,\
SPEC,\
dest))
}'
#%IU%(message)
#%MDESC%
# Send an email with the specificied patch
#
def _icepap_email(subject, str) '{
dest = "perez@esrf.fr jclement@esrf.fr"
unix(sprintf("echo \"%s\" |mailx -s \"%s: session: \\\"%s\\\"\" %s",\
str,\
subject,\
SPEC,\
dest))
}'
#%IU%()
#%MDESC%
# Init the ICEPAP history if needed
#
def _icepap_hist_init() '{
global ICEPAP_HISTORY[]
if(!("size" in ICEPAP_HISTORY)) {
ICEPAP_HISTORY["size"]=1000
ICEPAP_HISTORY["end"] =0
}
}'
#%IU%(dev,cmd)
#%MDESC%
# Add to the ICEPAP history an entry
#
def _icepap_hist_add(dev, cmd) '{
global ICEPAP_HISTORY[]
local n
local tab
tab = " "
_icepap_hist_init()
n = ICEPAP_HISTORY["end"] + 1
if(n >= ICEPAP_HISTORY["size"]) { n = 0}
ICEPAP_HISTORY[n] = sprintf("%s%s%s%s%s",date(),tab,dev,tab,cmd)
ICEPAP_HISTORY["end"] = n
}'
#%IU%(str)
#%MDESC%
# Append a string to the last line in the ICEPAP history
#
def _icepap_hist_append(str) '{
global ICEPAP_HISTORY[]
local n
n = ICEPAP_HISTORY["end"]
ICEPAP_HISTORY[n] = sprintf("%s -> %s",ICEPAP_HISTORY[n], str)
}'
#%IU%()
#%MDESC%
# Return a string with the history of commands sent to ICEPAP systems
#
def _icepap_hist_dump() '{
global ICEPAP_HISTORY[]
local n
local i
local s
local ret
ret = ""
_icepap_hist_init()
s = ICEPAP_HISTORY["size"]
for(n=ICEPAP_HISTORY["end"];(n in ICEPAP_HISTORY) && (i<s);i++)
{
ret = sprintf("%s%s\n",ret,ICEPAP_HISTORY[n])
n--
if(n<0) { n = s - 1 }
}
return ret
}'
#%UU%()
#%MDESC%
# Print out the history of commands sent to ICEPAP systems
#
def icepap_history '{
print _icepap_hist_dump()
}'
#
# ----------------------- test macros -------------------------
#
#%IU%(dev,src_addr,dst_addr)
#%MDESC%
# Will copy the source driver configuration to the destination one
# (bypass of icepapcms)
# ex: ("iceid207",11,25)
#
def icepap_duplicate_conf(dev,src_addr,dst_addr) '{
local src_conf
local src_arr[]
local n i
local dst_cmd
local dst_err
if(!index(dev,":")) { dev = sprintf("%s:5000",dev) }
src_conf = _icepap_wrrd(dev,src_addr,"?CFG")
n = split(src_conf,src_arr,"\r\n") - 1
dst_addr = "#" dst_addr
for(i=1;i<n;i++) {
dst_cmd = sprintf("_cfg %s", src_arr[i])
dst_err = _icepap_wrrd(dev,dst_addr,dst_cmd)
if(!index(dst_err,"OK")) {
p "ERROR: sending command: "dst_cmd" error: "dst_err
return(-1)
}
}
dst_cmd = "_CFG SAVE"
dst_err = _icepap_wrrd(dev,dst_addr,dst_cmd)
if(!index(dst_err,"OK")) {
p "ERROR: sending command: "dst_cmd" error: "dst_err
return(-1)
}
# normal end
p "ICEPAP configuration of driver "dst_addr" updated"
return(0)
}'
#%MACROS%
#%IMACROS%
#%AUTHOR% MP BLISS (Original 9/07).
# %BR%$Revision: 2.0 $ / $Date: 2013/10/01 13:18:09 $
#%TOC%
|