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 <stdint.h>
#include <stdio.h>
#include <string.h>



#ifdef _CVI_
#  include <windows.h>
#  include "CAEN_V729_CVI.h"
#  include "asynctmr.h"
#  include "H1D.h"
#  include "H2D.h"
#  include "HDraw.h"
typedef signed char   int8_t;
typedef unsigned char  uint8_t;
typedef short  int16_t;
typedef unsigned short uint16_t;
typedef int  int32_t;
typedef unsigned int  uint32_t;
#  include <utility.h>
#  define usleep(x) Delay(x*1e-3)
#include "sa02lib.h"
#define printf sa02Printf
# else _CVI_
#  include <unistd.h>
#  include <ctype.h>
#  include <vector>
#  include <sys/time.h>
#  include <sys/stat.h>
#  include <signal.h>
#  include <string>
#endif _CVI_


#include "vme.h"
#include "CAEN_V729_DEF.h"
#include "CAEN_V729.h"
#include "dataio.h"

//#include <utility.h>
CAEN_V729_PARAM  CAEN_V729_param;

#define IREG_OFFSET 0x2000
#define V729_WAIT 100


#define TRUE 1
#define FALSE 0

uint32_t V729_module=0;


static int          g_timerId              = 0;

#ifdef V729_MAIN
int ctrl_c=0;
# else V729_MAIN
#  ifdef V729_WINMAIN
int ctrl_c=0;
#   else V729_WINMAIN
extern int ctrl_c;
#  endif V729_WINMAIN
#endif V729_MAIN

#ifndef WIN32
struct sigaction oact;
#endif WIN32
//---------------------------------------------------------


//---------------------------------------------------------
DefineThreadSafeScalarVar (int, TimerOut,0);


void timerast (int signumber) {

}

//---------------------------------------------------------

int CVICALLBACK TimerOutCallback (int reserved, int theTimerId, int event,
                                  void *callbackData, int eventData1,
                                  int eventData2) {
  double currentTime = 0.0;
  double deltaTime   = 0.0;
  int id;
  /* Like a regular UI timer, the async. timer's callback is passed the    */
  /* total elapsed time and the time since the last tick.                  */
  if ((double*)eventData1)
    currentTime = *((double*)eventData1);
  if ((double*)eventData2)
    deltaTime   = *((double*)eventData2);
  if (event == EVENT_TIMER_TICK) {
    SetTimerOut(TRUE);
    id= *((int *)callbackData);
    fprintf(stdout,"TIMEOUT %d !!!\n", id );

  }
  /* We will get an EVENT_DISCARD when the timer is destroyed. */
  if (event == EVENT_DISCARD)
    g_timerId = 0;
  return 0;
}

int g_tmlnk;
void tmlnk (int tout) {

  //timer_out=0;
#ifdef _CVI_
  g_tmlnk = tout;
  SetTimerOut(FALSE);
  g_timerId = NewAsyncTimer (((double)tout) *10./ 1000.0, 1, 1, TimerOutCallback, &g_tmlnk);
# else _CVI_

  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);
  }

#endif _CVI_
}

//---------------------------------------------------------
void tmulk ( void ){
#ifdef _CVI_
  DiscardAsyncTimer( g_timerId );
# else _CVI_
  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);
  }
#endif _CVI_
}

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

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

//---------------------------------------------------------


void V729_map( uint32_t addr) {
  V729_module = addr;
  return;
}
//---------------------------------------------------------  
int V729_status( void ){
  uint32_t status;
  VME_A24D16_R(V729_module+V729_CSR, &status);
  return status;
}
//---------------------------------------------------------
void V729_info(FILE *kam) {
  uint32_t code, mid, ver;


  VME_A24D16_R(V729_module+0xFA,&code);
  VME_A24D16_R(V729_module+0xFC,&mid);
  VME_A24D16_R(V729_module+0xFE,&ver);
  printf( "code/mid/ver = 0x%04X/0x%04X/0x%04X\n", code, mid, ver);
  printf( "Fixed code (0xFAF5) = 0x%04X\n", code);
  printf( "Manufacturer/Type = 0x%02X/0x%03X\n",
          (mid & 0xFC00)>>10, mid & 0x3FF);
  printf( "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;
  uint32_t val=0;
//  cbl=4096+12-100;
  cbl=4096+12-nbefore;

  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) ); //

  printf("CSR = 0x%x\n", V729_status() );
