//
 
//  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) {
 
  }
 
  if (setitimer (ITIMER_REAL, &tdelay, NULL) < 0) {
 
  }
 
 
 
#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) {
 
  }
 
  if (sigaction (SIGALRM, &oact, NULL) < 0) {
 
  }
 
#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
);  
 
 
// 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 (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 (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 ("-d <debuglevel>  \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;
 
  tstart=t;
 
  InitializeTimerOut();
 
  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++;
 
    }
 
#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);
 
      }
 
    }
 
  }
 
  CAEN_V729_param.fp = NULL;
 
  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();
 
  }
 
  // 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);
 
  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 ) {
 
      break;
 
    }
 
  } while (1);
 
 
 
  CmtDiscardThreadPool (poolHandle);
 
  DiscardPanel (p4h);
 
 
 
  VME_STOP();
 
  return 0;
 
}
 
#endif V729_WINMAIN