#include <stdlib.h> 
 
#include <stdio.h> 
 
#include <signal.h> 
 
#include <time.h> 
 
#include <string.h> 
 
#include <sys/types.h> 
 
#include <sys/time.h> 
 
#include <ctype.h> 
 
#include <unistd.h>
 
 
 
#ifdef MRP
 
#include <rp.h>
 
#else
 
#include "calib.h"
 
#endif
 
 
 
#include "fpga_osc.h" 
 
 
 
#define TRUE -1 
 
#define FALSE 0
 
 
 
int timer_out; struct sigaction oact;
 
 
 
int ctrl_c=0;
 
 
 
void SigInt (int sig) {
 
  ctrl_c = 1;
 
}
 
 
 
 
 
void timerast (signumber, code, context) int signumber, code; struct sigcontext context; {
 
  timer_out = TRUE;
 
}
 
 
 
void tmlnk (tout) int tout; {
 
  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)
 
  {
 
  }
 
}
 
 
 
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)
 
  {
 
  }
 
}
 
 
 
#ifndef MRP
 
rp_calib_params_t rp_calib_params; /** Pointer to externally defined calibration parameters. */ rp_calib_params_t *gen_calib_params = NULL;
 
#endif
 
int daq_init (char * buff) {
 
#ifdef DEBUG
 
        fprintf (stderr
, "Server: init\n");  
#endif
 
   int * hdr = (int *) buff;
 
   int delay = hdr[0];
 
   int decimation = hdr[1];
 
   float threshold_voltage = hdr[2]/1000.;
 
   fprintf(stderr
, "delay = %d\tdecimation = %d\tthreshold = %f\n", delay
, decimation
, threshold_voltage
);  
 
 
/*
 
 
 
   rp_default_calib_params(&rp_calib_params);
 
   gen_calib_params = &rp_calib_params;
 
   if(rp_read_calib_params(gen_calib_params) < 0) {
 
       fprintf(stderr, "rp_read_calib_params() failed, using default"
 
           " parameters\n");
 
   }
 
 
 
*/
 
 
 
  // use this to acquire calibrated offset: int offset = gen_calib_params->fe_ch1_dc_offs;
 
#ifdef MRP
 
        if(rp_Init() != RP_OK){
 
          fprintf(stderr
, "Rp api init failed!\n");  
        }
 
        rp_AcqReset();
 
        const int rpdecimation[6]={RP_DEC_1 ,RP_DEC_8 ,RP_DEC_64,
 
                                   RP_DEC_1024 ,RP_DEC_8192  ,RP_DEC_65536   };
 
        rp_AcqSetDecimation(rpdecimation[decimation%6]);
 
        const int c[2] = {RP_CH_1, RP_CH_2};
 
        rp_AcqSetTriggerLevel(c[0],threshold_voltage); //Trig level is set in Volts while in SCPI 
 
        rp_AcqSetTriggerLevel(c[1],threshold_voltage);  
 
        rp_AcqSetTriggerDelay(delay);
 
        return 0;
 
#else
 
  // initialization
 
  int start = osc_fpga_init();
 
  if(start)
 
  {
 
      printf("osc_fpga_init didn't work, retval = %d",start
);  
      return -1;
 
  }
 
 
 
  // set acquisition parameters
 
  osc_fpga_set_trigger_delay(delay);
 
  g_osc_fpga_reg_mem->data_dec = decimation;
 
  osc_fpga_reset();
 
  g_osc_fpga_reg_mem->chb_thr = osc_fpga_cnv_v_to_cnt(threshold_voltage); //sets trigger voltage
 
#endif
 
  fprintf(stderr
, "%s : %d\n", __FILE__
, __LINE__
);  
  return 0;
 
}
 
 
 
int daq_end () {
 
#ifdef DEBUG
 
#endif
 
#ifdef MRP
 
  rp_Release();
 
#else
 
  osc_fpga_exit();
 
#endif
 
  return 0;
 
}
 
 
 
int daq_clear () {
 
#ifdef DEBUG
 
        fprintf (stderr
, "Server: clear\n");  
#endif
 
  return 0;
 
}
 
 
 
 
 
int16_t  chdata[16*1024];
 
float *  chfdata = (float *) chdata;
 
int daq_run (const char *par, char ** data, int *maxlen)
 
 
 