// 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, "V729_CSR 0x0E = 0x%04X\n", status);
#endif V729_DEBUG

  VME_A24D16_W(V729_module+V729_CSR, mode); //aquisition mode
  usleep(V729_WAIT);
#ifdef V729_DEBUG
  fprintf(stderr, "V729_CSR 0x0E = 0x%04X\n", mode);
  VME_A24D16_R(V729_module+V729_CSR, &status);
  usleep(V729_WAIT);
  fprintf(stderr, "V729_CSR 0x0E = 0x%04X\n", status);
#endif V729_DEBUG
  return;
}

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

//---------------------------------------------------------
void V729_clear_buffer( void ){
    uint32_t data1,data2;
    const int tout=100; /* 1/100 of a second */
   
  int cnt=0;
  tmlnk (tout);

  do {
    VME_A24D32_R(V729_module+V729_OBR1, &data1);

    if (ctrl_c|| GetTimerOut()) break;


    cnt++;
  } while (data1 & (0x3<<29));

  cnt=0;
  do {
    VME_A24D32_R(V729_module+V729_OBR2, &data2);

    if (ctrl_c|| GetTimerOut()) break;

    cnt++;
  } 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;
}



//---------------------------------------------------------
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,0x1); // obaf = 1, disable start signals when there is at least one sample in the buffer
  V729_reset(nall,cbl,nall,4000); // obaf = 1, disable start signals when there is at least one sample in the buffer
  V729_set_bias(0,bias1,bias2);
  V729_aquisition_mode(0);
#ifndef WIN32
  CAENVME_SetFIFOMode(udev,1);
  sleep(1);
#endif WIN32
}


