#%TITLE% I400.MAC
#
#%NAME%
# Macros for operating the PTC (pyramid technical consultants inc.) I400 4-channel electrometer
#
#%CATEGORY% Detection, BPM
#
#%OVERVIEW%
# This macro set allows to control I400 units in %B%spec%B% and configure
# their signal inputs as pseudocounters.
# %BR%
# More than one I400 unit can be operated through this macro set.
#
#%EXAMPLE%
# %DL%
# %DT%i400setup mydev 0 c1=curr1 c2=curr2 c3=curr3 c4=curr4
# %DD%Configures an I400 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 2 cx=beamX cy=beamY
# %DD%Configures an I400 unit connected through the serial line #2 and
# associates normalised current differences to the pseudocounters
# beamX and beamY.
# %DT%i400show
# %DD%Display the list of I400 units currently configured.
# %XDL%
#
#%SETUP%
# Serial line in spec %B%config%B% has to be set as %B%raw%B%, %B%19200%B% baud
# %BR%
# The mode rotary switch on the I400 unit has to be set to 8.
#%END%
#%UU% <i4name> <serline> [<parameter>=<value> ...]
#%MDESC%
# Configures a I400 connected to <serline> with the name <i4name>.
# 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. By default, the address
# is read from the unit assuming only one unit on the serial line.
# %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% ci=<cnt_mne>
# %DD%If <cnt_mne> is a valid counter mnemonic, it gets configured as
# a pseudocounter loaded with sum of all channels
# ci= c1+c2+c3+c4
# The "Scale Factor" value in the %B%spec%B% config file applies.
# %DT% cx=<cnt_mne>
# %DT% cy=<cnt_mne>
# %DD%If <cnt_mne> is a valid counter mnemonic, it gets configured as
# a pseudocounter loaded with the normalised current difference:
#%BR% cx= ((c2+c3)-(c1+c4))/(c1+c2+c3+c4)
#%BR% cy= ((c1+c2)-(c3+c4))/(c1+c2+c3+c4)
#%BR% (x,y) defined for a geometry like:
#%BR% y
#%BR% ^ c1 | c2
#%BR% |---------> x
#%BR% | c4 | c3
#%BR% The "Scale Factor" value in the %B%spec%B% config file applies.
# %DT%samples[=1]
# %DD%Sets the number of sub-samples per integration period
# %XDL%
# %XUL%
#
def i400setup '{
local ret
if (ret= _i400_setup("$*")) {
if (SETUP) print "ERROR in line: $0 $*"
if (ret < 0) {
print "Usage: $0 name serline [parameter=value ...]"
if (yesno("\nDisplay online help", 0))
eval ("help local i400")
}
}
}'
def _i400_init() '{
global I400_GAIN[]
I400_GAIN[1]["range"]= 1e-9
I400_GAIN[1]["period"]= 1e-1
I400_GAIN[1]["capa"]= 0
I400_GAIN[2]["range"]= 1e-8
I400_GAIN[2]["period"]= 1e-2
I400_GAIN[2]["capa"]= 0
I400_GAIN[3]["range"]= 1e-7
I400_GAIN[3]["period"]= 1e-1
I400_GAIN[3]["capa"]= 1
I400_GAIN[4]["range"]= 1e-6
I400_GAIN[4]["period"]= 1e-2
I400_GAIN[4]["capa"]= 1
I400_GAIN[5]["range"]= 1e-5
I400_GAIN[5]["period"]= 1e-3
I400_GAIN[5]["capa"]= 1
I400_GAIN[6]["range"]= 1e-4
I400_GAIN[6]["period"]= 1e-4
I400_GAIN[6]["capa"]= 1
}'
#%IU%
def _i400_setup(args) '{
global I400_PAR[]
local ipar npar pars[] setval[] tarr[]
local name sdev addr
local cname cnum defname
_i400_init()
npar= split(args, pars)
for (ipar=0; ipar<npar; ipar++) {
if (split(pars[ipar], tarr, "=") > 1) {
setval[tarr[0]]= tarr[1]
delete pars[ipar]
}
else if (ipar>1) {
setval[pars[ipar]]= "yes"
delete pars[ipar]
}
}
if (!((0 in pars)&&(1 in pars))) {
printf("I400 ERROR: bad setup parameters\n")
return (-1)
}
name= pars[0]
sdev= pars[1]
if (name + 0 == name) {
printf("I400 ERROR: Bad name\n")
return (-1)
}
if (sdev + 0 != sdev) {
printf("I400 ERROR: Bad serial unit\n")
return (-1)
}
if (I400_PAR["setup_n"] != SETUP_N) {
list_init I400_PAR
I400_PAR["setup_n"] = SETUP_N
}
list_add(I400_PAR, name)
I400_PAR[name]["serline"]= sdev + 0
addr= ("address" in setval)? setval["address"]+0 : -1
delete setval["address"]
I400_PAR[name]["address"]= addr
if (_i400_initcom(name)<0) {
return (1)
}
if ("samples" in setval) {
I400_PAR[name]["samples"]= setval["samples"]
delete setval["samples"]
} else {
I400_PAR[name]["samples"]= 1
}
if ("capacitor" in setval) {
_i400_setcapacitor(name, setval["capacitor"])
delete setval["capacitor"]
}
if ("gain" in setval) {
_i400_setgain(name, setval["gain"])
delete setval["gain"]
}
_i400_initdata
for (cname in I400_DATA) {
I400_PAR[name][cname]= -1
if (cname in setval) {
if ((cnum= cnt_num(setval[cname]))!=-1) {
I400_PAR[name][cname]= cnum
I400_PAR[name]["pseudo"]= 1
} else {
printf("I400 WARNING: counter <%s> is not valid\n", cname)
}
delete setval[cname]
}
}
if (I400_PAR[name]["pseudo"]) {
defname= "i4_" name
cdef("user_prepcount", sprintf("_i400_prepcount(\"%s\")\n", name), defname)
cdef("user_getcounts", sprintf("_i400_getcounts(\"%s\")\n", name), defname)
}
setup_tail("i400", name)
ipar= ""
for (ipar in setval) {
printf("I400 ERROR: Invalid parameter <%s> \n", ipar)
}
if (ipar != "")
return (-1)
return (0)
}'
#%UU% <i4name> <samples>
#%MDESC%
# Sets the number of sub-samples taken during intergration period
# for the i400 unit <i4name>
#
def i400samples '{
local name samp
if ($#!=2) {
print "Usage: $0 <name> <samples>"
exit
}
name= "$1"
if (list_check(I400_PAR, name)<=0) {
printf("I400 ERROR: wrong i400 name <%s>\n", name)
} else {
samp= ($2+0)>0 ? ($2+0) : 1
I400_PAR[name]["samples"]= samp
}
}'
def i400gainlist '{
local ig
printf("\nI400 GAIN settings:\n")
printf("GAIN CAPAC PERIOD RANGE\n")
for (ig=1; ig<7; ig++) {
printf("%4d %-5.5s %8.3g s %8.3g A\n", ig, I400_GAIN[ig]["capa"] ? "HIGH" : "LOW", \
I400_GAIN[ig]["period"], I400_GAIN[ig]["range"])
}
printf("\n")
}'
def i400gain '{
local name gain
if (($#!=1)&&($#!=2)) {
print "Usage: $0 <name> [<gain>]"
exit
}
name= "$1"
if (list_check(I400_PAR, name)<=0) {
printf("I400 ERROR: wrong i400 name <%s>\n", name)
} else {
if ($#==2) {
gain= $2 + 0
if ((gain<0)||(gain>6)) {
printf("I400 ERROR: gain values ranges from 1 to 6\n")
} else {
_i400_setgain(name, gain)
}
} else {
gain= _i400_getgain(name)
if (gain) {
printf("Current Gain is : %d\n", gain)
printf("- Capacitor = %s\n", I400_GAIN[gain]["capa"])
printf("- Period = %g s\n", I400_GAIN[gain]["period"])
printf("- Range = %g A\n", I400_GAIN[gain]["range"])
} else {
printf("Gain is not set.")
}
}
}
}'
def _i400_setgain(name, gain) '{
local cap per
if (gain>0) {
_i400_setcapacitor(name, I400_GAIN[gain]["capa"])
_i400_setperiod(name, I400_GAIN[gain]["period"])
}
I400_PAR[name]["gain"]= gain
}'
def _i400_getgain(name) '{
return I400_PAR[name]["gain"]
}'
def _i400_setperiod(name, per, samp) '{
local cmd
if (samp>0) {
cmd= sprintf("CONF:GAT:INT:PER %g %d", per, samp)
} else {
cmd= sprintf("CONF:GAT:INT:PER %g", per)
}
if (_i400_io(name, cmd)<0) {
printf("I400 ERROR: Fail to set acquisition period\n")
return (-1)
}
return (0)
}'
#%UU% <i4name> <capacitor>
#%MDESC%
# Sets feedback capacitor to low value (0) or high value (1)
#
def i400capacitor '{
local name cap
if (($#!=1)&&($#!=2)) {
print "Usage: $0 <name> [<capacitor>]"
exit
}
name= "$1"
if (list_check(I400_PAR, name)<=0) {
printf("I400 ERROR: wrong i400 name <%s>\n", name)
} else {
if ($#==2) {
cap= $2 + 0
if ((cap<0)||(cap>1)) {
printf("I400 ERROR: capacitor can either 0 (low) or 1 (high)\n")
} else {
_i400_setcapacitor(name, cap)
}
} else {
cap= _i400_getcapacitor(name)
printf("I400 module <%s> capacitor is %s (%d).\n", name, cap?"HIGH":"LOW", cap)
}
}
}'
#%IU%
def _i400_setcapacitor(name, cap) '{
local cmd
cmd= sprintf("CONF:CAP %d", cap>0 ? 1 : 0)
if (_i400_io(name, cmd)<0) {
printf("I400 ERROR: Fail to set capacitor\n")
return (-1)
}
return (0)
}'
#%IU%
def _i400_getcapacitor(name) '{
local ret cap val
if ((ret=_i400_io(name, "CONF:CAP?"))<0) {
printf("I400 ERROR: failed to read capacitor\n")
return (-1)
}
if (sscanf(ret, "%d,%f F", cap, val)!=2) {
printf("I400 ERROR: failed to parse capacitor value\n")
return (-1)
}
return (cap)
}'
#%UU%
#%MDESC%
# Shows the list of I400 units configured
#
def i400show '{
local nb ii name
nb= list_n(I400_PAR)
if (!nb) {
printf("\nNO I400 device configured.\n")
}
else {
printf("\nName SL Addr Samples\n")
printf("-------- -- ---- -------\n")
for (ii=1; ii<=nb; ii++) {
name= list_item(I400_PAR, ii)
printf("%-8.8s %2d %4d %7d\n", name, I400_PAR[name]["serline"], \
I400_PAR[name]["address"], I400_PAR[name]["samples"])
}
}
}'
#%IU%
def _i400_initdata '{
global I400_DATA[]
I400_DATA["c1"]= -1.
I400_DATA["c2"]= -1.
I400_DATA["c3"]= -1.
I400_DATA["c4"]= -1.
I400_DATA["ci"]= -1.
I400_DATA["cx"]= -1.
I400_DATA["cy"]= -1.
I400_DATA["ci12"]= -1.
I400_DATA["cd12"]= -1.
}'
#%IU% [<i4name>]
#%MDESC%
# Unsetup given i400 unit or all units
#
def i400unsetup '{
local ncfg icfg
if ($#==1) {
_i400_unsetup("$1")
} else {
ncfg= list_n(I400_PAR)
for (icfg=1; icfg<=ncfg; icfg++)
_i400_unsetup(list_item(I400_PAR, icfg))
}
if (list_n(I400_PAR)==0) {
unglobal I400_PAR I400_DATA
}
}'
#%IU%
def _i400_unsetup(name) '{
local defname
defname= "i4_" name
cdef("", "", defname, "delete")
list_remove(I400_PAR, name)
}'
#%IU%
def _i400_prepcount(name) '{
local period samples cmd minper
I400_PAR[name]["started"]= 0
if (I400_PAR[name]["gain"]>0) {
period= I400_GAIN[I400_PAR[name]["gain"]]["period"]
if (COUNT_TIME < period) {
printf("I400 WARNING: Integration time should be greater than %g s. with gain %d\n", period, I400_PAR[name]["gain"])
}
}
else {
period= COUNT_TIME
minper= 1e-4*I400_PAR[name]["samples"]
if (period < minper) {
printf("I400 WARNING: Integration time cannot be lower than %g s. with %d samples\n", minper, I400_PAR[name]["samples"])
period= minper
}
if (period > 65.0) {
printf("I400 WARNING: Integration time cannot be greater than 65 s.\n")
period= 65.
}
samples= I400_PAR[name]["samples"]
_i400_setperiod(period, samples)
}
if (_i400_io(name, sprintf("TRIG:POIN %d", I400_PAR[name]["samples"]))<0) {
printf("I400 ERROR: failed to set trigger point\n")
return (-1)
}
if (_i400_io(name, "INIT")<0) {
printf("I400 ERROR: Fail to start acquisition period\n")
return (-1)
}
I400_PAR[name]["started"]= 1
}'
#%IU%
def _i400_getcounts(name) '{
local cname cnum
if (_i400_read(name)==-1) {
printf("I400 ERROR> Failed to read I400 values\n")
_i400_initdata
}
for (cname in I400_DATA) {
cnum= I400_PAR[name][cname]
if ((cnum!=-1)&&(!counter_par(cnum, "disable"))) {
S[cnum]= I400_DATA[cname] / counter_par(cnum, "scale")
}
}
}'
#%IU%
def _i400_read(name) '{
local data[] dstr
local per c1 c2 c3 c4 ov
_i400_initdata
if (!I400_PAR[name]["started"])
return (0)
if ((dstr=_i400_io(name, "FETC:CURR?"))==-1) {
printf("I400 ERROR: Failed to read data\n")
return (-1)
}
# --- dstr = 1.0000e-02 S,5.7983e-12 A,-1.2207e-12 A,1.2207e-12 A,1.8311e-12 A,0
if (sscanf(dstr, "%f S,%f A,%f A,%f A,%f A,%d", per, c1, c2, c3, c4, ov)!=6) {
printf("I400 ERROR: Failed to parse data\n")
return (-1)
}
I400_PAR[name]["period"]= per
if (ov) {
printf("I400 ERROR: over range byte set\n")
return (-1)
}
I400_DATA["c1"]= c1
I400_DATA["c2"]= c2
I400_DATA["c3"]= c3
I400_DATA["c4"]= c4
I400_DATA["ci12"]= I400_DATA["c1"]+I400_DATA["c2"]
if (I400_DATA["ci12"]!=0) {
I400_DATA["cd12"]= (I400_DATA["c1"]-I400_DATA["c2"])/I400_DATA["ci12"]
} else {
I400_DATA["cd12"]= -1.
}
I400_DATA["ci"]= I400_DATA["c1"]+I400_DATA["c2"]+I400_DATA["c3"]+I400_DATA["c4"]
if (I400_DATA["ci"]!=0) {
I400_DATA["cx"]= ((I400_DATA["c2"]+I400_DATA["c3"])-(I400_DATA["c1"]+I400_DATA["c4"]))/I400_DATA["ci"]
I400_DATA["cy"]= ((I400_DATA["c1"]+I400_DATA["c2"])-(I400_DATA["c3"]+I400_DATA["c4"]))/I400_DATA["ci"]
} else {
I400_DATA["cx"]= -1.
I400_DATA["cy"]= -1.
}
return (0)
}'
#%IU%
def _i400_initcom(name) '{
local addr
if (_i400_io(name, "\r")<0) {
printf("I400 ERROR: serial access failed\n")
return (-1)
}
addr= I400_PAR[name]["address"]
if (addr==-1) {
addr= _i400_io(name, "#?") + 0
if (addr < 0) {
printf("I400 ERROR: cannot get device address\n")
return (-1)
}
I400_PAR[name]["address"]= addr
}
if (_i400_io(name, sprintf("#%d", addr), 1)<0) {
printf("I400 ERROR: failed to select device by address\n")
return (-1)
}
if (_i400_io(name, "TRIG:SOUR INT")<0) {
printf("I400 ERROR: failed to set internal trigger\n")
return (-1)
}
return (0)
}'
#%IU%
def _i400_io(name, com, noack) '{
local rep str sdev
sdev= I400_PAR[name]["serline"]
ser_par(sdev, "flush")
ser_put(sdev, str=com "\n")
rep= ser_get(sdev, "\n")
rep= substr(rep, 1, length(rep)-1)
if (rep != com) {
printf("I400 ERROR: command not echoed\n")
return (-1)
}
if (!noack) {
rep= ser_get(sdev, "\r\n")
rep= substr(rep, 1, length(rep)-2)
if (index(com, "?")) {
return (rep)
} else {
if (rep!="OK") {
printf("I400 ERROR: command <%s> failed\n", com)
return (-1)
}
}
}
return (0)
}'
#%IMACROS%
#%MACROS%
#%AUTHOR% EP, BLISS
# $Revision: 1.2 $ / $Date: 2008/09/26 12:40:30 $
#%TOC%
#%END%
#%LOG%
#$Log:$
|