Subversion Repositories f9daq

Rev

Blame | Last modification | View Log | RSS feed

#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) {
    perror ("sigaction(tmlnk)");
    exit (EXIT_FAILURE);
  }
  if (setitimer (ITIMER_REAL, &tdelay, NULL) < 0) {
    perror ("setitimer(tmlnk)");
    exit (EXIT_FAILURE);
  }
}

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) {
    perror ("setitimer(tmulk)");
    exit (EXIT_FAILURE);
  }
  if (sigaction (SIGALRM, &oact, NULL) < 0) {
    perror ("sigaction(tmulk)");
    exit (EXIT_FAILURE);
  }
}

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 ("Arguments: \n");
  printf ("-i input parameter filename // can be specified multiple times  \n");
  printf ("-v verbosity \n");
  printf ("-g bltreadout \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 ("-d data\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 ("Examples:\n\n");
  printf ("Threshold scan:\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);
    if (len>2) printf("\n");
    for (uint32_t i=0; i<len; i++) {
      if (j< count) printf("0x%0x\t", rdata[j]);
      if (i%4==3) printf("\n");
      j++;
    }
    printf("\n");
    if (len) j--;
  }
  return 0;
}

//-------------------------------------------------------------------------
int main( int argc , char ** argv) {
  // intercept routine
  if (signal (SIGINT, SigInt) == SIG_ERR) {
    perror ("sigignore");
  }

  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':
        sprintf(filename,"%s", optarg );
        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':
        address =  strtoul (optarg,NULL,0);
        break;             // address
      case 'r':
        toread =  strtoul (optarg,NULL,0);
        break;             // number of readings per event
      case 'v':
        verbose =  strtoul (optarg,NULL,0);
        break;             // verbosity
      case 't':
        dt0 =  strtoul (optarg,NULL,0);
        break;                // sec sleep between events
      case 's':
        dstep =  strtoul (optarg,NULL,0);
        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':
        neve =  atoi (optarg);
        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;
        dataoff  = strtoul (optarg,NULL,0);
        break;    // scan channels instead of parameter; the value is the off value of the channel
      case 'c':
        chip  = strtoul (optarg,NULL,0);
        break;                // chip number  or initial channel number in the case of -b option
      case 'x':
        ch  = strtoul (optarg,NULL,0);
        break;                 // channel number or initial channel in the case of -b option
      case 'd':
        data  = strtoul (optarg,NULL,0);
        if (remap) {
          data = mux_map[data];
          printf("MUX %d\n",data);
        }
        break;                 // data or initial data in the case of scan
      case 'q':
        tpenb  = strtoul (optarg,NULL,0);
        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);
        else if (isprint (optopt))
          fprintf (stderr, "Unknown option `-%c'.\n", optopt);
        else
          fprintf (stderr,
                   "Unknown option character `\\x%x'.\n",
                   optopt);
        return 1;
      default:
        abort ();
    }

  for (int i=optind; i<argc; i++) data = strtoul (argv[i],NULL,0);

  if (argc <2) {
    help();
    exit(-1);
  }

  // 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 (strlen(filename)>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;
  time(&t);
  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 ) {
            time(&t);
            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--;
      time(&t);
      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);
      system(ecmd);
    }
    if (output && writeevent) {
      evtrec.id=EVTREC_ID;
      evtrec.len=count*sizeof(uint32_t)+ sizeof(evtrec);
      evtrec.time=time(NULL);
      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);
    fclose(fp);
  }
  if (verbose>1)  {
    printf("%d bytes written to file %s\n", nbtotal, filename);
  }
  VME_STOP();
  time(&t);
  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;
}