//---------------------------------------------------------
int V729_blt=0;
int V729_SetBltMode(int mode) {
  V729_blt = mode;
  return mode;
}

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


  //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   // KEK magnet
  //
  do {

    VME_A24D16_R(V729_module+V729_CSR, &status);

    count++;
    if (ctrl_c || GetTimerOut()) {
      tmulk ();
      printf("[%d] daq=%x status %x AE01=%d AE23=%d Waiting for DATA TRG bit... at line %d\n",count ,  (status>>4)&0x3,status, status&0x1,(status>>2)&0x1 , __LINE__);

      V729_clear_buffer();

      return -1;
    }

  } while ((status & 0x5) ^ 0x5);
  tmulk ();
  //count =  (nall+5);
  count =  (nall+1);
  if (V729_blt) {

//#ifdef CAEN_V1718
//  VME_A24D32_FIFOBLTR(V729_module+V729_OBR1,data1,count*sizeof(uint32_t),&nb);
//  VME_A24D32_FIFOBLTR(V729_module+V729_OBR2,data2,count *sizeof(uint32_t),&nb);
//#endif CAEN_V1718
    for (i=0; i<count; i++) {
      data[2*i]   = data1[i];
      data[2*i+1] = data2[i];
    }
    nb*=2;
  } else {
    int nc=0;
    int j=0;
    VME_MRRST(); // MultiReadReset

    do {
      VME_R(VME_A24,VME_D32,V729_module+V729_OBR1, &data[nc]);
    } while ( !((data[nc]>>31)&0x1) );
    nc++;
    do {
      VME_R(VME_A24,VME_D32,V729_module+V729_OBR2, &data[nc]);
    } while ( !((data[nc]>>31)&0x1) );
    nc++;
    for (i=0; i<nall; i++) {
      //if (mask & 0x3)
      VME_MR(VME_A24,VME_D32,V729_module+V729_OBR1, &data[nc++]);
      //if (mask & 0xc)
      VME_MR(VME_A24,VME_D32,V729_module+V729_OBR2, &data[nc++]);
    }
 
    j = nc;
    if ( VME_GetInterface()!= WIENER_VMEMM ) j = VME_MREXEC(data); // MultiReadExecute  
                                           

    nb=j*sizeof(uint32_t);

  }

  return nb;
}
int V729_plothandle;
//---------------------------------------------------------
int V729_plot(int first, uint16_t *buf ) {
#ifdef _CVI_
  int start=23;
  int end=35;

  //const double maxy=2048;
  const double maxy=512;
  const double maxx=512;
  //const double maxy=2048;
  //const double maxy=128;
  //const double maxy=512;
  const int nx=500;

  const int ny=100;
  const int h0=10;

  int i;
  uint32_t *hdr = (uint32_t *)buf;
  int nb= hdr[1]-2*sizeof(uint32_t);
  int nitems = nb /sizeof(uint16_t);
  unsigned int recid=hdr[0];
  uint16_t *data = &buf[4];
  double x,y;
  double baseline=0;
  double charge=0;


  while (nitems>0) {
    int id = data[0]-1;
    int len= data[1]/sizeof(uint16_t)-2;

    if (CAEN_V729_param.verbose)  printf("\t->> recid=%d nb=%d nitems=%d id=%d len=%d\n", recid, hdr[1],nitems,id,len);
    if (id>3) return 0;

    data+=2;

    if (first) {
      for (i=0; i<4; i++) {
        char hname[0xFF];
        char htitle[0xFF];
        sprintf (hname,"hwf%d",i);
        sprintf (htitle,"CAEN V729 ch%d",i);
        H2DInit(h0+i,hname, htitle ,len,-0.5,1,ny,-maxy,2*maxy/ny);
        H2DSetTitleX(h0+i,"timebin");
        H2DSetTitleY(h0+i,"pulse height");

        sprintf (hname,"hcharge%d",i);
        sprintf (htitle,"CAEN V729 ch%d",i);
        H1DInit(h0+i,hname, htitle ,nx,-maxx,2*maxx/nx);
        H1DSetTitleX(h0+i,"timebin");
        H1DSetTitleY(h0+i,"charge");
      }
      first=0;
      // h1d=new TH1F("h1d","Charge;signal charge(a.u.);N",500,-maxy,5*maxy);

    }

    baseline=0;
    for (i=0; i<20; i++) baseline += data[i];
    baseline /=20.;
    // baseline=2000;


    for (i=0; i<len; i++) {
      if (CAEN_V729_param.verbose >2) printf("ADC %d %d\n", i, data[i]);
      x=i;
      y=data[i];
      y-=baseline;
      if (i>=start && i<end) charge += y;

      H2DFill(h0+id,x,y,1);
    }
    charge /=(end-start);
    H1DFill(h0+id,charge,1);

    data+=len;
    nitems=nitems - len-2;
    //if (id==2) h1d->Fill(charge);
  }
#else
#warning _CVI_ is not defined  
#endif _CVI_
 
  return 0;
}

