#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include <ctype.h>
#include <zlib.h>
#include <vector>
#include <sys/time.h>
#include <sys/stat.h>
#include <signal.h>
#include <string>
#include "vme.h"
#include "dataio.h"
#include "SA02_DEF.h"
#include "sa02lib.h"
#include "H2D.h"
#define TRUE 1
#define FALSE 0
#define TIMEOUT 3
RUNINFO runinfo;
EVTREC evtrec;
//const int mux_map[4]={ 1,3,0,2};
const int mux_map[4]= { 2,0,3,1};
int verbose=0;
int timer_out;
struct sigaction oact;
int bltreadout=0;
int ctrl_c=0;
void SigInt (int sig) {
ctrl_c = 1;
timer_out=TRUE;
sa02TimerOut = TRUE;
}
void sa02Timerast (int signumber) {
timer_out = TRUE;
sa02TimerOut = TRUE;
sa02Printf("->>> TIMEOUT !!!\n");
}
void tmlnk (int tout) {
timer_out = FALSE;
struct sigaction act;
struct itimerval tdelay;
act.sa_handler = sa02Timerast;
sigemptyset (&act.sa_mask);
act.sa_flags = 0;
tdelay.it_value.tv_sec = tout / 100;
tdelay.it_value.tv_usec = 10000 * (tout % 100);
tdelay.it_interval.tv_sec = 0;
tdelay.it_interval.tv_usec = 0;
if (sigaction (SIGALRM, &act, &oact) < 0) {
}
if (setitimer (ITIMER_REAL, &tdelay, NULL) < 0) {
}
}
void tmulk () {
struct itimerval tdelay;
tdelay.it_value.tv_sec = 0;
tdelay.it_value.tv_usec = 0;
tdelay.it_interval.tv_sec = 0;
tdelay.it_interval.tv_usec = 0;
if (setitimer (ITIMER_REAL, &tdelay, NULL) < 0) {
}
if (sigaction (SIGALRM, &oact, NULL) < 0) {
}
}
void sa02Tmlnk (int tout) {
sa02TimerOut = FALSE;
tmlnk (tout);
// ResetTimer (p1h, P1_DAQ_TIMEOUT);
}
void sa02Tmulk () {
tmulk();
}
int help() {
printf ("*********************************************************************************:\n");
printf ("Usage: Performs single/multiple read or write access to SA02 via Belle PTS multipurpose IO board:\n\n");
printf ("-i input parameter filename // can be specified multiple times \n");
printf ("-o output filename \n");
printf ("-f output filename - append data to file\n");
printf ("-w write command (FE TP DLY0 MUX MUXASIC VTH0 VTH1 TPLVL0 TPLVL1 GREG CREG CMON TMON0 TMON1 DMON) \n");
printf ("-a vme base address 0x32100000 \n");
printf ("-c asic chip number (0..3) \n");
printf ("-x asic channel number (0..36) \n");
printf ("-t sleep time bewteen events (sec) \n");
printf ("-b dataoff - scan over the asic channels instead of the parameter, data step is the channel step, chip and channel are initial chip and channel. Should apper after -p or-w\n");
printf ("-s data step or in case of -b the channel step \n");
printf ("-r number of readouts for each event\n");
printf ("-n number of events\n");
printf ("-h <command> at each event execute external command after readouts are done");
printf ("-q set status register bit TPENB of the CAEN1495 IO before event loop\n");
printf ("-e send software trigger before reading the data\n");
printf ("-p asicparameter ( PHASECMPS GAIN SHAPINGTIME COMPARATOR VRDRIVE MONITOR ID)\n");
printf ("-p asicparameter ( DECAYTIME OFFSET FINEADJ_UNIPOL FINEADJ_DIFF TPENB KILL)\n\n");
printf ("-u value ... send test SEU software trigger \n");
printf ("-z value ... finish the execution of the program in <value> s \n");
printf ("-m fixeddata : test fixed data, if error occurs, abort \n");
printf ("-l board number \n");
printf ("*********************************************************************************:\n");
printf ("100 events TMON0 reading and 10 readings of the data for each event:\n");
printf ("./sa02_ctrl -a 0x32100000 -w TMON0 -n 100 -r 10 -t 10000 -v 1\n\n");
printf ("scan 9 points TPLVL0 inital data 111 stepsize 11, send 1 test pulse, read data :\n");
printf ("./sa02_ctrl -a 0x32100000 -w TPLVL0 -d 111 -s 11 -n 9 -e 1 -r 1 -v 1\n\n");
printf ("Initialize the board from input.param, Read 10000 events of data. the result is saved in the output.dat\n");
printf ("./sa02_ctrl -a 0x32100000 -i input.param -n 10000 -r 1 -o output.dat \n\n");
printf ("Initialize the board from input.param, Read 10000 events of data. scan TPENB from 0 to 144 channels, send test pulse before the data acquisition,\n ");
printf ("set TPENB to b after the acquisition, the result is saved in the output.dat\n");
printf ("./sa02_ctrl -a 0x32100000 -i input.param -p TPENB -d 1 -b 0 -s 1 -n 144 -c 0 -x 0 -e 1 -r 10000 -o output.dat \n\n");
return 0;
}
int module_header(int recid,uint32_t *data,int len) {
data[0] = recid;
data[1] = (len >0)? len : 0 ;
return data[1]+2;
}
//-------------------------------------------------------------------------
int PrintData(uint32_t *rdata, int count) {
for (int j=0; j<count; j++) {
uint32_t recid = rdata[j++];
uint32_t len = rdata[j++];
printf(" recid=0x%0x len=%d pos=%d(maxpos %d) val=",recid
, len
, j
, count
);
for (uint32_t i=0; i<len; i++) {
if (j
< count
) printf("0x%0x\t", rdata
[j
]);
j++;
}
if (len) j--;
}
return 0;
}
//-------------------------------------------------------------------------
int main( int argc , char ** argv) {
// intercept routine
if (signal (SIGINT, SigInt) == SIG_ERR) {
}
uint32_t fixeddata =0;
int testfixeddata =0;
uint32_t data =0;
uint32_t dataoff =0;
uint32_t address =0;
uint32_t cmd =0;
uint32_t chip =0;
uint32_t asicpar =0;
uint32_t asicshft=0;
uint32_t dstep =0;
uint32_t sendswtrg =0;
uint32_t tpenb =0;
uint32_t sendseutrg =0;
int aborttimeout =0;
int append =0;
int remap =0;
int dt0 =0;
int neve =0;
int towrite =0;
int toread =0;
int ch =0;
int output =0;
int externalcmd =0;
int getstatus =0;
int writeevent =1;
int c;
char filename[0xFF]="";
char externalcommand[0xFF]="";
int sa02BoardMask = 0xF;
opterr = 0;
std::vector<std::pair<std::string,uint32_t> > inputfiles;
while ((c = getopt (argc, argv, "a:b:c:d:e:f:g:h:i:j:k:l:m:n:o:p:q:r:s:t:u:v:z:x:w:y:")) != -1)
switch (c) {
case 'i':
inputfiles.push_back(make_pair(std::string(optarg), sa02BoardMask));
break; // input file
case 'f':
append=1; // append the data to the file filename
case 'o':
break; // output
case 'z':
aborttimeout
=atoi (optarg
); // abort timeout in s
break;
case 'h':
sprintf(externalcommand
,"%s", optarg
);
externalcmd=1;
break; // output
case 'm':
fixeddata
= strtoul (optarg
,NULL
,0);
testfixeddata=1;
break; // address
case 'a':
break; // address
case 'r':
break; // number of readings per event
case 'v':
break; // verbosity
case 't':
break; // sec sleep between events
case 's':
break; // step size in data or channel increase
case 'g':
bltreadout
= strtoul (optarg
,NULL
,0);
break; // bltreadout
case 'l':
sa02BoardMask
= strtoul (optarg
,NULL
,0);
if ( sa02BoardMask > 0xF) {
printf("Error! Board Mask 0..15 . Set to 0.");
sa02BoardMask = 0xF;
}
break; // board mask
case 'j':
sa02BoardType
= strtoul (optarg
,NULL
,0);
if ( sa02BoardType > 3) {
printf("Error! Board type sa02 0 / sa03 1 / FEB1_0 2 / FEB1_1 3 . Set to 3");
sa02BoardType = 3;
}
break; // board number
case 'n':
break; // number of events or number of scan points
case 'e':
sendswtrg
= strtoul (optarg
,NULL
,0);
break; // send sotware trigger before reading out the data
case 'u':
sendseutrg
= strtoul (optarg
,NULL
,0);
break; // send software SEU trigger before reading out the data
case 'w':
towrite=1;
if (strcmp(optarg
,"MUXASIC")==0) remap
=1;
cmd =sa02GetCmdCode(optarg);
break; // write command
case 'p':
towrite=2;
cmd = sa02GetAsicCode(optarg, &asicpar, &asicshft);
break; // asic parameter
case 'b':
towrite=3;
break; // scan channels instead of parameter; the value is the off value of the channel
case 'c':
break; // chip number or initial channel number in the case of -b option
case 'x':
break; // channel number or initial channel in the case of -b option
case 'd':
if (remap) {
data = mux_map[data];
}
break; // data or initial data in the case of scan
case 'q':
break; // set TPENB bit of the CAEN1495 IO
case 'y':
writeevent
= strtoul (optarg
,NULL
,0);
break; // write event data
case 'k':
getstatus
= strtoul (optarg
,NULL
,0);
break; // print board status
case '?':
if (optopt == 'c')
fprintf (stderr
, "Option -%c requires an argument.\n", optopt
);
fprintf (stderr
, "Unknown option `-%c'.\n", optopt
);
else
"Unknown option character `\\x%x'.\n",
optopt);
return 1;
default:
}
for (int i
=optind
; i
<argc
; i
++) data
= strtoul (argv
[i
],NULL
,0);
if (argc <2) {
help();
}
// printf ("[neve=%d] a=0x%08x cmd= 0x%08x Data 0x%0x ",neve,address, cmd,data);
//VME_START(CAEN_V1718);
VME_START(ZYNQ_XILLINUX);
int daqmode =3;
int trglen = 1000;
Sa02DaqMode (daqmode);
Sa02SelectTriggerWithMaskAndLength (sendswtrg, sa02BoardMask , trglen);
for (unsigned int i=0; i<inputfiles.size(); i++) {
sa02LoadParametersFromFile(inputfiles[i].first.c_str(), inputfiles[i].second);
}
if (getstatus){
char saddress[0xFF];
double sdata[20];
for (int board=0;board<4;board++){
if (sa02BoardMask &(1<<board)) {
printf("sa02Status => board %d\n",board
);
sa02Status(board, saddress,sdata);
}
}
}
if (sendseutrg) Sa02SEUTrigger();
#define MAXSIZE 10000
int maxsize = MAXSIZE;
uint32_t *rdata = new uint32_t[maxsize];
FILE * fp=NULL;
// uint32_t hdr[10];
int nbtotal=0;
if (verbose
) printf("Data in the file:%s\n", filename
);
if (append
) fp
=fopen(filename
,"ab");
else fp
=fopen(filename
,"wb");
output=1;
// run header
runinfo.id= RUNINFO_ID; // run record ID
runinfo.len= sizeof(runinfo);
runinfo.cmd= cmd;
runinfo.x0 = data;
runinfo.dx = dstep;
runinfo.nx = neve;
runinfo.chip= chip;
runinfo.ch = ch;
runinfo.neve= toread;
runinfo.writemode= towrite;
sa02Printf("RUNINFO x0=%d nx=%d dx=%d\n", runinfo.x0,runinfo.dx,runinfo.nx);
nbtotal
+=fwrite(&runinfo
, 1,sizeof(runinfo
),fp
); //gzip
} else {
if (verbose
) printf("Data are not written to the file!\n");
}
// hdr[0]= 0x1; // event record ID
if (!neve & (towrite || toread) ) neve=1;
time_t t,told,tstart;
tstart=t;
int ncount=0;
int nerrors=0;
int readerror=0;
uint32_t response[2]= {0,0};
Sa02TestPulseEnable(address, tpenb);
///////////////////////////////////////////////////////////////
int h2=0;
if(neve>1) {
H2DInit(h2, "h2d","Sa02 Chip Scan", 144, 0,1,neve,data, dstep);
H2DSetTitleX(h2,"channel");
H2DSetTitleY(h2,"Scan");
}
for (int i=0; i<neve; i++) {
int nb = sizeof(uint32_t);
int count=0;
switch (towrite) {
case 1: {
rdata[count+2]= data;
rdata[count+3]= sa02Cmd(address,cmd, data, chip, ch , 2, response);
count+=module_header(cmd,&rdata[count],2 );
break;
}
case 2: {
uint32_t datal = asicpar & (data << asicshft);
rdata[count+2] = data;
rdata[count+3] = sa02AsicWrite(address, cmd, datal, chip, ch, asicpar,asicshft);
count+=module_header(cmd ,&rdata[count],2); // recid cmd
break;
}
case 3: {
rdata[count+2] = chip*36+ch;
rdata[count+3] = sa02AsicWrite(address, cmd, data, chip, ch, asicpar,asicshft); // switch on the channel
count+=module_header(cmd ,&rdata[count],2); // recid cmd
break;
}
}
// const int dsize = ( FEB_DATA_STOP - FEB_DATA_START) / FEB_DATA_INC;
const int dsize = 144*4;
Sa02SetNeve(toread);
sa02Reset();
for ( int j=0; j< toread; j++) {
int eventerror = 0;
if ((count+2+dsize) >= maxsize) {
int oldsize = maxsize;
maxsize*=2;
printf("Increasing data buffer to %d elements\n", maxsize
);
uint32_t *tmpdata = rdata;
rdata = new uint32_t[maxsize];
//memcpy(tmpdata,rdata, oldsize*sizeof(uint32_t));
for (int ki=0; ki<oldsize; ki++) rdata[ki]=tmpdata[ki];
delete tmpdata;
}
Sa02TestPulseEnable(address, tpenb);
if (sendswtrg) Sa02SoftwareTrigger();
nb = sa02Read(sa02BoardMask, &rdata[count+2] );
if (neve>1) {
for (int ich=0; ich<144*4; ich++){
int xch = (143 - ich%144) + ich/144*144;
H2DFillBin(h2, xch,i,rdata[count+2+ich]);
}
}
if (testfixeddata && nb>0) {
int len = nb / sizeof(uint32_t);
for (int ir=0; ir<len; ir++) {
if ( rdata[count+2+ir]!=fixeddata ) {
printf("INSERT INTO fixederror VALUES ( '%d', '%d','%d','%d','0x%08x','0x%08x' ) \n", int(t
), int(t
-tstart
), i
*toread
+j
, ir
, rdata
[count
+2+ir
], fixeddata
);
eventerror++;
}
}
}
if (eventerror) {
readerror++;
if (readerror==3) {
ctrl_c = 1;
system("date >> firmware.lock");
}
} else {
readerror= 0;
}
if (nb>=0) count+=module_header(0x3,&rdata[count],nb/sizeof(uint32_t)); // recid 0x3
if (ctrl_c) break;
if (timer_out) j--;
if (t
!=told
) printf("%d events in %2.2f min (%d s) TIMEOUTS=%d %s",ncount
, (double)(t
-tstart
)/60.
,int(t
-tstart
), nerrors
, ctime(&t
));
if (aborttimeout && (t-tstart)>aborttimeout) {
printf("Abort timeout reached ....\n");
ctrl_c=1;
break;
}
told=t;
if (nb<0) {
nerrors++;
j--;
} else ncount++;
}
if (externalcmd) {
char ecmd[256];
sprintf(ecmd
,"%s %u %u %u %u",externalcommand
,(unsigned int) tstart
,data
, rdata
[2], rdata
[3]);
if (verbose
) printf("Executing external command %s\n",ecmd
);
}
if (output && writeevent) {
evtrec.id=EVTREC_ID;
evtrec.len=count*sizeof(uint32_t)+ sizeof(evtrec);
evtrec.nev=i;
nb
= fwrite( &evtrec
, 1, sizeof(evtrec
),fp
); //gzip
if (count
) nb
+=fwrite(&rdata
[0],1,count
*sizeof(uint32_t),fp
); //gzip
if (nb
!= (int) evtrec.
len) printf("Error writing! %d!=%d\n",nb
,evtrec.
len);
nbtotal+= nb;
}
if (verbose==1) {
printf("[%d/%d] %u \t", i
,count
, (unsigned int) time(NULL
));
PrintData(rdata,count);
}
if (dt0) sleep(dt0);
if (towrite ==3) {
sa02AsicWrite(address, cmd, dataoff, chip, ch, asicpar, asicshft);
ch += dstep;
if (ch>35) {
ch-=36;
chip++;
}
} else {
data += dstep;
}
if (ctrl_c) {
if (!testfixeddata
) printf("Ctrl+C Program interrupted ....\n");
break;
}
}
if (output) {
if (neve>1) H2DWrite2File(h2,fp);
}
if (verbose>1) {
printf("%d bytes written to file %s\n", nbtotal
, filename
);
}
VME_STOP();
if (toread
&& !testfixeddata
) printf("%d events in %2.2f min (%d s) TIMEOUTS=%d %s",ncount
, (double)(t
-tstart
)/60.
,int(t
-tstart
), nerrors
, ctime(&t
));
return 0;
}