#%TITLE% ICPLUS.MAC
#
#%NAME%
# Macros for operating the Oxford Danfysik 4-channel IC_PLUS electrometer
#
#%CATEGORY% Detection, BPM
#
#%OVERVIEW%
# This macro set allows to control IC-PLUS units in %B%spec%B% and configure
# their signal inputs as pseudocounters.
# %BR%
# More than one IC-PLUS unit can be operated through this macro set.
#
#%EXAMPLE%
# %DL%
# %DT%icplussetup mydev 0 c1=curr1 c2=curr2 c3=curr3 c4=curr4
# %DD%Configures an IC-PLUS unit connected to the spec serial line #0 and
# associates its four input channels to the pseudocounters
# curr1, curr2, curr3 and curr4.
# %DT%icplussetup bpm0 id33/sl_lid331/3 c1c2=beamX c3c4=beamY
# %DD%Configures an IC-PLUS unit connected through the serial line device
# id33/sl_lid331/3.
# Associates normalised current differences to the pseudocounters
# beamX and beamY.
# %DT%icplus
# %DD%Display the list of IC-PLUS units currently configured.
# %XDL%
#
#%END%
#%HISTORY%
#$Log: icplus.mac,v $
#Revision 1.2 2008/07/17 14:19:34 rey
#Documentation changes.
#
#Revision 1.1 2008/04/04 12:59:24 rey
#Counter identifiers have been changed from #1, #2 etc to c1, c2
#as newer versions of spec would interpret, (correctly), those
#symbols as comments.
#WARNING: this is an incompatible change but in principle only
#one beamline was using these macros at the time of the
#change.
#
#Revision 1.0 2005/09/23 08:18:35 blissadm
#Initial revision
#
#
#%UU% <icpname> <serline> [<parameter>=<value> ...]
#%MDESC%
# Configures a IC-PLUS connected to <serline> with the name <icpname>.
# The following optional parameters can be also set.
# %UL%
# %LI%Valid parameters:%DL%
# %DT%address=<addr>
# %DD%This parameter allows to address a particular unit when the serial
# line is shared by several IC-PLUS units. The default address is 0.
# %DT% c1=<cnt_mne>
# %DT% c2=<cnt_mne>
# %DT% c3=<cnt_mne>
# %DT% c4=<cnt_mne>
# %DD%If <cnt_mne> is a valid counter mnemonic, it gets configured as
# a pseudocounter loaded with the current in the corresponding
# channel (1 to 4).
# The "Scale Factor" value in the %B%spec%B% config file applies.
# %DT% c1c2=<cnt_mne>
# %DT% c3c4=<cnt_mne>
# %DD%If <cnt_mne> is a valid counter mnemonic, it gets configured as
# a pseudocounter loaded with the normalised current difference
# (c1-c2)/(c1+c2) or (c3-c4)/(c3+c4).
# The "Scale Factor" value in the %B%spec%B% config file applies.
# %DT% c12c34=<cnt_mne>
# %DT% c13c24=<cnt_mne>
# %DD%If <cnt_mne> is a valid counter mnemonic, it gets configured as
# a pseudocounter loaded with the normalised current difference
# (c1+c2-c3-c4)/(c1+c2+c3+c4) or (c1-c2+c3-c4)/(c1+c2+c3+c4).
# The "Scale Factor" value in the %B%spec%B% config file applies.
# %DT%autorange[=YES]
# %DD%Sets the autorange mode
# %DT%window={<wtime> | AUTO}
# %DD%Sets the integration window width to <wtime> seconds or to auto mode.
# The width range of the integration time window is limited.
# %XDL%
# %XUL%
#
def icplussetup '{
local retval
if (retval = _icplussetup("$*")) {
if (SETUP) print "Error in line: $0 $*"
if (retval < 0) {
print "Usage: $0 name serial_line [parameter=value ...]"
if (yesno("\nDisplay online help", 0)) eval("help local icplus")
}
}
}'
def _icplussetup(args) '{
global ICPLUS[]
local i nparam auxlist0[] auxlist1[] larr
local icpname comdev mode
local address testcomm
local cscale auto
nparam = split(args, auxlist0)
for (i = 0; i < nparam; i++) {
if (split(auxlist0[i], larr, "=") > 1){
delete auxlist0[i]
auxlist1[larr[0]] = larr[1]
} else if (i > 1) {
delete auxlist0[i]
auxlist1[larr[0]] = "yes"
}
}
if (!((0 in auxlist0) && (1 in auxlist0))) {
printf("Bad parameters\n")
return(-1)
}
icpname = auxlist0[0]
comdev = auxlist0[1]
if (icpname + 0 == icpname) {
printf("Bad IC-PLUS name : %s\n", icpname)
return(-1)
}
if (comdev + 0 == comdev) {
mode = "spec"
} else if (index(comdev, "/")) {
mode = "dserver"
serpar[0] = 3; serpar[1] = 256 ; # 1 sec
serpar[2] = 4; serpar[3] = 0 ; # No parity
serpar[4] = 5; serpar[5] = 0 ; # 8 data bits
serpar[6] = 6; serpar[7] = 0 ; # 1 stop bit
serpar[8] = 7; serpar[9] = 19200 ; # baud rate
serpar[10] = 8; serpar[11] = 0xa ; # newline
ESRF_ERR = -1
if (esrf_io(comdev, "DevSerSetParameter", serpar) < 0)
return(-1)
} else {
printf("Bad serial line : %s\n", comdev)
return(-1)
}
if (ICPLUS["setup_n"] != SETUP_N) {
list_init ICPLUS
ICPLUS["setup_n"] = SETUP_N
}
address = ("address" in auxlist1)? auxlist1["address"] : 0
delete auxlist1["address"]
testcomm = ":CONF" address ":CURR:RANG?\n"
icplus__put(comdev, mode, testcomm)
currrang = icplus__get(comdev, mode)
if (currrang == "") {
printf("No IC-PLUS found at serial line: %s , address: %d\n", comdev, address)
return(1)
}
list_add(ICPLUS, icpname)
ICPLUS[icpname]["mode"] = mode
ICPLUS[icpname]["comdev"] = comdev
ICPLUS[icpname]["range"] = currrang
ICPLUS[icpname]["setup"] = "icplussetup " args
ICPLUS[icpname]["address"] = address
ICPLUS[icpname]["conf"] = ":CONF" address ":"
ICPLUS[icpname]["read"] = ":READ" address ":"
cscale = auxlist1["cscale"] + 0
delete auxlist1["cscale"]
ICPLUS[icpname]["cscale"] = cscale = (scale <= 0) ? 1 : cscale
ICPLUS[icpname][1] = 350e-9
ICPLUS[icpname][2] = 700e-9
ICPLUS[icpname][3] = 1.4e-6
ICPLUS[icpname][4] = 7e-6
ICPLUS[icpname][5] = 70e-6
ICPLUS[icpname][6] = 700e-6
icplus_getrange(icpname)
auto = auxlist1["autorange"]
ICPLUS[icpname]["autorange"] = (auto == "yes" || auto == "YES" || auto == 1)
delete auxlist1["autorange"]
i = auxlist1["window"]
delete auxlist1["window"]
if (i == "auto" || i == "AUTO" || i <= 0) {
ICPLUS[icpname]["window"] = "auto"
if (i <= 0)
printf("IC-PLUS %s: Bad integration window : %g sec\n", icpname, i)
} else {
ICPLUS[icpname]["window"] = i
icplus_setwin(icpname, ICPLUS[icpname]["window"]);
}
ICPLUS[icpname]["pseudo"] = 0
icp_add_pseudo "c1"
icp_add_pseudo "c2"
icp_add_pseudo "c3"
icp_add_pseudo "c4"
icp_add_pseudo "c1c2"
icp_add_pseudo "c3c4"
icp_add_pseudo "c12c34"
icp_add_pseudo "c13c24"
if (ICPLUS[icpname]["pseudo"]) {
macrodef = sprintf("icplus_getcounts(\"%s\", %d)\n", icpname, auto)
cdef("user_getcounts", macrodef, icpname)
} else {
cdef("user_getcounts", "", isgname, "delete")
}
setup_tail("icplus", icpname)
i = ""
for (i in auxlist1) {
print "Invalid parameter: " i "=" auxlist1[i]
}
if (i != "")
return(-1)
else
return(0)
}'
def icp_add_pseudo '{
local chx cnum
chx = "$1"
if (chx in auxlist1) {
ICPLUS[icpname][chx] = cnum = cnt_num(auxlist1[chx])
delete auxlist1[chx]
if (cnum >= 0)
ICPLUS[icpname]["pseudo"] = 1
} else
ICPLUS[icpname][chx] = -1
}'
def icplusunsetup '{
local idname key
key = "$1"
cdef("", "", key, "delete")
list_remove(ICPLUS, key)
if (list_n(ICPLUS) <= 0)
unglobal ICPLUS
}'
def icplus_conf(icpname, comm) '{
local read
read = (substr(comm, length(comm)) == "?")
comm = ICPLUS[icpname]["conf"] comm "\n"
return(icplus__comm(icpname, comm, read))
}'
def icplus_read(icpname, comm) '{
comm = ICPLUS[icpname]["read"] comm "\n"
return(icplus__comm(icpname, comm, 1))
}'
def icplus__comm(icpname, comm, read) '{
local mode comdev
mode = ICPLUS[icpname]["mode"]
comdev = ICPLUS[icpname]["comdev"]
icplus__put(comdev, mode, comm)
if (read) {
return(icplus__get(comdev, mode))
} else {
return("")
}
}'
def icplus__put(comdev, mode, comm) '{
local nchar
if (ISGDEBUG) print "icplus__put[" comdev"]: <" comm ">"
if (mode == "spec") {
ser_par(comdev, "flush")
nchar = ser_put(comdev, comm)
} else if (mode == "dserver") {
nchar = esrf_io(comdev, "DevSerWriteString", comm)
}
}'
def icplus__get(comdev, mode) '{
local answer len c
if (mode == "spec") {
answer = ser_get(comdev, "\n")
} else if (mode == "dserver") {
answer = esrf_io(comdev, "DevSerReadString", 2)
} else {
print "icplus__get[" comdev"]: Wrong serial mode"
return("")
}
while ((c = asc(answer)) && c <= 32) {
answer = substr(answer, 2)
}
if (c) {
answer = substr(answer, 1, length(answer) - 1)
if (ISGDEBUG) print "icplus__get[" comdev"]: <" answer ">"
return(answer)
} else
return("")
}'
#%IU% (<icpname>, <itime>)
#%MDESC%
# Sets the integration window <wtime> in sec
def icplus_setwin(icpname, wtime) '{
local wsamples
# The IC-PLUS sampling time is 10 ms (1/100 sec)
wsamples = int(wtime * 100)
# the number of averaged samples is 1 to 50
if (wsamples < 1) wsamples = 1
if (wsamples > 50) wsamples = 50
if (wsamples != ICPLUS[icpname]["wsamples"]) {
printf("IC-PLUS %s: using %g sec as integration window\n", \
icpname, wsamples / 100)
ICPLUS[icpname]["wsamples"] = wsamples
}
icplus_conf(icpname, sprintf("WDWCURR %d", wsamples))
}'
#%IU% (<icpname>, <range>)
#%MDESC%
# Selects one of the 6 available gain ranges (1 to 6).
def icplus_setrange(icpname, range) '{
icplus_conf(icpname, sprintf("CURR:RANG %d", range))
range = icplus_getrange(icpname)
printf("Setting IC-PLUS %s to range %d, %g Amps\n", \
icpname, range, ICPLUS[icpname]["fscale"])
return(range)
}'
#%IU% (<icpname>)
#%MDESC%
# Returns the currently selected gain range (1 to 6).
def icplus_getrange(icpname) '{
local comm range fullscale
range = icplus_conf(icpname, "CURR:RANG?")
if (range >= 1 && range <= 6) {
ICPLUS[icpname]["range"] = range
fullscale = ICPLUS[icpname][range]
ICPLUS[icpname]["fscale"] = fullscale
ICPLUS[icpname]["cfactor"] = ICPLUS[icpname]["cscale"] * fullscale / 0x100000
if (range == 1)
ICPLUS[icpname]["minval"] = 0
else
ICPLUS[icpname]["minval"] = \
0.5 * ICPLUS[icpname][range - 1] / fullscale * 0x100000
if (range == 6)
ICPLUS[icpname]["maxval"] = 0x200000
else
ICPLUS[icpname]["maxval"] = 0x100000
}
return(range)
}'
#%IU% (<icpname>)
#%MDESC%
#
def icplus_setfullscale(icpname, fs) '{
local r
for (r = 1; r <= 6; r++)
if (ICPLUS[icpname][r] > fs) break;
icplus_setrange(icpname, r)
return(ICPLUS[icpname]["fscale"])
}'
def icplus_default() '{
local icpname
if (list_n(ICPLUS) <= 0)
return(0)
icpname = ICPLUS["default"]
if (list_item(ICPLUS, icpname) <= 0) {
icpname = list_item(ICPLUS, 1)
ICPLUS["default"] = icpname
}
return(icpname)
}'
#%UU% {<full_scale> | <range>} [<unit>]
#%MDESC%
#
def icplusrange '{
local par icpname
par = $1
if (par <= 0 || $# > 2) {
print "Usage: $0 <full_scale> [<unit>]"
print " $0 <range> [<unit>]"
print
print "<full_scale> is current in Amps"
print "<range> is 1 to 6"
exit
}
if ((icpname = icplus_default()) == 0) {
print "No IC-PLUS units configured"
exit
}
if (par < 1)
icplus_setfullscale(icpname, par)
else
icplus_setrange(icpname, par)
}'
def icplus_getcounts(icpname, auto) '{
local answ i1 i2 i3 i4
local f imax
while(1) {
answ = icplus_read(icpname, "CURRALL?")
sscanf(answ, "%d %d %d %d", i1, i2, i3, i4)
if (!ICPLUS[icpname]["autorange"] && !auto)
break;
imax = i1
if (i2 > imax) imax = i2
if (i3 > imax) imax = i3
if (i4 > imax) imax = i4
if (imax < ICPLUS[icpname]["minval"])
icplus_setrange(icpname, ICPLUS[icpname]["range"] - 1)
else if (imax > ICPLUS[icpname]["maxval"])
icplus_setrange(icpname, ICPLUS[icpname]["range"] + 1)
else
break
sleep(ICPLUS[icpname]["wsamples"] / 100)
}
f = ICPLUS[icpname]["cfactor"]
if ((cnt = ICPLUS[icpname]["c1"]) >= 0)
S[cnt] = i1 * f / counter_par(cnt, "scale")
if ((cnt = ICPLUS[icpname]["c2"]) >= 0)
S[cnt] = i2 * f / counter_par(cnt, "scale")
if ((cnt = ICPLUS[icpname]["c3"]) >= 0)
S[cnt] = i3 * f / counter_par(cnt, "scale")
if ((cnt = ICPLUS[icpname]["c4"]) >= 0)
S[cnt] = i4 * f / counter_par(cnt, "scale")
if ((cnt = ICPLUS[icpname]["c1c2"]) >= 0)
S[cnt] = (i1-i2) / (i1+i2) / counter_par(cnt, "scale")
if ((cnt = ICPLUS[icpname]["c3c4"]) >= 0)
S[cnt] = (i3-i4) / (i3+i4) / counter_par(cnt, "scale")
if ((cnt = ICPLUS[icpname]["c12c34"]) >= 0)
S[cnt] = (i1+i2-i3-i4) / (i1+i2+i3+i4) / counter_par(cnt, "scale")
if ((cnt = ICPLUS[icpname]["c13c24"]) >= 0)
S[cnt] = (i1-i2+i3-i4) / (i1+i2+i3+i4) / counter_par(cnt, "scale")
}'
#%UU%
#%MDESC%
# Adjusts the gain range
def icplusauto '{
local icpname auto
if ((icpname = icplus_default()) == 0) {
print "No IC-PLUS units configured"
exit
}
auto = 1
icplus_getcounts(icpname, auto)
}'
#%UU%
#%MDESC%
# Shows the list of IC-PLUS units configured
def icplus '{
local ndev comdev dev_id
if (whatis("ICPLUS") & 0x01000000) {
print "\nIC-PLUS units currently configured:"
print
ndev = list_n(ICPLUS)
printf(" # %-9s %-8s %-20s %-8s\n", "Name", "Range", "Serial Line", "Address")
printf("--- --------- -------- -------------------- ---------\n")
for (i = 1; i <= ndev; i++) {
name = ICPLUS[i]
comdev = ICPLUS[name]["comdev"]
dev_id = "#" comdev "_" ICPLUS[name]["pos"]
printf("%2d %-9s %-8s %-20s %-8s\n", i, name, ICPLUS[name]["range"],\
comdev, ICPLUS[name]["address"])
}
} else {
print "No IC-PLUS currently configured."
}
}'
#%MACROS%
#%AUTHOR% P.Fajardo, (Original 04/05).
# $Revision: 1.2 $ / $Date: 2008/07/17 14:19:34 $
#%TOC%
|