//---------------------------------------------------------
int V729_decode(uint32_t mask, int nall, uint32_t *data,  uint16_t *dadc, int debug) {

  int hdrlen=6;  // 4+2
  uint16_t *adc[4]= {0};
  int i,j;

  int nc=0;
  int narrays=0;


  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 (i=0; i<4; i++) {
    adc[i] = &dadc[hdrlen+i*(nall+2)];
    // printf("---->ID %d len %d ,%d\n",dadc[hdrlen+i*(nall-2)],dadc[hdrlen+i*(nall-1)],hdrlen+i*(nall+2)) ;
  }
  if (mask & 0x3) narrays++;
  if (mask & 0xc) narrays++;

  for (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 (j=0; j<nmask; j++) {
    nc=0;
    for (i=0; i<nall+1; 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 %d\n", (data1>>29) & 0x3, data1 & 0xFFFFFF, data1 & 0xFFFFFF);
      } else if ((data1>>29) & 0x3) {
        if (nc<nall) {
          adc[j][nc] = (data1>>shft[j]) & 0xFFF;
          if (debug >2) 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;
}

//---------------------------------------------------------
void V729_Usage(void) {

  printf ("*********************************************************************************:\n");
  printf ("Usage: CAEN_V729 <arguments> .........   CAEN V729A data aquisition:\n\n");
  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");
}
//---------------------------------------------------------
// test program

int V729_GetParams(int argc,char **argv) {
#ifdef _CVI_
  int p = CAEN_V729_param.panel;
  GetCtrlVal(p,P4_MASK,&CAEN_V729_param.mask);
  GetCtrlVal(p,P4_CBL ,&CAEN_V729_param.cbl);
  GetCtrlVal(p,P4_NALL,&CAEN_V729_param.nall);
  GetCtrlVal(p,P4_FILENAME,CAEN_V729_param.filename);
  GetCtrlVal(p,P4_VERBOSE,&CAEN_V729_param.verbose);
  GetCtrlVal(p,P4_NEVE,&CAEN_V729_param.neve);
  GetCtrlVal(p,P4_ADDR,&CAEN_V729_param.addr);
  GetCtrlVal(p,P4_BIAS1,&CAEN_V729_param.bias1);
  GetCtrlVal(p,P4_BIAS2,&CAEN_V729_param.bias2);
  GetCtrlVal(p,P4_FRACTION,&CAEN_V729_param.fraction);

# else _CVI_
  CAEN_V729_param.mask=0xF;
  CAEN_V729_param.cbl=13;
  CAEN_V729_param.nall=1330;
  CAEN_V729_param.filename= 0;
  CAEN_V729_param.verbose = 0;
  CAEN_V729_param.neve    = 1;
  CAEN_V729_param.addr = V729_OFFSET;
  CAEN_V729_param.bias1 = 0x500; // vecje vrednosti povzrocajo tezave in zacno kanali oscilirat ....
  CAEN_V729_param.bias2 = 0x500;
  CAEN_V729_param.append = 0;
  CAEN_V729_param.fp = NULL;
  CAEN_V729_param.fraction = 0;
  int c=0;
  while ((c = getopt (argc, argv, "b:e:a:d:c:l:n:o:m:f:r:")) != -1)
    switch (c) {
      case 'd':
        CAEN_V729_param.verbose=atoi(optarg);
        break;
      case 'c':
        CAEN_V729_param.cbl=atoi(optarg);
        break;
      case 'l':
        CAEN_V729_param.nall=atoi(optarg);

        if (CAEN_V729_param.nall%16) {
          printf ("buffer length should be multiple of 16 , modulo = %d\n",CAEN_V729_param.nall%16);
          // exit(-1);
        }
        break;
      case 'n':
        CAEN_V729_param.neve=atoi(optarg);
        break;
      case 'r':
        CAEN_V729_param.fraction=atof(optarg);
        break;
      case 'a':
        CAEN_V729_param.addr=strtoul (optarg,NULL,0);
        break;             // address
      case 'b':
        CAEN_V729_param.bias1=strtoul (optarg,NULL,0);
        break;             // bias
      case 'e':
        CAEN_V729_param.bias2=strtoul (optarg,NULL,0);
        break;             // bias

      case 'm':
        CAEN_V729_param.mask=strtoul (optarg,NULL,0);
        break;             // mask
      case 'o':
        sprintf(CAEN_V729_param.filename,"%s", optarg );
        CAEN_V729_param.append=0;
        break;       // output
      case 'f':
        sprintf(CAEN_V729_param.filename,"%s", optarg );
        CAEN_V729_param.append=1;
        break;       // output
    }
#endif _CVI_
  return 0;
}

int V729_LoadPanel (int Parent_Panel_Handle, char Filename[], int Panel_Resource_ID) {

  CAEN_V729_param.panel = LoadPanel(Parent_Panel_Handle, Filename, Panel_Resource_ID);
  return CAEN_V729_param.panel;
}



#ifdef _CVI_
int CVICALLBACK HDrawCB (int panel, int control, int event,
                         void *callbackData, int eventData1, int eventData2) {
  int ch=0,type=0;
  switch (event) {
    case EVENT_COMMIT:
      GetCtrlVal(CAEN_V729_param.panel,P4_ADCCH, &ch);
      GetCtrlVal(CAEN_V729_param.panel,P4_HDISPLAY, &type);
      if (type) {
        H2DDraw(10+ch,CAEN_V729_param.panel,P4_GRAPH, &V729_plothandle);
      } else {
        H1DDraw(10+ch,CAEN_V729_param.panel,P4_GRAPH, &V729_plothandle);
      }
      break;
  }
  return 0;
}

int CVICALLBACK V729_daq(void *functionData) {
  return V729_main ( 0, NULL);
}
#endif _CVI_

void CatchSig (int i) {
  ctrl_c = 1;
}

int p4h;

int  V729_SetFilePointer (FILE *fp) {
  CAEN_V729_param.fp = fp;
  return 0;
}

int  V729_main (int argc,char **argv) {
  int hdrlen=4; // number of u16 words
  FILE *fp=NULL;
  int output=0;
  int bsize;
  int nmask,imask;
  int i,ch, len,nb;
  int adclen;
  uint32_t *data , *data1 ,*data2 ;
  uint16_t *adc ;
  uint32_t *evhdr;
  int ncount =0;
  int nerrors=0;
  int nball  =0;


  // reset timers
  time_t t,told=0, tstart;
  time(&t);
  tstart=t;
  InitializeTimerOut();
  printf("V729_main \n");
  V729_GetParams(argc,argv);
  // open file
  if (CAEN_V729_param.fp !=NULL) {
    fp= CAEN_V729_param.fp;
    output=2;
    printf("V729_main Data file is already opened\n");
  } else {
    if (strlen(CAEN_V729_param.filename)>0) {
      if (CAEN_V729_param.verbose) printf("Data in the file:%s\n", CAEN_V729_param.filename);
      if (CAEN_V729_param.append) fp=fopen(CAEN_V729_param.filename,"a");
      else        fp=fopen(CAEN_V729_param.filename,"w");
      output=1;
    }
  }


  // allocate storage

  bsize = sizeof(uint32_t)*2*(CAEN_V729_param.nall+1);
  data  = (uint32_t *)malloc(bsize);
  data1 = (uint32_t *)malloc(bsize);
  data2 = (uint32_t *)malloc(bsize);
  nmask=0;
  for (i=0; i<4; i++) if (CAEN_V729_param.mask & (1<<i)) nmask++;
  adclen = CAEN_V729_param.nall+2;
  len    = nmask* adclen+hdrlen;
  adc = (uint16_t *) malloc(len  *sizeof(uint16_t)); // 4 channels + 4 ch header + 1 event hdr

  // write headers
  evhdr  = (uint32_t *) &adc[0];
  evhdr[0] = CAENV729REC_ID;
  evhdr[1] = len  *sizeof(uint16_t);
  imask=0;
  for (ch=0; ch<4; ch++) {
    if (  CAEN_V729_param.mask & (1<<ch) ) {
      uint16_t *chhdr= &adc[hdrlen+imask*adclen];
      chhdr[0] = (uint16_t) ch+1;
      chhdr[1] = (uint16_t) adclen * sizeof(uint16_t);
      //printf("========>%d %d [%d,%d,%d]hdr=%d %d\n",ch, hdrlen+imask*adclen,hdrlen,imask,adclen,chhdr[0],chhdr[1]);
      imask++;

    }
  }

  // start


  // open VME and initialize board

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

  // event loop
  for (i=0; i<CAEN_V729_param.neve; i++) {
    GetCtrlVal(CAEN_V729_param.panel,P4_VERBOSE,&CAEN_V729_param.verbose);
    if ( CAEN_V729_param.verbose) printf("neve=%d\n",i);
    nb = V729_event(CAEN_V729_param.mask,CAEN_V729_param.nall,data, data1,data2);

    if (ctrl_c) {

      break;
    }
    if (nb<0) {  // timeout
      i--;
      nerrors++;
    } else {

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

#ifdef _CVI_
      V729_plot(!i, adc );
#endif _CVI_

      if (output) {
        if (Random(0,1)<CAEN_V729_param.fraction) {
          nball += fwrite(adc  ,   1, sizeof(uint16_t)*len, fp);
        }
      }
      ncount++;
    }
    time(&t);
#ifdef _CVI_
    if (t/4!=told ) {
      double done=0;
      if (CAEN_V729_param.neve) done= (double) (i)/CAEN_V729_param.neve;
      HDrawCB ( 0, 0, EVENT_COMMIT ,NULL, 0,0);

      EstimatedFinish(CAEN_V729_param.panel, P4_PROGRESS, P4_ETA, tstart, done);
    }
#endif _CVI_
    if (t/4!=told ) printf("%d events in %2.2f min (%d s) TIMEOUTS=%d %s",ncount, (double)(t-tstart)/60.,(int)(t-tstart), nerrors, ctime(&t));
    told=t/4;
  }
#ifdef _CVI_
  HDrawCB ( 0, 0, EVENT_COMMIT ,NULL, 0,0);
#endif _CVI_
  // end
  if (output) {
    for (ch=0; ch<4; ch++) {
      if (  CAEN_V729_param.mask & (1<<ch) ) {
        H2DWrite2File(10+ch,fp);
        H1DWrite2File(10+ch,fp);
      }
    }
    if (output==1) fclose(fp);
  }
  CAEN_V729_param.fp = NULL;
  free(data);
  free(data2);
  free(data1);
  free(adc);
  time(&t);
  printf("%d events in %2.2f min  (%d s)  TIMEOUTS=%d  %s\n",ncount, (double)(t-tstart)/60.,(int)(t-tstart), nerrors, ctime(&t));
  return 0;
}



#ifdef V729_MAIN
int main(int argc,char **argv) {
  if (argc == 1) {

    V729_Usage();
    exit (-1);
  }
  // intercept routine
  if (signal (SIGINT, CatchSig) == SIG_ERR)  perror ("sigignore");
  VME_START(NULL);
  V729_main (argc,argv);
  VME_STOP();
  return ;
}
#endif V729_MAIN

#ifdef V729_WINMAIN

int CVICALLBACK HidePanelCB (int panel, int control, int event,
                             void *callbackData, int eventData1, int eventData2) {
  switch (event) {
    case EVENT_COMMIT:
      HidePanel (panel);
      break;
  }
  return 0;
}


void SetDimming(int state) {
  SetCtrlAttribute (p4h, P4_DAQ, ATTR_DIMMED, state);
  SetCtrlAttribute (p4h, P4_STOP, ATTR_DIMMED, !state);
}

void CVICALLBACK EndOfThread (int poolHandle, int functionID, unsigned int event, int value, void *callbackData) {


  SetDimming(0);
  printf("End of Thread \n");
  return ;

}

static int poolHandle = 0;
static int p1h, pID, rID, tfID;
#  define MAX_THREADS 10
int __stdcall WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                       LPSTR lpszCmdLine, int nCmdShow) {
  char title[0xFF]="";
  int i;
  if (InitCVIRTE (hInstance, 0, 0) == 0)
    return -1;  /* out of memory */

  SetSleepPolicy(VAL_SLEEP_MORE);
  CmtNewThreadPool (MAX_THREADS, &poolHandle);

  VME_START(WIENER_VMEMM);
  SetStdioPort (CVI_STDIO_WINDOW );
  if ((p4h = V729_LoadPanel (0, "CAEN_V729_CVI.uir", P4)) < 0)
    return -1;

  GetPanelAttribute (p4h, ATTR_TITLE, title );

  SetPanelAttribute (p4h, ATTR_TITLE, title );


  DisplayPanel (p4h);

  InitColors();

  do {
    ThreadFunctionPtr mythread = NULL;
    GetUserEvent (1, &pID, &rID);


    if (pID ==p4h && rID == P4_DAQ            ) mythread=V729_daq;
    if (mythread!=NULL) {
      printf("New Thread panel=%d button=%d\n", pID, rID);
      ctrl_c=0;


      CmtScheduleThreadPoolFunctionAdv (poolHandle, mythread, &rID,
                                        DEFAULT_THREAD_PRIORITY,
                                        EndOfThread,
                                        EVENT_TP_THREAD_FUNCTION_END,
                                        NULL, RUN_IN_SCHEDULED_THREAD,
                                        &tfID);
      SetDimming(1);
    }

    if ( pID==p4h && rID == P4_STOP ) {
      printf("Stopping the  Thread %d\n", tfID);
      ctrl_c=1;
    }
    if ( pID==p4h && rID == P4_HIDE ) {
      printf("Exit\n");
      break;
    }
  } while (1);

  CmtDiscardThreadPool (poolHandle);
  DiscardPanel (p4h);

  VME_STOP();
  return 0;
}
#endif V729_WINMAIN