Subversion Repositories f9daq

Rev

Blame | Last modification | View Log | RSS feed

//
//  test.c
//  
//  Description : test program for V729
//
//  Author : S. Korpar
//  Date   : 2005/07/15
// adapted to CAEN V1719 by R. Pestotnik  2012/09/07

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <ctype.h>

#include <vector>
#include <sys/time.h>
#include <sys/stat.h>
#include <signal.h>
#include <string>
#include "vme.h"
#include "CAEN_V729_DEF.h"

#define V729_OFFSET 0x880000
#define IREG_OFFSET 0x2000
#define V729_WAIT 1


#define TRUE 1
#define FALSE 0

uint32_t V729_module=0;


int timer_out;
struct sigaction oact;

//---------------------------------------------------------
void SigInt (int sig)
{

    timer_out=1;
}

//---------------------------------------------------------
void timerast (int signumber)
{
    timer_out = TRUE;
    fprintf(stderr,"TIMEOUT !!!\n");
}

//---------------------------------------------------------
void tmlnk (int tout)
{
    timer_out = FALSE;
    struct sigaction act;
    struct itimerval tdelay;

    act.sa_handler = timerast;
    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);
    }
}

//---------------------------------------------------------
int wait_while(int num){
  int i, tmp;

  for ( i =0; i <num; i++ ) tmp = 0;
  return tmp;
}

//---------------------------------------------------------
void V729_map( uint32_t addr)
{
  V729_module = addr;
  return;
}

//---------------------------------------------------------
void V729_info(FILE *kam)
{
  unsigned short code, mid, ver;

 
  VME_A24D16_R(V729_module+0xFA,&code);
  VME_A24D16_R(V729_module+0xFC,&mid);
  VME_A24D16_R(V729_module+0xFE,&ver);
  fprintf(kam, "code/mid/ver = 0x%04X/0x%04X/0x%04X\n", code, mid, ver);
  fprintf(kam, "Fixed code (0xFAF5) = 0x%04X\n", code);
  fprintf(kam, "Manufacturer/Type = 0x%02X/0x%03X\n",
         (mid & 0xFC00)>>10, mid & 0x3FF);
  fprintf(kam, "Version/Serial = %d/%d\n",
         (ver & 0xF000)>>12, ver & 0xFFF);
  return;
}


//---------------------------------------------------------
void V729_reg( uint32_t val){
 uint32_t push=0;
 
 VME_A24D16_W(V729_module+V729_FSR, &val);
 VME_A24D16_W(V729_module+V729_UFSR, &push); //push
 usleep(V729_WAIT);
 
}


//---------------------------------------------------------
void V729_reset(int nall,int nbefore,int obae,int obaf)
{
  uint32_t cbl;

//  cbl=4096+12-100;
  cbl=4096+12-nbefore;
  uint32_t val=0;
  VME_A24D16_W(V729_module+V729_RR, &val); // reset
  printf("nbefore=%d\t", nbefore);
  printf("nall=%d\t", nall);
  printf("obae=%d\t", obae);
  printf("obaf=%d\n", obaf);
 
// set AE
  V729_reg( (obae & 0xFF)<<8 ) ; //
  V729_reg( (obae & 0xF00) ) ; //
 
 
// set AF and CBL
  V729_reg( ((obaf & 0xFF)<<8) + (cbl & 0xFF)   );
  V729_reg( (obaf & 0xF00) + ((cbl & 0xF00)>>8) );
 
 

 VME_A24D16_W(V729_module+V729_SR,&nall); //total number of samples

  return;
}
//---------------------------------------------------------