{
 
  
 
  int *data_buf;
 
  int neve;
 
 
 
  unsigned short *sbuff   = (unsigned short *) (par);
 
  unsigned short maxeve   = sbuff[0];
 
  unsigned short nsamples = sbuff[1];
 
  unsigned short tout     = sbuff[2];
 
  unsigned char trigger   = par[6];
 
  unsigned char chmask    = par[7];
 
  clock_t t,t0;
 
  neve = 0;
 
 
 
  int eventsize = 0;
 
  if (chmask & 0x1) eventsize += (nsamples+2);
 
  if (chmask & 0x2) eventsize += (nsamples+2);
 
  eventsize+=4;
 
  int required_size = eventsize * maxeve+3;
 
  
 
#ifdef DEBUG
 
        time_t mtime;
 
        fprintf (stderr
, "daq_run:\tmaxeve %d\tnsamples=%d\ttimeout=%d\ttrigger=%d\tchmask=%d\t%s",  maxeve 
,nsamples
,tout
,trigger
,chmask
, ctime(&mtime
)); //   
#endif
 
    
 
   
 
   if (required_size > *maxlen ) {
 
     *data 
= (char *) malloc(required_size 
*sizeof(int));  
     fprintf(stderr
, "New Buffer with size %d allocated. Old size %d\n", required_size
, *maxlen
);  
     *maxlen = required_size;
 
   } 
 
 
 
  int *ibuf  = (int *)  (*data);
 
 
 
  
 
  data_buf = ibuf + 3;
 
  const int sleeptime = 135*nsamples/16386; //135 us for 16386 samples and to fill the 16k ADC buffer/
 
 
 
  for (int ieve=0; ieve < maxeve; ieve++)
 
    {
 
 
 
#ifdef MRP
 
 
 
rp_AcqStart();
 
usleep(sleeptime);
 
rp_AcqSetTriggerSrc(trigger);
 
timer_out = FALSE;
 
tmlnk (tout); 
 
rp_acq_trig_src_t source;
 
do {
 
  rp_AcqGetTriggerSrc(&source); 
 
  //printf("TRG %d src %d\n", trigger, source);  
 
  if (timer_out || ctrl_c) break;
 
} while (source == trigger);
 
 
 
tmulk ();
 
usleep(sleeptime);
 
 
 
 
 
#else
 
 
 
       osc_fpga_arm_trigger();
 
       usleep(sleeptime);
 
       osc_fpga_set_trigger(trigger);
 
 
 
       while (g_osc_fpga_reg_mem->trig_source != 0){
 
           if (timer_out || ctrl_c) break;
 
       }
 
       // with this loop the program waits until the acquistion is completed before continue.
 
       int trig_ptr = g_osc_fpga_reg_mem->wr_ptr_trigger; // get pointer to mem. adress where trigger was met
 
       int * ch_signal[2];
 
       osc_fpga_get_sig_ptr(&ch_signal[0], &ch_signal[1]);
 
#endif
 
       *(data_buf++) = 0x2;
 
       *(data_buf++) = chmask;
 
 
 
       for (int id = 0;id<2;id++){
 
         if ( !(chmask & (1 << id)) ) continue;
 
 
 
         *(data_buf++) = id;
 
         *(data_buf++) = nsamples;
 
#ifdef MRP
 
        const int c[2] = {RP_CH_1, RP_CH_2};
 
        unsigned int isamples = nsamples;  
 
        rp_AcqGetLatestDataV(c[id], &isamples, (float *) data_buf ); 
 
        data_buf+=nsamples; 
 
#else
 
 
 
         const int BUF = 16*1024;
 
         const int offset =  0;
 
         if (trig_ptr > (BUF-nsamples)) // Enter logic to transition from end to beginning of cha_signal buffer.
 
         {
 
            for (int i=trig_ptr;i<BUF;i++) *(data_buf++) = ch_signal[id][i]-offset;
 
            for (int i=0;i<nsamples-(BUF-trig_ptr);i++) *(data_buf++) = ch_signal[id][i]-offset;
 
         }
 
         else // Enter simple logic to send sampleSize from trigger point
 
         {
 
           for (int i=0;i<nsamples;i++) *(data_buf++) = ch_signal[id][trig_ptr + i]-offset;
 
         }
 
#endif
 
       }
 
       *(data_buf++) = 0x3;
 
       *(data_buf++) = neve;
 
       neve++;
 
       if (ieve
+1 % 500 == 0) fprintf(stderr
, "Event %d\n", ieve
);  
       if (timer_out) break;
 
 
 
    }
 
 
 
 
 
  
 
  int *len   = ibuf;
 
  int *nev   = ibuf + 1;
 
  float *dt = (float *)(ibuf + 2);
 
  
 
  *len   = (data_buf-len)*sizeof(int);
 
  *nev   = neve;
 
  *dt = t-t0;
 
  *dt /= CLOCKS_PER_SEC;
 
  
 
  return *len;
 
}
 
 
 
#define MAXLEN 0XFFFF
 
struct RUNHDR {
 
  unsigned short neve;
 
  unsigned short nsamples;
 
  unsigned short tout;
 
