• Main Page
  • Related Pages
  • Namespaces
  • Data Structures
  • Files
  • File List
  • Globals

utilities/UtilityApp.cxx (r4864/r4198)

Go to the documentation of this file.
00001 //===========================================================================
00002 /* \file UtilityApp.cxx
00003  * \author W.F.J.Mueller/GSI, restructured, significant additional functionality
00004  * \author Stefan Mueller-Klieser/KIP, Sergei Linev/GSI: original UtilityApp
00005  * \author Volker Kleipa/GSI, Anton Lymanets/GSI: original TestApp
00006  * \author Iurii Sorokin/GSI: added autotrim and idsigch commands
00007  * \author Tomas Balog/GSI: added autosettrh
00008  */
00009 //============================================================================
00010 
00011 #include <ctype.h>
00012 #include <errno.h>
00013 #include <signal.h>
00014 #include <sys/time.h>
00015 #include <time.h>
00016 #include <unistd.h>
00017 #include <stdio.h>
00018 #include <string.h>
00019 
00020 // just to have round(), which is not in cmath !!
00021 #include <math.h>
00022 
00023 #include <cmath>
00024 #include <cstdlib>
00025 
00026 #include <algorithm>
00027 #include <iostream>
00028 #include <string>
00029 #include <vector>
00030 #include <map>
00031 #include <fstream>
00032 #include <memory>
00033 
00034 #include <readline/readline.h>
00035 #include <readline/history.h>
00036 
00037 #include "boost/format.hpp"
00038 
00039 #include "roc/defines_roc.h"
00040 #include "base/defines_gpio.h"
00041 #include "nxyter/defines_nxyter.h"
00042 #include "roc/defines_udp.h"
00043 #include "roc/defines_optic.h"
00044 
00045 #include "base/Board.h"
00046 #include "sp605/Board.h"
00047 #include "roc/Board.h"
00048 #include "base/Gpio.h"
00049 #include "roc/I2cDevice.h"
00050 #include "roc/UdpBoard.h"
00051 #include "nxyter/RocNx.h"
00052 #include "nxyter/FebBase.h"
00053 #include "nxyter/Feb1nxGenB.h"
00054 #include "nxyter/Feb1nxGenC.h"
00055 #include "nxyter/Feb1nxGenD.h"
00056 #include "nxyter/Feb2nxGas.h"
00057 #include "nxyter/Feb4nxBT.h"
00058 #include "nxyter/NxI2c.h"
00059 #include "nxyter/NxContext.h"
00060 #include "nxyter/FebUtil.h"
00061 #include "nxyter/QuickDaq.h"
00062 #include "nxyter/DistFunc.h"
00063 #include "nxyter/DistFuncArray.h"
00064 #include "nxyter/NxDataSummary.h"
00065 #include "feet/RocFeet.h"
00066 
00067 base::Board*      gBaseBoard = 0;
00068 roc::Board*       gRocBoard = 0;
00069 sp605::Board*     gSP605Board = 0;
00070 base::Gpio*       gGpio  = 0;
00071 nxyter::RocNx*    gRocNx = 0;
00072 nxyter::FebBase*  gFeb   = 0;
00073 nxyter::QuickDaq* gQdaq  = 0;
00074 nxyter::FebUtil*  gUtil  = 0;
00075 
00076 std::string gBoardName;
00077 
00078 int gIntCount = 0;
00079 
00080 std::vector<std::string> argspos;
00081 std::vector<std::string> argsopt;
00082 
00083 enum ArgNeedConstants {
00084    kNeedBoard    = (1<<0),
00085    kNeedRocBoard = (1<<1),
00086    kNeedFeb      = (1<<2),
00087    kNeedDaq      = (1<<3),
00088 };
00089 
00090 //----------------------------------------------------------------------------
00091 //++ the command table +++++++++++++++++++++++++++++++++++++++++++++++++++++++
00092 
00093 int cmd_autoped();
00094 int cmd_autosettrh();
00095 int cmd_autotrim();
00096 int cmd_autovbiass();
00097 int cmd_board();
00098 int cmd_discover();
00099 int cmd_dlm();
00100 int cmd_feb();
00101 int cmd_firepulser();
00102 int cmd_getadcdirect();
00103 int cmd_geti2c();
00104 int cmd_puti2c();
00105 int cmd_getnx();
00106 int cmd_getroc();
00107 int cmd_help();
00108 int cmd_ident();
00109 int cmd_idsigch();
00110 int cmd_initfeb();
00111 int cmd_printadc();
00112 int cmd_printdata();
00113 int cmd_printdatadbg();
00114 int cmd_printfeb();
00115 int cmd_printgpio();
00116 int cmd_printid();
00117 int cmd_printmon();
00118 int cmd_printnx();
00119 int cmd_printroc();
00120 int cmd_printrocmap();
00121 int cmd_printstatus();
00122 int cmd_putroc();
00123 int cmd_quit();
00124 int cmd_resetnxi2cbus();
00125 int cmd_resetnxi2creg();
00126 int cmd_resetrocnxts();
00127 int cmd_restartbrd();
00128 int cmd_saverocconf();
00129 int cmd_scanadclat();
00130 int cmd_scanmonadc();
00131 int cmd_scanvbiasf();
00132 int cmd_scanvbiass();
00133 int cmd_setadc();
00134 int cmd_setadcclock();
00135 int cmd_setadcdef();
00136 int cmd_setadcpatt();
00137 int cmd_setaux();
00138 int cmd_setdebug();
00139 int cmd_setfebdef();
00140 int cmd_seti2c();
00141 int cmd_setlhwater();
00142 int cmd_setnx();
00143 int cmd_setnxaddr();
00144 int cmd_setnxdef();
00145 int cmd_setnxmask();
00146 int cmd_setnxmode();
00147 int cmd_setnxoff();
00148 int cmd_setnxpower();
00149 int cmd_setnxtrim();
00150 int cmd_setbrddef();
00151 int cmd_setrocdef();
00152 int cmd_setsyncm();
00153 int cmd_setsyncs();
00154 int cmd_settrace();
00155 int cmd_testadccntl();
00156 int cmd_testadcdata();
00157 int cmd_testfebcntl();
00158 int cmd_testnxcntl();
00159 int cmd_testnxdata();
00160 int cmd_testnxregs();
00161 int cmd_testrocaux();
00162 int cmd_testrocsync();
00163 
00164 
00165 typedef struct
00166 {
00167   const char* name;                         
00168   int       (*func)();                      
00169   const char* shelp;                        
00170   const char* lhelp;                        
00171 } cmditem_t;
00172 
00173 
00174 // this is list of the currently-active commands
00175 std::vector<cmditem_t*> cmdlist;
00176 
00177 
00178 cmditem_t cmdlist_base[] = {
00179    { name:    "help|h",
00180      func: cmd_help,
00181      shelp:"[-g -v|command] : help on rocutil and its commands",
00182      lhelp:"  -g      gives general help on using rocutil\n"
00183            "  -v      gives full help test for all commands\n"
00184            "  -a      gives list of command abbreviations\n"
00185            "  command gives help text for the given command"
00186    },
00187    { name:    "board|b",
00188      func: cmd_board,
00189      shelp:"brdname : connect to board",
00190      lhelp:"  brdname  address of the board to connect\n"
00191            "    Note: connection mode (DAQ, Control, or Observer) could be specified as\n"
00192            "          optional argument like cbmtest03?Control. Default is DAQ mode\n"
00193            "    Example of valid addresses: \n"
00194            "        board=cbmtest08   -  udp connection to ROC board with address cbmtest08\n"
00195            "        board=140.181.115.234?Control  - udp connection to ROC board with specified IP in control mode\n"
00196            "        board=abb1  - optic connection to ROC board, connected via second SFP\n"
00197            "        board=optic://abb13/sp605 - optic connection to SP605 board, connected via second SFP on ABB and forth SFP on DCB"
00198    },
00199    { name:    "quit|q",
00200      func: cmd_quit,
00201      shelp:"exit program",
00202      lhelp:""
00203    },
00204    { name: 0,
00205      func: 0,
00206      shelp:0,
00207      lhelp:0
00208    }
00209 };
00210 
00212 cmditem_t cmdlist_board[] = {
00213    { name:    "getroc|get",
00214      func: cmd_getroc,
00215      shelp:"aname : direct get() from board control space !! EXPERT ONLY !!",
00216      lhelp:"  aname   symbolic name of the board control space resource"
00217    },
00218    { name:    "putroc|put",
00219      func: cmd_putroc,
00220      shelp:"aname,val : direct put() to board control space !! EXPERT ONLY !!",
00221      lhelp:"  aname   symbolic name of the board control space resource\n"
00222            "  val     value to be written"
00223    },
00224    { name:    "ident|id",
00225      func: cmd_ident,
00226      shelp:" : print connection data and current time",
00227      lhelp:""
00228    },
00229    { name:    "printrocmap|printmap",
00230      func: cmd_printrocmap,
00231      shelp:"[-n] : print board control space address map !! FOR EXPERTS !!",
00232      lhelp:"  -n      sort by name (default is sort by address)"
00233    },
00234    { name:    "restartbrd",
00235      func: cmd_restartbrd,
00236      shelp:"restart board  !! THINK BEFORE !!",
00237      lhelp:"  Note: this command will disconnect the board/feb !!!\n"
00238            "        restart rocutil and used 'setbrddef' to initialize board"
00239    },
00240    { name:    "setbrddef",
00241      func: cmd_setbrddef,
00242      shelp:" : set board registers to default values",
00243      lhelp:""
00244    },
00245    { name:    "geti2c",
00246      func: cmd_geti2c,
00247      shelp:"[-l -w] addr,reg : read from I2C selected device",
00248      lhelp:"  -l      scope loop (repeat until ^C)\n"
00249            "  -w      16 bit access (default is 8 bit)\n"
00250            "  addr    I2C slave address (0:127)\n"
00251            "  reg     device register number (0:255)"
00252    },
00253    { name:    "puti2c",
00254      func: cmd_puti2c,
00255      shelp:"addr,reg,value : write I2C register",
00256      lhelp:"  addr    I2C slave address (0:127)\n"
00257            "  reg     device register number (0:255)"
00258            "  value   register value (0:255)"
00259    },
00260    { name:    "printdata|pd",
00261      func: cmd_printdata,
00262      shelp:"[-m -r -h -t -s -d -n -ia][nmsg,time,npuls,pper,pdly] : print data",
00263      lhelp:"  -m      print messages (default if no -s -d given)\n"
00264            "  -r      print messages in raw format (def is human readable)\n"
00265            "  -h      print hex dump of message\n"
00266            "  -t      print wall clock timestamp in front of message\n"
00267            "  -s      print statistics\n"
00268            "  -d      print nx distribution parameters\n"
00269            "  -n      no ROC initialization, use ROC config as is\n"
00270            " -ia      init nx/roc timestamp system after DAQ start\n"
00271            "  nmsg    number of messages to print (def=100, see Note below)\n"
00272            "  time    maximal time to look for data (def=10., see Note below)\n"
00273            "  npuls   if >0 fire pulser, send np pulses (0:32767, def=0)\n"
00274            "  pper    pulser period in units of 4ns (2:2^24, def=100000)\n"
00275            "  pwth    pulser period in units of 4ns (-2^24:2^24, def=32)\n"
00276            "  pdly    pulser delay in units of 4ns (1:65535, def=1000)\n"
00277            "    Note: if neither nmsg nor time is specified, the defaults of\n"
00278            "          nmsg=100 and time=10. are used. If only one of the two\n"
00279            "          is specified, the other is unlimited\n"
00280            "  Note 2: One could use pd for printout of messages from lmd file.\n"
00281            "          One can do \"rocutil b=file.lmd pd\". In this case all \n"
00282            "          messages will be printout if other not specified."
00283    },
00284    { name: 0,
00285      func: 0,
00286      shelp:0,
00287      lhelp:0
00288    }
00289 };
00290 
00291 
00293 cmditem_t cmdlist_sp605[] = {
00294    { name:    "set605def",
00295      func: cmd_setrocdef,
00296      shelp:" : set SP605 registers to default values",
00297      lhelp:"    Note: use after board boot"
00298    },
00299    { name: 0,
00300      func: 0,
00301      shelp:0,
00302      lhelp:0
00303    }
00304 };
00305 
00307 cmditem_t cmdlist_nxyter[] = {
00308    { name:    "feb|f",
00309      func: cmd_feb,
00310      shelp:"[port,type] : configure feb",
00311      lhelp:"  port    port number, default is first available\n"
00312            "  type    feb type either Feb1nxGen[BCD], Feb2nxGas,\n"
00313            "          Feb4nxBT, if omitted the discoverFebs() autodetect\n"
00314            "          heuristics is used\n"
00315            "    Note: Feb1nxGenB MUST be configured manually, the autodetect\n"
00316            "          will recognize them as errorously as Feb1nxGenC !!"
00317    },
00318    { name:    "getnx|gx",
00319      func: cmd_getnx,
00320      shelp:"nx,reg : read nXYTER register reg",
00321      lhelp:"  nx      nXYTER index ('*' for all or specific index)\n"
00322            "  reg     nXYTER register number"
00323    },
00324    { name:    "initfeb|if",
00325      func: cmd_initfeb,
00326      shelp:" : set nx on/off flags to ROC",
00327      lhelp:""
00328    },
00329    { name:    "printadc|pa",
00330      func: cmd_printadc,
00331      shelp:"prints device registers the MainAdc of a FEB",
00332      lhelp:""
00333    },
00334    { name:    "printfeb|pf",
00335      func: cmd_printfeb,
00336      shelp:"[-m -c -t -a] : prints all device registers of a FEB",
00337      lhelp:"  -m      print only nXYTER mask part\n"
00338            "  -c      print only nXYTER core part (default unless -m -c -t -a)\n"
00339            "  -t      print only nXYTER trim part\n"
00340            "  -a      print all parts\n"
00341    },
00342    { name:    "printnx|px",
00343      func: cmd_printnx,
00344      shelp:"[-m -c -t -a][nx] : print device registers one nXYTER of a FEB",
00345      lhelp:"  -m      print only mask part\n"
00346            "  -c      print only core part (default unless -m -c -t -a given)\n"
00347            "  -t      print only trim part\n"
00348            "  -a      print all parts\n"
00349            "  nx      nXYTER index ('*' for all or specific index)"
00350    },
00351    { name:    "resetnxi2cbus",
00352      func: cmd_resetnxi2cbus,
00353      shelp:"reset I2C bus state machine in all nXYTER",
00354      lhelp:""
00355    },
00356    { name:    "resetnxi2creg",
00357      func: cmd_resetnxi2creg,
00358      shelp:"reset all I2C registers to power-up defauls in all nXYTER",
00359      lhelp:""
00360    },
00361    { name:    "setadc",
00362      func: cmd_setadc,
00363      shelp:"reg,val : set ADC register reg to val",
00364      lhelp:"  reg     ADC register number\n"
00365            "  val     new value\n"
00366    },
00367    { name:    "setnx|sx",
00368      func: cmd_setnx,
00369      shelp:"nx,reg,val : set for nXYTER nx the register reg to val",
00370      lhelp:"  nx      nXYTER index ('*' for all or specific index)\n"
00371            "  reg     nXYTER register number\n"
00372            "  val     new value\n"
00373    },
00374    { name:    "setnxaddr",
00375      func: cmd_setnxaddr,
00376      shelp:"nx,addr : set I2C slave address for nXYTER",
00377      lhelp:"  nx      nXYTER index\n"
00378            "  addr    nXYTER I2C slave address"
00379    },
00380    { name:    "setnxdef|sxd",
00381      func: cmd_setnxdef,
00382      shelp:"[nx,pos] : set nXYTER registers to default values",
00383      lhelp:"  nx      nXYTER index ('*' for all or specific index, def=*)\n"
00384            "  pos     if 1 than nXYTER is setup for positive signals\n"
00385    },
00386    { name:    "setnxmask|sxm",
00387      func: cmd_setnxmask,
00388      shelp:"nx,[val,ibeg,iend,istep] : set channel-off mask to val in range",
00389      lhelp:"  nx      nXYTER index ('*' for all or specific index)\n"
00390            "  val     channel-off bit, 1 means off (0:1, def=0)\n"
00391            "  ibeg    first channel number (0:127, def=0)\n"
00392            "  iend    last channel number (0:127, def=127)\n"
00393            "  istep   cha. num. increment, touch ibeg+n*istep (1:64, def=1)"
00394    },
00395    { name:    "setnxmode|sxmo",
00396      func: cmd_setnxmode,
00397      shelp:"nx,[tpul,ttri,csel] : set test pulser and test trigger modes",
00398      lhelp:"  nx      nXYTER index ('*' for all or specific index)\n"
00399            "  tpul    test pulser mode flag (0:1, def=0)\n"
00400            "  ttri    test trigger mode flag (0:1, def=0)\n"
00401            "  csel    calibration group select (0:3, def=3)\n"
00402            "    Note: the csel default is 3 to have test channel 128 active"
00403    },
00404    { name:    "setfebdef|sfd",
00405      func: cmd_setfebdef,
00406      shelp:"[pos0,pos1] : set ADC and nXYTER registers to default values",
00407      lhelp:"  pos0    if 1 setup 1st half of nXYTER for positive signals\n"
00408            "  pos1    if 1 setup 2nd half of nXYTER for positive signals"
00409    },
00410    { name:    "firepulser|fp",
00411      func: cmd_firepulser,
00412      shelp:"[-a -s][per,wth,num,dly] : fire test pulse train",
00413      lhelp:"  -a      setup AUX2, enable ext&alt, or if -s disable ext\n"
00414            "  -s      stop pulse train\n"
00415            "  per     period in units of 4ns (2:2^24, def=100000)\n"
00416            "  wth     width in units of 4ns (-2^24:+2^24, def=350)\n"
00417            "  num     number of pulses (0:32768, def=0)\n"
00418            "  dly     delay after reset in units of 4ns (0:65535, def=0)\n"
00419            "    Note: number=0 causes permanent pulse activity\n"
00420            "          to terminate this do 'firepulser -s'\n"
00421            "    Note: 'firepulser' will cause continuous 2.5 kHz pulsing"
00422    },
00423    { name: 0,
00424      func: 0,
00425      shelp:0,
00426      lhelp:0
00427    }
00428 };
00429 
00430 cmditem_t cmdlist_gpio[] = {
00431    { name:    "setaux|sa",
00432      func: cmd_setaux,
00433      shelp:"ch,[re,fe,thr,ext,alt] : setup aux channel",
00434      lhelp:"  ch      channel number (0:3)\n"
00435            "  re      rising edge enable flag (0:1, def=0)\n"
00436            "  fe      falling edge enable flag (0:1, def=0)\n"
00437            "  thr     throttled option (0:1, def=1)\n"
00438            "  ext     enable TP_in(2) Thr_In(3) (0:1, def=0)\n"
00439            "  alt     use alt. input TP_busy(1),TP_gen(2),Thr_out(3) (0:1,def=0)"
00440    },
00441    { name:    "setsyncm|ssm",
00442      func: cmd_setsyncm,
00443      shelp:"scale[,baud]: set sync message sender",
00444      lhelp:"  scale   rate scale-down (0:21)\n"
00445            "  baud    baud rate in MHz (def=62.5)"
00446    },
00447    { name:    "setsyncs|sss",
00448      func: cmd_setsyncs,
00449      shelp:"ch,en[,thr,baud,loop] : setup sync message receiver channel",
00450      lhelp:"  ch      channel number (0:1)\n"
00451            "  en      enable flag (0:1)\n"
00452            "  thr     throttled option (0:1, def=0)\n"
00453            "  baud    baud rate in MHz (def=62.5)\n"
00454            "  loop    enable syncm->syncs internal loop back (0:1, def=0)"
00455    },
00456    { name:    "printgpio|pg",
00457      func: cmd_printgpio,
00458      shelp:"lists gpio options",
00459      lhelp:""
00460    },
00461    { name: 0,
00462      func: 0,
00463      shelp:0,
00464      lhelp:0
00465    }
00466 };
00467 
00468 
00469 
00470 cmditem_t cmdlist_roc[] = {
00471   { name:    "autoped",
00472     func: cmd_autoped,
00473     shelp:"[tmeas,tped] : auto-pedestal sequencer [EXPERIMENTAL!!]",
00474     lhelp:"  tmeas   length of measurement time interval (def=30.)\n"
00475           "  tped    length of pedestal time intervalta (def=0.1)\n"
00476   },
00477   { name:    "autosettrh|ath", 
00478     func: cmd_autosettrh,
00479     shelp:"time, min, nch, nnx",
00480     lhelp:"  time    sets the time of DAq for setup (real time is 8x higher)\n"
00481           "  min     crutial minimal value of working channels\n"
00482           "  nch     maximum rate of noise per channel\n"
00483           "  nnx     maximum rate of per chip\n"
00484   },
00485   { name:    "autotrim|att",
00486     func: cmd_autotrim,
00487     shelp:"[-k -t -q] nx,rate[,time,vth_min,vth_max,target] : trim n-XYTER thresholds",
00488     lhelp:"  -k      keep vth at target efficiency after execution\n"
00489           "  -m      only measure the signal rate, without changing vth or trim register\n"
00490           "  -t      use actual vth, do not adjust it. Only adjust trim\n"
00491           "  -q      quiet mode\n"
00492           "  rate    expected pulse rate {Hz}\n"
00493           "  time    duration of one measurement {s} (def=4.)\n"
00494           "  target  detection efficiency to adjust the thresholds to (def=0.5)\n"
00495           "  vth_min low limit of n-XYTER threshold (def=20)\n"
00496           "  vth_max high limit of n-XYTER threshold (def=255)\n"
00497           "    Hint: One can test autotrim with n-XYTER internal pulser:\n"
00498           "             rocutil> sxmo * tpul=1\n"
00499           "             rocutil> fp -a\n"
00500           "             rocutil> setnxmask=0,val=1\n"
00501           "             rocutil> setnxmask=0,val=0,ibeg=3,istep=4\n"
00502           "             rocutil> autotrim * rate=2500\n"
00503   },
00504   { name:    "autovbiass",
00505     func: cmd_autovbiass,
00506     shelp:"[-v] nx,[base,npuls] : VBiasS autotrim",
00507     lhelp:"  -v      show data for each channel\n"
00508           "  nx      nXYTER index ('*' for all or specific index)\n"
00509           "  base    target value for median baseline(0:4095, def=2000)\n"
00510           "  npuls   number of pulses to accumulate (1:10000, def=200)"
00511   },
00512   { name:    "discover",
00513     func: cmd_discover, 
00514     shelp:"[-v] : discover (probe for) nXYTER and FEBs", 
00515     lhelp:"  -v      gives a verbose listing of all return codes\n"
00516           "    Note: probes all even I2C addresses on both ports for nXYTER\n"
00517           "          and uses discoverFebs() heuristics to identify FEBs"
00518   },
00519   { name:    "dlm",
00520     func: cmd_dlm,
00521     shelp:"[num] : issue DLM message, default 1",
00522     lhelp:"  num     number of DLM message\n"
00523           "          num=1 used for time synchronisation\n"
00524   },
00525   { name:    "getadcdirect",
00526     func: cmd_getadcdirect,
00527     shelp:"[-d] : peak at adc data directly",
00528     lhelp:"  -d      use decimal output, default is hex"
00529   },
00530   { name:    "idsigch|isc",
00531     func: cmd_idsigch,
00532     shelp:" [-m -q] nx [amp, vth, rate, time] : identify channels with signal !! UNDER DEVELOPMENT !!",
00533     lhelp:"  -m      mask channels with no signal\n"
00534           "  -q      quite mode, print only error messages\n"
00535           // "  -v      allow \n"
00536           "  -t      do not reqire any separation between signal and noise,\n"
00537           "          simply apply the threshold, suppresses -v\n"
00538           "  amp     minimal amplitude (def=50)\n"
00539           "  vth     work with the specified vth, set to initial value\n"
00540           "          when finish. 0 -- don't change vth. (def=0)\n"
00541           "  rate    require a minimal signal rate. (def=1./time)\n"
00542           "  time    measurement time in seconds (def=4.)"
00543   },
00544   { name:    "printdatadbg|pdd",
00545     func: cmd_printdatadbg,
00546     shelp:"[-c -ib -ia][nmsg,time] : print data from debug port !! EXPERT !!",
00547     lhelp:"  -c      clear FIFO's before accessing data\n"
00548           "  -ib     init nx/roc timestamp system before FIFO clear\n"
00549           "  -ia     init nx/roc timestamp system after FIFO clear\n"
00550           "  nmsg    number of messages to print (def=100)\n"
00551           "  time    maximal time to look for data (def=1.)"
00552   },
00553   { name:    "printid|pi",
00554     func: cmd_printid,
00555     shelp:"Prints all system id's and versions specifications",
00556     lhelp:""
00557   },
00558   { name:    "printmon|pm",
00559     func: cmd_printmon,
00560     shelp:"print monitoring ADC readings",
00561     lhelp:""
00562   },
00563   { name:    "printroc|pr",
00564     func: cmd_printroc,
00565     shelp:"lists ROC register settings",
00566     lhelp:""
00567   },
00568   { name:    "printstatus|ps",
00569     func: cmd_printstatus,
00570     shelp:"brief status summary of ROC and FEBs",
00571     lhelp:""
00572   },
00573   { name:    "restartroc",
00574     func: cmd_restartbrd,
00575     shelp:"restart ROC (FPGA reconfigure and PPC reboot) !! THINK BEFORE !!",
00576     lhelp:"  Note: this command will disconnect the board/feb !!!\n"
00577           "        restart rocutil and used 'setrocdef' to initialize ROC"
00578   },
00579   { name:    "saverocconf",
00580     func: cmd_saverocconf,
00581     shelp:"will write the current ROC setting to the SDcard",
00582     lhelp:"    Note: This will change the startup default of the ROC"
00583   },
00584   { name:    "scanadclat",
00585     func: cmd_scanadclat,
00586     shelp:"[-v -d] nx[,ch,lbeg,lend,dbeg,dend,npuls,ch2] : ADC latency scan",
00587     lhelp:"  -v      show data for each scan point\n"
00588           "  -d      full delay scan, default is full latency scan\n"
00589           "  nx      nXYTER index\n"
00590           "  ch      channel to be used (0:127, def=0)\n"
00591           "  lbeg    start value for ADC latency (0:127, def=61)\n"
00592           "  lend    end value for ADC latency (0:127, def=68)\n"
00593           "  dbeg    start value for ADC clock delay (0:31, def=0)\n"
00594           "  dend    end value for ADC clock delay (0:31, def=31)\n"
00595           "  npuls   number of pulses to accumulate (1:10000, def=100)\n"
00596           "  ch2     second channel to be activated (0:127, def=<none>)\n"
00597           "    Note: For a latency scan (no -d) 8 delay settings are\n"
00598           "          inspected in the range dbeg:dend, step size is adjusted.\n"
00599           "          For a delay scan (-d) 8 latency settings are inspected\n"
00600           "          in the range lbeg:lend, step size is adjusted to 1,2,4\n"
00601           "          or lend is reduced\n"
00602   },
00603   { name:    "scanmonadc",
00604     func: cmd_scanmonadc,
00605     shelp:"nx,reg[,vbeg,vend,vstep] : parameter scan for monitor ADCs",
00606     lhelp:"  nx      nXYTER index ('*' for all or specific index)\n"
00607           "  reg     nXYTER register number to be varied\n"
00608           "  vbeg    start value for scan (0:255, def=0)\n"
00609           "  vend    end value for scan (0:255, def=255)\n"
00610           "  vstep   step size of scan (1:255, def=1)\n"
00611   },
00612   { name:    "scanvbiasf",
00613     func: cmd_scanvbiasf,
00614     shelp:"[-v] nx[,vbeg,vend,vstep,npuls] : VBiasF scan",
00615     lhelp:"  -v      show data for each channel\n"
00616           "  nx      nXYTER index ('*' for all or specific index)\n"
00617           "  vbeg    start value for VBiasF scan (0:255, def=0)\n"
00618           "  vend    end value for VBiasF scan (0:255, def=255)\n"
00619           "  vstep   step size of scan (1:255, def=1)\n"
00620           "  npuls   number of pulses to accumulate (1:10000, def=100)"
00621   },
00622   { name:    "scanvbiass",
00623     func: cmd_scanvbiass,
00624     shelp:"[-v] nx[,vbeg,vend,vstep,npuls] : VBiasS scan",
00625     lhelp:"  -v      show data for each channel\n"
00626           "  nx      nXYTER index ('*' for all or specific index)\n"
00627           "  vbeg    start value for VBiasS scan (0:255, def=0)\n"
00628           "  vend    end value for VBiasS scan (0:255, def=255)\n"
00629           "  vstep   step size of scan (1:255, def=1)\n"
00630           "  npuls   number of pulses to accumulate (1:10000, def=100)"
00631   },
00632   { name:    "setadcclock",
00633     func: cmd_setadcclock,
00634     shelp:"dly : set main clock delay",
00635     lhelp:"  dly     delay in 2ns units (0:31)"
00636   },
00637   { name:    "setadcdef|sad",
00638     func: cmd_setadcdef,
00639     shelp:"set ADC registers to default values",
00640     lhelp:""
00641   },
00642   { name:    "setadcpatt",
00643     func: cmd_setadcpatt,
00644     shelp:"[tm0,tm1,tm2,tm3,upatt] : set main adc test pattern mode",
00645     lhelp:"  tm*     adc channel i (0,1,2,3) test pattern mode\n"
00646           "  upatt   user data pattern (12 bit used, default='keep old')\n"
00647           "    Note: modes are: 0=none(ADC data); 1=0x800; 2=0xfff;\n"
00648           "          3=0x000; 4=0xaaa,0x555; 5=PNlong; 6=PNshort;\n"
00649           "          7=0xfff,0x000; 8=upatt; 9=0xaaa; 10=0x03f;\n"
00650           "          11=0x800; 12=0xa33;"
00651   },
00652   { name:    "setdebug",
00653     func: cmd_setdebug, 
00654     shelp:"lvl : set debug level",
00655     lhelp:"  lvl     0 only errors, >0 also debug infos"
00656   },
00657   { name:    "seti2c",
00658     func: cmd_seti2c,
00659     shelp:"[-l -v] addr,reg,val : write into I2C selected device",
00660     lhelp:"  -l      scope loop (repeat until ^C)\n"
00661           "  -v      do readback verification\n"
00662           "  addr    I2C slave address (0:127)\n"
00663           "  reg     device register number (0:255)\n"
00664           "  val     value to be written (0:255)"
00665   },
00666   { name:    "setlhwater|lhw",
00667     func: cmd_setlhwater,
00668     shelp:"low,high : low/high water",
00669     lhelp:"  low     low limit of PowerPC buffer in KB, min 8K\n"
00670           "  high    high limit of PowerPC buffer in KB, max 128M\n"
00671   },
00672   { name:    "setnxoff", 
00673     func: cmd_setnxoff, 
00674     shelp:"nx,val : set 'offline' flag for nXYTER",
00675     lhelp:"  nx      nXYTER index\n"
00676           "  val     nXYTER offline flag, 1 means off (0:1)"
00677   },
00678   { name:    "setnxpower|sxp",
00679     func: cmd_setnxpower,
00680     shelp:"nx,[val,ibeg,iend,istep] : set the power-down bit to val in range",
00681     lhelp:"  nx      nXYTER index ('*' for all or specific index)\n"
00682           "  val     power down bit, 1 means off (0:1, def=0)\n"
00683           "  ibeg    first channel number (0:128, def=0)\n"
00684           "  iend    last channel number (0:128, def=127)\n"
00685           "  istep   cha. num. increment, touch ibeg+n*istep (1:64, def=1)\n"
00686           "    Note: channel range is 0:128, channel 128 is the test channel\n"
00687           "    Note: the default for iend is 127, sparing the test channel" 
00688   },
00689   { name:    "setnxtrim|sxt",
00690     func: cmd_setnxtrim,
00691     shelp:"nx,[val,ibeg,iend,istep] : set the trim to val in range",
00692     lhelp:"  nx      nXYTER index ('*' for all or specific index)\n"
00693           "  val     trim value (0:31, def=16)\n"
00694           "  ibeg    first channel number (0:128, def=0)\n"
00695           "  iend    last channel number (0:128, def=127)\n"
00696           "  istep   cha. num. increment, touch ibeg+n*istep (1:64, def=1)\n"
00697           "    Note: channel range is 0:128, channel 128 is the test channel\n"
00698           "    Note: the default for iend is 127, sparing the test channel" 
00699   },
00700   { name:    "setrocdef|srd",
00701     func: cmd_setrocdef,
00702     shelp:" : set ROC registers to default values",
00703     lhelp:"    Note: use after ROC boot, replaces old SDcard config file"
00704   },
00705   { name:    "settrace|st",
00706     func: cmd_settrace,
00707     shelp:"[lvl] : set get/put/opergen trace level",
00708     lhelp:"  lvl     0 none; 1 only comm err; 2 only err; 3 all (def=1)"
00709   },
00710   { name:    "testadccntl",
00711     func: cmd_testadccntl,
00712     shelp:"[time] : test ADC control interface (SPI) for some time",
00713     lhelp:"  time    length of test in sec (def=10.)"
00714   },
00715   { name:    "testadcdata",
00716     func: cmd_testadcdata,
00717     shelp:"[time] : test ADC data interface for some time",
00718     lhelp:"  time    length of test in sec (def=10.)"
00719   },
00720   { name:    "testfebcntl",
00721     func: cmd_testfebcntl,
00722     shelp:"[time] : test ADC(not yet!) and all nXYTER control interfaces",
00723     lhelp:"  time    length of test in sec (def=10.)\n"
00724                   "    Note: does a random pattern test on many regsisters of all\n"
00725                   "          nXYTERs of the FEB and some ADC registers. See also\n"
00726                   "          'testnxcntl' and 'testadccntl'"
00727   },
00728   { name:    "testnxcntl",
00729     func: cmd_testnxcntl,
00730     shelp:"nx[,time] : test nXYTER control interface (I2C) for some time",
00731     lhelp:"  nx      nXYTER index ('*' for all or specific index)\n"
00732           "  time    length of test in sec (def=10.)\n"
00733           "    Note: calls the NxI2c::probe() method continuously.\n"
00734           "          To check all nXYTERs of a FEB together use 'testfebcntl'\n"
00735           "          To check a I2C address use 'seti2c -l' or 'geti2c -l'"
00736   },
00737   { name:    "testnxdata",
00738     func: cmd_testnxdata,
00739     shelp:"[-p -r -s][time] : test whether FEB responds to test triggers",
00740     lhelp:"  -p      print messages\n"
00741           "  -r      use raw format (default is human readable)\n"
00742           "  -s      print statistics\n"
00743           "  time    length of test in sec (def=10.)\n"
00744           "    Note: will put FEB into default settings !!!"
00745   },
00746   { name:    "testnxregs",
00747     func: cmd_testnxregs,
00748     shelp:"nx : test nXYTER registers",
00749     lhelp:"  nx      nXYTER index ('*' for all or specific index)\n"
00750           "    Note: Writes and read-checks patterns in all registers"
00751   },
00752   { name:    "testrocaux",
00753     func: cmd_testrocaux,
00754     shelp:"[-v -n] [ch,scale,time] : test ROC aux for some time",
00755     lhelp:"  -v      verbose, show first aux's, trends, stats\n"
00756           "  -n      no ROC initialization, use ROC config as is\n"
00757           "  ch      aux channel (0:3, def=2)\n"
00758           "  scale   aux scale (0:11, def=0)\n"
00759           "  time    length of test in sec (def=10.)\n"
00760           "    Note: expects to receive periodic aux pulses from SysGlue\n"
00761           "          with given frequency scale"
00762   },
00763   { name:    "testrocsync",
00764     func: cmd_testrocsync,
00765     shelp:"[-v -n] [ch,scale,time] : test ROC sync for some time",
00766     lhelp:"  -v      verbose, show first sync's, trends, stats\n"
00767           "  -n      no ROC initialization, use ROC config as is\n"
00768           "  ch      sync channel (0:1, def=0)\n"
00769           "  scale   sync scale down (0:21, def=5)\n"
00770           "  time    length of test in sec (def=10.)\n"
00771           "    Note: expects to receive periodic sync markers with the given\n"
00772           "          scale down, either via loop-back or external"
00773   }, 
00774   { name:    "resetrocnxts",
00775     func: cmd_resetrocnxts,
00776     shelp:"resetrocnxts : reset timing of nx time stamp",
00777     lhelp:"  Note: should probably not used for optic"
00778   }, // terminator must be at end !
00779   { name: 0, 
00780     func: 0, 
00781     shelp:0, 
00782     lhelp:0
00783   }
00784 };
00785 
00786 void add_cmdlist(cmditem_t* lst)
00787 {
00788    for (cmditem_t* item = lst; item->name; item++)
00789       cmdlist.push_back(item);
00790 }
00791 
00792 
00793 void reset_cmdlist()
00794 {
00795    cmdlist.clear();
00796 
00797    add_cmdlist(cmdlist_base);
00798 }
00799 
00800 //----------------------------------------------------------------------------
00801 //++ some helper functions needed throughout the program +++++++++++++++++++++
00802 
00803 //----------------------------------------------------------------------------
00805 
00809 int check_feb(bool needfeb=true)
00810 {
00811   if (needfeb && gFeb==0) {
00812     std::cerr << "rocutil-E: command requires connected FEB, use 'feb'" << std::endl;
00813     return 1;
00814   }
00815   return 0;
00816 }
00817 
00818 //----------------------------------------------------------------------------
00820 
00825 int check_daq(bool needdaq)
00826 {
00827    if (needdaq && (gQdaq==0)) {
00828       std::cerr << "rocutil-E: command requires active DAQ, use 'board=addr?DAQ'"<< std::endl;
00829       return 1;
00830    }
00831    return 0;
00832 }
00833 
00834 //----------------------------------------------------------------------------
00836 
00849 int args_check(int needs) 
00850 {
00851    if (argspos.size() || argsopt.size()) {
00852       std::cerr << "rocutil-E: leftover arguments '";
00853       int cnt=0;
00854       for (int i=0; i<argspos.size(); i++) {
00855          if (cnt != 0) std::cerr << ",";
00856          std::cerr << argspos[i];
00857          cnt++;
00858       }
00859       for (int i=0; i<argsopt.size(); i++) {
00860          if (cnt != 0) std::cerr << ",";
00861          std::cerr << argsopt[i];
00862          cnt++;
00863       }
00864       std::cerr << "'" << std::endl;
00865       return 1;
00866    }
00867 
00868    if (needs & kNeedFeb) needs |= kNeedBoard; // needFeb implies needBoard
00869    if (needs & kNeedDaq) needs |= kNeedBoard; // needDaq implies needBoard
00870 
00871    if (((needs & kNeedBoard) != 0) && (gBaseBoard==0)) {
00872       std::cerr << "rocutil-E: command requires connected board, use 'board'" << std::endl;
00873       return 1;
00874    }
00875 
00876    if (((needs & kNeedRocBoard)!=0) && (gRocBoard==0)) {
00877       std::cerr << "rocutil-E: command requires connected ROC, use 'board'" << std::endl;
00878       return 1;
00879    }
00880 
00881    if (check_feb((needs & kNeedFeb)!=0)) return 1;
00882    if (check_daq((needs & kNeedDaq)!=0)) return 1;
00883 
00884    return 0;
00885 }
00886 
00887 //----------------------------------------------------------------------------
00889 
00894 void trim_whitespace(std::string& str) 
00895 {
00896   // trim leading white space
00897   size_t pos_nwhitebeg = str.find_first_not_of(" \t");
00898   str.erase(0, pos_nwhitebeg);
00899 
00900   // trim trailing white space
00901   size_t pos_nwhiteend = str.find_last_not_of(" \t");
00902   str.erase(pos_nwhiteend+1);
00903 }
00904 
00905 //----------------------------------------------------------------------------
00906 
00907 bool cmd_full_short(const char* cmd, std::string& cmdfull, std::string& cmdshort)
00908 {
00909   bool hasshort = false;
00910   cmdfull = cmd;
00911   cmdshort.erase();
00912   size_t pos_delcmd = cmdfull.find("|");
00913   if (pos_delcmd != std::string::npos) {
00914     cmdshort = cmdfull;
00915     cmdfull.erase(pos_delcmd);
00916     cmdshort.erase(0, pos_delcmd+1);
00917     hasshort = true;
00918   }
00919   return hasshort;
00920 }
00921 
00922 //----------------------------------------------------------------------------
00923 
00924 std::string get_timestamp(const char* fields="dtm") 
00925 {
00926   char buf[100];
00927   std::string str;
00928   struct timeval tv;
00929   struct tm tm_now;
00930   gettimeofday(&tv, 0);
00931   localtime_r(&tv.tv_sec, &tm_now);
00932 
00933   if (strchr(fields, 'd')) {
00934     strftime(buf, sizeof(buf), "%F", &tm_now);
00935     str += buf;
00936   }
00937   if (strchr(fields, 't')) {
00938     if (strchr(fields, 'd')) str += " ";
00939     strftime(buf, sizeof(buf), "%T", &tm_now);
00940     str += buf;
00941   }
00942   if (strchr(fields, 'm')) {
00943     snprintf(buf, sizeof(buf), ".%03d", int(tv.tv_usec/1000));
00944     str += buf;
00945   }
00946   return str;
00947 }
00948 
00949 //----------------------------------------------------------------------------
00950 
00951 int print_opererr(const char* text, int rc)
00952 {
00953   static boost::format fmt(": rc = %|4|,%|2| -> ");
00954   if (rc) {
00955     std::cout << "rocutil-E: " << text << " : " 
00956          << base::Board::operErrToString(rc) << std::endl;
00957   }
00958   return rc;
00959 }
00960 
00961 //----------------------------------------------------------------------------
00962 
00963 void print_loop_stats(const char* text, int ecnt)
00964 {
00965   std::cout << "rocutil-I: " << text << " ";
00966   std::cout << ( (ecnt)?"FAILED":"PASSED" );
00967   std::cout << " after " << std::dec << gUtil->getLoopCount()
00968        << " test loops";
00969   double dtime = gUtil->now() - gUtil->getStartLoopTime();
00970   if (dtime > 0) {
00971     static boost::format fmt(" in %4.2f sec");
00972     std::cout << fmt % dtime;
00973   }
00974   if (ecnt) std::cout << " with " << ecnt << " errors";
00975   std::cout << std::endl;
00976 }
00977 
00978 //----------------------------------------------------------------------------
00979 
00980 void print_daq_stats(const char* text, uint64_t cnt, int ecnt)
00981 {
00982   std::cout << "rocutil-I: " << text << " ";
00983   std::cout << ( (ecnt)?"FAILED":"PASSED" );
00984   std::cout << " after " << std::dec << cnt
00985        << " messages";
00986   double dtime = gQdaq->getStopTime() - gQdaq->getStartTime();
00987   if (dtime > 0) {
00988     static boost::format fmt(" in %4.2f sec");
00989     std::cout << fmt % dtime;
00990   }
00991   if (ecnt) std::cout << " with " << ecnt << " errors";
00992   std::cout << std::endl;
00993 }
00994 
00995 //----------------------------------------------------------------------------
00996 //++ helper functions for command argument handling ++++++++++++++++++++++++++
00998 
00999 int get_arg(std::string& arg, const char* aname, bool& defaulting)
01000 {
01001   defaulting = false;
01002   if (argspos.size()) {                     // use positionals if available
01003     arg = argspos.front();
01004     argspos.erase(argspos.begin());
01005     return 0;
01006 
01007   } else if (aname && aname[0]) {           // optional arg "name=" given
01008     for (int i=0; i<argsopt.size(); i++) {
01009       size_t pos = argsopt[i].find(aname);
01010       if (pos == 0) {                       // if match
01011         arg = argsopt[i];                   // take it
01012         arg.erase(0, strlen(aname));        // drop "name=" prefix
01013         argsopt.erase(argsopt.begin()+i);   // and delete from argsopt list
01014         return 0;
01015       }
01016     }
01017     defaulting = true;
01018     return 0;                               // ok defaulting for optional arg
01019   }
01020   std::cerr << "rocutil-E: Argument missing" << std::endl;
01021   return 1;
01022 }
01023 
01024 //----------------------------------------------------------------------------
01025 
01027 
01028 int get_arg(std::string& arg, const char* aname=0)
01029 {
01030   bool defaulting;
01031   return get_arg(arg, aname, defaulting);
01032 }
01033 
01034 //----------------------------------------------------------------------------
01036 
01037 int get_arg(int32_t& arg, const char* aname=0, 
01038             int32_t min=(1<<31), int32_t max=~(1<<31))
01039 {
01040   std::string str;
01041   bool defaulting;
01042   if (get_arg(str, aname, defaulting)) return 1;
01043   if (defaulting) return 0;
01044   trim_whitespace(str);
01045 
01046   if (str.size()!=0) {                      // if non-empty argument
01047     const char* cstr = str.c_str();
01048     char* eptr;
01049     int base=0;
01050     
01051     if (cstr[0]=='b' || cstr[0]=='B') {
01052       cstr += 1;
01053       base  = 2;
01054     }
01055     
01056     errno = 0;
01057     int res = strtol(cstr, &eptr, base);
01058     if (errno || (eptr && eptr[0]!=0)) {
01059       std::cerr << "rocutil-E: conversion error in '" << str << "'" << std::endl;
01060       return 1;
01061     } else {
01062       arg = res;
01063     }
01064 
01065   } else {                                  // for empty arg assume 0
01066     arg = 0;
01067   }
01068 
01069   if (arg < min || arg > max) {
01070     std::cerr << "rocutil-E: value " << arg << " is out of range " 
01071          << min << ",...," << max << std::endl;
01072     return 1;
01073   }
01074 
01075   return 0;
01076 }
01077 
01078 //----------------------------------------------------------------------------
01080 
01081 int get_arg(double& arg, const char* aname=0)
01082 {
01083   std::string str;
01084   bool defaulting;
01085   if (get_arg(str, aname, defaulting)) return 1;
01086   if (defaulting) return 0;
01087   trim_whitespace(str);
01088 
01089   if (str.size()!=0) {                      // if non-empty argument
01090     const char* cstr = str.c_str();
01091     char* eptr;
01092     
01093     errno = 0;
01094     double res = strtod(cstr, &eptr);
01095     if (errno || (eptr && eptr[0]!=0)) {
01096       std::cerr << "rocutil-E: conversion error in '" << str << "'" << std::endl;
01097       return 1;
01098     } else {
01099       arg = res;
01100     }
01101 
01102   } else {                                  // for empty arg assume 0
01103     arg = 0.;
01104   }
01105 
01106   return 0;
01107 }
01108 
01109 //----------------------------------------------------------------------------
01111 
01112 int get_arg(bool& arg, const char* aname=0)
01113 {
01114   int32_t inp = -1;
01115   if (get_arg(inp, aname, 0, 1)) return 1;
01116   if (inp != -1) arg = (inp != 0);          // if not defaulting
01117   return 0;
01118 }
01119 
01120 //----------------------------------------------------------------------------
01122 
01123 int get_nxind(int32_t& nx, const char* aname=0)
01124 {
01125   if (get_arg(nx, aname)) return 1;
01126   if (check_feb()) return 1;
01127   
01128   if (nx<0 || nx>=gFeb->numNx()) {
01129     std::cout << "nXYTER index '" << nx << "' out of range, use 0,..," 
01130          << gFeb->numNx()-1 << std::endl;
01131     return 1;
01132   }
01133   return 0;
01134 }
01135 
01136 //----------------------------------------------------------------------------
01138 
01139 int get_nxrange(int32_t& nxbeg, int32_t& nxend, const char* aname=0)
01140 {
01141   std::string str;
01142   bool defaulting;
01143 
01144   if (check_feb()) return 1;
01145   if (get_arg(str, aname, defaulting)) return 1;
01146   if (defaulting || str == "*") {
01147     nxbeg = 0;
01148     nxend = gFeb->numNx()-1;
01149     return 0;
01150   }
01151 
01152   trim_whitespace(str);
01153 
01154   int32_t nx = 0;
01155   if (str.size()!=0) {                      // if non-empty argument
01156     const char* cstr = str.c_str();
01157     char* eptr;    
01158     errno = 0;
01159     nx = strtol(cstr, &eptr, 0);
01160     if (errno || (eptr && eptr[0]!=0)) {
01161       std::cerr << "rocutil-E: conversion error in '" << str << "'" << std::endl;
01162       return 1;
01163     } 
01164   }
01165 
01166   if (nx<0 || nx>=gFeb->numNx()) {
01167     std::cout << "nXYTER index '" << nx << "' out of range, use 0,..," 
01168          << gFeb->numNx()-1 << std::endl;
01169     return 1;
01170   }
01171   nxbeg = nx;
01172   nxend = nx;
01173   return 0;
01174 }
01175 
01176 //----------------------------------------------------------------------------
01178 
01179 bool get_opt(const std::string& opt)
01180 {
01181    for (std::vector<std::string>::iterator it=argsopt.begin(); it!=argsopt.end(); it++) {
01182       if (*it == opt) {
01183          argsopt.erase(it);
01184          return true;
01185       }
01186    }
01187    return false;
01188 }
01189 
01190 //----------------------------------------------------------------------------
01192 
01193 bool check_nxoffline(int nxind, int nxbeg, int nxend)
01194 {
01195   if (nxbeg == nxend) return false;         // force false for single access
01196   return gFeb->getNxOffline(nxind);         // use offline flag for range
01197 }
01198 
01199 //----------------------------------------------------------------------------
01200 //++ command action routines +++++++++++++++++++++++++++++++++++++++++++++++++
01201 
01202 int cmd_help()
01203 {
01204   bool verbose = get_opt("-v");
01205   bool genhelp = get_opt("-g");
01206   bool listabr = get_opt("-a");
01207   std::string cmd;
01208 
01209   get_arg(cmd, "command=");
01210   
01211   if (cmd.size()) verbose = true;
01212   bool cmdok = false;
01213   
01214   if (genhelp) {
01215     std::cout 
01216       << "rocutil is a general purpose utility for all kinds of operations\n"
01217       << "on ROCs and FEBs. It can handle one ROC and one FEB at a time.\n"
01218       << "Commands can be specified on the shell command line or at a prompt.\n"
01219       << "\n"
01220       << "Command syntax is simple, a command name followed by a comma or\n"
01221       << "white space separated list of arguments.\n"
01222       << "The delimiter between command name and arguments can be '=' or\n"
01223       << "white space. The '=' is more convenient at the shell command line\n"
01224       << "white space after a command prompt.\n"
01225       << "A shell command line might look like\n"
01226       << "   rocutil board=cbmtest42 feb=0,Feb1nx setfebdef\n"
01227       << "\n"
01228       << "If no command is given on the command line or the last is '-'\n"
01229       << "rocutil will enter command prompt mode with a 'rocutil>' prompt.\n"
01230       << "The prompt mode supports command editing and history recall,\n"
01231       << "the command history is stored across program invocations in the\n"
01232       << "file ./.rocutil_history in the current working directory.\n"
01233       << "\n"
01234       << "Integer numerical arguments can be entered in four radix:\n"
01235       << "   decimal      like   123\n"
01236       << "   hexadecimal  like 0x123\n"
01237       << "   octal        like  0123    !Note: leading zero means octal!\n"
01238       << "   binary       like b1011    is 11 (dec) 0xB (hex) 013 (oct)\n"
01239       << "\n"
01240       << "Optional arguments can be given in the form 'name=value'. They are\n"
01241       << "put in [...] in the help text and always have a default value. The\n"
01242       << "two command lines:\n"
01243       << "   setnxmode 0 ttri=1 csel=2\n"
01244       << "   setnxmode 0,0,1,2\n"
01245       << "are equivalent. Command options have the UNIX style '-v' form and\n"
01246       << "can be placed anywhere in the argument list. The two commands\n"
01247       << "   seti2c=-l,-v,0,8,0xaa\n"
01248       << "   seti2c -l -v 0 8 b10101010\n"
01249       << "are again equivalent.\n"
01250       << "\n"
01251       << "It is convenient to leave setup configuration commands at the shell\n"
01252       << "command and do the rest at the prompt, like:\n"
01253       << "   rocutil board=cbmtest42 feb=0,Feb1nx -\n"
01254       << "   rocutil> setfebdef\n"
01255       << "   rocutil> setnxmask 0 1 4\n"
01256       << "   rocutil> setnxmode 0 tpul=1 csel=2\n"
01257       << "   rocutil> printfeb\n"
01258       << "\n"
01259       << "Command files can be executed with a command like\n"
01260       << "   @filename\n"
01261       << "\n"
01262       << "Command lines can have comments in two forms:\n"
01263       << "   1. everything after '//' is discarted\n"
01264       << "   2. a line starting with '/*' is copied to stdout\n"
01265       << "\n"
01266       << "Finally, some commands have abreviated names, see 'help -s' for a"
01267       << "list of abbreviations. The full help text 'help <cmd>' will also"
01268       << "indicate when an abbreviation is defined."
01269       << "\n"
01270       << std::flush;
01271     return 0;
01272   }
01273 
01274   if (listabr) {
01275     std::map<std::string, std::string> map_short2full;
01276     typedef std::map<std::string,std::string>::iterator map_iter_t;
01277 
01278     for (unsigned i=0; i<cmdlist.size(); i++) {
01279       std::string cmdfull;
01280       std::string cmdshort;
01281       cmd_full_short(cmdlist[i]->name, cmdfull, cmdshort);
01282       if (cmdshort.size()==0) continue;
01283 
01284       map_iter_t it = map_short2full.find(cmdshort);
01285       
01286       if (it != map_short2full.end()) {
01287         std::cout << "rocutil-E: duplicate command abbreviation: "
01288              << cmdshort << " -> '" << (*it).second
01289              << "' and '" << cmdfull << "'"
01290              << std::endl;
01291       } else {
01292         map_short2full[cmdshort] = cmdfull;
01293       }
01294     }
01295     
01296     for (map_iter_t it = map_short2full.begin(); 
01297          it != map_short2full.end(); it++) {
01298       static boost::format fmt("%|-4| -> %s");
01299       std::cout << fmt % (*it).first % (*it).second << std::endl;
01300     }
01301 
01302     return 0;
01303   }
01304 
01305   for (unsigned i=0; i<cmdlist.size(); i++) {
01306     std::string cmdfull;
01307     std::string cmdshort;
01308     cmd_full_short(cmdlist[i]->name, cmdfull, cmdshort);
01309 
01310     static boost::format fmt("%|-12| %s");
01311     if (cmd.size() == 0 || cmd == cmdfull || cmd == cmdshort) {
01312       cmdok = true;
01313       std::cout << fmt % cmdfull % cmdlist[i]->shelp << std::endl;
01314       if (verbose && cmdlist[i]->lhelp[0]) {
01315         size_t pos_cur = 0;
01316         while(pos_cur != std::string::npos) {
01317           std::string lhelp(cmdlist[i]->lhelp);
01318           std::cout << "             ";
01319           size_t pos_eol = lhelp.find("\n", pos_cur);
01320           if (pos_eol != std::string::npos) {
01321             std::cout << lhelp.substr(pos_cur, pos_eol-pos_cur);
01322             pos_cur = pos_eol+1;
01323             if (pos_cur >= lhelp.size()) pos_cur = std::string::npos;
01324           } else {
01325             std::cout << lhelp.substr(pos_cur);
01326             pos_cur = std::string::npos;
01327           }
01328           std::cout << std::endl;
01329         }
01330         if (cmdshort.size()) {
01331           std::cout << "            " 
01332                << cmdfull << " can be abreviated as " 
01333                << cmdshort << std::endl;
01334         }
01335       }
01336     }
01337   }
01338 
01339   if (cmd.size() == 0) {
01340     std::cout 
01341       << "\n"
01342       << "For command syntax and general help use 'help -g'\n"
01343       << "For detailed help on a command cmd use  'help cmd'\n"
01344       << "For a full long listing of all command  'help -v'\n"
01345       << "For list of command abbreviations see   'help -a'\n"
01346       << std::flush;
01347   }
01348 
01349   if (cmd.size() && (!cmdok)) {
01350     std::cout << "rocutil-E: Command '" << cmd << "' not found." << std::endl;
01351     std::cout << "rocutil-I: Use 'help', 'help -g', 'help -s' or 'help -v'." << std::endl;
01352   }
01353 
01354   return 0;
01355 }
01356 
01357 //----------------------------------------------------------------------------
01358 
01359 int cmd_quit()
01360 {
01361   return -1;
01362 }
01363 
01364 //----------------------------------------------------------------------------
01365 
01366 int cmd_board()
01367 {
01368   if (gBaseBoard) {
01369     std::cerr << "rocutil-E: Already connected to a board, command ignored" << std::endl;
01370     return 0;
01371   }
01372 
01373   std::string brdname;
01374   if (get_arg(brdname)) return 1;
01375   if (args_check(0)) return 1;
01376 
01377   gBaseBoard = base::Board::Connect(brdname.c_str(), base::roleDAQ);
01378 
01379   if (gBaseBoard==0) {
01380      std::cerr << "rocutil-E: Fail connect to the board " << brdname << std::endl;
01381      return 1;
01382   }
01383 
01384   gBoardName = brdname;
01385 
01386   reset_cmdlist();
01387   add_cmdlist(cmdlist_board);
01388 
01389   gRocBoard = dynamic_cast<roc::Board*> (gBaseBoard);
01390   gSP605Board = dynamic_cast<sp605::Board*>(gBaseBoard);
01391 
01392   if (gBaseBoard!=0) {
01393      gUtil = new nxyter::FebUtil(0);           // to have loops for roc-only tests
01394   }
01395 
01396   uint32_t fee_kind = gBaseBoard->getFrontendKind();
01397 
01398   bool isnxyter = (fee_kind == base::kind_nXYTER) || (fee_kind == base::kind_newNX);
01399   bool isfeet = (fee_kind == base::kind_FEET) || (fee_kind == base::kind_oldFEET);
01400 
01401   if (gBaseBoard->getRole() == base::roleDAQ) {
01402      gQdaq = new nxyter::QuickDaq(gBaseBoard);
01403   }
01404 
01405   if (isnxyter)
01406      add_cmdlist(cmdlist_nxyter);
01407 
01408   if (gRocBoard!=0) {
01409      // this is all about readout controller with nXYTER frontend
01410 
01411      add_cmdlist(cmdlist_gpio);
01412      add_cmdlist(cmdlist_roc);
01413 
01414      roc::I2cDevice::addAddrMap(gRocBoard);
01415      base::Gpio::addAddrMap(gRocBoard);
01416      gGpio = new base::Gpio(gRocBoard);
01417 
01418      if (isnxyter) {
01419         gRocNx = new nxyter::RocNx(gRocBoard);
01420         nxyter::RocNx::addAddrMap(gRocBoard, fee_kind);
01421         nxyter::MainAdc::addAddrMap(gRocBoard);
01422      }
01423 
01424      if (isfeet)
01425         feet::RocFeet::addAddrMap(gRocBoard, fee_kind);
01426 
01427      // now to a few sanity checks
01428      if (!gRocBoard->isFile()) {
01429         uint32_t hw_vers;
01430         uint32_t lts_delay(1);
01431         int rc;
01432         rc = gRocBoard->get(ROC_HWV, hw_vers);
01433         print_opererr("Board::get(HARDWARE_VERSION)", rc);
01434 
01435         if (fee_kind == base::kind_nXYTER) {
01436            rc = gRocBoard->get(ROC_NX_DELAY_LTS, lts_delay);
01437            print_opererr("Board::get(DELAY_LTS)", rc);
01438         }
01439 
01440         if (hw_vers < 0x01070213)
01441            std::cout << "rocutil-W: Detected outdated firmware version. This version of\n"
01442                      << "           rocutil expects HARDWARE_VERSION 01070213 or higher"  << std::endl;
01443 
01444         if (lts_delay == 0)
01445            std::cout << "rocutil-W: Detected uninitialized ROC registers. Use 'setrocdef'." << std::endl;
01446      }
01447   } else
01448 
01449   if (gSP605Board!=0) {
01450      add_cmdlist(cmdlist_gpio);
01451      add_cmdlist(cmdlist_sp605);
01452 
01453      roc::I2cDevice::addAddrMap(gBaseBoard);
01454      base::Gpio::addAddrMap(gBaseBoard);
01455 
01456      gGpio = new base::Gpio(gBaseBoard);
01457 
01458      if (isnxyter) {
01459         gRocNx = new nxyter::RocNx(gBaseBoard);
01460         nxyter::RocNx::addAddrMap(gBaseBoard, fee_kind);
01461         nxyter::MainAdc::addAddrMap(gBaseBoard);
01462      }
01463   }
01464 
01465   return 0;
01466 }
01467 
01468 //----------------------------------------------------------------------------
01469 
01470 int cmd_setdebug()
01471 {
01472   int32_t lvl;
01473   if (get_arg(lvl)) return 1;
01474   if (args_check(kNeedRocBoard)) return 1;
01475 
01476   gRocBoard->setVerbosity(lvl);
01477   return 0;
01478 }
01479 
01480 //----------------------------------------------------------------------------
01481 
01482 int cmd_settrace()
01483 {
01484   int32_t lvl=1;
01485   if (get_arg(lvl, "lvl=")) return 1;
01486   if (args_check(kNeedBoard)) return 1;
01487 
01488   gBaseBoard->setOperTrace(lvl);
01489   return 0;
01490 }
01491 
01492 //----------------------------------------------------------------------------
01493 
01494 int cmd_ident()
01495 {
01496   if (gBaseBoard)
01497     std::cout << "--- Connected to " << gBoardName;
01498   else
01499     std::cout << "--- Not yet connected";
01500 
01501   std::cout << " at " << get_timestamp("dtm") << std::endl;
01502   return 0;
01503 }
01504 
01505 //----------------------------------------------------------------------------
01506 
01507 int cmd_initfeb()
01508 {
01509    if (gFeb==0) {
01510       std::cout << " Feb not created" << std::endl;
01511    } else {
01512       gFeb->initRoc();
01513       std::cout << "set nxyter on/off flags to ROC" << std::endl;
01514    }
01515 
01516    return 0;
01517 }
01518 
01519 
01520 //----------------------------------------------------------------------------
01521 
01522 int cmd_discover()
01523 {
01524   bool opt_verb = get_opt("-v");
01525   if (args_check(kNeedRocBoard)) return 1;
01526   nxyter::FebUtil::probe(gRocBoard, opt_verb);
01527   return 0;
01528 }
01529 
01530 //----------------------------------------------------------------------------
01531 
01532 int cmd_dlm()
01533 {
01534    int num = 1;
01535    if (get_arg(num, "num=")) return 1;
01536    if (gRocBoard==0) return 1;
01537 
01538    gRocBoard->invokeDLM(num);
01539 
01540    std::cout << "Invoke DLM = " << num << std::endl;
01541 
01542    return 0;
01543 }
01544 
01545 //----------------------------------------------------------------------------
01546 
01547 int cmd_feb()
01548 {
01549   int32_t port = -1;
01550   std::string type("auto");
01551   if (get_arg(port, "port=")) return 1;
01552   if (get_arg(type, "type=")) return 1;
01553   if (args_check(kNeedBoard)) return 1;
01554 
01555   delete gFeb;   gFeb  = 0;
01556   delete gQdaq;  gQdaq = 0;
01557   delete gUtil;  gUtil = 0;
01558 
01559   int ftyp=-1;
01560 
01561   if (type != "auto") {
01562     if      (type == "Feb1nxGenB") ftyp = nxyter::FebBase::kFeb1nxGenB;
01563     else if (type == "Feb1nxGenC") ftyp = nxyter::FebBase::kFeb1nxGenC;
01564     else if (type == "Feb1nxGenD") ftyp = nxyter::FebBase::kFeb1nxGenD;
01565     else if (type == "Feb2nxGas")  ftyp = nxyter::FebBase::kFeb2nxGas;
01566     else if (type == "Feb4nxBT")   ftyp = nxyter::FebBase::kFeb4nxBT;
01567     else {
01568       std::cout << "Unknown type, use Feb1nxGen[BCD], Feb2nxGas, Feb4nxBT" << std::endl;
01569       return 1;
01570     }    
01571   }
01572 
01573   if (port==-1 || type=="auto") {
01574     int ftyp0, ftyp1;
01575     nxyter::FebBase::discoverFebs(gRocBoard, ftyp0, ftyp1, true);
01576     if (port==-1) {
01577       if (ftyp0 != 0) {
01578         port = 0;
01579         ftyp = ftyp0;
01580       } else if (ftyp1 != 0) {
01581         port = 1;
01582         ftyp = ftyp1;
01583       } else {
01584         std::cout << "No FEB detected, use 'discover'" << std::endl;
01585         return 1;
01586       }
01587     }
01588     if (ftyp == -1) {
01589       ftyp = (port==0) ? ftyp0 : ftyp1;
01590       if (ftyp==0) {
01591         std::cout << "No FEB detected on port " << port << ", use 'discover'" << std::endl;
01592         return 1;
01593       }
01594     }
01595     std::cout << "rocutil-I: connect on port " << port
01596               << " " << nxyter::FebBase::typeToString(ftyp) << std::endl;
01597   }
01598 
01599   gFeb = nxyter::FebBase::newFeb(gBaseBoard, port, ftyp);
01600 
01601   if (!gFeb)
01602     std::cout << "Internal error, no FEB attached" << std::endl;
01603   
01604   if (gBaseBoard && (gBaseBoard->getRole() == base::roleDAQ))
01605      gQdaq = new nxyter::QuickDaq(gFeb);
01606 
01607   gUtil = new nxyter::FebUtil(gFeb, gQdaq);
01608 
01609   return 0;
01610 }
01611 
01612 //----------------------------------------------------------------------------
01613 
01614 int cmd_setnxaddr()
01615 {
01616   int32_t nxind;
01617   int32_t addr;
01618   if (get_nxind(nxind)) return 1;
01619   if (get_arg(addr, 0, 0, 255)) return 1;
01620   if (args_check(kNeedFeb)) return 1;
01621 
01622   gFeb->nx(nxind).i2c().setSlaveAddr(uint8_t(addr));
01623   return 0;
01624 }
01625 
01626 //----------------------------------------------------------------------------
01627 
01628 int cmd_setnxoff()
01629 {
01630   int32_t nxind;
01631   bool val;
01632   if (get_nxind(nxind)) return 1;
01633   if (get_arg(val)) return 1;
01634   if (args_check(kNeedFeb)) return 1;
01635 
01636   gFeb->setNxOffline(nxind, val);
01637   return 0;
01638 }
01639 
01640 //----------------------------------------------------------------------------
01641 
01642 int cmd_printroc()
01643 {
01644   uint32_t alist[] = {ROC_TYPE,
01645                       ROC_HWV,
01646                       ROC_ROCID,
01647                       base::GPIO_CONFIG,
01648                       base::GPIO_SYNCM_SCALEDOWN,
01649                       base::GPIO_SYNCM_BAUD1,
01650                       base::GPIO_SYNCM_BAUD2,
01651                       base::GPIO_SYNCS0_BAUD1,
01652                       base::GPIO_SYNCS0_BAUD2,
01653                       ROC_NX_HWV,
01654                       ROC_NX_NXACTIVE,
01655                       ROC_NX_FEB4NX,
01656                       ROC_NX_PARITY_CHECK,
01657                       ROC_NX_ADC_PORT_SELECT1,
01658                       ROC_NX_ADC_PORT_SELECT2,
01659                       ROC_NX_ADC_PORT_SELECT3,
01660                       ROC_NX_ADC_PORT_SELECT4,
01661                       ROC_NX_SR_INIT,
01662                       ROC_NX_BUFG_SELECT,
01663                       ROC_NX_SR_INIT2,
01664                       ROC_NX_BUFG_SELECT2,
01665                       ROC_NX_ADC_LATENCY1,
01666                       ROC_NX_ADC_LATENCY2,
01667                       ROC_NX_ADC_LATENCY3,
01668                       ROC_NX_ADC_LATENCY4,
01669                       ROC_NX_DELAY_LTS,
01670                       ROC_NX_DELAY_NX0,
01671                       ROC_NX_DELAY_NX1,
01672                       ROC_NX_DELAY_NX2,
01673                       ROC_NX_DELAY_NX3,
01674                       ROC_NX_DEBUG_MODE,
01675                       ROC_ETH_HWV,
01676                       ROC_ETH_SWV,
01677                       ROC_ETH_IP_ADDRESS,
01678                       ROC_ETH_MAC_ADDRESS_UPPER,
01679                       ROC_ETH_MAC_ADDRESS_LOWER,
01680                       ROC_ETH_BUFFER_FLUSH_TIMER,
01681                       ROC_ETH_LOWWATER,
01682                       ROC_ETH_HIGHWATER,
01683                       ROC_ETH_NUMBUFALLOC,
01684                       ROC_ETH_LOST_ETHER_FRAMES,
01685                       ROC_ETH_TEMAC_REG0
01686   };
01687 
01688   if (args_check(kNeedRocBoard)) return 1;
01689 
01690   for (int i=0; i<sizeof(alist)/sizeof(alist[0]); i++) {
01691 
01692      // do not try to read Ethernet-specific registers in Optic case
01693      if ((alist[i]==ROC_ETH_SWV) &&
01694          (gRocBoard->getTransportKind() != roc::kind_UDP)) break;
01695          
01696      // do not try to read nXYTER-specific registers in FEET case
01697     if ((alist[i]==ROC_NX_HWV) &&
01698         (gRocBoard->getRocFrontendKind() != base::kind_nXYTER)) break;
01699 
01700     const char* sname = gRocBoard->findRegNameByAddress(alist[i]);
01701 
01702     if (sname==0) {
01703        std::cout << alist[i] << " not available on ROC" << std::endl;
01704        continue;
01705     }
01706 
01707     static boost::format fmt_pref("get(%-24s [0x%08x]) -> ");
01708     std::cout << fmt_pref % sname % alist[i];
01709 
01710     uint32_t value;
01711     int rc = gRocBoard->get(alist[i], value);
01712     if (rc==0) {
01713       static boost::format fmt_data("0x%08x %10d");
01714       std::cout << fmt_data % value % value << std::endl;
01715     } else {
01716       std::cout << base::Board::operErrToString(rc) << std::endl;
01717     }
01718   }
01719                       
01720   return 0;
01721 }
01722 
01723 //----------------------------------------------------------------------------
01724 
01725 int cmd_printid()
01726 {  
01727   if (args_check(kNeedRocBoard)) return 1;                      
01728 
01729   int rc;
01730   uint32_t value;
01731 
01732   rc = gRocBoard->get(ROC_TYPE, value);
01733   if (rc==0) std::cout << "ROC type:             " 
01734                   << gRocBoard->versionToString(value) << std::endl;
01735   rc = gRocBoard->get(ROC_HWV, value);
01736   if (rc==0) std::cout << "ROC hardware version: " 
01737                   << gRocBoard->versionToString(value) << std::endl;
01738   if (gRocBoard->getTransportKind() == roc::kind_UDP) {
01739     rc = gRocBoard->get(ROC_ETH_HWV, value);
01740     if (rc==0) std::cout << "Eth hardware version: " 
01741                     << gRocBoard->versionToString(value) << std::endl;
01742     rc = gRocBoard->get(ROC_ETH_SWV, value);
01743     if (rc==0) std::cout << "Eth software version: " 
01744                     << gRocBoard->versionToString(value) << std::endl;
01745   }
01746   if (gRocBoard->getTransportKind() == roc::kind_ABB) {
01747     rc = gRocBoard->get(ROC_OPTICS_HWV, value);
01748     if (rc==0) std::cout << "Opt hardware version: " 
01749                     << gRocBoard->versionToString(value) << std::endl;
01750   }
01751   rc = gRocBoard->get(ROC_NX_HWV, value);
01752   if (rc==0) std::cout << "Nx  hardware version: " 
01753                   << gRocBoard->versionToString(value) << std::endl;
01754 
01755   return 0;
01756 }
01757 
01758 //----------------------------------------------------------------------------
01759 
01760 int cmd_printfeb()
01761 {
01762   bool opt_m = get_opt("-m");
01763   bool opt_c = get_opt("-c");
01764   bool opt_t = get_opt("-t");
01765   bool opt_a = get_opt("-a");
01766   if (args_check(kNeedFeb)) return 1;
01767 
01768   if (!(opt_m | opt_c | opt_t | opt_a)) opt_c = true;
01769   int domask = 0;
01770   if (opt_m | opt_a) domask |= nxyter::kDoMask;
01771   if (opt_c | opt_a) domask |= nxyter::kDoCore;
01772   if (opt_t | opt_a) domask |= nxyter::kDoTrim;
01773 
01774   gFeb->printRegisters(std::cout, domask);
01775   return 0;
01776 }
01777 
01778 //----------------------------------------------------------------------------
01779 
01780 int cmd_printadc()
01781 {
01782   if (args_check(kNeedFeb)) return 1;
01783   gFeb->adc().printRegisters(std::cout);
01784   return 0;
01785 }
01786 
01787 //----------------------------------------------------------------------------
01788 
01789 int cmd_printnx()
01790 {
01791   bool opt_m = get_opt("-m");
01792   bool opt_c = get_opt("-c");
01793   bool opt_t = get_opt("-t");
01794   bool opt_a = get_opt("-a");
01795   int nxbeg=0;
01796   int nxend=0;
01797   if (get_nxrange(nxbeg, nxend, "nx=")) return 1;
01798   if (args_check(kNeedFeb)) return 1;
01799 
01800   if (!(opt_m | opt_c | opt_t | opt_a)) opt_c = true;
01801   int domask = 0;
01802   if (opt_m | opt_a) domask |= nxyter::kDoMask;
01803   if (opt_c | opt_a) domask |= nxyter::kDoCore;
01804   if (opt_t | opt_a) domask |= nxyter::kDoTrim;
01805 
01806   for (int i=nxbeg; i<=nxend; i++) {
01807     gFeb->printNxHeadLine(std::cout, i);    
01808     if (!gFeb->getNxOffline(i)) gFeb->nx(i).i2c().printRegisters(std::cout, domask);
01809   }
01810   return 0;
01811 }
01812 
01813 //----------------------------------------------------------------------------
01814 
01815 int cmd_printmon()
01816 {
01817   if (args_check(kNeedFeb)) return 1;
01818 
01819   if (!gFeb->monAdcSupport()) {
01820     std::cout << "no monitoring ADC support for this FEB type" << std::endl;
01821     return 0;
01822   }
01823 
01824   uint16_t val[4];
01825     for (int ch=0; ch<4; ch++) {
01826     int rc = gFeb->getMonAdc(ch, val[ch]);
01827     print_opererr("FebBase::getMonAdc", rc);
01828   }
01829 
01830   for (int ch=0; ch<4; ch++) {
01831     static boost::format fmt("%|4|");
01832     std::cout << " " << fmt % uint32_t(val[ch]);
01833   }
01834   std::cout << std::endl;
01835   
01836   return 0;
01837 }
01838 
01839 //----------------------------------------------------------------------------
01840 
01841 int cmd_setbrddef()
01842 {
01843   if (args_check(kNeedBoard)) return 1;
01844 
01845   int rc = gBaseBoard->setToDefault();
01846   print_opererr("Board::setToDefault", rc);
01847 
01848   return 0;
01849 }
01850 
01851 //----------------------------------------------------------------------------
01852 
01853 int cmd_setrocdef()
01854 {
01855   if (args_check(kNeedBoard)) return 1;
01856 
01857   int rc = gBaseBoard->setToDefault();
01858   print_opererr("Board::setToDefault", rc);
01859 
01860   if (gRocNx) {
01861      rc = gRocNx->setToDefault();
01862      print_opererr("RocNx::setToDefault", rc);
01863   }
01864 
01865   return 0;
01866 }
01867 
01868 //----------------------------------------------------------------------------
01869 
01870 int cmd_setsyncm()
01871 {
01872    int32_t scale;
01873    double baud = 62.5;
01874    if (get_arg(scale, 0, 0, 21)) return 1;
01875    if (get_arg(baud, "baud=")) return 1;
01876    if (args_check(kNeedBoard)) return 1;
01877    if (gGpio == 0) { std::cerr << "No Gpio instance" << std::endl; return 1; }
01878 
01879    int ratediv = int(std::floor((500./baud)+0.5));
01880    if (ratediv > 511 || std::abs(baud - 500./double(ratediv)) > 0.01) {
01881       std::cout << "rocutil-E: baud rate not supported" << std::endl;
01882       return 1;
01883    }
01884 
01885    int rc;
01886    rc = gGpio->setSyncScale(scale);
01887    print_opererr("Gpio::setSyncScale", rc);
01888    rc = gGpio->setSyncBaud(1, ratediv);
01889    print_opererr("Gpio::setSyncBaud", rc);
01890 
01891    return 0;
01892 }
01893 
01894 //----------------------------------------------------------------------------
01895 
01896 int cmd_setsyncs()
01897 {
01898   int32_t ch;
01899   bool enable;
01900   bool throttled = false;
01901   double baud = 62.5;
01902   int32_t loop = 0;
01903   if (get_arg(ch, 0, 0, 1)) return 1;
01904   if (get_arg(enable)) return 1;
01905   if (get_arg(throttled, "thr=")) return 1;
01906   if (get_arg(baud, "baud=")) return 1;
01907   if (get_arg(loop, "loop=", 0, 1)) return 1;
01908   if (args_check(kNeedBoard)) return 1;
01909   if (gGpio == 0) { std::cerr << "No Gpio instance" << std::endl; return 1; }
01910 
01911   int ratediv = int(std::floor((500./baud)+0.5));
01912   if (ratediv > 511 || std::abs(baud - 500./double(ratediv)) > 0.01) {
01913     std::cout << "rocutil-E: baud rate not supported" << std::endl;
01914     return 1;
01915   }
01916 
01917   int rc;
01918   rc = gGpio->setConfig(2+ch, enable, enable, throttled, loop, false);
01919   print_opererr("Gpio::setConfig", rc);
01920   rc = gGpio->setSyncBaud(2+ch, ratediv);
01921   print_opererr("Gpio::setSyncBaud", rc);
01922 
01923   return 0;
01924 }
01925 
01926 //----------------------------------------------------------------------------
01927 
01928 int cmd_setaux()
01929 {
01930   int32_t ch;
01931   bool riseedge = false;
01932   bool falledge = false;
01933   bool throttled = true;
01934   bool extrafunc = false;
01935   bool altin = false;
01936   if (get_arg(ch, 0, 0, 3)) return 1;
01937   if (get_arg(riseedge, "re=")) return 1;
01938   if (get_arg(falledge, "fe=")) return 1;
01939   if (get_arg(throttled, "thr=")) return 1;
01940   if (get_arg(extrafunc, "ext=")) return 1;
01941   if (get_arg(altin, "alt=")) return 1;
01942   if (args_check(kNeedBoard)) return 1;
01943   if (gGpio == 0) { std::cerr << "No Gpio instance" << std::endl; return 1; }
01944 
01945   int rc = gGpio->setConfig(4+ch, riseedge, falledge, throttled, 
01946                             extrafunc,altin);
01947   print_opererr("Gpio::setConfig", rc);
01948   return 0;
01949 }
01950 
01951 //----------------------------------------------------------------------------
01952 int cmd_setlhwater()
01953 {
01954    int32_t low(0), high(0);
01955 
01956    roc::UdpBoard* udp = dynamic_cast<roc::UdpBoard*> (gRocBoard);
01957    if (udp==0) return 1;
01958 
01959    if (get_arg(low,  "low=")) return 1;
01960    if (get_arg(high, "high=")) return 1;
01961 
01962    if ((low<8) || (high>128*1024) || (low>=high-8)) return 1;
01963 
01964    if (!udp->setRocLowHighWater(low, high)) return 1;
01965 
01966    return 0;
01967 }
01968 
01969 
01970 //----------------------------------------------------------------------------
01971 
01972 int cmd_printgpio()
01973 {
01974   if (args_check(kNeedBoard)) return 1;
01975   if (gGpio == 0) { std::cerr << "No Gpio instance" << std::endl; return 1; }
01976 
01977   const char* names[8] = {"",
01978                           "sync-m  ",
01979                           "sync-0  ",
01980                           "sync-1  ",
01981                           "aux-0   ",
01982                           "aux-1   ",
01983                           "aux-2   ",
01984                           "aux-3   "
01985   };
01986   const char* namext[8] = {"",              // -
01987                            "",              // sync m
01988                            "loop-back",     // sync 0
01989                            "loop-back",     // sync 1
01990                            " <unused>",     // aux 0
01991                            " <unused>",     // aux 1
01992                            "TP-source",     // aux 2
01993                            "THR-input"      // aux 3
01994   };
01995   const char* namalt[8] = {"",              // -
01996                            "",              // sync m
01997                            "",              // sync 0
01998                            "",              // sync 1
01999                            " <unused>",     // aux 0
02000                            "  TP-busy",     // aux 1
02001                            "   TP-gen",     // aux 2
02002                            " THR-loop"      // aux 3
02003   };
02004 
02005   uint32_t mask;
02006   int rc = gGpio->getConfig(mask);
02007   print_opererr("Gpio::getConfig", rc);
02008   if (rc) return 0;  
02009 
02010   bool riseedge;
02011   bool falledge;
02012   bool throttled;
02013   bool extrafunc;
02014   bool altin;
02015 
02016   for (int i=1; i<4; i++) {                 // sync channels
02017     uint32_t bauds;
02018     uint32_t baud1;
02019     uint32_t baud2;
02020     rc = gGpio->getSyncBaud(i, bauds, baud1, baud2);
02021     print_opererr("Gpio::getSyncBaud", rc);
02022     
02023     double baud = 500. / (double(baud1+baud2));
02024 
02025     std::cout << names[i] << " :  baud(";
02026     static boost::format fmt_3d("%3d");
02027     std::cout << fmt_3d % bauds;
02028     std::cout << "," << fmt_3d % baud1;
02029     std::cout << "," << fmt_3d % baud2;
02030     static boost::format fmt_4p1f("%4.1f");
02031     std::cout << ")= " << fmt_4p1f % baud;
02032     std::cout << " MHz";
02033 
02034     if (i==1) {
02035       uint32_t scale;
02036       rc = gGpio->getSyncScale(scale);
02037       print_opererr("Gpio::getSyncScale", rc);
02038       std::cout << "  scale=" << fmt_3d % scale;
02039       std::cout << " 1:" << std::dec << (1<<scale);
02040     } else {
02041       gGpio->unpackConfig(mask, i, riseedge, falledge, throttled, 
02042                           extrafunc, altin);
02043       std::cout << "  enable=" << riseedge
02044                 << "  throttled=" << throttled
02045                 << "  " << namext[i] << "=" << extrafunc;
02046     }
02047     std::cout << std::endl;
02048   }
02049 
02050   for (int i=4; i<=7; i++) {                // aux channels
02051     gGpio->unpackConfig(mask, i, riseedge, falledge, throttled, 
02052                         extrafunc, altin);
02053     std::cout << names[i] << " :  rise=" <<  riseedge
02054               << "  fall=" << falledge
02055               << "  throttled=" << throttled
02056               << "  " << namext[i] << "=" << extrafunc
02057               << "  " << namalt[i] << "=" << altin;
02058     std::cout << std::endl;
02059   }
02060 
02061   return 0;
02062 }
02063 
02064 //----------------------------------------------------------------------------
02065 
02066 int cmd_printstatus()
02067 {
02068   if (args_check(kNeedRocBoard)) return 1;
02069   if (gGpio == 0) { std::cerr << "No Gpio instance" << std::endl; return 1; }
02070 
02071 
02072   int rc;
02073   uint32_t mask;
02074   rc = gGpio->getConfig(mask);
02075   print_opererr("Gpio::getConfig", rc);
02076   if (rc) return 0;
02077 
02078   bool riseedge;
02079   bool falledge;
02080   bool throttled;
02081   bool extrafunc;
02082   bool altin;
02083 
02084   for (int i=0; i<=1; i++) {
02085     gGpio->unpackConfig(mask, i+2, riseedge, falledge, throttled, 
02086                         extrafunc, altin);
02087     if (riseedge | falledge) {
02088       std::cout << "SYN " << std::dec << i << ":"
02089            << " enabled";
02090       if (extrafunc) {
02091         std::cout << " in loop-back mode";
02092         uint32_t scale;
02093         rc = gGpio->getSyncScale(scale);
02094         print_opererr("Gpio::getSyncScale", rc);
02095         std::cout << "; syncm scale = " << scale;
02096       }
02097       std::cout << std::endl;
02098     }
02099   }
02100 
02101   for (int i=0; i<=3; i++) {
02102     gGpio->unpackConfig(mask, i+4, riseedge, falledge, throttled, 
02103                         extrafunc, altin);
02104     if (riseedge | falledge | extrafunc) {
02105       std::cout << "AUX " << std::dec << i << ":"
02106            << " re=" << riseedge
02107            << " fe=" << falledge
02108            << " thr=" << throttled
02109            << " ext=" << extrafunc
02110            << " alt=" << altin
02111            << "  ";
02112       if (i==3) {
02113         if (extrafunc) {
02114           std::cout << "THR active";
02115           if (altin) std::cout << " as auto throttle";
02116         }
02117       }
02118       std::cout << std::endl;
02119      }
02120  }
02121 
02122   if (gFeb) {                               // FEB connected
02123     static boost::format fmt_3d("%3d");
02124     static boost::format fmt_02x("%02x");
02125     for (int nx=0; nx<gFeb->numNx(); nx++) {
02126       std::cout << "NX  " << gFeb->getPortNumber()
02127            << "," << nx
02128            << "," << gFeb->nx(nx).getNxNumber()
02129            << ":";
02130 
02131       if (gFeb->getNxOffline(nx)) {
02132         std::cout << " is offline" << std::endl;
02133         continue;
02134       }
02135 
02136       nxyter::NxContext cntx;
02137       rc = gFeb->nx(nx).i2c().getContext(cntx, nxyter::kDoCore);  // core only
02138       if (rc) {
02139         std::cout << "!! ERROR: NX NOT REACHABLE:"
02140              << base::Board::operErrToString(rc)
02141              << " <===" << std::endl;
02142         continue;
02143       }
02144 
02145       uint8_t vth    = cntx.getRegister(nxyter::kNxRegVth);
02146       uint8_t vbiasf = cntx.getRegister(nxyter::kNxRegVbiasF);
02147       uint8_t vbiass = cntx.getRegister(nxyter::kNxRegVbiasS);
02148 
02149       std::cout << " Vth="    << fmt_3d % int(vth);
02150       std::cout << " VbiasF=" << fmt_3d % int(vbiasf);
02151       std::cout << " VbiasS=" << fmt_3d % int(vbiass);
02152 
02153       int n128 = 0;
02154       for (int i=nxyter::kNxRegVcg; i<=nxyter::kNxRegiTWC; i++) {
02155         if (cntx.getRegister(i) == 128) n128 += 1;
02156       }
02157       if (n128 >= (nxyter::kNxRegiTWC-nxyter::kNxRegVcg)-2) {
02158         std::cout << "!! ERROR: NX in RESET STATE <===";
02159       } else {
02160         uint8_t conf0 = cntx.getRegister(nxyter::kNxRegConfig0);
02161         uint8_t conf1 = cntx.getRegister(nxyter::kNxRegConfig1);
02162         
02163         std::cout << " conf=" << fmt_02x % uint32_t(conf0);
02164         std::cout << "," << fmt_02x % uint32_t(conf1);
02165         std::cout << " tpul=" << ((conf0&nxyter::kNxC0TestPulsEnable)   ? "1" : "0");
02166         std::cout << " ttri=" << ((conf0&nxyter::kNxC0TestTrigEnable)   ? "1" : "0");
02167         std::cout << " pos="  << ((conf0&nxyter::kNxC1FrontEndPolarity) ? "1" : "0");
02168       }
02169 
02170       std::cout << std::endl;
02171     }
02172   }
02173 
02174   return 0;
02175 }
02176 
02177 //----------------------------------------------------------------------------
02178 
02179 int cmd_firepulser()
02180 {
02181   bool opt_s  = get_opt("-s");
02182   bool opt_a  = get_opt("-a");
02183   int32_t period(100000);
02184   int32_t width(350);
02185   int32_t number(0);
02186   int32_t delay(0);
02187   if (get_arg(period, "per=",  2, 0x00ffffff)) return 1;
02188   if (get_arg(width,  "wth=",  -0x00ffffff, 0x00ffffff)) return 1;
02189   if (get_arg(number, "num=",  0, 0x00008fff)) return 1;
02190   if (get_arg(delay,  "dly=",   0, 0x0000ffff)) return 1;
02191   if (args_check(kNeedBoard)) return 1;
02192 
02193   if (gRocNx==0) {
02194      std::cout << "RocNx instance is required" << std::endl;
02195      return 1;
02196   }
02197 
02198   if (gGpio==0) {
02199      std::cout << "Gpio instance is required" << std::endl;
02200      return 1;
02201   }
02202 
02203   int rc;
02204 
02205   if (opt_a) {                              // setup AUX2
02206     uint32_t mask;
02207     rc = gGpio->getConfig(mask);
02208     print_opererr("Gpio::getConfig", rc);
02209     bool riseedge, falledge, throttled, extrafunc, altin;
02210     base::Gpio::unpackConfig(mask, 6,
02211                        riseedge, falledge, throttled, extrafunc, altin);
02212 
02213     if (opt_s) {
02214       extrafunc = false;
02215     } else {
02216       extrafunc = true;
02217       altin = true;
02218     }
02219     
02220     base::Gpio::packConfig(mask, 6, riseedge, falledge, throttled, extrafunc, altin);
02221     rc = gGpio->setConfig(mask);
02222     print_opererr("Gpio::setConfig", rc);
02223   }
02224 
02225   if (delay == 0) {
02226     if (opt_s) {                            // stop pulser
02227       period = 0;
02228       width  = 0;
02229       number = 0;
02230     }
02231     rc = gRocNx->fireTestPulse(period, width, number);
02232   } else {
02233     rc = gRocNx->fireTestPulse(delay, period, width, number);
02234   }
02235   print_opererr("RocNx::fireTestPulse", rc);
02236   return 0;
02237 }
02238 
02239 //----------------------------------------------------------------------------
02240 
02241 int cmd_setfebdef()
02242 {
02243   bool ispos0(false), ispos1(false);
02244   if (get_arg(ispos0, "pos0=")) return 1;
02245   if (get_arg(ispos1, "pos1=")) return 1;
02246   if (args_check(kNeedFeb)) return 1;
02247   int rc = gFeb->setToDefault(ispos0, ispos1);
02248   print_opererr("FebBase::setToDefault", rc);
02249   printf("Note: Vbfb default value is changed now from 6 to 30!\n");
02250   return 0;
02251 }
02252 
02253 //----------------------------------------------------------------------------
02254 
02255 int cmd_setnxdef()
02256 {
02257    int32_t nxbeg(0), nxend(0);
02258    bool ispos(false);
02259    if (get_nxrange(nxbeg, nxend, "nx=")) return 1;
02260    if (get_arg(ispos, "pos=")) return 1;
02261    if (args_check(kNeedFeb)) return 1;
02262    for (int i=nxbeg; i<=nxend; i++) {
02263       if (check_nxoffline(i, nxbeg, nxend)) continue; // skip of offline
02264       int rc = gFeb->nx(i).i2c().setToDefault(ispos);
02265       print_opererr("NxI2c::setToDefault", rc);
02266    }
02267    return 0;
02268 }
02269 
02270 //----------------------------------------------------------------------------
02271 
02272 int cmd_setnx()
02273 {
02274   int32_t nxbeg=0;
02275   int32_t nxend=0;
02276   int32_t reg;
02277   int32_t val;
02278   if (get_nxrange(nxbeg, nxend)) return 1;
02279   if (get_arg(reg, 0, 0, 255)) return 1;
02280   if (get_arg(val, 0, 0, 255)) return 1;
02281   if (args_check(kNeedFeb)) return 1;
02282 
02283   if (reg == nxyter::kNxRegTrimDAQPower) {
02284     std::cout << "rocutil-E: use 'setnxtrim' and 'setnxpower' for Reg 42" << std::endl;
02285     return 1;
02286   }
02287 
02288   if ((reg == nxyter::kNxRegdelayTestPuls) ||
02289       (reg == nxyter::kNxRegdelayTestTrig) ||
02290       (reg == nxyter::kNxRegdelayClock1) ||
02291       (reg == nxyter::kNxRegdelayClock2) ||
02292       (reg == nxyter::kNxRegdelayClock3)) {
02293     int32_t del = val;
02294     val = nxyter::NxI2c::delayToSetting(del);
02295     std::cout << "rocutil-I: map delay " << del
02296               << " to register value " << val << std::endl;
02297   }
02298 
02299   for (int i=nxbeg; i<=nxend; i++) {
02300     if (check_nxoffline(i, nxbeg, nxend)) continue; // skip of offline
02301     int rc = gFeb->nx(i).i2c().setRegister(uint8_t(reg), uint8_t(val), true);
02302     print_opererr("NxI2c::setRegister", rc);
02303   }
02304   
02305   return 0;
02306 }
02307 
02308 //----------------------------------------------------------------------------
02309 
02310 int cmd_getnx()
02311 {
02312   int32_t nxbeg=0;
02313   int32_t nxend=0;
02314   int32_t reg;
02315   if (get_nxrange(nxbeg, nxend)) return 1;
02316   if (get_arg(reg, 0, 0, 255)) return 1;
02317   if (args_check(kNeedFeb)) return 1;
02318 
02319   if (reg == nxyter::kNxRegTrimDAQPower) {
02320     std::cout << "rocutil-E: use 'printnx' to see Reg 42" << std::endl;
02321     return 1;
02322   }
02323 
02324   for (int i=nxbeg; i<=nxend; i++) {
02325     if (check_nxoffline(i, nxbeg, nxend)) { // skip of offline
02326       std::cout << "nxind=" << i << " is is set OFFLINE" << std::endl;
02327       continue; 
02328     }
02329     
02330     uint8_t val;
02331     int rc = gFeb->nx(i).i2c().getRegister(uint8_t(reg), val);
02332     if (print_opererr("NxI2c::getRegister", rc)) return 0;
02333 
02334     static boost::format fmt("nxind=%|1| (%|1|,%|3|) "
02335                       "Reg(%|2|) %|-14|: 0x%|02x| %|3|");
02336 
02337     const char* name = nxyter::NxI2c::registerName(reg);
02338     if (name[0] == 0) name = "..not in nX..";
02339     
02340     std::cout << fmt % i % gFeb->getPortNumber() % 
02341       uint32_t(gFeb->nx(i).i2c().getSlaveAddr()) % reg %
02342       name % uint32_t(val)% uint32_t(val);
02343     
02344     std::cout << " : ";
02345     for (int i=7; i>=0; i--) std::cout << ((val & (1<<i)) ? " 1" : " 0");
02346     
02347     if (reg == nxyter::kNxRegdelayTestPuls ||
02348         reg == nxyter::kNxRegdelayTestTrig ||
02349         reg == nxyter::kNxRegdelayClock1 ||
02350         reg == nxyter::kNxRegdelayClock2 ||
02351         reg == nxyter::kNxRegdelayClock3) {
02352       static boost::format fmt_del(" : delay=%|3|");
02353       std::cout << fmt_del % uint16_t(nxyter::NxI2c::settingToDelay(val));
02354     }
02355     std::cout << std::endl;
02356   }
02357   
02358   return 0;
02359 }
02360 
02361 //----------------------------------------------------------------------------
02362 
02363 int cmd_setnxmode()
02364 {
02365   int32_t nxbeg=0;
02366   int32_t nxend=0;
02367   bool testpuls=false;
02368   bool testtrig=false;
02369   int32_t calselect=3;
02370   if (get_nxrange(nxbeg, nxend)) return 1;
02371   if (get_arg(testpuls, "tpul=")) return 1;
02372   if (get_arg(testtrig, "ttri=")) return 1;
02373   if (get_arg(calselect, "csel=", 0, 3)) return 1;
02374   if (args_check(kNeedFeb)) return 1;
02375 
02376   for (int i=nxbeg; i<=nxend; i++) {
02377     if (check_nxoffline(i, nxbeg, nxend)) continue; // skip of offline
02378     int rc;
02379     rc = gFeb->nx(i).i2c().setTestModes(testpuls, testtrig, calselect);
02380     print_opererr("NxI2c::setTestModes", rc);
02381   }
02382   return 0;
02383 }
02384 
02385 //----------------------------------------------------------------------------
02386 
02387 int cmd_setnxmask()
02388 {
02389   int32_t nxbeg=0;
02390   int32_t nxend=0;
02391   bool val=false;
02392   int32_t ibeg=0;
02393   int32_t iend=127;
02394   int32_t istep=1;
02395   if (get_nxrange(nxbeg, nxend)) return 1;
02396   if (get_arg(val, "val=")) return 1;
02397   if (get_arg(ibeg, "ibeg=", 0, 127)) return 1;
02398   if (get_arg(iend, "iend=", 0, 127)) return 1;
02399   if (get_arg(istep, "istep=", 1, 64)) return 1;
02400   if (args_check(kNeedFeb)) return 1;
02401 
02402   for (int i=nxbeg; i<=nxend; i++) {
02403     if (check_nxoffline(i, nxbeg, nxend)) continue; // skip of offline
02404     int rc;
02405     nxyter::NxContext cntx;
02406     rc = gFeb->nx(i).i2c().getContext(cntx, nxyter::kDoMask);  // mask only
02407     print_opererr("NxI2c::getContext", rc);
02408     
02409     cntx.setChannelMaskBit(ibeg, iend, val, istep);
02410     
02411     rc = gFeb->nx(i).i2c().setContext(cntx, nxyter::kDoMask);  // mask only
02412     print_opererr("NxI2c::setContext", rc);
02413   }
02414   return 0;
02415 }
02416 
02417 //----------------------------------------------------------------------------
02418 
02419 int cmd_setnxtrim()
02420 {
02421   int32_t nxbeg=0;
02422   int32_t nxend=0;
02423   int32_t val=16;
02424   int32_t ibeg=0;
02425   int32_t iend=127;
02426   int32_t istep=1;
02427   if (get_nxrange(nxbeg, nxend)) return 1;
02428   if (get_arg(val, "val=", 0,  31)) return 1;
02429   if (get_arg(ibeg, "ibeg=", 0, 128)) return 1;
02430   if (get_arg(iend, "iend=", 0, 128)) return 1;
02431   if (get_arg(istep, "istep=", 1, 64)) return 1;
02432   if (args_check(kNeedFeb)) return 1;
02433 
02434   for (int i=nxbeg; i<=nxend; i++) {
02435     if (check_nxoffline(i, nxbeg, nxend)) continue; // skip of offline
02436     int rc;
02437     nxyter::NxContext cntx;
02438     rc = gFeb->nx(i).i2c().getContext(cntx, nxyter::kDoTrim); // trim only
02439     print_opererr("NxI2c::getContext", rc);
02440     
02441     cntx.setThresholdTrim(ibeg, iend, uint8_t(val), istep);
02442     
02443     rc = gFeb->nx(i).i2c().setContext(cntx, nxyter::kDoTrim); // trim only 
02444     print_opererr("NxI2c::setContext", rc);
02445   }
02446   return 0;
02447 }
02448 
02449 //----------------------------------------------------------------------------
02450 
02451 int cmd_setnxpower()
02452 {
02453   int32_t nxbeg=0;
02454   int32_t nxend=0;
02455   bool val=false;
02456   int32_t ibeg=0;
02457   int32_t iend=127;
02458   int32_t istep=1;
02459   if (get_nxrange(nxbeg, nxend)) return 1;
02460   if (get_arg(val, "val=")) return 1;
02461   if (get_arg(ibeg, "ibeg=", 0, 128)) return 1;
02462   if (get_arg(iend, "iend=", 0, 128)) return 1;
02463   if (get_arg(istep, "istep=", 1, 64)) return 1;
02464   if (args_check(kNeedFeb)) return 1;
02465 
02466   for (int i=nxbeg; i<=nxend; i++) {
02467     if (check_nxoffline(i, nxbeg, nxend)) continue; // skip of offline
02468     int rc;
02469     nxyter::NxContext cntx;
02470     rc = gFeb->nx(i).i2c().getContext(cntx, nxyter::kDoTrim);  // trim only
02471     print_opererr("NxI2c::getContext", rc);
02472     
02473     cntx.setPowerOffMaskBit(ibeg, iend, val, istep);
02474     
02475     rc = gFeb->nx(i).i2c().setContext(cntx, nxyter::kDoTrim);  // trim only
02476     print_opererr("NxI2c::setContext", rc);
02477   }
02478   
02479   return 0;
02480 }
02481 
02482 //----------------------------------------------------------------------------
02483 
02484 int cmd_resetnxi2cbus()
02485 {
02486   if (args_check(kNeedFeb)) return 1;
02487   gFeb->resetNxI2cBus();
02488   return 0;
02489 }
02490 
02491 //----------------------------------------------------------------------------
02492 
02493 int cmd_resetnxi2creg()
02494 {
02495   if (args_check(kNeedFeb)) return 1;
02496   gFeb->resetNxI2cRegister();
02497   return 0;
02498 }
02499 
02500 //----------------------------------------------------------------------------
02501 
02502 int cmd_seti2c()
02503 {
02504   bool loop = get_opt("-l");
02505   bool veri = get_opt("-v");
02506   int32_t addr;
02507   int32_t reg;
02508   int32_t val;
02509   int32_t ecnt = 0;
02510 
02511   if (get_arg(addr, 0, 0, 127)) return 1;
02512   if (get_arg(reg, 0, 0, 255)) return 1;
02513   if (get_arg(val, 0, 0, 255)) return 1;
02514   if (args_check(kNeedFeb)) return 1;
02515 
02516   roc::I2cDevice i2c(gRocBoard, gFeb->getPortNumber(), addr);
02517   gUtil->startLoop(0.);
02518   while(gUtil->testLoop()) {
02519     int rc = i2c.setRegister(reg, val, veri);
02520     if (rc) {
02521       std::cout << std::dec << ecnt << " : " << base::Board::operErrToString(rc) << std::endl;
02522       ecnt++;
02523     }
02524     if (!loop) break;
02525   }
02526 
02527   if (loop) print_loop_stats("seti2c", ecnt);
02528 
02529   return 0;
02530 }
02531 
02532 //----------------------------------------------------------------------------
02533 
02534 int cmd_geti2c()
02535 {
02536   bool loop = get_opt("-l");
02537   bool wide = get_opt("-w");
02538   int32_t addr;
02539   int32_t reg;
02540   uint8_t  val8;
02541   uint16_t val;
02542   uint16_t valold = 0;
02543   uint64_t count = 0;
02544   int ecnt = 0;
02545 
02546   if (get_arg(addr, 0, 0, 127)) return 1;
02547   if (get_arg(reg, 0, 0, 255)) return 1;
02548   if (args_check(kNeedBoard)) return 1;
02549   if (gRocBoard)
02550      if (args_check(kNeedFeb)) return 1;
02551   
02552   if (gUtil==0) {
02553      printf("No utility instance available - break\n");
02554      return 1;
02555   }
02556 
02557   roc::I2cDevice i2c(gBaseBoard, gFeb ? gFeb->getPortNumber() : 0, addr);
02558   
02559   gUtil->startLoop(0.);
02560 
02561   while(gUtil->testLoop()) {
02562     int rc;
02563 
02564     if (wide) {
02565       rc = i2c.getRegister16(reg, val);
02566     } else {
02567       rc = i2c.getRegister(reg, val8);
02568       val = uint16_t(val8);
02569     }
02570     if (rc) std::cout << base::Board::operErrToString(rc) << std::endl;
02571     if (count==0) {
02572       static boost::format fmt("addr=%|3|,reg=%|3| -> read %|5|  0x%04x");
02573       std::cout << fmt % addr % reg % uint32_t(val) % uint32_t(val);
02574       if (wide) {
02575         static boost::format fmt("   (%|2|,%|4|)");
02576         std::cout << fmt % uint32_t((val>>12)&0xf) % uint32_t(val&0xfff);
02577       }
02578       std::cout << std::endl;
02579       valold = val;
02580     } else if (val != valold) {
02581       ecnt++;
02582       static boost::format fmt("   loop %|8| -> read %|5|  0x%04x");
02583       std::cout << fmt % count % uint32_t(val) % uint32_t(val) << std::endl;
02584       valold = val;
02585     }
02586     count++;
02587     if (!loop) break;
02588   }
02589 
02590   if (loop) print_loop_stats("geti2c", ecnt);
02591 
02592   return 0;
02593 }
02594 
02595 //----------------------------------------------------------------------------
02596 
02597 int cmd_puti2c()
02598 {
02599   int32_t addr;
02600   int32_t reg;
02601   int32_t val;
02602 
02603   if (get_arg(addr, 0, 0, 127)) return 1;
02604   if (get_arg(reg, 0, 0, 255)) return 1;
02605   if (get_arg(val, 0, 0, 255)) return 1;
02606   if (args_check(kNeedBoard)) return 1;
02607   if (gRocBoard)
02608      if (args_check(kNeedFeb)) return 1;
02609 
02610   if (gUtil==0) {
02611      printf("No utility instance available - break\n");
02612      return 1;
02613   }
02614 
02615   roc::I2cDevice i2c(gBaseBoard, gFeb ? gFeb->getPortNumber() : 0, addr);
02616 
02617   int rc = i2c.setRegister(reg, val);
02618   if (rc) std::cout << base::Board::operErrToString(rc) << std::endl;
02619   static boost::format fmt("addr=%|3|,reg=%|3| -> write %|5|  0x%04x");
02620   std::cout << fmt % addr % reg % uint32_t(val) % uint32_t(val) << std::endl;
02621 
02622   return 0;
02623 }
02624     
02625 
02626 //----------------------------------------------------------------------------
02627 
02628 int cmd_setadcdef()
02629 {
02630   if (args_check(kNeedFeb)) return 1;
02631   int rc = gFeb->adc().setToDefault();
02632   print_opererr("MainAdc::setToDefault", rc);
02633   return 0;
02634 }
02635 
02636 //----------------------------------------------------------------------------
02637 
02638 int cmd_setadc()
02639 {
02640   int32_t reg;
02641   int32_t val;
02642   if (get_arg(reg, 0, 0, 255)) return 1;
02643   if (get_arg(val, 0, 0, 255)) return 1;
02644   if (args_check(kNeedFeb)) return 1;
02645   int rc = gFeb->adc().setRegister(uint8_t(reg), uint8_t(val), true);
02646   print_opererr("MainAdc::setRegister", rc);
02647   return 0;
02648 }
02649 
02650 //----------------------------------------------------------------------------
02651 
02652 int cmd_setadcpatt()
02653 {
02654   int32_t tm0(0), tm1(0), tm2(0), tm3(0), upatt(-1);
02655   if (get_arg(tm0, "tm0=", 0, 12)) return 1;
02656   if (get_arg(tm1, "tm1=", 0, 12)) return 1;
02657   if (get_arg(tm2, "tm2=", 0, 12)) return 1;
02658   if (get_arg(tm3, "tm3=", 0, 12)) return 1;
02659   if (get_arg(upatt, "upatt=")) return 1;
02660   if (args_check(kNeedFeb)) return 1;
02661   int rc;
02662              rc = gFeb->adc().setTestMode(0, uint8_t(tm0));
02663   if (rc==0) rc = gFeb->adc().setTestMode(1, uint8_t(tm1));
02664   if (rc==0) rc = gFeb->adc().setTestMode(2, uint8_t(tm2));
02665   if (rc==0) rc = gFeb->adc().setTestMode(3, uint8_t(tm3));
02666   if (rc==0 && upatt != -1) gFeb->adc().setUserPattern(uint16_t(upatt));
02667   print_opererr("MainAdc::setTestMode/setUserPattern", rc);
02668   return 0;
02669 }
02670 
02671 //----------------------------------------------------------------------------
02672 
02673 int cmd_setadcclock()
02674 {
02675   int32_t dly;
02676   if (get_arg(dly, 0, 0, 31)) return 1;
02677   if (args_check(kNeedFeb)) return 1;
02678   gFeb->adc().setClockDelay(dly);
02679   return 0;
02680 }
02681 
02682 //----------------------------------------------------------------------------
02683 
02684 int cmd_getadcdirect()
02685 {
02686   bool opt_d = get_opt("-d");
02687   if (args_check(kNeedFeb)) return 1;
02688 
02689   for (int ch=0; ch<4; ch++) {
02690     std::cout << " " << std::dec << ch << " : ";
02691     int imax = (opt_d) ? 14 : 18;
02692     int rcsum = 0;
02693     for (int i=0; i<imax; i++) {
02694       uint32_t val;
02695       int rc = gFeb->adc().getAdcDirect(ch, val);
02696       if (rc) rcsum = rc;
02697       if (opt_d) {
02698         static boost::format fmt(" %|4|");
02699         std::cout << fmt % val;
02700       } else {
02701         static boost::format fmt(" %03x");
02702         std::cout << fmt % val;      
02703       }
02704     }
02705     std::cout << std::endl;
02706     print_opererr("MainAdc::getAdcDirect", rcsum);
02707   }
02708   return 0;
02709 }
02710 
02711 //----------------------------------------------------------------------------
02712 void print_40f_41f(float val)
02713 {
02714   static boost::format fmt_40f("%4.0f");
02715   static boost::format fmt_41f("%4.1f");
02716   if (val < 99.9) {
02717     std::cout <<  " " << fmt_41f % val;
02718   } else {
02719     std::cout <<  " " << fmt_40f % val;
02720   }
02721 }
02722 
02723 //----------------------------------------------------------------------------
02724 void print_dfa_ent_med_w50(int vb, int ncha, nxyter::DistFunc& df_ent,
02725                            nxyter::DistFunc& df_med, nxyter::DistFunc& df_w50,
02726                            bool mode_ent, bool phead)
02727 {
02728   if (phead) {
02729     if (mode_ent) {
02730       std::cout << "                           #hits             :  ADC median    :ADC Width 25-75" << std::endl;
02731       std::cout << "val #ch :  min   3%  10%  med  90%  97%  max :  10%  med  90% :  med  w50  w80" << std::endl;
02732     } else {
02733       std::cout << "               #hits     :         ADC median value           :ADC Width 25-75" << std::endl;
02734       std::cout << "val #ch :   5%  med  95% :  min   3%  10%  med  90%  97%  max :  med  w50  w80" << std::endl;
02735     }
02736   }
02737 
02738   static boost::format fmt_3d("%3d");
02739   static boost::format fmt_40f("%4.0f");
02740   static boost::format fmt_41f("%4.1f");
02741   float p4of128 = 4./128.;
02742   
02743   std::cout << fmt_3d % vb;
02744   std::cout << " " << fmt_3d  % ncha;
02745   if (mode_ent) {
02746     std::cout << " : " << fmt_40f % df_ent.getMin();
02747     std::cout << " "   << fmt_40f % df_ent(p4of128);
02748     std::cout << " "   << fmt_40f % df_ent(.10);
02749     std::cout << " "   << fmt_40f % df_ent.getMedian();
02750     std::cout << " "   << fmt_40f % df_ent(.90);
02751     std::cout << " "   << fmt_40f % df_ent(1.-p4of128);
02752     std::cout << " "   << fmt_40f % df_ent.getMax();
02753     std::cout << " : " << fmt_40f % df_med(0.10);
02754     std::cout << " "   << fmt_40f % df_med.getMedian();
02755     std::cout << " "   << fmt_40f % df_med(0.90);
02756   } else {
02757     std::cout << " : " << fmt_40f % df_ent(0.05);
02758     std::cout << " "   << fmt_40f % df_ent.getMedian();
02759     std::cout << " "   << fmt_40f % df_ent(0.95);
02760     std::cout << " : " << fmt_40f % df_med.getMin();
02761     std::cout << " "   << fmt_40f % df_med(p4of128);
02762     std::cout << " "   << fmt_40f % df_med(.10);
02763     std::cout << " "   << fmt_40f % df_med.getMedian();
02764     std::cout << " "   << fmt_40f % df_med(.90);
02765     std::cout << " "   << fmt_40f % df_med(1.-p4of128);
02766     std::cout << " "   << fmt_40f % df_med.getMax();
02767   }
02768   std::cout << " :";
02769   print_40f_41f(df_w50.getMedian());
02770   print_40f_41f(df_w50.getWidth(.25));
02771   print_40f_41f(df_w50.getWidth(.40));
02772   std::cout << std::endl;
02773 }
02774 
02775 //----------------------------------------------------------------------------
02776 void get_vbiass_data(int nxind, int vb, float& med, int npuls,
02777                      bool opt_v, bool phead)
02778 {
02779   int ncha = 0;
02780   nxyter::DistFunc df_ent(128);
02781   nxyter::DistFunc df_med(128);
02782   nxyter::DistFunc df_w50(128);
02783 
02784   int rc;
02785   rc = gFeb->nx(nxind).i2c().setRegister(nxyter::kNxRegVbiasS, vb, true);
02786   print_opererr("setRegister(kNxRegVbiasS,...)", rc);
02787   nxyter::NxDataSummary nds;
02788   gUtil->acquireTestTriggerData(nxind, npuls, nds);
02789   if (opt_v) {
02790     nds.print(std::cout, gFeb->nx(nxind).getNxNumber());
02791     gQdaq->stats().print(std::cout);
02792   }
02793 
02794   for (int ch=0; ch<128; ch++) {
02795     if (nds.numEntries(ch)==0) continue;
02796     ncha += 1;
02797     df_ent.addEntry(nds.numEntries(ch));
02798     df_med.addEntry(nds.getMedian(ch));
02799     df_w50.addEntry(nds.getWidth50(ch));
02800   }
02801 
02802   print_dfa_ent_med_w50(vb, ncha, df_ent, df_med, df_w50, false, phead);
02803 
02804   med = df_med.getMedian();
02805 
02806 }
02807 
02808 //----------------------------------------------------------------------------
02809 
02810 int cmd_scanmonadc()
02811 {
02812   int32_t nxbeg=0;
02813   int32_t nxend=0;
02814   int32_t reg;
02815   int32_t vbeg=0;
02816   int32_t vend=255;
02817   int32_t vstep=1;
02818   int32_t npuls=100;
02819   if (get_nxrange(nxbeg, nxend)) return 1;
02820   if (get_arg(reg, 0, 0, 255)) return 1;
02821   if (get_arg(vbeg,  "vbeg=",  0, 255)) return 1;
02822   if (get_arg(vend,  "vend=",  0, 255)) return 1;
02823   if (get_arg(vstep, "vstep=", 1, 255)) return 1;
02824   if (args_check(kNeedFeb)) return 1;
02825 
02826   int rc;
02827   nxyter::NxContext save_cntx;
02828   
02829   gUtil->startLoop(0.);
02830   for (int nxind=nxbeg; nxind<=nxend; nxind++) {
02831     if (!gUtil->testLoop()) break;
02832     gFeb->printNxHeadLine(std::cout, nxind);
02833     if (check_nxoffline(nxind, nxbeg, nxend)) continue; // skip of offline
02834 
02835     rc = gFeb->nx(nxind).i2c().getContext(save_cntx, nxyter::kDoCore);
02836     print_opererr("NxI2c::getContext {save}", rc);
02837     
02838     std::cout << "val : adc0 adc1 adc2 adc3" << std::endl;
02839 
02840     for (int vb=vbeg; vb<=vend; vb+=vstep) {
02841       if (!gUtil->testLoop()) break;
02842       rc = gFeb->nx(nxind).i2c().setRegister(uint8_t(reg), uint8_t(vb), true);
02843       print_opererr("NxI2c::setRegister", rc);
02844       uint16_t val[4];
02845       for (int ch=0; ch<4; ch++) {
02846         rc = gFeb->getMonAdc(ch, val[ch]);
02847         print_opererr("FebBase::getMonAdc", rc);
02848       }
02849       static boost::format fmt_3("%|3|");
02850       static boost::format fmt_4("%|4|");
02851       std::cout << fmt_3 % vb << " :";
02852       for (int ch=0; ch<4; ch++) std::cout << " " << fmt_4 % val[ch];
02853       std::cout << std::endl;
02854     }
02855 
02856     rc = gFeb->nx(nxind).i2c().setContext(save_cntx, nxyter::kDoCore);
02857     print_opererr("NxI2c::setContext {restore}", rc);
02858   
02859   }
02860 
02861   return 0;
02862 }
02863 
02864 //----------------------------------------------------------------------------
02865 
02866 int cmd_scanvbiass()
02867 {
02868   bool opt_v = get_opt("-v");
02869   int32_t nxbeg=0;
02870   int32_t nxend=0;
02871   int32_t vbeg=0;
02872   int32_t vend=255;
02873   int32_t vstep=1;
02874   int32_t npuls=100;
02875   if (get_nxrange(nxbeg, nxend)) return 1;
02876   if (get_arg(vbeg,  "vbeg=",  0, 255)) return 1;
02877   if (get_arg(vend,  "vend=",  0, 255)) return 1;
02878   if (get_arg(vstep, "vstep=", 1, 255)) return 1;
02879   if (get_arg(npuls, "npuls=", 1, 10000)) return 1;
02880   if (args_check(kNeedFeb|kNeedDaq)) return 1;
02881 
02882   int rc;
02883   nxyter::NxContext save_cntx;
02884   
02885   gUtil->startLoop(0.);
02886   for (int nxind=nxbeg; nxind<=nxend; nxind++) {
02887     if (!gUtil->testLoop()) break;
02888     gFeb->printNxHeadLine(std::cout, nxind);
02889     if (check_nxoffline(nxind, nxbeg, nxend)) continue; // skip of offline
02890 
02891     rc = gFeb->nx(nxind).i2c().getContext(save_cntx, nxyter::kDoCore);
02892     print_opererr("NxI2c::getContext {save}", rc);
02893 
02894     rc = gFeb->nx(nxind).i2c().setTestModes(false, true, 0);
02895     print_opererr("NxI2c::setTestModes", rc);
02896     
02897     
02898     for (int vb=vbeg; vb<=vend; vb+=vstep) {
02899       if (!gUtil->testLoop()) break;
02900       float med;
02901       get_vbiass_data(nxind, vb, med, npuls, opt_v, vb==vbeg);
02902     }
02903 
02904     rc = gFeb->nx(nxind).i2c().setContext(save_cntx, nxyter::kDoCore);
02905     print_opererr("NxI2c::setContext {restore}", rc);
02906   
02907   }
02908 
02909   return 0;
02910 }
02911 
02912 //----------------------------------------------------------------------------
02913 
02914 int cmd_autovbiass()
02915 {
02916   bool opt_v = get_opt("-v");
02917   int32_t nxbeg=0;
02918   int32_t nxend=0;
02919   int32_t base=2000;
02920   int32_t npuls=200;
02921   if (get_nxrange(nxbeg, nxend)) return 1;
02922   if (get_arg(base, "base=", 0, 4095)) return 1;
02923   if (get_arg(npuls, "npuls=", 1, 10000)) return 1;
02924   if (args_check(kNeedFeb|kNeedDaq)) return 1;
02925 
02926   int rc;
02927   nxyter::NxContext save_cntx;
02928   
02929   gUtil->startLoop(0.);
02930   for (int nxind=nxbeg; nxind<=nxend; nxind++) {
02931     if (!gUtil->testLoop()) break;
02932     gFeb->printNxHeadLine(std::cout, nxind);
02933     if (check_nxoffline(nxind, nxbeg, nxend)) continue; // skip of offline
02934 
02935     rc = gFeb->nx(nxind).i2c().getContext(save_cntx, nxyter::kDoCore);
02936     print_opererr("NxI2c::getContext {save}", rc);
02937 
02938     rc = gFeb->nx(nxind).i2c().setTestModes(false, true, 0);
02939     print_opererr("NxI2c::setTestModes", rc);
02940     
02941     int vb_beg =   0;
02942     int vb_end = 255;
02943     int vb_mid =   0;
02944     float med_beg;
02945     float med_end;
02946     float med_mid;
02947     bool nxabort = false;
02948     
02949     get_vbiass_data(nxind, vb_beg, med_beg, npuls, opt_v, true);
02950     get_vbiass_data(nxind, vb_end, med_end, npuls, opt_v, false);
02951  
02952     if (float(base) < std::min(med_beg, med_end) ||
02953         float(base) > std::max(med_beg, med_end)) {
02954       std::cout << "!! ABORT autovbiass: baseline target of " << std::dec << base
02955            << " is outside the range possible\n"
02956            << "   with VBiasS between 0 and 255, see two lines above" << std::endl;
02957       nxabort = true;
02958     }
02959 
02960     bool posgain = (med_end > med_beg);     // vb->med gain is positive
02961 
02962     while (!nxabort && vb_end-vb_beg >=2) {
02963       if (!gUtil->testLoop()) break;
02964       vb_mid = (vb_end+vb_beg)/2;
02965       get_vbiass_data(nxind, vb_mid, med_mid, npuls, opt_v, false);
02966 
02967       // allow some tolerance
02968       float tol = 300.;
02969       if (med_mid < std::min(med_beg, med_end)-tol ||
02970           med_mid > std::max(med_beg, med_end)+tol) {
02971         nxabort = true;
02972         std::cout << "!! ABORT autovbiass: ADC median for vb=" 
02973              << std::dec << vb_mid << " outside the previous bounds\n"
02974              << "   determined for vb_beg=" << vb_beg
02975              << " and vb_end=" << vb_end << ", values see above." << std::endl;
02976         break;
02977       }
02978 
02979       bool keepend;                         // keep vb_end, vb_beg <- vb_mid
02980       bool unsteady = false;                // if mid ouside [beg,end]
02981       if (posgain) {
02982         keepend = base >= med_mid;
02983       } else {
02984         keepend = base <= med_mid;
02985       }
02986 
02987       if (keepend) {                        // in upper sector ?
02988         vb_beg = vb_mid;
02989         med_beg = med_mid;
02990       } else {                              // otherwise lower sector
02991         vb_end = vb_mid;
02992         med_end = med_mid;
02993       }
02994     }
02995 
02996     // end game: check whether beg, mid or end is best
02997     float dif_beg = std::abs(med_beg - base);
02998     float dif_mid = std::abs(med_mid - base);
02999     float dif_end = std::abs(med_end - base);
03000     int vb_fin = 0;
03001     float med_fin = 0.;
03002     
03003     if (!nxabort) {
03004       if (dif_beg < dif_mid) {
03005         vb_fin  = vb_beg;
03006         med_fin = med_beg;
03007       } else if (dif_end < dif_mid) {
03008         vb_fin  = vb_end;
03009         med_fin = med_end;
03010       } else {
03011         vb_fin  = vb_mid;
03012         med_fin = med_mid;
03013       }
03014       static boost::format fmt("==> VBiasS=%3d  median ADC=%4.0f  (target=%4d)");
03015       std::cout << fmt % vb_fin % med_fin % base << std::endl;
03016     }
03017 
03018     rc = gFeb->nx(nxind).i2c().setContext(save_cntx, nxyter::kDoCore);
03019     print_opererr("NxI2c::setContext {restore}", rc);    
03020 
03021     if (!nxabort && gUtil->testLoop()) {    // if not aborted
03022       rc = gFeb->nx(nxind).i2c().setRegister(nxyter::kNxRegVbiasS, 
03023                                              vb_fin, true);
03024       print_opererr("setRegister(kNxRegVbiasS,...)", rc);
03025     }
03026     
03027   }
03028 
03029   return 0;
03030 }
03031 
03032 //----------------------------------------------------------------------------
03033 
03034 int cmd_scanvbiasf()
03035 {
03036   bool opt_v = get_opt("-v");
03037   int32_t nxbeg=0;
03038   int32_t nxend=0;
03039   int32_t vbeg=0;
03040   int32_t vend=255;
03041   int32_t vstep=1;
03042   int32_t npuls=100;
03043   if (get_nxrange(nxbeg, nxend)) return 1;
03044   if (get_arg(vbeg,  "vbeg=",  0, 255)) return 1;
03045   if (get_arg(vend,  "vend=",  0, 255)) return 1;
03046   if (get_arg(vstep, "vstep=", 1, 255)) return 1;
03047   if (get_arg(npuls, "npuls=", 1, 10000)) return 1;
03048   if (args_check(kNeedFeb|kNeedDaq)) return 1;
03049 
03050   int rc;
03051   nxyter::NxContext save_cntx;
03052   
03053   gUtil->startLoop(0.);
03054   for (int nxind=nxbeg; nxind<=nxend; nxind++) {
03055     if (!gUtil->testLoop()) break;
03056     gFeb->printNxHeadLine(std::cout, nxind);
03057     if (check_nxoffline(nxind, nxbeg, nxend)) continue; // skip of offline
03058 
03059     rc = gFeb->nx(nxind).i2c().getContext(save_cntx, 
03060                                           nxyter::kDoCore|nxyter::kDoMask);
03061     print_opererr("NxI2c::getContext {save}", rc);
03062 
03063     rc = gFeb->nx(nxind).i2c().setTestModes(true, false, 0);
03064     print_opererr("NxI2c::setTestModes", rc);
03065     
03066     for (int vb=vbeg; vb<=vend; vb+=vstep) {
03067       if (!gUtil->testLoop()) break;
03068       rc = gFeb->nx(nxind).i2c().setRegister(nxyter::kNxRegVbiasF, vb, true);
03069       print_opererr("setRegister(kNxRegVbiasF,...)", rc);
03070 
03071       nxyter::NxDataSummary nds;
03072       gUtil->acquireTestPulserData(nxind, save_cntx, npuls, nds);
03073       if (opt_v) {
03074         nds.print(std::cout, gFeb->nx(nxind).getNxNumber());
03075         gQdaq->stats().print(std::cout);
03076       }
03077 
03078       int ncha = 0;
03079       nxyter::DistFunc df_ent(128);
03080       nxyter::DistFunc df_med(128);
03081       nxyter::DistFunc df_w50(128);
03082     
03083       for (int ch=0; ch<128; ch++) {
03084         if (nds.numEntries(ch)==0) continue;
03085         ncha += 1;
03086         df_ent.addEntry(nds.numEntries(ch));
03087         df_med.addEntry(nds.getMedian(ch));
03088         df_w50.addEntry(nds.getWidth50(ch));
03089       }
03090 
03091       print_dfa_ent_med_w50(vb, ncha, df_ent, df_med, df_w50, true, vb==vbeg);
03092 
03093     }
03094 
03095     rc = gFeb->nx(nxind).i2c().setContext(save_cntx, 
03096                                           nxyter::kDoCore|nxyter::kDoMask);
03097     print_opererr("NxI2c::setContext {restore}", rc);
03098   
03099   }
03100 
03101   return 0;
03102 }
03103 
03104 //----------------------------------------------------------------------------
03105 
03106 int cmd_scanadclat()
03107 {
03108   bool opt_v = get_opt("-v");
03109   bool opt_d = get_opt("-d");
03110   int32_t nxind=0;
03111   int32_t ch=0;
03112   int32_t ch2=-1;
03113   int32_t lbeg=61;
03114   int32_t lend=68;
03115   int32_t dbeg=0;
03116   int32_t dend=31;
03117   int32_t npuls=100;
03118   if (get_nxind(nxind)) return 1;
03119   if (get_arg(ch,    "ch=",    0, 127)) return 1;
03120   if (get_arg(lbeg,  "lbeg=",  0, 127)) return 1;
03121   if (get_arg(lend,  "lend=",  0, 127)) return 1;
03122   if (get_arg(dbeg,  "dbeg=",  0, 31)) return 1;
03123   if (get_arg(dend,  "dend=",  0, 31)) return 1;
03124   if (get_arg(npuls, "npuls=", 1, 10000)) return 1;
03125   if (get_arg(ch2,   "ch2=",   0, 127)) return 1;
03126   if (args_check(kNeedFeb|kNeedDaq)) return 1;
03127 
03128   int32_t dstep=1;
03129   int32_t lstep=1;
03130 
03131   if (opt_d) {
03132     int nlat = lend-lbeg+1;
03133     if (nlat > 16) {
03134       lstep = 4;
03135       if (lend > lbeg + (nlat-1)*lstep) lend = lbeg + (nlat-1)*lstep;
03136     } else if (nlat > 8) {
03137       lstep = 2;
03138     } 
03139 
03140   } else {
03141     int ndly = dend-dbeg+1;
03142     if (ndly > 16) {
03143       dstep = 4;
03144     } else if (ndly >  8) {
03145       dstep = 2;
03146     }
03147   }
03148 
03149   int rc;
03150   int nxnum = gFeb->nx(nxind).getNxNumber();
03151   nxyter::NxContext save_cntx;
03152 
03153   rc = gFeb->nx(nxind).i2c().getContext(save_cntx, 
03154                                         nxyter::kDoCore|nxyter::kDoMask);
03155   print_opererr("NxI2c::getContext {save}", rc);
03156   if (rc) return 0;                         // quit if save fails...
03157 
03158   nxyter::NxContext cntx;
03159   cntx.setToDefault(false);                 // all default
03160   cntx.setChannelMaskBit(0, 127, true);     // all channels off
03161   cntx.setChannelMaskBit(ch, ch, false);    // except channel ch
03162   if (ch2 >= 0) {
03163     cntx.setChannelMaskBit(ch2, ch2, false); // and optionally channel ch2
03164   }
03165   cntx.setRegister(nxyter::kNxRegVbiasS, 0);        // VBiasS = 0
03166   uint8_t config0 = cntx.getRegister(nxyter::kNxRegConfig0);
03167   cntx.setRegister(nxyter::kNxRegConfig0, 
03168                    config0 | nxyter::kNxC0TestTrigEnable);
03169 
03170   rc = gFeb->nx(nxind).i2c().setContext(cntx, nxyter::kDoCore|nxyter::kDoMask);
03171   print_opererr("NxI2c::setContext {setup}", rc);
03172 
03173   gUtil->startLoop(0.);
03174 
03175   uint32_t clkinit[32];
03176   uint32_t clkbufg[32];
03177 
03178   float ent[128][32];
03179   float med[128][32];
03180   float w80[128][32];
03181 
03182   for (int dly=0; dly<32; dly++) {
03183     clkinit[dly] = 0;
03184     clkbufg[dly] = 0;
03185     for (int lat=0; lat<128; lat++) {
03186       ent[lat][dly] = 0.;
03187       med[lat][dly] = 0.;
03188       w80[lat][dly] = 0.;
03189     }
03190   }  
03191 
03192   uint32_t save_clkinit;
03193   uint32_t save_clkbufg;
03194   uint32_t save_adclat;
03195   rc = gFeb->adc().getClockDelaySrInit(save_clkinit);
03196   print_opererr("MainAdc::getClockDelaySrInit {save}", rc);
03197   rc = gFeb->adc().getClockDelayBufg(save_clkbufg);
03198   print_opererr("MainAdc::getClockDelayBufg {save}", rc);
03199   rc = gFeb->adc().getChannelLatency(nxnum, save_adclat);
03200   print_opererr("MainAdc::getChannelLatency {save}", rc);
03201 
03202   static boost::format fmt_04x("%04x");
03203   static boost::format fmt_1d("%1d");
03204   static boost::format fmt_2d("%2d");
03205   static boost::format fmt_3d("%3d");
03206   static boost::format fmt_40f("%4.0f");
03207 
03208   if (opt_v) std::cout << "dly lat nhit   med  w50  w80  min  max" << std::endl;
03209 
03210   for (int dly=dbeg; dly<=dend; dly+=dstep) {
03211     if (!gUtil->testLoop()) break;
03212 
03213     gFeb->adc().setClockDelay(dly);
03214     rc = gFeb->adc().getClockDelaySrInit(clkinit[dly]);
03215     print_opererr("MainAdc::getClockDelaySrInit", rc);
03216     rc = gFeb->adc().getClockDelayBufg(clkbufg[dly]);
03217     print_opererr("MainAdc::getClockDelayBufg", rc);
03218 
03219     for (int lat=lbeg; lat<=lend; lat+=lstep) {
03220       if (!gUtil->testLoop()) break;
03221 
03222       rc = gFeb->adc().setChannelLatency(nxnum, lat);
03223       print_opererr("MainAdc::setChannelLatency", rc);
03224 
03225       nxyter::NxDataSummary nds;
03226       gUtil->acquireTestTriggerData(nxind, npuls, nds);
03227       ent[lat][dly] = nds.numEntries(ch);
03228       med[lat][dly] = nds.getMedian(ch);
03229       w80[lat][dly] = nds.getWidth80(ch);
03230       if (opt_v) {
03231         std::cout << " " << fmt_2d  % dly;
03232         std::cout << " " << fmt_3d  % lat;
03233         std::cout << " " << fmt_40f % nds.numEntries(ch);
03234         std::cout << ((nds.full(ch)) ? '+' : ' ');
03235         std::cout << " " << fmt_40f % nds.getMedian(ch);
03236         std::cout << " " << fmt_40f % nds.getWidth50(ch);
03237         std::cout << " " << fmt_40f % nds.getWidth80(ch);
03238         std::cout << " " << fmt_40f % nds.getMin(ch);
03239         std::cout << " " << fmt_40f % nds.getMax(ch);
03240         std::cout << std::endl;
03241       }
03242     }
03243   }
03244 
03245   rc = gFeb->adc().setClockDelaySrInit(save_clkinit);
03246   print_opererr("MainAdc::setClockDelaySrInit {restore}", rc);
03247   rc = gFeb->adc().setClockDelayBufg(save_clkbufg);
03248   print_opererr("MainAdc::setClockDelayBufg {restore}", rc);
03249   rc = gFeb->adc().setChannelLatency(nxnum, save_adclat);
03250   print_opererr("MainAdc::setChannelLatency {restore}", rc);
03251 
03252   if (opt_d) {
03253     // find warp point for the default case lstep==4 and dstep==1
03254     // simply search for largest absolute step between neighboring dly's
03255     int inddmed = -1;
03256     if (lstep==4 && dstep==1) {
03257       float maxdmed = 0.;
03258       for (int dly=dbeg; dly<=dend; dly+=dstep) {
03259         float absdmed = 0.;
03260         for (int lat=lbeg; lat<=lend; lat+=2*lstep) {
03261           absdmed += std::abs(med[lat][dly] - med[lat][(dly+1)%32]);
03262           if (lat+lstep <= lend) {
03263             absdmed += std::abs(med[lat+4][(dly+16)%32] - 
03264                                 med[lat+4][(dly+17)%32]);
03265           }
03266         }
03267         if (absdmed > maxdmed) {
03268           inddmed = dly;
03269           maxdmed = absdmed;
03270         }
03271       }
03272     }
03273     
03274     std::cout << "dly init s  ";
03275     for (int lat=lbeg; lat<=lend; lat+=lstep) std::cout << " lat=" << fmt_3d % lat;
03276     std::cout << std::endl;
03277     
03278     for (int dly=dbeg; dly<=dend; dly+=dstep) {
03279       std::cout << " " << fmt_2d  % dly;
03280       std::cout << " " << fmt_04x % clkinit[dly];
03281       std::cout << " " << fmt_1d  % clkbufg[dly];
03282       std::cout << ": ";
03283       for (int lat=lbeg; lat<=lend; lat+=lstep) {
03284         std::cout << " " << fmt_40f % med[lat][dly];
03285         const char* del = "/";
03286         if (inddmed >= 0) {
03287           if (((lat-lbeg)%8==0) &&         dly==inddmed) del = "\\";
03288           if (((lat-lbeg)%8==4) && (dly+16)%32==inddmed) del = "\\";
03289         }
03290         std::cout << del;
03291         int width = int(w80[lat][dly]);
03292         if (width > 99) width = 99;
03293         std::cout << fmt_2d % width;
03294       }
03295       std::cout << std::endl;
03296     }
03297 
03298   } else {
03299     std::cout << "lat :";
03300     for (int dly=dbeg; dly<=dend; dly+=dstep) std::cout << "   dly=" << fmt_2d % dly;
03301     std::cout << std::endl;
03302 
03303     for (int lat=lbeg; lat<=lend; lat+=lstep) {
03304       std::cout << fmt_3d % lat << " :";
03305       for (int dly=dbeg; dly<=dend; dly+=dstep) {
03306         std::cout << "  " << fmt_40f % med[lat][dly];
03307         std::cout << "/";
03308         int width = int(w80[lat][dly]);
03309         if (width > 99) width = 99;
03310         std::cout << fmt_2d % width;
03311       }
03312       std::cout << std::endl;
03313     }
03314     
03315   }
03316 
03317   rc = gFeb->nx(nxind).i2c().setContext(save_cntx, 
03318                                         nxyter::kDoCore|nxyter::kDoMask);
03319   print_opererr("NxI2c::setContext {restore}", rc);
03320 
03321   return 0;
03322 }
03323 
03324 //----------------------------------------------------------------------------
03325 
03326 int cmd_testrocsync()
03327 {
03328   bool opt_n  = get_opt("-n");
03329   bool opt_v  = get_opt("-v");
03330   int32_t ch=0;
03331   int32_t scale=5;
03332   double time=10.;
03333   if (get_arg(ch, "ch=", 0, 1)) return 1;
03334   if (get_arg(scale, "scale=", 0, 21)) return 1;
03335   if (get_arg(time, "time=")) return 1;
03336   if (args_check(kNeedDaq)) return 1;
03337 
03338   uint64_t nsync = 0;
03339   uint32_t syncdata_last = 0;
03340   uint32_t syncdata_inc  = (1<<scale);
03341   double   synctime_last = -1.;
03342   double   synctime_inc  = double(1<<(scale+14))/1.e9;
03343   int ecnt = 0;
03344 
03345   uint32_t syncmask = ~(-(1<<scale));       // mask with scale 1's LSB's
03346 
03347   double dif_avr = 0.;
03348   double sync_per_sec = 1.e9/(16384.*(1<<scale));//1GHz / 16k / 1<<scale
03349   double dif_avr_weight = 1./sync_per_sec;
03350   
03351   static boost::format fmt_06x("%06x");
03352   static boost::format fmt_4d("%4d");
03353   static boost::format fmt_5d("%5d");
03354   static boost::format fmt_159f("%15.9f");
03355   static boost::format fmt_63f("%6.3f");
03356   static boost::format fmt_p102e("%+10.2e");
03357 
03358   gQdaq->startRun(0, time, opt_n);
03359 
03360   while(gQdaq->testRun()) {
03361     roc::Message& msg = gQdaq->msg();
03362     if (msg.isSyncMsg()) {
03363       if (msg.getSyncChNum() != ch) continue;
03364 
03365       uint32_t syncdata = msg.getSyncData();
03366       uint32_t syncdata_exp = (syncdata_last + syncdata_inc) & 0xffffff;
03367       double   synctime = gQdaq->getMsgTime();
03368       double   synctime_exp = synctime_last + synctime_inc;
03369       double   synctime_dif = synctime - synctime_exp;
03370 
03371       nsync += 1;
03372 
03373       if (opt_v && nsync <= 30) {
03374         std::cout << get_timestamp("tm");
03375         std::cout << " @" << fmt_159f % synctime;
03376         std::cout << ": SYNC ";
03377         std::cout << " Ts: " << fmt_5d % msg.getSyncTs();
03378         std::cout << " Data: 0x" <<  fmt_06x % syncdata;
03379         if (synctime_last >= 0.) {
03380           std::cout << " delta: " << fmt_4d % int(round(1.e9*synctime_dif));
03381           std::cout << " ns";
03382         }
03383         std::cout << std::endl;
03384       }
03385 
03386       if ((syncdata & syncmask) != 0) {
03387         std::cout << get_timestamp("tm");
03388         std::cout << " @" << fmt_159f % synctime;
03389         std::cout << ": BAD LSB ERROR";
03390         std::cout << " data: 0x" << fmt_06x % syncdata;
03391         std::cout << " expected: 0x" << fmt_06x % syncdata_exp;
03392         std::cout << std::endl;
03393         ecnt += 1; 
03394 
03395       } else {
03396 
03397         if (synctime_last>=0.) {            // if not first sync
03398           if (syncdata != syncdata_exp) {
03399             int nmiss = syncdata - syncdata_exp;
03400             if (nmiss < 0) nmiss += 1<<24;
03401             nmiss = nmiss >> scale;
03402             std::cout << get_timestamp("tm");
03403             std::cout << " @" << fmt_159f % synctime;
03404             std::cout << ": SYNC MISS";
03405             std::cout << " now: 0x" << fmt_06x % syncdata;
03406             std::cout << " last: 0x" << fmt_06x % syncdata_last;
03407             std::cout << " nmiss: " << std::dec << nmiss;
03408             std::cout << std::endl;
03409             ecnt += 1;       
03410           }
03411           dif_avr = (1.-dif_avr_weight)*dif_avr + dif_avr_weight*synctime_dif;
03412         }
03413         
03414         if (opt_v && ((nsync<<scale) & 0xffff) == 0) {
03415           std::cout << get_timestamp("tm");
03416           std::cout << " @" << fmt_159f % synctime;
03417           std::cout << " : shift: ";
03418           std::cout << fmt_63f % (1.e9*dif_avr);
03419           std::cout << " ns/sync";
03420           std::cout << " drift: " << fmt_p102e % (dif_avr/synctime_inc);
03421           std::cout << std::endl;
03422         }
03423         
03424         syncdata_last = syncdata;
03425         synctime_last = synctime;
03426       }
03427 
03428     } else if (msg.isSysMsg() & msg.getSysMesType() == roc::SYSMSG_SYNC_PARITY) {
03429       // getMsgTime() returns 0 for system messages...
03430       // so generate msgtime from last received epoch marker...
03431       double msgtime = gQdaq->getMsgTime();
03432       std::cout << get_timestamp("tm");
03433       std::cout << " @" << fmt_159f % msgtime;
03434       std::cout << ": SYNC PARITY ERROR";
03435       std::cout << " data: 0x" << fmt_06x % msg.getSysMesData();
03436       std::cout << std::endl;
03437       ecnt += 1;
03438     }
03439 
03440   }
03441 
03442   if (opt_v || gQdaq->stats().errorCount()>0 ) {
03443     double dtime = gQdaq->getStopTime() - gQdaq->getStartTime();
03444     gQdaq->stats().print(std::cout, dtime);
03445   }
03446   
03447   print_daq_stats("testrocsync", nsync, ecnt);
03448 
03449   return 0;
03450 }
03451 
03452 //----------------------------------------------------------------------------
03453 
03454 int cmd_testrocaux()
03455 {
03456   bool opt_n  = get_opt("-n");
03457   bool opt_v  = get_opt("-v");
03458   int32_t ch=2;
03459   int32_t scale=0;
03460   double time=10.;
03461   if (get_arg(ch, "ch=", 0, 3)) return 1;
03462   if (get_arg(scale, "scale=", 0, 11)) return 1;
03463   if (get_arg(time, "time=")) return 1;
03464   if (args_check(kNeedDaq)) return 1;
03465 
03466   uint64_t naux_re = 0;
03467   uint64_t naux_fe = 0;
03468   double   auxtime_re_last = -1.;
03469   double   auxtime_re_inc  = 31.25e-9*65536./(1<<scale);  // 31.25ns*64k/2^scale
03470   int      pw_last = -1;
03471   int ecnt = 0;
03472 
03473   static boost::format fmt_5d("%5d");
03474   static boost::format fmt_6d("%6d");
03475   static boost::format fmt_159f("%15.9f");
03476   static boost::format fmt_30f("%3.0f");
03477   static boost::format fmt_70f("%7.0f");
03478 
03479   gQdaq->startRun(0, time, opt_n);
03480 
03481   while(gQdaq->testRun()) {
03482     roc::Message& msg = gQdaq->msg();
03483     if (msg.isAuxMsg()) {
03484       if (msg.getAuxChNum() != ch) continue;
03485 
03486       double auxtime = gQdaq->getMsgTime();
03487       double dtime = auxtime-auxtime_re_last;
03488       int   nclock = int(round(dtime/31.25e-9)); // 32 MHz clock on SysGlue
03489 
03490       if (opt_v && (naux_re <= 20 || naux_fe <= 20)) {
03491         std::cout << get_timestamp("tm");
03492         std::cout << " @" << fmt_159f % auxtime;
03493         std::cout << ": AUX ";
03494         std::cout << " Ts: " << fmt_5d % msg.getAuxTs();
03495         if (auxtime_re_last >= 0.) {
03496           if (!msg.getAuxFalling()) {      // re
03497             std::cout << " rise, peri: ";
03498           } else {                          // fe
03499             std::cout << " fall, wdth: ";
03500           }
03501           std::cout << fmt_70f % (dtime*1.e9);
03502           std::cout << " ns";
03503           std::cout << fmt_6d % nclock;
03504           std::cout << " clk";
03505         }
03506         std::cout << std::endl;
03507       }
03508 
03509       if (!msg.getAuxFalling()) {          // re
03510         naux_re += 1;
03511         if (auxtime_re_last >=0.) {
03512           double dterr = dtime-auxtime_re_inc;
03513           double relerrlimit = 5.e-5;
03514           double dttol = auxtime_re_inc*relerrlimit;
03515           if (dttol < 10.e-9) dttol = 10.e-9;
03516           if (std::abs(dterr) > dttol) {
03517             std::cout << get_timestamp("tm");
03518             std::cout << " @" << fmt_159f % auxtime;
03519             std::cout << ": AUX ERROR PERI: ";
03520             std::cout << fmt_70f % (dtime*1.e9);
03521             std::cout << " ns exp: " << fmt_70f % (auxtime_re_inc*1.e9);
03522             std::cout << "+-" << fmt_30f % (dttol*1.e9);
03523             std::cout << " ns" << std::endl;
03524             ecnt += 1;
03525           }
03526         }
03527         auxtime_re_last = auxtime;
03528 
03529       } else {                              // fe
03530         naux_fe += 1;
03531         if (auxtime_re_last >= 0.) {
03532           if (pw_last >= 0) {
03533             int pw_exp = (pw_last & 0xf) + 1;
03534             if (nclock != pw_exp) {
03535             std::cout << get_timestamp("tm");
03536             std::cout << " @" << fmt_159f % auxtime;
03537             std::cout << ": AUX ERROR WDTH: ";
03538             std::cout << fmt_70f % (dtime*1.e9);
03539             std::cout << " ns exp: " << fmt_70f % (pw_exp*31.25);
03540             std::cout << "+- 14 ns" << std::endl;
03541             ecnt += 1;
03542             }
03543           }
03544           pw_last = nclock;
03545         }
03546       }
03547       
03548     }
03549 
03550   }
03551 
03552   if (opt_v || gQdaq->stats().errorCount()>0 ) {
03553     double dtime = gQdaq->getStopTime() - gQdaq->getStartTime();
03554     gQdaq->stats().print(std::cout, dtime);
03555   }
03556   
03557   print_daq_stats("testrocaux", naux_re, ecnt);
03558 
03559   return 0;
03560 }
03561 
03562 //----------------------------------------------------------------------------
03563 
03564 int cmd_testnxcntl()
03565 {
03566   int32_t nxbeg=0;
03567   int32_t nxend=0;
03568   double time=10.;
03569   if (get_nxrange(nxbeg, nxend)) return 1;
03570   if (get_arg(time, "time=")) return 1;
03571   if (args_check(kNeedFeb)) return 1;
03572 
03573   for (int i=nxbeg; i<=nxend; i++) {
03574     if (check_nxoffline(i, nxbeg, nxend)) continue; // skip of offline
03575     if (nxend!=nxbeg) std::cout << "Test nx:" << i << std::endl;
03576     int ecnt = gUtil->testNxControlPath(i, time);
03577     print_loop_stats("testnxcntl", ecnt);
03578     if (gUtil->getLoopState()==nxyter::FebUtil::kLoopInterrupted) break;
03579   }
03580   return 0;
03581 }
03582 
03583 //----------------------------------------------------------------------------
03584 
03585 int cmd_testnxregs()
03586 {
03587   int32_t nxbeg=0;
03588   int32_t nxend=0;
03589   if (get_nxrange(nxbeg, nxend)) return 1;
03590   if (args_check(kNeedFeb)) return 1;
03591 
03592   for (int i=nxbeg; i<=nxend; i++) {
03593     if (check_nxoffline(i, nxbeg, nxend)) continue; // skip of offline
03594     if (nxend!=nxbeg) std::cout << "Test nx:" << i << std::endl;
03595     int ecnt = gUtil->testNxRegisters(i);
03596     print_loop_stats("testnxregs", ecnt);
03597     if (gUtil->getLoopState()==nxyter::FebUtil::kLoopInterrupted) break;
03598   }
03599   return 0;
03600 }
03601 
03602 //----------------------------------------------------------------------------
03603 int cmd_testadccntl()
03604 {
03605   double time=10.;
03606   if (get_arg(time, "time=")) return 1;
03607   if (args_check(kNeedFeb)) return 1;
03608 
03609   int ecnt = gUtil->testMainAdcControlPath(time);
03610   print_loop_stats("testadccntl", ecnt);
03611   return 0;
03612 }
03613 
03614 //----------------------------------------------------------------------------
03615 int cmd_testadcdata()
03616 {
03617   double time=10.;
03618   if (get_arg(time, "time=")) return 1;
03619   if (args_check(kNeedFeb)) return 1;
03620 
03621   int ecnt = gUtil->testMainAdcDataPath(time);
03622   print_loop_stats("testadcdata", ecnt);
03623   return 0;
03624 }
03625 
03626 //----------------------------------------------------------------------------
03627 int cmd_testfebcntl()
03628 {
03629   double time=10.;
03630   if (get_arg(time, "time=")) return 1;
03631   if (args_check(kNeedFeb)) return 1;
03632 
03633   int ecnt = gUtil->testFebControlPathCombo(time);
03634   print_loop_stats("testfebcntl", ecnt);
03635   return 0;
03636 }
03637 
03638 //----------------------------------------------------------------------------
03639 int cmd_printdata()
03640 {
03641    bool opt_m  = get_opt("-m");
03642    bool opt_r  = get_opt("-r");
03643    bool opt_h  = get_opt("-h");
03644    bool opt_t  = get_opt("-t");
03645    bool opt_s  = get_opt("-s");
03646    bool opt_d  = get_opt("-d");
03647    bool opt_n  = get_opt("-n");
03648    bool opt_ia = get_opt("-ia");
03649    int32_t nmsg=-1;
03650    double time=-1.;
03651    int32_t npuls=0;
03652    int32_t pper=100000;
03653    int32_t pwth=32;
03654    int32_t pdly=1000;
03655    if (get_arg(nmsg,  "nmsg=", 0)) return 1;
03656    if (get_arg(time,  "time=")) return 1;
03657    if (get_arg(npuls, "npuls=", 0, 32767)) return 1;
03658    if (get_arg(pper,  "pper=", 2, 0x00ffffff)) return 1;
03659    if (get_arg(pwth,  "pwth=", -0x00ffffff, 0x00ffffff)) return 1;
03660    if (get_arg(pdly,  "pdly=", 1, 0x0000ffff)) return 1;
03661    if (args_check(kNeedDaq)) return 1;
03662 
03663    if (nmsg < 0 && time < 0.) {              // neither nmsg nor time specified
03664       if (gBaseBoard->isFile()) {
03665          nmsg = 0;
03666          time = 0.;
03667       } else {
03668          nmsg = 100;
03669          time = 10.;
03670       }
03671    }
03672    if (nmsg < 0) nmsg = 0;
03673    if (time < 0) time = 0.;
03674 
03675    if (!(opt_s | opt_d)) opt_m = true;       // assume -m if no -s or -d
03676 
03677    int rc;
03678 
03679    if (gRocNx && (npuls > 0)) {                          // test pulser requested ?
03680       if (opt_ia) {
03681          rc = gRocNx->fireTestPulse(0,0,0);      // if init-after just stop it
03682          print_opererr("RocNx::fireTestPulse", rc);
03683       } else {
03684          rc = gRocNx->fireTestPulse(pdly, pper, pwth, npuls); // or setup train
03685          print_opererr("RocNx::fireTestPulse", rc);
03686       }
03687    }
03688 
03689    gQdaq->startRun(nmsg, time, opt_n);
03690 
03691    if (opt_ia && gRocNx) {
03692       if (npuls > 0) {
03693          rc = gRocNx->fireTestPulse(pdly, pper, pwth, npuls); // setup pulse train
03694          print_opererr("RocNx::fireTestPulse", rc);
03695       }
03696       rc = gRocNx->resetRocNxTs();
03697       print_opererr("RocNx::resetRocNxTs", rc);
03698    }
03699 
03700    typedef std::auto_ptr<nxyter::DistFuncArray> ptr_dfa;
03701    ptr_dfa dfa[4];
03702    if (opt_d) {
03703       for (int i=0; i<4; i++)
03704          dfa[i] = ptr_dfa(new nxyter::DistFuncArray(128, 512));
03705    }
03706 
03707    // limit stats to 100k entries/channel
03708    // that will consume at most 4*128*4*100k = 200 MByte
03709    const static int nentmax = 100000;
03710 
03711    while(gQdaq->testRun()) {
03712       roc::Message& msg = gQdaq->msg();
03713       if (opt_m) {
03714          if (opt_t) std::cout << get_timestamp("tm") << ": ";
03715          unsigned kind = roc::msg_print_Human;
03716          if (opt_r) kind  = roc::msg_print_Prefix | roc::msg_print_Data;
03717          if (opt_h) kind |= roc::msg_print_Hex;
03718          msg.printData(std::cout, kind, gQdaq->getMsgEpoch());
03719       }
03720 
03721       if (opt_d) {
03722          if (msg.isHitMsg()) {
03723             int nxnum = msg.getNxNumber();
03724             int nxcha = msg.getNxChNum();
03725             int nxadc = msg.getNxAdcValue();
03726             if ((*dfa[nxnum])[nxcha].numEntries() < nentmax) {
03727                (*dfa[nxnum]).addEntry(nxcha, float(nxadc));
03728             }
03729          }
03730       }
03731    }
03732 
03733    if (gRocNx && (npuls > 0)) {
03734       rc = gRocNx->fireTestPulse(0,0,0);      // stop and disable pulser
03735       print_opererr("RocNx::fireTestPulse", rc);
03736    }
03737 
03738    if (opt_d) {
03739       for (int nxnum=0; nxnum<4; nxnum++) {
03740          if ((*dfa[nxnum]).numEntries() == 0) continue;
03741          nxyter::NxDataSummary nds;
03742          nds.analyse((*dfa[nxnum]));
03743          nds.print(std::cout, nxnum);
03744       }
03745    }
03746 
03747    double dtime = gQdaq->getStopTime() - gQdaq->getStartTime();
03748    gQdaq->stats().print(std::cout, dtime);
03749 
03750    return 0;
03751 }
03752 
03753 //----------------------------------------------------------------------------
03754 // helper for cmd_autoped
03755 // this is a temporary hack, to be removed when ROC hardware support is added.
03756 
03757 int autoped_issue_system_message(uint32_t type)
03758 {
03759   int rc = gRocBoard->operPPP(
03760         ROC_NX_FIFO_RESET, 1,   // and flush fifo
03761         ROC_NX_FIFO_RESET, 0,
03762         ROC_ADDSYSMSG, type ); // insert sysmsg
03763   print_opererr("operPPP(ROC_ADDSYSMSG,...)", rc);
03764   return rc;
03765 }
03766 
03767 //----------------------------------------------------------------------------
03768 // helper for cmd_autoped
03769 
03770 int autoped_setnxmode(bool testtrig)
03771 {
03772   int32_t nxbeg = 0;
03773   int32_t nxend = gFeb->numNx()-1;
03774   int rc = 0;
03775 
03776   for (int i=nxbeg; i<=nxend; i++) {
03777     if (check_nxoffline(i, nxbeg, nxend)) continue; // skip of offline
03778     rc = gFeb->nx(i).i2c().setTestModes(false, testtrig, 0);
03779     print_opererr("NxI2c::setTestModes", rc);
03780   }
03781 
03782   return rc;
03783 }
03784 
03785 //----------------------------------------------------------------------------
03786 int cmd_autoped()
03787 {
03788   double tmeas=30.;
03789   double tped=0.1;
03790   if (get_arg(tmeas, "tmeas=")) return 1;
03791   if (get_arg(tped,  "tped=")) return 1;
03792   if (args_check(kNeedFeb)) return 1;
03793 
03794   if (tmeas < 0.1 || tped < 0.05) {
03795     std::cout << "rocutil-E: tmeas or tped out of range" << std::endl;
03796     return 1;
03797   }
03798 
03799   int rc;
03800 
03801   // setup AUX2
03802   uint32_t gpio_mask_save;
03803   rc = gGpio->getConfig(gpio_mask_save);
03804   print_opererr("Gpio::getConfig", rc);
03805   bool riseedge, falledge, throttled, extrafunc, altin;
03806   base::Gpio::unpackConfig(gpio_mask_save, 6,
03807                      riseedge, falledge, throttled, extrafunc, altin);
03808 
03809   extrafunc = true;
03810   altin     = true;
03811   uint32_t gpio_mask_on = gpio_mask_save;
03812   base::Gpio::packConfig(gpio_mask_on, 6,
03813                    riseedge, falledge, throttled, extrafunc, altin);
03814 
03815   extrafunc = false;
03816   altin     = false;
03817   uint32_t gpio_mask_off = gpio_mask_save;
03818   base::Gpio::packConfig(gpio_mask_off, 6,
03819                    riseedge, falledge, throttled, extrafunc, altin);
03820 
03821 
03822   // setup test pulse generator
03823   int32_t period=250000;                    // 1 khz
03824   rc = gRocNx->fireTestPulse(period, 128, 0);
03825   print_opererr("RocNx::fireTestPulse", rc);
03826 
03827   int imeas = (int) ((tmeas + 0.0999) / 0.1);
03828 
03829   struct timespec ts_tmeas;
03830   uint64_t itmeas = (uint64_t) (1.e9*tmeas);     // tmeas in ns
03831   ts_tmeas.tv_sec  = itmeas / (1000*1000*1000);
03832   ts_tmeas.tv_nsec = itmeas % (1000*1000*1000);
03833 
03834   struct timespec ts_tped;
03835   uint64_t itped = (uint64_t) (1.e9*tped);     // tped in ns
03836   ts_tped.tv_sec  = itped / (1000*1000*1000);
03837   ts_tped.tv_nsec = itped % (1000*1000*1000);
03838 
03839   gUtil->startLoop(0.);
03840   while (true) {
03841     // switch for pedestal taking mode
03842     autoped_issue_system_message(roc::SYSMSG_USER_RECONFIGURE);
03843     autoped_setnxmode(true);
03844     rc = gGpio->setConfig(gpio_mask_on);
03845     print_opererr("Gpio::setConfig{ped_on}", rc);
03846     autoped_issue_system_message(roc::SYSMSG_USER_CALIBR_ON);
03847     
03848     // do pedestal taking
03849     std::cout << get_timestamp() << " +++1a before tped  wait" << std::endl;
03850     nanosleep(&ts_tped, 0);
03851     std::cout << get_timestamp() << " +++1b after  tped  wait" << std::endl;
03852 
03853     // switch back to data taking mode
03854     autoped_issue_system_message(roc::SYSMSG_USER_RECONFIGURE);
03855     rc = gGpio->setConfig(gpio_mask_off);
03856     print_opererr("Gpio::setConfig{ped_off}", rc);
03857     autoped_setnxmode(false);
03858     autoped_issue_system_message(roc::SYSMSG_USER_CALIBR_OFF);
03859 
03860     // do data taking
03861     if (!gUtil->testLoop()) break;
03862     std::cout << get_timestamp() << " +++1c before tmeas wait" << std::endl;
03863     nanosleep(&ts_tmeas, 0);
03864     std::cout << get_timestamp() << " +++1d after  tmeas wait" << std::endl;
03865     if (!gUtil->testLoop()) break;
03866   }
03867 
03868   rc = gGpio->setConfig(gpio_mask_save);
03869   print_opererr("Gpio::setConfig{restore}", rc);
03870 
03871   // stop test pulse generator
03872   rc = gRocNx->fireTestPulse(0, 0, 0);
03873   print_opererr("RocNx::fireTestPulse", rc);
03874 
03875   return 0;
03876 }
03877 
03878 //----------------------------------------------------------------------------
03879 int cmd_testnxdata()
03880 {
03881   std::cout << "currently deactivated" << std::endl;
03882 
03883 #ifdef never  
03884   bool opt_p = get_opt("-p");
03885   bool opt_r = get_opt("-r");
03886   bool opt_s = get_opt("-s");
03887   double time=10.;
03888   if (get_arg(time, "time=")) return 1;
03889   if (args_check(kNeedFeb|kNeedDaq)) return 1;
03890 
03891   int rc;
03892   rc = gFeb->setToDefault();
03893   if (print_opererr("FebBase::setToDefault", rc)) return 0;
03894 
03895   for (int i=0; i<16; i++) {
03896     rc = gFeb->setNxRegisterAll(i,0xff);
03897     if (print_opererr("FebBase::setNxRegisterAll", rc)) return 0;
03898   }
03899 
03900   rc = gFeb->setNxRegisterAll(1,0xf0);
03901   if (print_opererr("FebBase::setNxRegisterAll", rc)) return 0;
03902 
03903   rc = gFeb->setNxTestModes(false, true, 0); // use test trigger mode
03904   if (print_opererr("FebBase::setNxTestModes", rc)) return 0;
03905 
03906   nxyter::QuickDaq qd(gRocBoard, gFeb);
03907 
03908   qd.startRun(0, time);
03909 
03910   rc = gRocNx->fireTestPulse(100000, 50000, 0); // use 2.5 kHz pulse rate
03911   print_opererr("RocNx::fireTestPulse", rc);
03912 
03913   gUtil->startLoop(time+2.);
03914 
03915   double npulslast = -1.;
03916   int nhit         =  4;
03917   double tsbase    = -1.;
03918 
03919   int numnx = gFeb->numNx();
03920 
03921   // FIXME, logic now different !!
03922   nxyter::Data data;
03923   while(gUtil->testLoop()) {
03924     int rc = qd.getData(data);              // get data
03925     if (rc) break;                          // if end-of-run quit
03926     if (msg.isNopMsg()) continue;          //  if nop ignore
03927     if (opt_p) msg.printData(std::cout, opt_r ? 3 : 8, qd.getEpoch());
03928     if (msg.isHitMsg()) {
03929       int nxnum = msg.getNxNumber();
03930       int nxchn = msg.getNxChNum();
03931       double ts = msg.getMsgFullTime(qd.getEpoch())*1.e-9;
03932       if (tsbase < 0.) tsbase = ts;
03933 
03934       double npuls = floor((2500. * (ts - tsbase)) + 0.5);
03935       double tsoffset = ts - (tsbase + npuls/2500.);
03936 
03937       if (opt_p) {
03938         static boost::format fmt("Nx:%|1| Chn:%|3| puls: %|6.0f| offset:%|3.0f|");
03939         std::cout << fmt % nxnum % nxchn % npuls % (1.e9*tsoffset) << std::endl;
03940       }
03941 
03942       if (npuls != npulslast) {
03943         if (tsoffset < -4.e-9 || tsoffset > +4.e-9) {
03944           std::cout << "outlayer hit, offset " << int(1.e9*tsoffset) 
03945                << "ns" << std::endl;
03946           msg.printData(std::cout, opt_r ? 3 : 8, qd.getEpoch());
03947         }
03948         if (nhit != 4*numnx) {
03949           std::cout << "last pulse has != 4*numnx hits, nhit = " << nhit << std::endl;
03950         }
03951         if (npuls != npulslast + 1.) {
03952           std::cout << "pulses missing, now " << int(npuls)
03953                << " last was " << int(npulslast) << std::endl;
03954         }
03955         nhit = 0;
03956         npulslast = npuls;
03957       }
03958 
03959       nhit += 1;
03960 
03961     }
03962   }
03963   
03964   if (opt_s) qd.getStats().print(std::cout);
03965   // show errors in case not -s !!
03966 
03967   rc = gRocNx->fireTestPulse(0, 0, 0);          // stop pulser
03968   print_opererr("RocNx::fireTestPulse", rc);
03969 #endif
03970 
03971   return 0;
03972 }
03973 
03974 //----------------------------------------------------------------------------
03975 
03976 int cmd_saverocconf()
03977 {
03978   if (args_check(kNeedRocBoard)) return 1;
03979 
03980   roc::UdpBoard* udp = dynamic_cast<roc::UdpBoard*> (gRocBoard);
03981   if (udp) {
03982     udp->saveConfig();
03983   } else {
03984     std::cout << "rocutil-E: only supported for 'ROC-over-Ethernet'" << std::endl;
03985   }
03986   
03987   return 0;
03988 }
03989 
03990 //----------------------------------------------------------------------------
03991 
03992 int cmd_restartbrd()
03993 {
03994   if (args_check(kNeedBoard)) return 1;
03995 
03996   std::cout << "rocutil-I: Board self-destruct initiated, have a nice day :)" << std::endl;
03997   gBaseBoard->restartBoard();
03998   std::cout << "rocutil-I: restart rocutil when board back on-line" << std::endl;
03999   std::cout << "rocutil-I: use 'setbrddef' command to initialize board" << std::endl;
04000 
04001   return -2;
04002 }
04003 
04004 //----------------------------------------------------------------------------
04005 
04006 int cmd_printrocmap()
04007 {
04008    bool byname = get_opt("-n");
04009    if (args_check(kNeedBoard)) return 1;
04010    gBaseBoard->printRegAddressMap(std::cout, byname);
04011    return 0;
04012 }
04013 
04014 
04015 //----------------------------------------------------------------------------
04016 
04017 int cmd_putroc()
04018 {
04019   std::string sname;
04020   int32_t val;
04021   if (get_arg(sname, 0)) return 1;
04022   if (get_arg(val, 0)) return 1;
04023   if (args_check(kNeedBoard)) return 1;
04024 
04025   uint32_t addr = gBaseBoard->findRegAddressByName(sname.c_str());
04026 
04027   if (addr==base::Board::kAddrError) {
04028      const char* cstr = sname.c_str();
04029      char* eptr(0);
04030      int base(0);
04031 
04032      if (cstr[0]=='b' || cstr[0]=='B') { cstr += 1; base = 2; }
04033      addr = strtol(cstr, &eptr, base);
04034      if (errno || (eptr && (*eptr!=0))) {
04035         std::cout << "Board address '" << sname << "' not known" << std::endl;
04036         return 0;
04037      }
04038   }
04039 
04040   uint32_t value = uint32_t(val);
04041   int rc = gBaseBoard->put(addr, value);
04042   print_opererr("Board::put", rc);
04043   if (rc==0) {
04044      static boost::format fmt("put(%s [0x%08x]) -> 0x%08x  %10d");
04045      std::cout << fmt % sname % addr % value % value << std::endl;
04046   }
04047   return 0;
04048 }
04049 
04050 //----------------------------------------------------------------------------
04051 
04052 int cmd_getroc()
04053 {
04054   std::string sname;
04055   if (get_arg(sname, 0)) return 1;
04056   if (args_check(kNeedBoard)) return 1;
04057 
04058   uint32_t addr = gBaseBoard->findRegAddressByName(sname.c_str());
04059   if (addr==base::Board::kAddrError) {
04060      const char* cstr = sname.c_str();
04061      char* eptr(0);
04062      int base(0);
04063 
04064      if (cstr[0]=='b' || cstr[0]=='B') { cstr += 1; base = 2; }
04065      addr = strtol(cstr, &eptr, base);
04066      if (errno || (eptr && (*eptr!=0))) {
04067         std::cout << "Board address '" << sname << "' not known" << std::endl;
04068         return 0;
04069      }
04070   }
04071 
04072   uint32_t value;
04073   int rc = gBaseBoard->get(addr, value);
04074   if (rc==0) {
04075     static boost::format fmt("get(%s [0x%08x]) -> 0x%08x %10d");
04076     std::cout << fmt % sname % addr % value % value  << std::endl;
04077   }
04078   print_opererr("Board::get", rc);
04079   return 0;
04080 }
04081 
04082 //----------------------------------------------------------------------------
04083 
04084 int cmd_resetrocnxts()
04085 {
04086    if (gRocNx==0) return 1;
04087    int rc = gRocNx->resetRocNxTs();
04088    print_opererr("RocNx::resetRocNxTs", rc);
04089    return 0;
04090 }
04091 
04092 
04093 //----------------------------------------------------------------------------
04094 
04095 int cmd_printdatadbg()
04096 {
04097   bool    opt_c  = get_opt("-c");
04098   bool    opt_ib = get_opt("-ib");
04099   bool    opt_ia = get_opt("-ia");
04100   int32_t nmsg=100;
04101   double  time=1.;
04102   if (get_arg(nmsg, "nmsg=", 1)) return 1;
04103   if (get_arg(time, "time=")) return 1;
04104   if (args_check(kNeedDaq)) return 1;
04105 
04106   std::vector<nxyter::DataDebug> datvec;
04107 
04108   int rc = gRocNx->setDebugMode(1);
04109   print_opererr("RocNx::setDebugMode", rc);
04110 
04111   gUtil->startLoop(time);
04112   int nempty = 0;
04113 
04114   if (opt_ib) {
04115     rc = gRocNx->resetRocNxTs();
04116     print_opererr("RocNx::resetRocNxTs", rc);
04117   }
04118 
04119   if (opt_c)  gRocBoard->clearRocFifo();
04120 
04121   if (opt_ia) {
04122     rc = gRocNx->resetRocNxTs();
04123     print_opererr("RocNx::resetRocNxTs", rc);
04124   }
04125   
04126   std::cout << "getDataDebug(): ";
04127   while(gUtil->testLoop() && datvec.size() < nmsg) {
04128     rc = gRocNx->getDataDebug(datvec, nmsg-datvec.size());
04129     if (rc < 0) {
04130       std::cout << "getDataDebug(): bail-out with rc=" << rc << std::endl;
04131       break;
04132     }
04133     if (rc >0) {
04134       if (nempty > 0) std::cout << "(" << nempty << ") ";
04135       std::cout << rc << " ";
04136       nempty = 0;
04137     } else {
04138       nempty += 1;
04139     }
04140   }
04141   std::cout << std::endl;
04142 
04143   rc = gRocNx->setDebugMode(0);
04144   print_opererr("RocNx::setDebugMode", rc);
04145 
04146   for (int i=0; i<datvec.size(); i++) {
04147     datvec[i].print(std::cout);
04148   }
04149 
04150   return 0;
04151 }
04152 
04153 
04154 void acquire_data( int nxind, std::vector<std::vector<float> > & data, float time )
04155 {
04156         if( data.size() != 128 ) {
04157                 printf("Error in acquire_data: data must be vector[128][4096] of floats\n");
04158                 return;
04159         }
04160         for( int iChannel = 0; iChannel < 128; iChannel++ ) {
04161                 if( data.at(iChannel).size() != 4096 ) {
04162                         printf("Error in acquire_data: data must be vector[128][4096] of floats\n");
04163                         return;
04164                 }
04165                 data.at(iChannel).assign( 4096, 0. );
04166         }
04167 
04168         gQdaq->startRun( 0, time, true );
04169 
04170         while( gQdaq->testRun() ) {
04171                 roc::Message & msg = gQdaq->msg();
04172 
04173                 if( msg.isHitMsg() ) {
04174                         int num = msg.getNxNumber();
04175                         if (num != nxind) {
04176                                 printf("Error in acquire_data: hit from nXYTER %d received, while not expected\n", num);
04177                         }
04178                         uint8_t ch = msg.getNxChNum();
04179                         uint16_t adcVal = msg.getNxAdcValue();
04180                         data.at(ch).at(adcVal)++;
04181                 }
04182         }
04183         if (gQdaq->stats().errorCount()) {
04184                 gQdaq->stats().print(std::cout, 0., nxyter::QuickDaqStats::kPrintError);
04185         }
04186 }
04187 
04188 //----------------------------------------------------------------------------
04189 void acquire_data(int nxind, std::vector<int> & nhits, float time)
04190 {
04191         if( nhits.size() != 128 ) {
04192                 printf("Error in count_pulses: npulses is expected to be 128 in size\n");
04193                 return;
04194         }
04195         nhits.assign( 128, 0 );
04196 
04197         gQdaq->startRun( 0, time, true );
04198 
04199         while( gQdaq->testRun() ) {
04200                 roc::Message & msg = gQdaq->msg();
04201 
04202                 if( msg.isHitMsg() ) {
04203                         int num = msg.getNxNumber();
04204                         if (num != nxind) {
04205                                 printf("Error in acquire_data: hit from nXYTER %d received, while not expected\n", num);
04206                         }
04207                         int ch = msg.getNxChNum();
04208                         nhits.at(ch)++;
04209                 }
04210         }
04211         if (gQdaq->stats().errorCount()) {
04212                 gQdaq->stats().print(std::cout, 0., nxyter::QuickDaqStats::kPrintError);
04213         }
04214 }
04215 
04216 
04217 void autotrim_print_rates(const std::vector<int> & npulses, double time )
04218 {
04219         printf("    -- -- -- -- -- -- -- -- -- -- -- Rates per channel -- -- -- -- -- -- -- -- -- -- --\n");
04220         for( int i=0; i < 16; i++ ) {
04221                 printf("     %3d..%-3d:", i*8, i*8 + 7);
04222                 for( int j=0; j < 8; j++ ) {
04223                         printf( "%9.1f", static_cast<float>( npulses.at(i*8 + j) ) / time );
04224                 }
04225                 printf("\n");
04226         }
04227         printf("    -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --\n");
04228 }
04229 
04230 void autotrim_print_trim(const nxyter::NxContext & cntx_trim)
04231 {
04232         printf("    -- -- -- -- -- -- -- -- -- -- -- -- Trim values -- -- -- -- -- -- -- -- -- -- -- --\n");
04233         for( int i = 0; i < 16; i++ ) {
04234                 printf("     %3d..%-3d:", i*8, i*8 + 7);
04235                 for( int j = 0; j < 8; j++ ) {
04236                         int ch = i * 8 + j;
04237                         printf("%9d", cntx_trim.getThresholdTrim(ch));
04238                 }
04239                 printf("\n");
04240         }
04241         printf("    -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --\n");
04242 }
04243 
04244 void autotrim_print_trim_dbg(const nxyter::NxContext & cntx_trim, const std::vector<int> & trim_min, const std::vector<int> & trim_max )
04245 {
04246         printf("    -- -- -- -- -- -- -- -- -- -- -- -- Trim values -- -- -- -- -- -- -- -- -- -- -- --\n");
04247         for( int i = 0; i < 16; i++ ) {
04248                 printf("     %3d..%-3d:", i*8, i*8 + 7);
04249                 for( int j = 0; j < 8; j++ ) {
04250                         int ch = i * 8 + j;
04251                         printf("%2d(%2d-%2d)", cntx_trim.getThresholdTrim(ch), trim_min.at(ch), trim_max.at(ch));
04252                 }
04253                 printf("\n");
04254         }
04255         printf("    -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --\n");
04256 }
04257 
04258 float get_npuls_avg( const std::vector< int > & npuls, int nchactive )
04259 {
04260         int npuls_tot = 0;
04261         for( int ch = 0; ch < npuls.size(); ch++ ) {
04262                 npuls_tot += npuls[ch];
04263         }
04264         return static_cast<float>( npuls_tot ) / nchactive;
04265 }
04266 
04267 
04268 
04269 
04270 //----------------------------------------------------------------------------
04271 int cmd_autotrim()
04272 {
04273         const int knch = 128; // nXYTER number of channels
04274         int gainsign_vth = 1; // 1, if physical threshold increase with the vth register value, -1 otherwise
04275         int gainsign_trim = -1; // 1, if physical threshold increase with the trim register value, -1 otherwise
04276         bool posgain_vth = true;
04277         bool posgain_trim = false;
04278 
04279         // *** process arguments and prerequisites ***:
04280         bool opt_k = get_opt("-k");
04281         bool opt_m = get_opt("-m");
04282         bool opt_q = get_opt("-q");
04283         bool opt_t = get_opt("-t");
04284 
04285 
04286         int32_t nxbeg=0;
04287         int32_t nxend=0;
04288         if (get_nxrange(nxbeg, nxend)) return 1;
04289 
04290         double rate;
04291         if (get_arg(rate)) return 1;
04292 
04293         double time = 4;
04294         if (get_arg(time,"time=")) return 1;
04295         if( time < 0. ) {
04296                 printf("ERROR in cmd_autotrim: time must be larger than 0.\n");
04297                 return 1;
04298         }
04299 
04300         int32_t vth_range_min = 20;
04301         if (get_arg(vth_range_min, "vth_min=", 0, 255)) return 1;
04302 
04303         int32_t vth_range_max = 255;
04304         if (get_arg(vth_range_max, "vth_max=", 1, 255)) return 1;
04305         if( vth_range_max < vth_range_min ) {
04306                 printf("ERROR in cmd_autotrim: vth_max must be larger than vth_min\n");
04307                 return 1;
04308         }
04309 
04310         double target = 0.5;
04311         if (get_arg(target, "target=")) return 1;
04312         if( target < 0. || target > 1.) {
04313                 printf("ERROR in cmd_autotrim: target must be within ( 0. ; 1. ) range \n");
04314                 return 1;
04315         }
04316 
04317         if (args_check(kNeedFeb|kNeedDaq)) return 1;
04318 
04319         //      printf("nxbeg=%d nxend=%d\n",nxbeg,nxend);
04320         //      printf("rate=%lf\n",rate);
04321         //      printf("time=%lf\n",time);
04322         //      printf("vth_min=%d vth_max=%d\n",vth_min, vth_max);
04323         //      printf("target=%lf\n",target);
04324         //      printf("arguments processed successfully\n");
04325         //      return 0;
04326 
04327         for( int nxind = nxbeg; nxind <= nxend; nxind++ ) {
04328 
04329                 // *** remember initial value of vth ***
04330                 int rc;
04331                 uint8_t vth_init;
04332                 rc = gFeb->nx(nxind).i2c().getRegister(nxyter::kNxRegVth, vth_init);
04333                 print_opererr("getRegister(kNxRegVth,...)", rc);
04334 
04335                 // *** get list of masked channels ***
04336                 nxyter::NxContext mask_cntx;
04337                 rc = gFeb->nx(nxind).i2c().getContext(mask_cntx, nxyter::kDoMask);
04338 
04339                 // *** get number of active channels ***
04340                 int nchactive = 0;
04341                 for( int ch = 0; ch < knch; ch++ ) {
04342                         nchactive += ( ! mask_cntx.getChannelMaskBit(ch) );
04343                 }
04344 
04345                 // *** read trim values ***
04346                 nxyter::NxContext cntx_trim;
04347                 rc = gFeb->nx(nxind).i2c().getContext(cntx_trim, nxyter::kDoTrim);
04348                 print_opererr("GetContext(cntx_trim,...)", rc);
04349 
04350                 std::vector< int > npuls( knch );
04351                 float npuls_exp = rate * time;
04352                 if( opt_m ) {
04353                         if( ! opt_q ) printf("Measuring efficiency at vth=%d, and with trim values:\n", vth_init);
04354                         if( ! opt_q ) autotrim_print_trim(cntx_trim);
04355                         acquire_data( nxind, npuls, time );
04356                         if( ! opt_q ) autotrim_print_rates( npuls, time );
04357                         if( ! opt_q ) printf( "Average efficiency: %f\n", get_npuls_avg( npuls, nchactive ) / npuls_exp );
04358                         return 0;
04359                 }
04360 
04361                 // *** reset trim values ***
04362                 if( ! opt_q ) printf("Setting trim to 16 in all channels...\n");
04363                 nxyter::NxContext cntx_trim_reset;
04364                 cntx_trim_reset.setThresholdTrim(0, knch - 1, 16, 1);
04365                 rc = gFeb->nx(nxind).i2c().setContext(cntx_trim_reset, nxyter::kDoTrim);
04366                 print_opererr("SetContext(cntx_trim_reset,...)", rc);
04367 
04368                 if( ! opt_t ) {
04369                         // *** adjust vth to 50% detection efficiency in average within the chip ***
04370                         if( ! opt_q ) printf("Start adjusting vth to average detection efficiency of %f\n", target);
04371 
04372                         uint8_t vth_step = 0;
04373                         int vth_step_prev_signed = 0;
04374                         uint8_t vth_curr = vth_init;
04375                         uint8_t vth_prev = 0;
04376 
04377                         {
04378                                 bool first = true;
04379                                 float eff_curr = 0;
04380                                 float eff_prev = 0;
04381                                 float diff_curr = 0;
04382                                 float diff_prev = 0;
04383                                 int vth_step_sign = 0;
04384                                 while( true ) {
04385 
04386                                         // *** remember previous results ***
04387                                         if( ! first ) {
04388                                                 eff_prev = eff_curr;
04389                                                 diff_prev = diff_curr;
04390                                         }
04391                                         // *** remember the previous step ***
04392                                         vth_step_prev_signed = vth_step * vth_step_sign;
04393 
04394                                         // *** measure the rate ***
04395                                         if( ! opt_q ) printf("Measuring efficiency at vth=%d...\n", vth_curr);
04396                                         acquire_data( nxind, npuls, time );
04397                                         if( ! opt_q ) autotrim_print_rates( npuls, time );
04398                                         eff_curr = get_npuls_avg( npuls, nchactive ) / npuls_exp;
04399                                         if( ! opt_q ) printf( "Average efficiency: %f\n", eff_curr );
04400                                         diff_curr = std::abs( target - eff_curr );
04401 
04402                                         // *** check if the efficiency changes in the expected direction ***
04403                                         if( ! first ) {
04404                                                 if( ( eff_prev > eff_curr) != ( (vth_step_sign > 0) == posgain_vth )  ) {
04405                                                         printf("WARNING: detection efficiency changes in the same direction as physical threshold -- system is not stable. Try to increase the measurement time?\n");
04406                                                 }
04407                                         }
04408 
04409                                         // *** evaluate the sign of the next vth step ***
04410                                         if( ( eff_curr > target) == posgain_vth ) {
04411                                                 vth_step_sign = 1; }
04412                                         else {
04413                                                 vth_step_sign = -1;
04414                                         }
04415 
04416                                         // *** evaluate the magnitude of the next vth step ***
04417                                         if( first ) {
04418                                                 if( vth_step_sign > 0 ) {
04419                                                         vth_step = vth_range_max - vth_curr;
04420                                                 }
04421                                                 else {
04422                                                         vth_step = vth_curr - vth_range_min;
04423                                                 }
04424                                         }
04425                                         vth_step = vth_step / 2 + vth_step % 2;
04426 
04427                                         // *** check if the step is within the vth range ***
04428                                         int vth_prelim =  vth_curr + vth_step * vth_step_sign;
04429                                         if( vth_prelim > vth_range_max || vth_prelim < vth_range_min ) {
04430                                                 printf("ERROR: target efficiency can not be reached with vth within the specified range\n");
04431                                                 return 1;
04432                                         }
04433 
04434                                         // *** check if converged ***
04435                                         if( ! first ) {
04436                                                 if( vth_step == 1 && vth_step_sign == - vth_step_prev_signed ) {
04437                                                         if( diff_prev < diff_curr ) {
04438                                                                 vth_curr = vth_prev;
04439                                                                 rc = gFeb->nx(nxind).i2c().setRegister(nxyter::kNxRegVth, vth_curr, true);
04440                                                                 print_opererr("setRegister(kNxRegVth,...)", rc);
04441                                                         }
04442                                                         break;
04443                                                 }
04444                                         }
04445 
04446                                         // *** make the step in vth ***
04447                                         vth_prev = vth_curr;
04448                                         vth_curr = vth_curr + vth_step * vth_step_sign;
04449                                         rc = gFeb->nx(nxind).i2c().setRegister(nxyter::kNxRegVth, vth_curr, true);
04450                                         print_opererr("setRegister(kNxRegVth,...)", rc);
04451 
04452                                         first = false;
04453                                 }
04454                                 if( ! opt_q ) printf("Finished with vth=%d\n", vth_curr);
04455                         }
04456                 }
04457 
04458                 // *** adjust threshold trim ***
04459                 if( ! opt_q ) printf("Start trimming the thresholds\n");
04460 
04461                 std::vector<int> trim_step(128, 16);
04462                 std::vector<int> trim_step_sign(128, 0);
04463                 std::vector<int> trim_step_prev_signed(128, 0);
04464                 std::vector<float> eff_curr(128, 0);
04465                 std::vector<float> eff_prev(128, 0);
04466                 std::vector<float> diff_curr(128, 0);
04467                 std::vector<float> diff_prev(128, 0);
04468 
04469                 bool first = true;
04470 
04471                 nxyter::NxContext cntx_trim_prev( cntx_trim );
04472 
04473                 while( 1 ) {
04474 
04475                         // *** evaluate the detection efficiencies ***
04476                         for( int ch = 0; ch < knch; ch++ ) {
04477                                 if( ! mask_cntx.getChannelMaskBit(ch) ) {
04478                                         eff_prev.at(ch) = eff_curr.at(ch);
04479                                         eff_curr.at(ch) = npuls.at(ch) / npuls_exp;
04480                                         diff_prev.at(ch) = diff_curr.at(ch);
04481                                         diff_curr.at(ch) = std::abs( target - eff_curr.at(ch) );
04482                                 }
04483                         }
04484 
04485                         // *** remember the previous trim step ***
04486                         for( int ch = 0; ch < knch; ch++ ) {
04487                                 if( ! mask_cntx.getChannelMaskBit(ch) ) {
04488                                         trim_step_prev_signed.at(ch) = trim_step.at(ch) * trim_step_sign.at(ch);
04489                                 }
04490                         }
04491 
04492                         // *** check if the rate changes in the expected direction ***
04493                         for( int ch = 0; ch < knch; ch++ ) {
04494                                 if( ! mask_cntx.getChannelMaskBit(ch) ) {
04495                                         if( trim_step_prev_signed.at(ch) != 0 ) {
04496                                                 if( ( eff_curr.at(ch) < eff_prev.at(ch) ) != ( ( trim_step_prev_signed.at(ch) > 0 ) == posgain_trim ) ) {
04497                                                         printf("WARNING: In channel %d detection efficiency changes in the same direction as physical threshold -- system is not stable. Try to increase the measurement time?\n", ch);
04498                                                 }
04499                                         }
04500                                 }
04501                         }
04502 
04503                         // *** evaluate the sign of the next trim step ***
04504                         for( int ch = 0; ch < knch; ch++ ) {
04505                                 if( ! mask_cntx.getChannelMaskBit(ch) ) {
04506                                         if( ( eff_curr.at(ch) > target ) == posgain_trim ) {
04507                                                 trim_step_sign.at(ch) = 1;
04508                                         }
04509                                         else {
04510                                                 trim_step_sign.at(ch) = -1;
04511                                         }
04512                                         // printf("Ch=%d, trim_step_sign=%d\n", ch, trim_step_sign.at(ch) );
04513                                 }
04514                         }
04515 
04516                         // *** evaluate the trim step magnitude ***
04517                         for( int ch = 0; ch < knch; ch++ ) {
04518                                 if( ! mask_cntx.getChannelMaskBit(ch) ) {
04519                                         trim_step.at(ch) = trim_step.at(ch) / 2 + trim_step.at(ch) % 2;
04520                                         int prelim_new_trim = cntx_trim.getThresholdTrim(ch) + trim_step_sign.at(ch) * trim_step.at(ch);
04521                                         if( prelim_new_trim > 31 ) {
04522                                                 trim_step.at(ch) -= prelim_new_trim - 31;
04523                                         }
04524                                         if( prelim_new_trim < 0 ) {
04525                                                 trim_step.at(ch) -= 0 - prelim_new_trim;
04526                                         }
04527                                 }
04528                         }
04529 
04530                         // *** check if converged ***
04531                         if( ! first ) {
04532                                 bool all_ch_converge = true;
04533                                 nxyter::NxContext cntx_trim_converge(cntx_trim);
04534                                 for( int ch = 0; ch < knch; ch++ ) {
04535                                         if( ! mask_cntx.getChannelMaskBit(ch) ) {
04536                                                 if( trim_step.at(ch) == 0 || ( trim_step.at(ch) == 1 && trim_step_sign.at(ch) == - trim_step_prev_signed.at(ch) ) ) {
04537                                                         if( diff_prev.at(ch) < diff_curr.at(ch) ) {
04538                                                                 cntx_trim_converge.setThresholdTrim( ch, static_cast<uint8_t>( cntx_trim.getThresholdTrim(ch) - trim_step_prev_signed.at(ch) ) );
04539                                                         }
04540                                                 }
04541                                                 else {
04542                                                         all_ch_converge = false;
04543                                                 }
04544 
04545                                         }
04546                                 }
04547                                 if( all_ch_converge ) {
04548                                         for( int ch = 0; ch < knch; ch++ ) {
04549                                                 if( ! mask_cntx.getChannelMaskBit(ch) ) {
04550                                                         cntx_trim.setThresholdTrim( ch, cntx_trim_converge.getThresholdTrim(ch) );
04551                                                 }
04552                                         }
04553                                         rc = gFeb->nx(nxind).i2c().setContext(cntx_trim, nxyter::kDoTrim);
04554                                         print_opererr("SetContext(cntx_trim,...)", rc);
04555                                         break;
04556                                 }
04557                         }
04558 
04559                         // *** apply new trim ***
04560                         for( int ch = 0; ch < knch; ch++ ) {
04561                                 if( ! mask_cntx.getChannelMaskBit(ch) ) {
04562                                         cntx_trim_prev.setThresholdTrim( ch, cntx_trim.getThresholdTrim(ch) );
04563                                         cntx_trim.setThresholdTrim(ch, cntx_trim.getThresholdTrim(ch) + trim_step.at(ch) * trim_step_sign.at(ch) );
04564                                 }
04565                         }
04566 
04567 
04568                         // *** measure with new trim values ***
04569                         rc = gFeb->nx(nxind).i2c().setContext(cntx_trim, nxyter::kDoTrim);
04570                         print_opererr("SetContext(cntx_trim_reset,...)", rc);
04571                         if( ! opt_q ) printf("Measuring with trim values:\n");
04572                         if( ! opt_q ) autotrim_print_trim(cntx_trim);
04573                         // if( ! opt_q ) autotrim_print_trim_dbg(cntx_trim, trim_min, trim_max);
04574                         acquire_data( nxind, npuls, time );
04575                         if( ! opt_q ) printf("Resulting rates:\n");
04576                         if( ! opt_q ) autotrim_print_rates( npuls, time );
04577 
04578                         first = false;
04579                 }
04580 
04581                 printf("Finished with trim values:\n");
04582                 autotrim_print_trim(cntx_trim);
04583 
04584                 return 0;
04585 
04586                 // *** set vth to the initial value ***
04587                 if( ! opt_k ) {
04588                         rc = gFeb->nx(nxind).i2c().setRegister(nxyter::kNxRegVth, vth_init, true);
04589                         print_opererr("setRegister(kNxRegVth,...)", rc);
04590                 }
04591 
04592         }
04593         return 0;
04594 
04595 }
04596 
04597 float get_mean( std::vector< float > const & vect )
04598 {
04599         double sum = 0;
04600         double ncnt = 0;
04601         for( int ch = 0; ch < vect.size(); ch++ ) {
04602                 sum += ch * vect.at(ch);
04603                 ncnt += vect.at(ch);
04604         }
04605         return sum / ncnt;
04606 }
04607 
04608 int cmd_idsigch()
04609 {
04610         int32_t nxbeg=0;
04611         int32_t nxend=0;
04612         int32_t npuls=2000;
04613         if (get_nxrange(nxbeg, nxend)) return 1;
04614         float time=4.;
04615         float amp_min = 100.;
04616         if (args_check(kNeedFeb|kNeedDaq)) return 1;
04617 
04618         int rc;
04619         nxyter::NxContext save_cntx;
04620 
04621         gUtil->startLoop(0.);
04622         for (int nxind=nxbeg; nxind<=nxend; nxind++) {
04623                 if (!gUtil->testLoop()) break;
04624                 gFeb->printNxHeadLine(std::cout, nxind);
04625                 if (check_nxoffline(nxind, nxbeg, nxend)) continue; // skip of offline
04626 
04627                 rc = gFeb->nx(nxind).i2c().getContext(save_cntx, nxyter::kDoCore);
04628                 print_opererr("NxI2c::getContext {save}", rc);
04629 
04630                 rc = gFeb->nx(nxind).i2c().setTestModes(false, true, 0);
04631                 print_opererr("NxI2c::setTestModes", rc);
04632 
04633                 int vb_beg =   0;
04634                 int vb_end = 255;
04635                 int vb_mid;
04636                 float med_beg;
04637                 float med_end;
04638                 float med_mid;
04639                 bool nxabort = false;
04640 
04641                 nxyter::DistFuncArray dfa_bl(128, npuls);
04642                 dfa_bl.setMaxEntries(2*npuls);
04643                 int rc = gUtil->acquireTestTriggerData(nxind, npuls, dfa_bl);
04644                 nxyter::NxDataSummary nds_bl;
04645                 nds_bl.analyse(dfa_bl);
04646 
04647                 rc = gFeb->nx(nxind).i2c().setTestModes(false, false, 0);
04648                 print_opererr("NxI2c::setTestModes", rc);
04649 
04650                 std::vector< std::vector<float> > data;
04651                 data.resize(128);
04652                 for( int ch = 0; ch < 128; ch++ )  {
04653                         data.at( ch ).resize( 4096 );
04654                 }
04655                 acquire_data(nxind, data, time );
04656 
04657                 for( int ch = 0; ch < 128; ch++) {
04658                         float bl = nds_bl.getMedian(ch);
04659                         float mean = get_mean( data.at(ch) ); //->GetMean();
04660                         //float sigma = data.at(ch)->GetRMS();
04661                         float amp = bl - mean;
04662                         if( amp > amp_min ) {
04663                                 printf("In idsigch: detected signal in channel %d, amp = %f\n", ch, amp );
04664                         }
04665                 }
04666         }
04667 
04668         return 0;
04669 }
04670 
04671 //----------------------------------------------------------------------------
04672 //++ command dispatcher, ^C interrupt handler and the main program +++++++++++
04673 
04674 int process_command(const std::string& line, int level)
04675 {
04676   gIntCount = 0;                            // reset interrupt watch
04677 
04678   std::string cmdline(line);
04679 
04680   size_t  pos_delcomment = 0;
04681 
04682   // trim everything beyond a '//' in the line
04683   while (pos_delcomment < cmdline.length()) {
04684      pos_delcomment = cmdline.find("//", pos_delcomment);
04685 
04686      if (pos_delcomment == std::string::npos) break;
04687 
04688      // but do not destroy url
04689      if ((pos_delcomment>0) && (cmdline[pos_delcomment-1]==':')) { pos_delcomment+=2;  continue; }
04690 
04691      cmdline.erase(pos_delcomment);
04692 
04693      break;
04694   }
04695 
04696 
04697   trim_whitespace(cmdline);
04698   if (cmdline.size() == 0) return 0;
04699 
04700   // if cmdline starts with '/*', print the line and quit
04701   if (cmdline.find("/*") == 0) {
04702     std::cout << cmdline << std::endl;
04703     return 0;
04704   }
04705   
04706   // if cmdline starts with '@' take it as command file name
04707   // in this case open the file and process the commands
04708   if (cmdline.find("@") == 0) {
04709     cmdline.erase(0,1);
04710     std::ifstream cmdfile;
04711     cmdfile.open(cmdline.c_str(), std::ifstream::in);
04712     if (cmdfile.fail()) {
04713       std::cerr << "rocutil-E: Failed to open file '" << cmdline << "'" << std::endl;
04714       return 1;
04715     }
04716 
04717     
04718     for (int i=0; i<std::max(int(0),level+1); i++) std::cout << ">";
04719     std::cout << " (open) @" << cmdline << std::endl;
04720 
04721     while (cmdfile.good()) {
04722       std::string line;
04723       std::getline(cmdfile, line);
04724       if (line.size()) {
04725         int rc = process_command(line, std::max(int(0),level) + 1);
04726         if (rc > 0) std::cerr << "rocutil-E: Aborting command file '" 
04727                          << cmdline << "'" << std::endl;
04728         if (rc) return rc;
04729       }
04730     }
04731 
04732     for (int i=0; i<level+1; i++) std::cout << ">";
04733     std::cout << " (close) @" << cmdline << std::endl;
04734 
04735     return 0;
04736   }
04737 
04738   if (level > 0) {
04739     for (int i=0; i<level; i++) std::cout << ">";
04740     std::cout << " " << cmdline << std::endl;
04741   }
04742 
04743   // replace all tabs by a blank
04744   for (size_t i=0; i<cmdline.size(); i++) {
04745     if (cmdline[i] == '\t') cmdline[i] = ' ';
04746   }
04747 
04748   // if '=' found before ' ', replace it with a ' '
04749   size_t pos_deleq = cmdline.find("=");
04750   size_t pos_delsp = cmdline.find(" ");
04751   if (pos_deleq != std::string::npos && pos_deleq < pos_delsp) {
04752     cmdline[pos_deleq] = ' ';
04753   }
04754   
04755   // now split cmdline into the command (before ' ') and argument list
04756   pos_delsp = cmdline.find(" ");
04757   std::string cmd;
04758   std::string args;
04759 
04760   if (pos_delsp != std::string::npos) {
04761     cmd  = cmdline.substr(0,pos_delsp);
04762     args = cmdline.substr(pos_delsp+1);
04763   } else {
04764     cmd  = cmdline;
04765   }
04766 
04767   // now split the ' ' or ',' separated argument list 
04768 
04769   argspos.clear();
04770   argsopt.clear();
04771 
04772   trim_whitespace(args);
04773 
04774   while(args.size()) {
04775     std::string curarg;
04776     size_t pos_del = args.find_first_of(" ,");
04777     if (pos_del != std::string::npos) {
04778       curarg = args.substr(0,pos_del);
04779       args.erase(0,pos_del+1);
04780       trim_whitespace(args);
04781     } else {
04782       curarg = args;
04783       args.clear();
04784     }
04785 
04786     bool isopt = false;
04787     if ((curarg.size()>=2) && (curarg[0]=='-') && isalpha(curarg[1])) {
04788       isopt = true;
04789     } else if (curarg.find("=") !=  std::string::npos) {
04790       isopt = true;
04791     }
04792 
04793     if (isopt) {
04794       argsopt.push_back(curarg);
04795     } else {
04796       argspos.push_back(curarg);
04797     }
04798   }
04799 
04800   for (unsigned i=0; i<cmdlist.size(); i++) {
04801     std::string cmdfull;
04802     std::string cmdshort;
04803     cmd_full_short(cmdlist[i]->name, cmdfull, cmdshort);
04804     if (cmd.compare(cmdfull)==0 || cmd.compare(cmdshort)==0) {
04805       int rc = cmdlist[i]->func();
04806       if (rc > 0) {
04807         std::cerr << "rocutil-E: Error in command '" << cmdline << "'" << std::endl;
04808       }
04809       return rc;
04810     }
04811   }
04812 
04813   std::cerr << "rocutil-E: Command '" << cmd << "' not defined, use 'help'" << std::endl;
04814   return 1;
04815 
04816 }
04817 
04818 //----------------------------------------------------------------------------
04819 
04820 void hdl_int(int sig, siginfo_t *info, void *cnxt)
04821 {
04822   switch (gIntCount) {
04823   case 1: 
04824     std::cerr << '\007' << std::flush;
04825     break;
04826   case 2:
04827     std::cerr << std::endl 
04828          << "rocutil-W: not responding on ^C, next will terminate" << std::endl;
04829     break;
04830   case 3:
04831     std::cerr << "rocutil-E: ^C abort, have a nice day..." << std::endl;
04832     exit(1);
04833     break;
04834   }
04835   gIntCount += 1;
04836   if (gUtil) gUtil->interruptLoop();
04837   if (gQdaq) gQdaq->interruptRun();
04838 }
04839 
04840 //----------------------------------------------------------------------------
04841 
04842 static const char* history_file = "./.rocutil_history";
04843 static const int   history_max  = 250;
04844 
04845 int main(int argc, char* argv[])
04846 {
04847   struct sigaction act;
04848   memset (&act, '\0', sizeof(act));
04849   act.sa_sigaction = &hdl_int;
04850   act.sa_flags = SA_SIGINFO;
04851   if (sigaction(SIGINT, &act, 0) < 0) {
04852     perror ("sigaction");
04853   }
04854 
04855   reset_cmdlist();
04856 
04857   bool prompt = (argc<=1);
04858   
04859   for (int i=1; i<argc; i++) {
04860     if (i==argc-1 && strcmp(argv[i],"-")==0) {
04861       prompt = true;
04862     } else {
04863       int rc = process_command(argv[i], -1);
04864       if (rc > 0) std::cerr << "rocutil-F: Aborting rocutil...." << std::endl;
04865       if (rc) { base::Board::Close(gRocBoard); return (rc<=0) ? 0 : rc; }
04866     }
04867   }
04868 
04869   if (!prompt) {
04870      // close board in the 
04871      base::Board::Close(gRocBoard);
04872      return 0;
04873   }
04874 
04875   std::string lastline;
04876 
04877   char* buf = 0;
04878   int rc;
04879   rc = read_history(history_file);
04880 
04881   while ( (buf=readline("rocutil> ")) ) {
04882     std::string line(buf);                       // get readline buf into std::string
04883     trim_whitespace(line);
04884     if (line.size() && line != lastline) add_history(buf);
04885     lastline = line;
04886     free(buf);                              // release readline buf
04887     int rc = process_command(line, 0);
04888     if (rc < 0) break;                      // exit on quit
04889   }
04890 
04891   // check whether 'quit' was used (buf!=0) or ^D (buf==0) to end rocutil.
04892   // in case of ^D, send a std::endl, otherwise shell prompt will be after rocutil
04893   // prompt.
04894   // This code is fragile and should be cleaned up/
04895   if (buf==0)  std::cout << std::endl;
04896 
04897   // Close connection to ROC to avoid dangling messages
04898   // But only of rc > -2; This prevents a close after
04899   // a 'restartroc' whih will always fail.
04900   //
04901   if (gRocBoard && rc>-2) {                    // if connected to a ROC
04902      base::Board::Close(gRocBoard);
04903      gRocBoard = 0;
04904   }
04905   
04906   rc = append_history (history_max, history_file);
04907   if (rc) {
04908     rc = write_history(history_file);
04909   } else {
04910     rc = history_truncate_file(history_file, history_max);
04911   }
04912 
04913   return 0;
04914 }
04915 
04916 int cmd_autosettrh()
04917 {
04918 
04919 
04920    // default: max 100 hits per channel per seconf, max 5000 hits per chip per second, min 80 unmasked channels - it's our goal - priority of this demands!!
04921    // finding rate - in 5 seconds? 10 seconds? let's say in 5
04922    // up in treshold - by 1? by 2? by 5? by 10? let's say by 5
04923    // should be defined - even if hits per all channels per second are ok, maybe some channels are much more noisy than the others, so maybe one has to mask
04924    // them  ... maybe not (or later improvement)
04925 
04926    int time = 5;
04927    int rc;
04928    int nentmax;
04929    int nxmax;
04930    int maskmax;
04931    int starttrh, up, low, diff;
04932    int step;
04933    int sig;
04934    int minchan, counter;
04935    int previous = 0, previous2 = 0;
04936    nentmax = 500;
04937    nxmax = 10000;                                       // for now default
04938    minchan = 100;                                       // prefered number of working channels
04939    starttrh = 255;
04940    up = 255;                    // upper limit
04941    low = 0;                     // lower limit
04942    step = 20;
04943 
04944    if (get_arg(time, "time=")) return 1;
04945    if (get_arg(minchan, "min=")) return 1;
04946    if (get_arg(nentmax, "nnc=")) return 1;
04947    if (get_arg(nxmax, "nnx=")) return 1;
04948 
04949 
04950    std::cout << "Used values:" << std::endl;
04951    std::cout << "     time: " << time << std::endl;
04952    std::cout << "     minimum working channels: " << minchan << std::endl;
04953    std::cout << "     maximum noise rate per channel: " << nentmax << std::endl;
04954    std::cout << "     maximum noise rate per chip: "<< nxmax << std::endl;
04955 
04956    diff = up - low;             //difference between thresholds
04957 
04958    nxyter::NxContext cntx;
04959 
04960    int32_t nonx = 0;
04961    if( gFeb ) {
04962       nonx = gFeb->numNx();
04963    }
04964    else {
04965       printf("Log to the FEB!\n");
04966    }
04967 
04968    std::cout << "Number of nXYTERs at FEB: " << nonx << std::endl;
04969 
04970 
04971    typedef std::auto_ptr<nxyter::DistFuncArray> ptr_dfa;
04972    ptr_dfa dfa[4];
04973 
04974    for (int i=0; i<gFeb->numNx(); i++) {
04975       dfa[i] = ptr_dfa(new nxyter::DistFuncArray(128, 512));
04976    }                                            // ending array creation
04977    rc = gRocNx->fireTestPulse(0,0,0);                   // turn off pulsar (self-triggering mode)
04978    // need to put - turn off test trigger mode and test pulse mode
04979    // remeber the initial state of nXYTERs
04980 
04981    // setting up threshohld to 255 for all nXYTERs
04982    for (int i=0; i<gFeb->numNx(); i++) {
04983       rc = gFeb->nx(i).i2c().setRegister(uint8_t(18), uint8_t(up), true);
04984    }
04985    // ending threshold setting
04986 
04987    bool mainstop = false;
04988    int totalentries[4];
04989    int totalrate[4];
04990    int channelentries[512];
04991    int channelrate[512];
04992    int channelcontrol[4];
04993    bool control[4];
04994    bool masking[4];
04995    bool trhcontrol[2];
04996    int trhvalue[2];
04997    int val[4];
04998    bool channelid[4][128];
04999 
05000 
05001    int noisy = 0;
05002    int maskedch = 0;
05003    int tobemasked = 0;
05004 
05005    for (int i=0;i<gFeb->numNx();i++) {                  //which nXYTER
05006 
05007       std::cout << "Setup is running for nXYTER: " << i << std::endl;
05008 
05009       mainstop = false;
05010       trhvalue[0]=up;
05011       trhvalue[1]=low;
05012       trhcontrol[0]=false;
05013       trhcontrol[1]=false;
05014 
05015 
05016       while (!mainstop)   {
05017 
05018          for (int k=0; k<2; k++){               //max k - number of FEBs
05019             masking[i]=false;
05020 
05021             for (int l=0; l<4; l++) {           // max l - number of nXYTERs
05022                totalentries[l] = 0;
05023                totalrate[l] = 0;
05024                channelcontrol[l] = 0;
05025                control[l] = false;
05026                masking[l] = false;
05027                for (int j=0; j<128; j++) {              // max j - number of channles in nXYTER
05028                   channelid[l][j] = false;
05029                   channelrate[(l*128)+j] = 0;
05030                   channelentries[(l*128)+j] = 0;
05031                }                                // ending j loop
05032             }// ending i loop
05033 
05034 
05035             delete gQdaq;
05036             gQdaq = 0;
05037             gQdaq = new nxyter::QuickDaq(gFeb);
05038             int rc = gFeb->nx(i).i2c().setRegister(uint8_t(18), uint8_t(trhvalue[k]), true);
05039             cntx.setChannelMaskBit(0, 127, 0, 1);                       // beg, end, val, step
05040             rc = gFeb->nx(i).i2c().setContext(cntx, nxyter::kDoMask);
05041             dfa[i] = ptr_dfa(new nxyter::DistFuncArray(128, 512));
05042 
05043             gQdaq->startRun(0, time);                                   // start DAQ
05044             //std::cout << " \n" << std::endl;
05045             //    std::cout << "Running set up for threshohld "<< trhvalue[k] << std::endl;
05046             // counting rate for whole chip and for each channel
05047             while(gQdaq->testRun()) {
05048                roc::Message& msg = gQdaq->msg();
05049                if (msg.isHitMsg()) {
05050                   int nxnum = msg.getNxNumber();
05051                   int nxcha = msg.getNxChNum();
05052                   int nxadc = msg.getNxAdcValue();
05053                   if (nxnum == i) {
05054                      (*dfa[i]).addEntry(nxcha, float(nxadc));
05055                   }
05056                }
05057             }
05058 
05059             for (int j=0; j< 128; j++) {
05060                totalentries[i] = totalentries[i] + (*dfa[i])[j].numEntries();
05061 
05062                channelrate[(i*128)+j] = (*dfa[i])[j].numEntries()/time;
05063             }
05064             totalrate[i] = totalentries[i]/time;
05065             //        std::cout << "Hit rate in chip is: " << totalrate[i] << std::endl;
05066             //        std::cout << "Channel rate in channel 64 is: " << channelrate[(i*128)+64] << std::endl;
05067 
05068             // counting how many channels have hit rate below the allowed
05069             for (int j=0; j<128; j++) {
05070                if (channelrate[(i*128)+j] <= (nentmax-1)){
05071                   channelcontrol[i]++;
05072                }
05073             }
05074             if ((channelcontrol[i] <= (minchan-1))) {           // && (totalrate[i] >= (nxmax+1))
05075                //       std::cout << "Threshold for "<< i << " nXYTER has to go up" << std::endl;
05076                trhcontrol[k] = false;
05077             }
05078 
05079             if ((channelcontrol[i] >= minchan) && (totalrate[i] >= nxmax)) {
05080                //       std::cout << "Masking of channels in "<< i << " nXYTER is coming" << std::endl;
05081                masking[i] = true;                                       // this threshold can be good, but it has to be found out according to how many channels must                                                           // be masked
05082                trhcontrol[k] = false;
05083 
05084             }
05085 
05086             if ((channelcontrol[i] >= minchan) && (totalrate[i] <= nxmax)) {
05087                //       std::cout << i << " nXYTER settings are sufficient" << std::endl;
05088                trhcontrol[k] = true;
05089             }
05090 
05091             tobemasked=0;
05092 
05093             if (masking[i]) {
05094 
05095                while (totalrate[i] >= (nxmax+1)) {                                      // checking if total rate at chip still higher that wanted value
05096                   tobemasked++;
05097 
05098                   noisy = 0;
05099                   for (int j=0; j<128; j++) {                                                   // go through all channels
05100                      if (!channelid[i][j]) {                                    // checks, if this channel is not already set to be masked, if not
05101 
05102                         if (channelrate[(i*128)+j]>=noisy) {
05103 
05104                            noisy = channelrate[(i*128)+j];
05105                            maskedch = j;
05106                         }
05107 
05108                      }
05109 
05110                   }
05111                   channelid[i][maskedch] = true;
05112                   totalrate[i] = totalrate[i] - channelrate[(i*128)+maskedch];
05113 
05114                   // puts channel to be masked
05115                   // reduces total rate to new level
05116                }
05117                for (int j=0; j<128; j++) {
05118                   if (!channelid[i][j]) {
05119                      if (channelrate[(i*128)+j]>=nentmax) {
05120                         tobemasked++;
05121                         channelid[i][j] = true;
05122                         totalrate[i] = totalrate[i] - channelrate[(i*128)+maskedch];
05123                      }
05124                   }
05125                }
05126 
05127 
05128 
05129                if (tobemasked >= (128-minchan)) {
05130                   totalrate[i]=0;
05131                   trhcontrol[k] = false;
05132                   //        std::cout << "Threshold has to be set higher - too many channels will be masked - " << tobemasked << std::endl;
05133                }
05134 
05135                if (tobemasked <= (128-minchan)) {
05136                   trhcontrol[k] = true;                                                 // this setting is still ok
05137                   //    std::cout << i << " nXYTER settings are sufficient" << std::endl;
05138                }
05139             }           // end of masking
05140 
05141             masking[i] = false;
05142             //end if previous
05143 
05144             if (previous == trhvalue[1]) {
05145                k++;
05146             }
05147             if (previous2 == trhvalue[1]) {
05148                k++;
05149             }
05150 
05151          }               //ends k run
05152 
05153 
05154          previous = trhvalue[1];
05155          previous2 = trhvalue[0];
05156 
05157          if ((diff/2) == 0) { //if (trhcontrol[0] && trhcontrol[1]) {
05158             mainstop = true;
05159          }
05160 
05161          if (trhcontrol[0]) {
05162             trhvalue[0] = trhvalue[0] - (diff/2);
05163             diff = trhvalue[0]-trhvalue[1];
05164          }
05165 
05166          if (!trhcontrol[0]) {
05167             trhvalue[1] = trhvalue[0];
05168             trhvalue[0] = trhvalue[0] + (diff/2);
05169             trhcontrol[1] = trhcontrol[0];
05170             diff = trhvalue[0]-trhvalue[1];
05171          }
05172 
05173 
05174 
05175       } //while
05176 
05177 
05178       for (int l=0; l<4; l++) {
05179          totalentries[l] = 0;
05180          totalrate[l] = 0;
05181          channelcontrol[l] = 0;
05182          control[l] = false;
05183          masking[l] = false;
05184          for (int j=0; j<128; j++) {
05185             channelid[l][j] = false;
05186             channelrate[(l*128)+j] = 0;
05187             channelentries[(l*128)+j] = 0;
05188          }                              // ending j loop
05189       }// ending i loop
05190 
05191       int settrhvalue = 0;
05192 
05193       if (trhvalue[0] && trhvalue[1]) {
05194          settrhvalue = trhvalue[1]+1;
05195       }
05196 
05197       if (trhvalue[0] && !trhvalue[1]){
05198          settrhvalue = trhvalue[0];
05199       }
05200 
05201       delete gQdaq;
05202       gQdaq = 0;
05203       gQdaq = new nxyter::QuickDaq(gFeb);
05204       int rc = gFeb->nx(i).i2c().setRegister(uint8_t(18), uint8_t(settrhvalue), true);
05205       cntx.setChannelMaskBit(0, 127, 0, 1);                     // beg, end, val, step
05206       rc = gFeb->nx(i).i2c().setContext(cntx, nxyter::kDoMask);
05207       dfa[i] = ptr_dfa(new nxyter::DistFuncArray(128, 512));
05208 
05209       gQdaq->startRun(0, time);                                 // start DAQ
05210       //    std::cout << "Running setup for threshohld "<< settrhvalue << std::endl;
05211       // counting rate for whole chip and for each channel
05212       while(gQdaq->testRun()) {
05213          roc::Message& msg = gQdaq->msg();
05214          if (msg.isHitMsg()) {
05215             int nxnum = msg.getNxNumber();
05216             int nxcha = msg.getNxChNum();
05217             int nxadc = msg.getNxAdcValue();
05218             if (nxnum == i) {
05219                (*dfa[i]).addEntry(nxcha, float(nxadc));
05220             }
05221          }
05222       }
05223 
05224 
05225       for (int j=0; j< 128; j++) {
05226          totalentries[i] = totalentries[i] + (*dfa[i])[j].numEntries();
05227          channelrate[(i*128)+j] = (*dfa[i])[j].numEntries()/time;
05228          //std::cout << (*dfa[i])[j].numEntries() << std::endl;
05229       }
05230       totalrate[i] = totalentries[i]/time;
05231       //       std::cout << "Hit rate in chip is: " << totalrate[i] << std::endl;
05232       //       std::cout << "Channel rate in channel 64 is: " << channelrate[(i*128)+64] << std::endl;
05233 
05234       while (totalrate[i] >= (nxmax+1)) {                                       // checking if total rate at chip still higher that wanted value
05235          tobemasked++;
05236 
05237          noisy = 0;
05238          for (int j=0; j<128; j++) {                                                    // go through all channels
05239             if (!channelid[i][j]) {                                     // checks, if this channel is not already set to be masked, if not
05240 
05241                if (channelrate[(i*128)+j]>=noisy) {
05242 
05243                   noisy = channelrate[(i*128)+j];
05244                   maskedch = j;
05245                }
05246 
05247             }
05248 
05249          }
05250          channelid[i][maskedch] = true;
05251          totalrate[i] = totalrate[i] - channelrate[(i*128)+maskedch];
05252       }
05253 
05254       for (int j=0; j<128; j++) {
05255          if (!channelid[i][j]) {
05256             if (channelrate[(i*128)+j]>=nentmax) {
05257                tobemasked++;
05258                channelid[i][j] = true;
05259                totalrate[i] = totalrate[i] - channelrate[(i*128)+j];
05260             }
05261          }
05262       }
05263 
05264 
05265 
05266       //masking
05267       for (int j=0; j<128; j++) {
05268          if (channelid[i][j]) {
05269             cntx.setChannelMaskBit(j, j, 1, 1);                         // beg, end, val, step
05270             rc = gFeb->nx(i).i2c().setContext(cntx, nxyter::kDoMask);
05271          }
05272       }
05273 
05274       for (int i=0; i<gFeb->numNx(); i++) {
05275 
05276          // std::cout << " \n" << std::endl;
05277          // std::cout << "Working channels are: \n" << std::endl;
05278          //
05279          //     for (int j=0; j<128; j++) {
05280          //
05281          //             if (!channelid[i][j]){
05282          //
05283          //             std::cout << "   nXYTER " << i << " channel "<< j << " with noise rate " << channelrate[(i*128)+j] << std::endl;
05284          //
05285          //            }
05286          //            }
05287          //
05288          // std::cout << " \n" << std::endl;
05289          std::cout << "\n Masked channels are:" << std::endl;
05290          std::cout << "   nXYTER " << i << " channels: " ;
05291          for (int j=0; j<128; j++) {
05292 
05293             if (channelid[i][j]){
05294 
05295                std::cout << " " << j << ", " ;
05296 
05297             }
05298          }
05299          std::cout << "\n" << std::endl;
05300 
05301          std::cout << "Total noise rate in chip is " << totalrate[i] << std::endl;
05302          std::cout << "Set threshold in " << i << " nXYTER is " << settrhvalue << std::endl;
05303 
05304       }
05305 
05306 
05307       std::cout << "Setup has finished this difficult work. You are welcome ...\n" << std::endl;
05308 
05309    }//for nxyters
05310 
05311 
05312    mainstop = false;
05313    return 0;
05314 
05315 }       // ending main program
05316 
05317 
05318 
05319 
05320 //----------------------------------------------------------------------------

Generated on Tue Dec 10 2013 04:52:24 for ROCsoft by  doxygen 1.7.1