void V729_set_bias(int range, int bias1, int bias2)
{
    int i;
    uint32_t bias;

    switch (range) {
        case 0: //User
            for (i=0x18;i<0x27;i+=4){
                VME_A24D16_W(V729_module+i, &bias1); //bias
                usleep(V729_WAIT);
                VME_A24D16_W(V729_module+i+2, &bias2); //bias
                usleep(V729_WAIT);
            }
            printf("Bias + %x  - %x\n", bias1, bias2);
            break;
        case 1: //Single Ended +
            for (i=0x18;i<0x27;i+=4){
                bias = 0xCC; VME_A24D16_W(V729_module+i, &bias); //bias
                usleep(V729_WAIT);
                bias =0x733; VME_A24D16_W(V729_module+i+2, &bias); //bias
                usleep(V729_WAIT);
            }
            break;
        case 2: //Single Ended -
            for (i=0x18;i<0x27;i+=4){
                bias =0x733; VME_A24D16_W(V729_module+i, &bias); //bias
                usleep(V729_WAIT);
                bias= 0xD99 ; VME_A24D16_W(V729_module+i+2, &bias); //bias
                usleep(V729_WAIT);
            }
            break;
        case 4: //Differential Unipolar
            for (i=0x18;i<0x27;i+=4){
                bias = 0x400; VME_A24D16_W(V729_module+i,&bias); //bias
                usleep(V729_WAIT);
                bias = 0xA66; VME_A24D16_W(V729_module+i+2, &bias); //bias
                usleep(V729_WAIT);
            }
            break;
        case 3: //Single Ended Bipolar
        case 5: //Differential Bipolar
        default:
            for (i=0x18;i<0x27;i+=2){
                bias=0x733; VME_A24D16_W(V729_module+i, &bias); //bias
                usleep(V729_WAIT);
            }
            break;
    }
    return;
}

//---------------------------------------------------------
void V729_aquisition_mode(uint32_t mode) // mode 0 aqusition mode, 0x30 buffers programming
{
#ifdef V729_DEBUG
  int status;
  VME_A24D16_R(V729_module+V729_CSR, &status);
  usleep(V729_WAIT);
  fprintf(stderr, "0x0E = 0x%04X\n", status);
#endif
 
  VME_A24D16_W(V729_module+V729_CSR, &mode); //aquisition mode
  usleep(V729_WAIT);
#ifdef V729_DEBUG
  VME_A24D16_W(V729_module+V729_CSR, &status);
  usleep(V729_WAIT);
  fprintf(stderr, "0x0E = 0x%04X\n", status);
#endif
  return;
}

//---------------------------------------------------------
void V729_soft_stop()
{
  uint32_t sw=1;
  VME_A24D16_W(V729_module+0x16,&sw);
//  usleep(V729_WAIT);
  sw =0;
  VME_A24D16_W(V729_module+0x16,&sw);
//  usleep(V729_WAIT);
  return;
}

//---------------------------------------------------------
void V729_clear_buffer()
{
    const int tout=100; /* 1/100 of a second */
    tmlnk (tout);
    uint32_t data1,data2;
    do {
        VME_A24D32_R(V729_module+V729_OBR1, &data1);
        if (timer_out) break;
    } while (data1 & (0x3<<29));

    do {
        VME_A24D32_R(V729_module+V729_OBR2, &data2);
        if (timer_out) break;
    } while (data2 & (0x3<<29));

    tmulk();
    return;
}

void V729_get_buffer(uint32_t *data1, uint32_t *data2)
{
    VME_A24D32_R(V729_module+V729_OBR1, data1);
//    usleep(V729_WAIT);
    VME_A24D32_R(V729_module+V729_OBR2, data2);
//    usleep(V729_WAIT);
    return;
}
int V729_status()
{
  uint32_t status;
  VME_A24D16_R(V729_module+V729_CSR, &status);
  return status;
}


//---------------------------------------------------------
void V729_init(uint32_t addr, int nall, int cbl, uint32_t bias1, uint32_t bias2){
  V729_map(addr);
  V729_info(stderr);
  V729_reset(nall,cbl,nall,0xC00);
  V729_set_bias(0,bias1,bias2);
  V729_aquisition_mode(0);
CAENVME_SetFIFOMode(udev,1);
  sleep(1);
}


