#%TITLE% OPIOM.MAC
#
#%NAME%
# OPIOM.MAC - Macros for operating and testing OPIOM units
#
#
#%CATEGORY% Generic I/O, Isg
#
#%OVERVIEW%
#
# An interactive macro %B%opiom%B% can be used for device configuration and
# monitoring.
# %BR%
# More than one OPIOM module can be operated through this macro set.
#
#%EXAMPLE%
# %DL%
# %DT%opiomsetup op1 2 address=O1
# %DD%Configures a OPIOM unit connected to the serial line #2 with address
# O1 and assigns the name \"op1\" to it .
# %DT%opiomsetup ldet2 id33/serial/0 address=2
# %DD%Configures a OPIOM unit connected in the second position of a daisychain
# accesed by the ESRF device id33/serial/0
# and assigns the name \"ldet2\" to it .
# %DT%opiom
# %DD%Starts the interactive test program with the default module.
# %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%opiomsetup%B% macro must be included in the setup file for every OPIOM
# module configured. Each module is identified by its name that must be a unique
# isgdevice identifier.
#%END%
#$Log: opiom.mac,v $
#Revision 1.6 2009/01/16 10:34:52 guilloud
#improve error message if opiomsetup error
#
#Revision 1.5 2008/08/12 15:19:20 rey
#documentation changes.
#
#Revision 1.4 2004/03/29 16:35:15 fajardo
#Revision log added
#
jtdo("isgdevice.mac")
jtdo("isg.mac")
#%UU% <opiom_name> <serline> [<parameter>=<value> ...]
#%MDESC%
# Configures an opiom module connected to <serline> with the name <opiom_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 module in the chain.
# %XDL%
# %XUL%
def opiomsetup '{
local retval
if ($# == 0 || (retval = _opiomsetup("$*"))) {
if (SETUP) {
print "/-------- OPIOM ERROR ---------------\\"
print "| Error in line: $0 $* "
print "\\------------------------------------/"
}
if (retval < 0) {
print "Usage: $0 serial_line [parameter=value ...]"
if (yesno("\nDisplay online help", 0)) eval("help local opiom")
}
}
}'
def _opiomsetup(args) '{
global OPIOM[]
global OPIOM_AUX[]
local i nparam auxlist0[] auxlist1[] larr
local serlin isgdev isgname
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]
serlin = auxlist0[1]
if ("address" in auxlist1){
if (auxlist1["address"] + 0 == auxlist1["address"])
isgdev = isgdevice_add(isgname, serlin , 0, auxlist1["address"])
else
isgdev = isgdevice_add(isgname, serlin , 1, auxlist1["address"])
delete auxlist1["address"]
} else
isgdev = isgdevice_add(isgname, serlin , 3, "OPIOM")
if (isgdev <= 0 || isgdevice_check(isgname, 3, "OPIOM") == 0) {
printf("No OPIOM device found at : %s\n", serlin)
return(1)
}
if (OPIOM_AUX["setup_n"] != SETUP_N) {
list_init OPIOM
OPIOM_AUX["setup_n"] = SETUP_N
}
if (list_add(OPIOM, isgname) <= 0) {
printf("Invalid OPIOM name: %s\n", isgname)
return(-1)
}
OPIOM[isgname]["setup"] = "opiomsetup " args
setup_tail("opiom", isgname)
i = ""
for (i in auxlist1) {
print "Invalid parameter: " i "=" auxlist1[i]
}
if (i != "")
return(-1)
else
return(0)
}'
def opiomunsetup '{
local isgname
isgname = "$1"
cdef("", "", isgname, "delete")
isgdevice_remove(isgname)
list_remove(OPIOM, isgname)
if (list_n(OPIOM) <= 0)
unglobal OPIOM OPIOM_AUX
}'
def opiom_setdefault(isgname) '{
if (OPIOM[0] <= 0) {
print "No OPIOM devices configured. Use first \`opiomsetup\'."
return(0)
}
if (isgname != "") {
OPIOM_AUX["default"] = isgname
if (!list_check(OPIOM, isgname)) {
print "\`" isgname "\' is not a valid OPIOM unit."
}
}
if (!list_check(OPIOM, OPIOM_AUX["default"])) {
OPIOM_AUX["default"] = OPIOM[1]
print "Setting \`" OPIOM_AUX["default"] "\' as default OPIOM unit."
}
return(1)
}'
#%UU% [<device_name>]
#%MDESC%
# Macro that runs the interactive loop. %B%opiom%B% refresh certain
# information on the screen and at the same time accepts commands
# from the standard input.
# %BR%
#
def opiom '{
local isgname options
isgname = $#? "$1": ""
if (!$# || list_check(OPIOM, isgname) > 0){
if (opiom_setdefault(isgname)) {
isgname = OPIOM_AUX["default"]
OPIOM[isgname]["prompt"] = "(" OPIOM_AUX["default"] ")"
}
} else if ((serdev = isgdevice_add("OPIOM", "$1", 3, "OPIOM")) > 0) {
isgname = "OPIOM"
OPIOM[isgname]["prompt"] = ""
} else {
print "No OPIOM unit found."
isgname = ""
}
if (!isgname) {
print "Usage: $0 opiom_name"
print " or $0 serial_line"
if (yesno("\nDisplay online help", 0))
eval("help local opiom")
} else {
rdef isg_prompt "opiom_prompt"
rdef isg_update "opiom_update"
rdef isg_show "opiom_show_comm"
rdef isg_process "opiom_process_comm"
isg_main(isgname, options, 0, OPIOM[isgname]["update"])
}
}'
def opiom_update '{
#update_flag = opiom_getstate(isgname)
}'
def opiom_getstate(isgname) '{
local state refstat
if ((state = isgdevice_comm(isgname, "?MODE")) == ISGDEV_ERR)
state = "???"
if (state != OPIOM[isgname]["state"]) {
OPIOM[isgname]["state"] = state
return(1)
} else
return(0)
}'
#%IU%
#%MDESC%
# Displays the prompt on the screen. If the "update" flag is set also
# displays the board status.
#
def opiom_prompt '
printf("OPIOM%s", OPIOM[isgname]["prompt"])
'
def opiom_show_comm '
isg_show_comm(".p, .program", "Program mode")
isg_show_comm(".e, .exec", "Execute command")
isg_show_comm(".c, .config", "Display spec setup")
'
#%IU%
#%MDESC%
#
def opiom_process_comm '
if (comm[0] == ".program" || comm[0] == ".p") {
local aux
opiom_upload_program(isgname)
return(1)
} else if (comm[0] == ".exec" || comm[0] == ".e") {
line = substr(line, length(comm[0]) + 1)
isg___command(isgname, line)
return(1)
} else if (comm[0] == ".config" || comm[0] == ".c") {
local aux
print
printf("\tSerial line: %s\n", ISGDEV_CONF[isgname]["serlin"])
printf("\tPosition : %d\n", ISGDEV_CONF[isgname]["pos"])
print
printf("\tSetup line: %s\n", OPIOM[isgname]["setup"])
return(1)
}
'
def opiom_getopmoffsets(opmarray, roffsets)'{
local i offset
#read the file offsets like python struct.unpack
roffsets["header"] = opiom_calcoffset(opmarray, 0)
roffsets["src"] = opiom_calcoffset(opmarray, 1)
roffsets["src_cc"] = opiom_calcoffset(opmarray, 2)
roffsets["src_c"] = opiom_calcoffset(opmarray, 3)
roffsets["jed"] = opiom_calcoffset(opmarray, 4)
}'
def opiom_calcoffset(data, i) '{
local offset
local OFF_BYTES HDR_CHARS
OFF_BYTES = 2 #Offset bytes
HDR_CHARS = 3 #Previous file chars(1byte)
offset = data[(i * OFF_BYTES) + HDR_CHARS]
offset |= data[(i * OFF_BYTES) + HDR_CHARS + 1] << 8
return offset
}'
def opiom_opm_header(path, file, opminfo) '{
local line i
filepath = path file
if (getline(filepath, "open") < 0) {
return(-1)
}
for (i = 0; i < 25; i++) {
local _line
_line = getline(filepath)
if (index(_line, "#user#")) {
line = _line
break
}
}
getline(filepath, "close")
if (!line)
return(-1)
opminfo["user"] = opiom_opm_hextract(line, "#user#")
opminfo["beamline"] = opiom_opm_hextract(line, "#beamline#")
opminfo["project"] = opiom_opm_hextract(line, "#project#")
opminfo["comment"] = opiom_opm_hextract(line, "#comment#")
opminfo["pldid"] = opiom_opm_hextract(line, "#pldid#")
opminfo["date"] = opiom_opm_hextract(line, "#date#")
opminfo["time"] = opiom_opm_hextract(line, "#time#")
return(0)
}'
def opiom_opm_hextract(line, field) '{
local beg len
beg = index(line, field)
if (!beg)
return("-")
beg += length(field)
len = index(substr(line, beg), field) - 1
return(substr(line, beg, len))
}'
def opiom_list_files(path, pldid) '{
local aux filelist[] opminfo[] file selected
uxcom = "cd " path "; ls *.opm"
unix(uxcom, aux)
n = split(aux, filelist, "\n")
filelist[n++] = "default"
print "File Date User Project"
print "---------------------------------- ---------- --------------- ---------------"
selected = 0
for (i = 0; i < n; i++) {
local epoch
if ((file = filelist[i]) == "")
continue
opminfo["pldid"] = 0
opminfo["date"] = "--/--/----"
opminfo["user"] = "-"
opminfo["project"] = "???"
if (file == "default") {
opminfo["pldid"] = 0x0000FF
opminfo["project"] = "<default>"
} else
opiom_opm_header(path, file, opminfo)
if (pldid == opminfo["pldid"])
tty_cntl("so")
printf("%-35s %-10s %-16s %s\n", file, \
opminfo["date"], opminfo["user"], opminfo["project"])
tty_cntl("se")
if (opminfo["pldid"] > epoch) {
epoch = opminfo["pldid"]
selected = i
}
}
return(filelist[selected])
}'
def opiom_upload_program(opiom_name, file) '{
local opminfo[] path filepath
local opmsize srcsz binsz
local roffsets[]
if (whatis("BLISSADM") & 0x04000000) {
path = BLISSADM "/local/isg/opiom/"
} else {
path = SPECD "/../local/isg/opiom/"
}
if (!file) {
file = opiom_list_files(path, isgdevice_comm(opiom_name, "?PLDID"))
file = getval("\nFile to load", file)
if (!file || index(file, "*"))
return(0)
if (file == "default") {
if (yesno("\nProgram the PLD with the default user code", 0)) {
print
opiom_cpld_prog(opiom_name,0,0)
}
return
}
if (!index(file, "."))
file = file ".opm"
}
if (opiom_opm_header(path, file, opminfo) < 0) {
print "Problem reading file: " file
return(-1)
}
filepath = path file
opmsize = file_info(filepath,"size")
local ubyte array opmfile[opmsize]
fmt_read(filepath,"raw",opmfile)
opiom_getopmoffsets(opmfile, roffsets)
print
print "============================================="
print "File : " file
print "Date : " opminfo["date"], "["opminfo["time"]"]"
print "User : " opminfo["user"]
print "Beamline: " opminfo["beamline"]
print "Project : " opminfo["project"]
print "Comment : " opminfo["comment"]
printf("PLD id : %08X\n", opminfo["pldid"])
print "============================================="
if (yesno("\nDisplay PLD user code", 0)) {
local i
print "\nBegin ::::::::::::::::::::::::::: Verilog User code\n\n"
for(i = roffsets["src"]; i < roffsets["src_cc"]; i++)
printf("%c",opmfile[i])
print
print "\nEnd ::::::::::::::::::::::::::::: Verilog User code\n\n"
}
if (yesno(sprintf("\nLoad program (%s) into the device", file), 0)) {
#Send the program command
# module size testing(if) "?SRCSZ"
if ((srcsz = isgdevice_comm(opiom_name, "?SRCSZ")) == ISGDEV_ERR) {
print "Cannot talk to \'" opiom_name "\'"
return(-1)
}
sscanf(srcsz, "%d", srcsz)
if ((roffsets["src_c"] - roffsets["src_cc"]) < srcsz) {
SRCST = roffsets["src_cc"]
srcsz = roffsets["src_c"] - roffsets["src_cc"]
} else {
SRCST = roffsets["src_c"]
srcsz = roffsets["jed"] - roffsets["src_c"]
}
binsz = opmsize - roffsets["jed"]
local ubyte array sendarray[srcsz + binsz]
# locate into sendarray the compressed fonts
# with or without comments
sendarray[0:srcsz-1] = opmfile[SRCST:SRCST+srcsz-1]
# locate into sendarray the entire binary JEDEC compressed file
sendarray[srcsz:] = opmfile[roffsets["jed"]:]
#instruction for starting download
opiom_cpld_prog(opiom_name, sendarray, binsz, srcsz, 256, \
opminfo["pldid"], opminfo["project"])
return(1)
} else
return(0)
}'
def opiom_cpld_prog(name, dat, binsz, srcsz, fsize, pldid, pldname) '{
local tsize page csz frame_n answer retry
local pstat
local answer pstat newpstat progress
answer = isgdevice_comm_ack(name, "MODE program")
if (answer != "OK"){
print "ERROR!"
return(-1)
}
if (binsz == 0) {
answer = isgdevice_comm_ack(name, sprintf("PROG DEFAULT", \
binsz, srcsz, fsize, pldid, pldname))
if (answer != "OK"){
print "ERROR!"
return(-1)
}
} else {
answer = isgdevice_comm_ack(name, sprintf("PROG %d %d %d %d \"%s\"", \
binsz, srcsz, fsize, pldid, pldname))
if (answer != "OK"){
print "ERROR!"
return(-1)
}
tsize = binsz + srcsz
print
for (csz = 0; csz < tsize; csz += fsize) {
page = tsize - csz
if (page > fsize)
page = fsize
frame_n = csz / fsize
comm = sprintf("#*FRM %d", frame_n)
for (retry = 0 ; retry < 3; retry++) {
printf("\r - LOAD %d%% ", 100 * csz / tsize)
answer = isgdevice_bincomm(name, comm, dat[csz:], page)
if (answer > 0)
break
printf("\n ERROR. Retrying frame %d\n", frame_n)
}
if (answer <= 0) {
print " Aborting PLD programming."
return(-1)
}
}
while (isgdevice_comm(name, "?PSTAT") == pstat)
;
printf ("\r - LOAD (100%)\n")
pstat = ""
}
while (1) {
answer = isgdevice_comm(name, "?PSTAT")
if (sscanf (answer, "%s %d", newpstat, progress) < 2) {
break;
}
if (newpstat != pstat) {
if (pstat != "")
printf ("\r - %s (100%)\n", pstat)
pstat = newpstat
}
printf ("\r - %s ", answer)
sleep(.1)
}
if (newpstat == "DONE") {
printf ("\r - %s (100%)\n", pstat)
print "\nPLD succesfully programmed"
return(0)
} else {
printf("\nError programming PLD (%s)\n", isgdevice_comm(name, "?PERR"))
return(-1)
}
}'
def opiom_bin_tpg(opiom_name, tpgtab, nlines) '{
local comm answer tsize dsize
max_time = array_op("max", tpgtab[][1])
if (max_time < 0x100) {
tsize = "BT"
dsize = 2
} else if (max_time < 0x10000) {
tsize = "WT"
dsize = 3
} else {
tsize = "LT"
dsize = 5
}
ubyte array alldata[nlines * dsize]
for (i = idx = 0; i < nlines; i++, idx += dsize) {
alldata[idx] = tpgtab[i][0];
tpg_time = tpgtab[i][1]
if (dsize == 2)
alldata[idx + 1] = tpg_time
else if (dsize == 3) {
alldata[idx + 1] = tpg_time >> 8
alldata[idx + 2] = tpg_time
} else {
alldata[idx + 1] = tpg_time >> 24
alldata[idx + 2] = tpg_time >> 16
alldata[idx + 3] = tpg_time >> 8
alldata[idx + 4] = tpg_time
}
}
comm = sprintf("#*TPG ADD 0x%x %s", nlines, tsize)
answer = isgdevice_bincomm(opiom_name, comm, alldata, dsize * nlines)
return
}'
#%MACROS%
#%AUTHOR% P.Fajardo, (Original 04/02).
# $Revision: 1.6 $ / $Date: 2009/01/16 10:34:52 $
#%TOC%
|