#%TITLE% MUSST.MAC
#
#%NAME%
# Macros for operating and testing the MUSST module
#
#%CATEGORY% Detection, Other hardware, Isg
#
#%OVERVIEW%
# This macro set allows to set MUSST isgdevices in %B%spec%B%, configure
# their signal inputs as pseudocounters, edit and download programs,
# and provide simple macros for basic operation.
# %BR%
# An interactive macro %B%musst%B% can be used for device configuration and
# monitoring.
# %BR%
# More than one MUSST module can be operated through this macro set.
#
#%EXAMPLE%
# %DL%
# %DT%musstsetup mainsync 2
# %DD%Configures a MUSST unit connected to the serial line #2 and assigns the
# name \"mainsync\" to it.
# %DT%musstsetup pitch id33/serlin/11
# %DD%Configures a MUSST unit associated to the TACO device \"id33/serlin/11\"
# %DT%musst
# %DD%Starts the interactive test program with the default unit.
# %XDL%
#
#%DEPENDENCIES%
# These macros make use of the following macro sets:
# %UL%
# %LI%stlist.mac
# %LI%isgdevice.mac
# %LI%isg.mac
# %XUL%
#%SETUP%
# A %B%musstsetup%B% macro must be included in the setup file for every MUSST
# unit configured. Each unit is identified by its name that must be a unique
# isgdevice identifier.
#%END%
#%HISTORY%
#$Log: musst.mac,v $
#Revision 1.12 2023/03/28 09:08:35 claustre
#Fix a bug in muss_config with timer_mode
#
#Revision 1.11 2014/10/09 13:20:31 berruyer
#Add a fon;
#
#musst_get_timer return the musst CLOCK
#improve Macro counter to be used without MUSST is the master spec timer
#
#Revision 1.10 2011/03/09 09:24:25 homsrego
#*musst_list_files: didn't list all files in the directory - fixed
#
#Revision 1.9 2010/08/16 11:56:35 guilloud
#*musst_list_files : add a +1 to be able to see all files of the directory.
#*cosmetic.
#
#Revision 1.8 2009/11/20 00:00:00 ahoms
#Do not ask channel values while RUNCT is active; estime it for timer
#
#Revision 1.7 2008/10/09 13:46:14 beteva
#changes in musst_getdata - maxln fixed to 1K
#
#Revision 1.6 2008/08/12 14:24:31 rey
#doc change
#
#Revision 1.5 2008/08/12 14:16:24 rey
#documentation changes
#
#Revision 1.4 2008/07/29 08:43:59 ahoms
#Added basic macro counter/timer support
#
#Revision 1.3 2008/06/30 10:40:54 guijarro
#added extra argument to musst_getdata to specify buffer (0 by default = old behaviour-
#
#Revision 1.2 2005/08/17 14:22:59 guijarro
#new version, added fast update and getdata
#
#Revision 1.1 2004/03/10 17:24:26 rey
#Initial revision
#
#
#%END%
jtdo("isg.mac")
#%UU% <musst_name> <comdev> [<parameter>=<value> ...]
#%MDESC%
# Configures a MUSST unit connected to <comdev> with the name <musst_name>.
# 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 isgdevices in dasychain.
# If <addr> is a non-numerical value, it is treated as the isgdevice
# address set by the ADDR command and stored internally in the unit.
# On the other hand if <addr> is a numerical value it indicates the
# relative position of the module in the serial line chain starting
# from 0.
# If this parameter is not specified, %B%spec%B% looks for the
# first MUSST unit in the chain.
# %DT%ch<n>=<cnt_mne>
# %DD%If <cnt_mne> is a valid counter mnemonic, it gets configured as a
# pseudocounter that uses the nth channel in MUSST (n = 1 to 6).
# The \"Scale Factor\" value in the %B%spec%B% config file applies.
# %DT%update=<update_time>
# %DD%Sets the update time in seconds for the interactive macro (musst).
# The default is 1 second.
# %XDL%
# %XUL%
def musstsetup '{
local retval
if ($# == 0 || (retval = _musstsetup("$*"))) {
if (SETUP) print "Error in line: $0 $*"
if (retval < 0) {
print "Usage: $0 musst_name comm_device [parameter=value ...]"
if (yesno("\nDisplay online help", 0)) eval("help local musst")
}
}
}'
def _musstsetup(args) '{
global MUSST[]
global MUSST_AUX[]
global MUSST_TIMER[]
local i nparam auxlist0[] auxlist1[] larr
local comdev isgdev isgname
local chmne[] nchan macrodef
MUSST_TIMER["1MHZ"]= 1e6
MUSST_TIMER["1KHZ"]= 1e3
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)
}
isgname = auxlist0[0]
comdev = auxlist0[1]
if (("address" in auxlist1) && !(index(comdev, ":"))){
if (auxlist1["address"] + 0 == auxlist1["address"])
isgdev = isgdevice_add(isgname, comdev , 0, auxlist1["address"])
else
isgdev = isgdevice_add(isgname, comdev , 1, auxlist1["address"])
delete auxlist1["address"]
} else
isgdev = isgdevice_add(isgname, comdev , 3, "MUSST")
if (isgdev <= 0 || isgdevice_check(isgname, 3, "MUSST") == 0) {
printf("No MUSST device found at %s: %s\n", \
index(comdev, ":")? "gpib address" : "serial port", comdev)
return(1)
}
if (MUSST_AUX["setup_n"] != SETUP_N) {
list_init MUSST
MUSST_AUX["setup_n"] = SETUP_N
}
if (list_add(MUSST, isgname) <= 0) {
printf("Invalid musst name: %s\n", isgname)
return(-1)
}
MUSST[isgname]["setup"] = "musstsetup " args
nchan = 0
macrodef = ""
for(i = 0; i <= 6; i++) {
local chname mne num
if (i == 0)
chname = "timer"
else
chname = "ch" i
num = (chname in auxlist1)? cnt_num(mne = auxlist1[chname]) : -1
delete auxlist1[chname]
if (num >=0 && counter_par(num, "controller")=="NONE") {
chmne[i] = mne
nchan++
} else
chmne[i] = -1
MUSST[isgname][chname] = chmne[i]
macrodef = macrodef ", " chmne[i]
}
if (nchan) {
macrodef = sprintf("musst_getcounts(\"%s\"%s)\n", isgname, macrodef)
cdef("user_getcounts", macrodef, isgname)
} else {
cdef("user_getcounts", "", isgname, "delete")
}
MUSST[isgname]["update"] = (auxlist1["update"] + 0)
delete auxlist1["update"]
setup_tail("musst", isgname)
i = ""
for (i in auxlist1) {
print "Invalid parameter: " i "=" auxlist1[i]
}
if (i != "")
return(-1)
else
return(0)
}'
def musstunsetup '{
local isgname
isgname = "$1"
cdef("", "", isgname, "delete")
isgdevice_remove(isgname)
list_remove(MUSST, isgname)
if (list_n(MUSST) <= 0)
unglobal MUSST MUSST_AUX
}'
def musst_setdefault(isgname) '{
if (MUSST[0] <= 0) {
print "No MUSST devices configured. Use first \`musstsetup\'."
return(0)
}
if (isgname != "") {
MUSST_AUX["default"] = isgname
if (!list_check(MUSST, isgname)) {
print "\`" isgname "\' is not a valid MUSST unit."
}
}
if (!list_check(MUSST, MUSST_AUX["default"])) {
MUSST_AUX["default"] = MUSST[1]
print "Setting \`" MUSST_AUX["default"] "\' as default MUSST unit."
}
return(1)
}'
def musst_comm(comm, isgname) '{
isgname = isgname? isgname : ""
if (!musst_setdefault(isgname)) {
print "Bad musst unit."
exit
}
isgname = MUSST_AUX["default"]
if (index(comm, "?") == 1)
return (isgdevice_comm(isgname, comm))
else
return (isgdevice_comm_ack(isgname, comm))
}'
def musst_get_timer_scale(isgname) '{
local cfg npar pars[]
cfg= musst_comm("?TMRCFG", isgname)
npar= split(cfg, pars)
return(MUSST_TIMER[pars[0]])
}'
def musstcomm '{
print musst_comm("$1", "$2")
}'
#%UU% [<musst_name>]
#%MDESC%
# Prints the current state (Sends the request ?STATE to MUSST).
def musststate 'musstcomm "?STATE RETCODE" $*'
#%UU% [<musst_name>]
#%MDESC%
# Starts program execution (Sends the command RUN to MUSST).
def musstrun 'musst_comm("RUN", "$*")'
#%UU% [<musst_name>]
#%MDESC%
# Stops program execution (Sends the command STOP to MUSST).
def musststop 'musst_comm("STOP", "$*")'
def musst_getstate(isgname) '{
local state
if ((state = isgdevice_comm(isgname, "?STATE")) == ISGDEV_ERR)
state = "???"
MUSST_AUX["nextT"] = time() + 30
if (state == "IDLE" || state == "STOP" || state == "BREAK") {
if ((state = isgdevice_comm(isgname, "?STATE RETCODE")) == ISGDEV_ERR)
state = "???"
}
if (state != MUSST[isgname]["state"]) {
MUSST[isgname]["state"] = state
return(1)
} else
return(0)
}'
def musst_getcounts(isgname, _timer, _ch1, _ch2, _ch3, _ch4, _ch5, _ch6) '{
local answ i j
local chlist[] chliststr
if (_timer >= 0 && !counter_par(_timer, "disable")) {
chlist[0] = _timer
chliststr = "TIMER"
} else {
chlist[0] = -1
chliststr = ""
}
chlist[1] = _ch1
chlist[2] = _ch2
chlist[3] = _ch3
chlist[4] = _ch4
chlist[5] = _ch5
chlist[6] = _ch6
for (i = 1; i <= 6; i++) {
if (chlist[i] >= 0 && !counter_par(chlist[i], "disable"))
chliststr = chliststr " CH" i
else
chlist[i] = -1
}
if (chliststr != "") {
local value[]
answ = isgdevice_comm(isgname, sprintf("?VAL %s", chliststr))
split(answ, value)
for (i = j = 0; i <= 6; i++) {
if (chlist[i] >= 0)
S[chlist[i]] = value[j++] / counter_par(chlist[i], "scale")
}
}
}'
#the value maxnl has been set to 1K instead of the calculated value to permit
#the transfer of all the data, as it seems that it overruns some of the data
#and unfortunately delivers bad data!!!!
def musst_getdata(isgname, nlines, npts, mdat, buffer) '{
local maxnl
maxnl = 1024 #int(((0x10000 / 4) - 1) / npts)
long array ldat[maxnl][npts]
for (nl = 0; nl < nlines; nl += maxnl) {
nn = nlines - nl
if (nn > maxnl)
nn = maxnl
comm = sprintf("?*EDAT %d %d %d", nn * npts, buffer, nl * npts)
ndat = isgdevice_getdata(isgname, comm, ldat)
if (ndat != nn * npts)
return(0)
mdat[nl:nl+nn-1][] = ldat
}
return(nlines)
}'
#%UU% [<device_name>]
#%MDESC%
# Macro that runs the interactive loop. %B%musst%B% refresh certain
# information on the screen and at the same time accepts commands
# from the standard input.
# %BR%
#
def musst '{
local isgname options
isgname = $#? "$1": ""
if (!$# || list_check(MUSST, isgname) > 0){
if (musst_setdefault(isgname)) {
isgname = MUSST_AUX["default"]
MUSST[isgname]["prompt"] = "(" MUSST_AUX["default"] ")"
}
} else if (isgdevice_add("Musst", "$1", 3, "MUSST") > 0) {
isgname = "Musst"
MUSST[isgname]["prompt"] = ""
} else {
print "No MUSST unit found."
isgname = ""
}
if (!isgname) {
print "Usage: $0 musstname"
print " or $0 comm_device (serial or GPIB)"
if (yesno("\nDisplay online help", 0))
eval("help local musst")
} else {
rdef isg_prompt "musst_prompt"
rdef isg_update "musst_update"
rdef isg_show "musst_show_comm"
rdef isg_process "musst_process_comm"
isg_main(isgname, options, 0, MUSST[isgname]["update"])
}
}'
def musst_update '{
update_flag = musst_getstate(isgname);
}'
#%IU%
#%MDESC%
# Displays the prompt on the screen. If the "update" flag is set also
# displays the board state.
#
def musst_prompt '
printf("MUSST%s: %s - %s", MUSST[isgname]["prompt"], date(), \
MUSST[isgname]["state"])
'
def musst_show_comm '
isg_show_comm(".p, .program", "Upload program")
isg_show_comm(".e, .edit", "Edit program file")
isg_show_comm(".t, .trace", "Trace program execution")
isg_show_comm(".c, .config", "Display spec setup")
'
#%IU%
#%MDESC%
#
def musst_process_comm '
if (comm[0] == ".program" || comm[0] == ".p") {
local filepath line clear _msg
filepath = musst_choose_file(isgname)
if (getline(filepath, "open") < 0){
printf("Can\'t open file \`%s\'.\n", filepath)
}
else {
_msg = sprintf("\nDisplay file content(%s)", filepath)
if (yesno(_msg, 0)) {
print "\nBegin ::::::::::::::::::::::::::: Program code\n\n"
getline(filepath, "open")
while ((line = getline(filepath)) != -1){
print line
}
print
print "\nEnd ::::::::::::::::::::::::::::: Program code\n\n"
}
if (yesno("\nUpload program into the device", 1)) {
clear = yesno("\nDelete existing program", 1)
print
if (musst_upload_program(isgname, filepath, clear)) {
print "\nProgram succesfully loaded."
}
}
}
return(1)
}
else if (comm[0] == ".edit" || comm[0] == ".e") {
local filepath line clear
filepath = musst_choose_file(isgname)
if (!file_info(filepath, "isreg")){
if (yesno(sprintf("File \`%s\' does not exist. Cancel", filepath), 1))
return(1)
}
unix(sprintf("touch %s", filepath))
if (getline(filepath, "open") < 0)
printf("\nCan\'t open file.")
else {
getline(filepath, "close")
unix(sprintf("%s %s &", EDITOR, filepath))
}
return(1)
}
else if (comm[0] == ".trace" || comm[0] == ".t") {
musst_trace_program(isgname)
return(1)
}
else if (comm[0] == ".config" || comm[0] == ".c") {
local aux
print
if (ISGDEV_CONF[isgname]["mode"] == "gpib") {
printf("\tGPIB address: %s\n", ISGDEV_CONF[isgname]["comdev"])
}
else {
printf("\tSerial line: %s (%s)\n", ISGDEV_CONF[isgname]["comdev"], \
ISGDEV_CONF[isgname]["mode"])
printf("\tPosition : %d\n", ISGDEV_CONF[isgname]["pos"])
}
print
aux = MUSST[isgname]["foutbeam"]
printf("\tPseudocounters:\n")
musst_cfg_show_cnt(isgname, "ch1")
musst_cfg_show_cnt(isgname, "ch2")
musst_cfg_show_cnt(isgname, "ch3")
musst_cfg_show_cnt(isgname, "ch4")
musst_cfg_show_cnt(isgname, "ch5")
musst_cfg_show_cnt(isgname, "ch6")
musst_cfg_show_cnt(isgname, "timer")
print
printf("\tSetup line: %s\n", MUSST[isgname]["setup"])
return(1)
}
'
def musst_cfg_show_cnt(isgname, chname) '{
local mne
printf("\t%20s: ", chname)
mne = MUSST[isgname][chname]
if (mne < 0)
printf("---")
else
printf("%s [x%g]", mne, counter_par(cnt_num(mne), "scale"))
print
}'
def musst_list_files(path, lastfilepath) '{
local aux filelist[] opminfo[] file selected
local ii, n, n0
uxcom = "ls " path
unix(uxcom, aux)
n0 = n = split(aux, filelist, "\n")
for (ii in filelist) {
filepath = path filelist[ii]
if (!file_info(filepath, "isreg")) {
delete filelist[ii]
n--
}
}
if (!n) {
printf("No files found in \`%s\'.\n", path)
return("")
}
print
print "Directory: " path
print
print "File Date"
print "------------------------ ------------------------"
selected = 0
for (ii = 0; ii < n0; ii++) {
local filepath lastfound mtime lastmtime
if (!(ii in filelist))
continue
file = filelist[ii]
filepath = path file
if (filepath == lastfilepath) {
lastfound = 1
selected = ii
tty_cntl("so")
}
mtime = file_info(filepath, "mtime")
printf("%-25s %s\n", file, date(mtime))
tty_cntl("se")
if (mtime > lastmtime) {
lastmtime = mtime
if (!lastfound)
selected = ii
}
}
return(filelist[selected])
}'
def musst_choose_file(isgname) '{
local file path
path = isg_path("musst/")
file = musst_list_files(path, MUSST[isgname]["lastfilepath"])
file = getval("\nFile to load", file)
if (index(file, "/"))
return(file)
else {
file = path file
return(file)
}
}'
def musst_slow_upload_program(musst_name, filepath, clear) '{
local line answer
if (getline(filepath, "open") < 0)
return(0)
MUSST[musst_name]["lastfilepath"] = filepath
if (clear)
isgdevice_comm_ack(musst_name, "CLEAR")
while ((line = getline(filepath)) != -1) {
answer = isgdevice_comm_ack(musst_name, sprintf("+%s", line))
if(answer == ISGDEV_ERR) {
printf("\nError sending command [%s].\n", line)
printf("Upload aborted.\n")
break;
} else if (answer != "OK") {
printf("Error in line: %s", line)
printf(" %s\n", answer)
}
}
return (1)
}'
def musst_upload_program(musst_name, filepath, clear) '{
local line answer prog
if (getline(filepath, "open") < 0) {
print "Cannot open program file:", filepath
return(0)
}
MUSST[musst_name]["lastfilepath"] = filepath
if (clear)
isgdevice_comm(musst_name, "CLEAR")
prog = ""
while ((line = getline(filepath)) != -1) {
prog = prog "+" line
}
answer = isgdevice_comm(musst_name, prog)
if(answer == ISGDEV_ERR) {
printf("\nError sending command [%s].\n", line)
printf("Upload aborted.\n")
return(0);
}
answer = isgdevice_comm_ack(musst_name, "?list err")
if (answer != "") {
print "Program contains errors:"
printf("%s\n", answer)
return(0)
} else
return (1)
}'
def musst_trace_program(isgname, step) '{
local state waitflg stepcomm
if (!step)
step = 1
if ((state = isgdevice_comm(isgname, "?STATE")) == ISGDEV_ERR)
return
if (state == "RUN" || state == "NOPROG" || state == "PROG") {
print "Cannot step program"
return
}
stepcomm = sprintf("STEP %d", step)
instrcomm = "?INSTR TIME CODE"
if (step < 0)
instrcomm = instrcomm " ASM"
print "\nSTEPPING: pulse the space bar to continue. \'Q\' to finish."
while(1) {
if (!waitflg) {
isgdevice_comm(isgname, stepcomm)
if ((state = isgdevice_comm(isgname, "?STATE")) == ISGDEV_ERR)
return
if (state == "IDLE") {
local retval
retval = isgdevice_comm(isgname, "?RETCODE")
printf("Program exit");
if (retval != "")
printf(" - return value : %s", retval);
print
return
} else if (state == "ERROR") {
print "Program ERROR - ", isgdevice_comm(isgname, "?RETCODE")
return
} else if (state == "BREAK"){
printf("Breakpoint #%d reached\n", \
isgdevice_comm(isgname, "?RETCODE"))
waitflg = 1
} else {
print " >> " isgdevice_comm(isgname, instrcomm)
waitflg = 0
}
}
while((time() - t0) < 0.3)
sleep(.01)
t0 = time()
if ((a = input(-1)) != "") {
if (a == " ") {
waitflg = !waitflg
if (waitflg)
print "PAUSED: pulse the space bar to continue. \'Q\' to finish"
} else if (a == "q" || a == "Q") {
print "Stepping aborted."
return
}
}
}
}'
def musst_config(cnum, type, unit, module, chan) '{
global MUSST_CT[]
local mne cmd factor
if (type == "ctrl") {
printf("Using MUSST \"%s\" counters\n", musst_ADDR)
MUSST_CT[musst_ADDR]["timer_mode"] = 0
return
}
mne = cnt_mne(cnum)
if (chan == 0) {
printf("Configuring \"%s\" as timer\n", mne)
factor = counter_par(cnum, "scale")
cmd = sprintf("TIMER %d", factor)
musst_comm(cmd, musst_ADDR)
MUSST_CT[musst_ADDR]["running"] = 0
MUSST_CT[musst_ADDR]["start_ts"] = 0
MUSST_CT[musst_ADDR] = cnum
MUSST_CT[musst_ADDR]["timer_mode"] = 1
}
}'
def musst_cmd(cnum, key, p1, p2) '{
global MUSST_CT[]
local chan name cmd ans val is_running
if (cnum != "..") {
chan = counter_par(cnum, "channel")
name = (chan == 0) ? "TIMER" : sprintf("CH%d", chan)
}
if (key == "get_status") {
ans = musst_comm("?STATE", musst_ADDR)
is_running = (ans == "RUN")
MUSST_CT[musst_ADDR]["running"] = is_running
return is_running
} else if (key == "prestart_all") {
if (!MUSST_CT[musst_ADDR]["timer_mode"]) {
MUSST_CT[musst_ADDR]["factor"] = musst_get_timer_scale(musst_ADDR)
cmd = sprintf("RUNCT %d", p1 * MUSST_CT[musst_ADDR]["factor"])
musst_comm(cmd, musst_ADDR)
MUSST_CT[musst_ADDR]["running"] = 1
MUSST_CT[musst_ADDR]["start_ts"] = time()
}
} else if ((key == "start_one") && (chan == 0)) {
MUSST_CT[musst_ADDR]["factor"] = counter_par(cnum, "scale")
cmd = sprintf("RUNCT %d", p1 * MUSST_CT[musst_ADDR]["factor"])
musst_comm(cmd, musst_ADDR)
MUSST_CT[musst_ADDR]["running"] = 1
MUSST_CT[musst_ADDR]["start_ts"] = time()
} else if (key == "counts") {
if (MUSST_CT[musst_ADDR]["running"]) {
if (chan == 0)
val = (time() - MUSST_CT[musst_ADDR]["start_ts"]) * MUSST_CT[musst_ADDR]["factor"]
else
val = 0
} else {
cmd = sprintf("?VAL %s", name)
ans = musst_comm(cmd, musst_ADDR)
sscanf(ans, "%d", val)
}
return val
} else if (key == "halt_all") {
musst_comm("ABORT", musst_ADDR)
musst_comm("BTRIG 0", musst_ADDR)
MUSST_CT[musst_ADDR]["running"] = 0
} else if (key == "halt_one") {
cmd = sprintf("%s%s STOP", (chan == 0) ? "" : "CH ", name)
musst_comm(cmd, musst_ADDR)
}
}'
#%MACROS%
#%AUTHOR% P.Fajardo, (Original 2/04).
# $Revision: 1.12 $ / $Date: 2023/03/28 09:08:35 $
#%TOC%
|