//---------------------------------------------------------
int V729_event(int mask, int nall, uint32_t *data,uint32_t *data1,uint32_t *data2){
  uint32_t status;
  const int tout=100; /* 1/100 of a second */
  tmlnk (tout);
  int count=0;

  //status= 0x80 ; VME_A16D16_W(IREG_OFFSET+0x8,&status); // pulse ch 8
 
  status = 0x1a ; VME_A16D16_W(IREG_OFFSET+0xC,&status); // clr1 enable1  .... clear busy1 flag
  do {
      //usleep(1);
      VME_A24D16_R(V729_module+V729_CSR, &status);
//    fprintf(stderr,"0x%X, 0x%X\n",status,(status & 0x5) ^ 0x5);
    count++;
    if (timer_out) {
       tmulk ();
       printf("[%d] daq=%x status AE01=%d AE23=%d Waiting for DATA TRG bit... at line %d\n",count , (status>>4)&0x3, status&0x1,(status>>2)&0x1 , __LINE__);
       
       V729_clear_buffer();
       
       return -1;
    }
  } while ((status & 0x5) ^ 0x5);
  tmulk ();

 
  int nb;
  const int blt=1;
  if (blt){
 
  VME_A24D32_FIFOBLTR(V729_module+V729_OBR1,data1,(nall+5)*sizeof(uint32_t),&nb);
  VME_A24D32_FIFOBLTR(V729_module+V729_OBR2,data2,(nall+5)*sizeof(uint32_t),&nb);
  for (int i=0;i<nall+5;i++){
    data[2*i]   = data1[i];
    data[2*i+1] = data2[i];
  }
  nb*=2;
  } else {


  VME_MRRST(); // MultiReadReset
  int nc=0;
  for (int i=0;i<nall+5;i++){
    //if (mask & 0x3)
    VME_A24D32_MR(V729_module+V729_OBR1, &data[nc++]);
    //if (mask & 0xc)
    VME_A24D32_MR(V729_module+V729_OBR2, &data[nc++]);
  }
  int j = VME_MREXEC(data); // MultiReadExecute
  nb=j*sizeof(uint32_t);

  }

  return nb;
}

//---------------------------------------------------------
int V729_decode(uint32_t mask, int nall, uint32_t *data,  uint16_t *dadc, int debug){
  uint16_t *adc[4];
  for (int i=0;i<4;i++) adc[i] = &dadc[4+i*(nall+2)];
 
  int nc=0;
  int narrays=0;
  if (mask & 0x3) narrays++;
  if (mask & 0xc) narrays++;

  int indx[4] ={0,0,0,0};
  int shft[4] ={0,0,0,0};
  int ashft[4]={0,0,0,0};
  int nmask=0;

  for (int i=0;i<4;i++) if (mask & (1<<i) ) {
    indx[nmask] = i;
    shft[nmask] = (i%2)*12;
    if (( (mask & 0x3) > 0 ) && (i>1))  ashft[nmask]=1  ;
    else ashft[nmask]=0;
    nmask++;
  }
  for (int j=0;j<nmask;j++){
    nc=0;
    for (int i=0;i<nall+5;i++){
      int ii=narrays*i+ashft[j];
     
      uint32_t data1 = data[ii];
     
      if (data1 & (1<<31)) {
        if (debug) fprintf(stdout,"data1: empty flags: 0x%X, time tag: 0x%06X\n", (data1>>29) & 0x3, data1 & 0xFFFFFF);
      } else if ((data1>>29) & 0x3){
        if (nc<nall){
          adc[j][nc] = (data1>>shft[j]) & 0xFFF;
          if (debug) printf("[%d/%d] ADC%d adc0=%d\n", i,nc,indx[j], adc[j][nc]);
          nc++;
        }

      } else {
        if (debug) fprintf(stdout,"Data(%4d) %d indx=%d %d nc=%d(%d) %d 0x%08X\n", i, indx[j],narrays*i+ashft[j],j,nc,nmask,narrays, data1);
      }
    }
  }
  return nc;
}
//---------------------------------------------------------

// test program
#ifdef V729_MAIN
int ctrlc=0;
 
void CatchSig (int i){
    ctrlc = 1;
}