  unsigned char trigger;
 
  unsigned char mask;
 
  int nloops ;
 
  int data [MAXLEN];
 
} ;
 
 
 
 
 
struct INIHDR {
 
  int delay ;  
 
  int decimation;
 
  int threshold;
 
};
 
 
 
 
 
int daq_help(char *fname, struct INIHDR * i, struct RUNHDR *r, int verbosity){
 
 
 
  printf("-o filename ... output filename %s\n", fname
);  
  printf("-v verbose ... verbosity %d\n", verbosity
);  
  printf("-b decimation ... decimation %d\n", i
->decimation
);  
  printf("-i timeout ... interrupt timeout %d\n", r
->tout
);  
  printf("-s nsamples ... number of samples %d\n", r
->nsamples
);  
  printf("-d delay ... delay %d\n", i
->delay
);  
  printf("-t trigger ... trigger type %d\n", r
->trigger
);  
  printf("-l level ... trigger level %f\n", i
->threshold
*0.001);  
  printf("-m mask ... channel mask %d\n", r
->mask 
);  
  printf("-n neve ... number of events per call %d\n", r
->neve
);  
  printf("-r nloops ... number of calls %d\n", r
->nloops
);  
  return 0;
 
}
 
 
 
 
 
 
 
int daq_main( int argc , char ** argv) {
 
  // intercept routine
 
  if (signal (SIGINT, SigInt) == SIG_ERR) {
 
  }
 
 
 
 
 
  char filename[0xFF]="";
 
 
 
 
 
struct INIHDR inihdr = {
 
  .decimation = 1,
 
  .threshold = 100,
 
  .delay = 1024
 
};
 
 
 
 
 
 
 
struct RUNHDR runhdr;
 
 
 
 
 
  runhdr.neve =10000;
 
  runhdr.nsamples = 1024;
 
  runhdr.tout = 1000;
 
  runhdr.trigger = 1;
 
  runhdr.mask = 0x1;
 
  runhdr.nloops = 1;
 
 
 
  int verbose = 0;
 
  int argdata = 0;
 
 
 
  if (argc <2) {
 
    daq_help(filename, &inihdr, &runhdr, verbose);
 
  }
 
 
 
  opterr = 0;
 
  int c;
 
  while ((c = getopt (argc, argv, "o:v:b:i:s:d:t:l:m:n:r:h")) != -1)
 
    switch (c) {
 
      case 'o':
 
        break; // output
 
      case 'v':
 
        break; // verbosity
 
      case 'b':
 
        inihdr.
decimation = strtoul (optarg
,NULL
,0); 
        break;
 
      case 'i':
 
        runhdr.
tout = strtoul (optarg
,NULL
,0); 
        break;
 
      case 's':
 
        runhdr.
nsamples = strtoul (optarg
,NULL
,0); 
        break;
 
      case 'd':
 
        inihdr.
delay = strtoul (optarg
,NULL
,0); 
        break;
 
      case 't':
 
        runhdr.
trigger = strtoul (optarg
,NULL
,0); 
        break;
 
      case 'm':
 
        runhdr.
mask = strtoul (optarg
,NULL
,0); 
        break;
 
      case 'n':
 
        runhdr.
neve = atoi (optarg
); 
        break;
 
      case 'r':
 
        runhdr.
nloops = atoi (optarg
); 
        break;
 
      case 'l':
 
        inihdr.
threshold = (int) (1000*atof (optarg
)); 
        break;
 
      case 'h':
 
        daq_help(filename, &inihdr, &runhdr, verbose);
 
        break;
 
      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
++) argdata 
= strtoul (argv
[i
],NULL
,0);  
  if (verbose) daq_help(filename, &inihdr, &runhdr, verbose);
 
  
 
  printf("argdata %d nloops %d\n",argdata
,runhdr.
nloops);  
 
 
  daq_init((char *)&inihdr);
 
  FILE *fp=NULL;
 
  
 
  
 
  int maxlen = MAXLEN; 
 
  char *data 
= (char *) malloc(maxlen 
* sizeof(int));  
  time_t t,tstart;
 
 
 
  for (int i=0;i< runhdr.nloops;i++){
 
    int nb =daq_run((const char*) &runhdr, &data, &maxlen);
 
    if (ctrl_c) break;
 
    fprintf(stderr
, "Loop %d dt=%d s\n", i
, (int)(t
-tstart
));  
    
 
    if (fp) {
 
      fprintf(stderr
, "Writing %d to %s", nb
, filename
);  
    }
 
    
 
  }
 
  fprintf(stderr
, "Total events %d in  %d s\n", runhdr.
nloops*runhdr.
neve, (int)(t
-tstart
));  
  if (data
!=NULL
) free(data
);  
  return 0;
 
}