int main(int argc,char **argv){

   if (argc == 1) {
   
    printf ("*********************************************************************************:\n");
    printf ("Usage: %s <arguments> .........   CAEN V729A data aquisition:\n\n", argv[0]);
    printf ("Arguments: \n");
    printf ("-d <debuglevel>  \n");
    printf ("-b <bias+>  \n");
    printf ("-e <bias->  \n");
    printf ("-a <VME address>  \n");
    printf ("-c <n samples before stop>  \n");
    printf ("-n <number of events> \n");
    printf ("-l <nall> number of samples \n");
    printf ("-m <channel mask: 4bits (1 bit/ch)> \n");
    printf ("-o <output file name> \n");

    printf ("*********************************************************************************:\n");
    exit (-1);
  }

  uint32_t mask=0xF;
  int  cbl=13;
  int nall=1330;
  char filename[0xFF]="";
  int verbose = 0;
  int neve    = 1;
  uint32_t addr= V729_OFFSET;
  uint32_t bias1 = 0x600; // vecje vrednosti povzročajo težave in zacno kanali oscilirat ....
  uint32_t bias2 = 0x200;
  int append=0;
  int c=0;
  while ((c = getopt (argc, argv, "b:e:a:d:c:l:n:o:m:f:")) != -1)
    switch (c){
      case 'd':
        verbose=atoi(optarg);
        break;
      case 'c':
        cbl=atoi(optarg);
        break;
      case 'l':
        nall=atoi(optarg);
       
        if (nall%16) {
          printf ("buffer length should be multiple of 16 , modulo = %d\n",nall%16);
         // exit(-1);
        }
        break;    
      case 'n':
        neve=atoi(optarg);
        break;  
      case 'a':
        addr=strtoul (optarg,NULL,0);
        break;             // address
      case 'b':
        bias1=strtoul (optarg,NULL,0);
        break;             // bias
      case 'e':
        bias2=strtoul (optarg,NULL,0);
        break;             // bias
 
      case 'm':
        mask=strtoul (optarg,NULL,0);
        break;             // mask
      case 'o':
        sprintf(filename,"%s", optarg );
        append=0;
        break;       // output
      case 'f':
        sprintf(filename,"%s", optarg );
        append=1;
        break;       // output
    }

// intercept routine
  if (signal (SIGINT, CatchSig) == SIG_ERR)  perror ("sigignore");

 
  // reset timers
  time_t t,told=0, tstart;
  time(&t);
  tstart=t;

  // open file
  FILE *fp=NULL;
  int output=0;
  if (strlen(filename)>0) {
    if (verbose) printf("Data in the file:%s\n", filename);
    if (append) fp=fopen(filename,"a");
    else        fp=fopen(filename,"w");
    output=1;
  }

  // alloocate storage
  uint32_t *data = new uint32_t[2*(nall+5)];
  uint32_t *data1 = new uint32_t[2*(nall+5)];
  uint32_t *data2 = new uint32_t[2*(nall+5)];
  int nmask=0;
  for (int i=0;i<4;i++) if (mask & (1<<i)) nmask++;
  int adclen = nall+2;
  int len    = nmask* adclen+2;
  uint16_t *adc = new uint16_t[len]; // 4 channels + 4 ch header + 1 event hdr
 
  // write headers
  uint16_t *evhdr  = &adc[0];
  evhdr[0] = 0;
  evhdr[1] = len  *sizeof(uint16_t);
  int imask=0;
  for (int ch=0;ch<4;ch++){
    if (  mask & (1<<ch) ) {
      uint16_t *chhdr= &adc[2+imask*adclen];
      chhdr[0] = ch+1;
      chhdr[1] = adclen *sizeof(uint16_t);
      imask++;
    }
  }

  // start
  int ncount =0;
  int nerrors=0;
  int nball  =0;

  // open VME and initialize board
  char *serial = new char[100];


  VME_START(serial);
  printf("CAEN V1718 BoardFWRelease %s\n", serial);

  V729_init(addr, nall, cbl, bias1,bias2);

  // event loop
  for (int j=0; j<neve; j++) {
     if (ctrlc) break;
     int nb= V729_event(mask,nall,data, data1,data2);
     if (nb<0) {  // timeout
       j--;
       nerrors++;
     } else {

       V729_decode(mask,nall,data,adc, verbose);

       // V729_clear_buffer();
       if (output) nball += fwrite(adc  ,   1, sizeof(uint16_t)*len, fp);

       ncount++;
     }
     time(&t);
     if (t/4!=told ) printf("%d events in %2.2f min (%d s) USBerr=%d TIMEOUTS=%d %s",ncount, (double)(t-tstart)/60.,int(t-tstart), VMEerrors, nerrors, ctime(&t));
     told=t/4;  
  }

  // end
  if (output) fclose(fp);
  VME_STOP();
  time(&t);
  printf("%d events in %2.2f min  (%d s) USBerr=%d TIMEOUTS=%d  %s\n",ncount, (double)(t-tstart)/60.,int(t-tstart),VMEerrors, nerrors, ctime(&t));
  return 0;
}

#endif //V729_MAIN