Details | Last modification | View Log | RSS feed
| Rev | Author | Line No. | Line |
|---|---|---|---|
| 360 | f9daq | 1 | #include <stdlib.h> |
| 2 | #include <stdio.h> |
||
| 3 | #include <signal.h> |
||
| 4 | #include <time.h> |
||
| 5 | #include <string.h> |
||
| 6 | #include <sys/types.h> |
||
| 7 | #include <sys/time.h> |
||
| 8 | #include <ctype.h> |
||
| 9 | #include <unistd.h> |
||
| 10 | |||
| 11 | #ifdef MRP |
||
| 12 | #include <rp.h> |
||
| 13 | #else |
||
| 14 | #include "calib.h" |
||
| 15 | #endif |
||
| 16 | |||
| 17 | #include "fpga_osc.h" |
||
| 18 | |||
| 19 | #define TRUE -1 |
||
| 20 | #define FALSE 0 |
||
| 21 | |||
| 22 | int timer_out; struct sigaction oact; |
||
| 23 | |||
| 24 | int ctrl_c=0; |
||
| 25 | |||
| 26 | void SigInt (int sig) { |
||
| 27 | ctrl_c = 1; |
||
| 28 | } |
||
| 29 | |||
| 30 | |||
| 31 | void timerast (signumber, code, context) int signumber, code; struct sigcontext context; { |
||
| 32 | fprintf(stderr, "Timeout\n"); |
||
| 33 | timer_out = TRUE; |
||
| 34 | } |
||
| 35 | |||
| 36 | void tmlnk (tout) int tout; { |
||
| 37 | struct sigaction act; |
||
| 38 | struct itimerval tdelay; |
||
| 39 | |||
| 40 | act.sa_handler = timerast; |
||
| 41 | sigemptyset (&act.sa_mask); |
||
| 42 | act.sa_flags = 0; |
||
| 43 | |||
| 44 | tdelay.it_value.tv_sec = tout / 100; |
||
| 45 | tdelay.it_value.tv_usec = 10000 * (tout % 100); |
||
| 46 | tdelay.it_interval.tv_sec = 0; |
||
| 47 | tdelay.it_interval.tv_usec = 0; |
||
| 48 | |||
| 49 | if (sigaction (SIGALRM, &act, &oact) < 0) |
||
| 50 | { |
||
| 51 | perror ("sigaction(tmlnk)"); |
||
| 52 | exit (EXIT_FAILURE); |
||
| 53 | } |
||
| 54 | if (setitimer (ITIMER_REAL, &tdelay, NULL) < 0) |
||
| 55 | { |
||
| 56 | perror ("setitimer(tmlnk)"); |
||
| 57 | exit (EXIT_FAILURE); |
||
| 58 | } |
||
| 59 | } |
||
| 60 | |||
| 61 | void tmulk () { |
||
| 62 | struct itimerval tdelay; |
||
| 63 | |||
| 64 | tdelay.it_value.tv_sec = 0; |
||
| 65 | tdelay.it_value.tv_usec = 0; |
||
| 66 | tdelay.it_interval.tv_sec = 0; |
||
| 67 | tdelay.it_interval.tv_usec = 0; |
||
| 68 | |||
| 69 | if (setitimer (ITIMER_REAL, &tdelay, NULL) < 0) |
||
| 70 | { |
||
| 71 | perror ("setitimer(tmulk)"); |
||
| 72 | exit (EXIT_FAILURE); |
||
| 73 | } |
||
| 74 | if (sigaction (SIGALRM, &oact, NULL) < 0) |
||
| 75 | { |
||
| 76 | perror ("sigaction(tmulk)"); |
||
| 77 | exit (EXIT_FAILURE); |
||
| 78 | } |
||
| 79 | } |
||
| 80 | |||
| 81 | #ifndef MRP |
||
| 82 | rp_calib_params_t rp_calib_params; /** Pointer to externally defined calibration parameters. */ rp_calib_params_t *gen_calib_params = NULL; |
||
| 83 | #endif |
||
| 84 | int daq_init (char * buff) { |
||
| 85 | #ifdef DEBUG |
||
| 86 | fprintf (stderr, "Server: init\n"); |
||
| 87 | #endif |
||
| 88 | int * hdr = (int *) buff; |
||
| 89 | int delay = hdr[0]; |
||
| 90 | int decimation = hdr[1]; |
||
| 91 | float threshold_voltage = hdr[2]/1000.; |
||
| 92 | fprintf(stderr, "delay = %d\tdecimation = %d\tthreshold = %f\n", delay, decimation, threshold_voltage); |
||
| 93 | |||
| 94 | /* |
||
| 95 | |||
| 96 | rp_default_calib_params(&rp_calib_params); |
||
| 97 | gen_calib_params = &rp_calib_params; |
||
| 98 | if(rp_read_calib_params(gen_calib_params) < 0) { |
||
| 99 | fprintf(stderr, "rp_read_calib_params() failed, using default" |
||
| 100 | " parameters\n"); |
||
| 101 | } |
||
| 102 | |||
| 103 | */ |
||
| 104 | |||
| 105 | // use this to acquire calibrated offset: int offset = gen_calib_params->fe_ch1_dc_offs; |
||
| 106 | #ifdef MRP |
||
| 107 | if(rp_Init() != RP_OK){ |
||
| 108 | fprintf(stderr, "Rp api init failed!\n"); |
||
| 109 | } |
||
| 110 | rp_AcqReset(); |
||
| 111 | const int rpdecimation[6]={RP_DEC_1 ,RP_DEC_8 ,RP_DEC_64, |
||
| 112 | RP_DEC_1024 ,RP_DEC_8192 ,RP_DEC_65536 }; |
||
| 113 | rp_AcqSetDecimation(rpdecimation[decimation%6]); |
||
| 114 | const int c[2] = {RP_CH_1, RP_CH_2}; |
||
| 115 | rp_AcqSetTriggerLevel(c[0],threshold_voltage); //Trig level is set in Volts while in SCPI |
||
| 116 | rp_AcqSetTriggerLevel(c[1],threshold_voltage); |
||
| 117 | rp_AcqSetTriggerDelay(delay); |
||
| 118 | return 0; |
||
| 119 | #else |
||
| 120 | // initialization |
||
| 121 | int start = osc_fpga_init(); |
||
| 122 | if(start) |
||
| 123 | { |
||
| 124 | printf("osc_fpga_init didn't work, retval = %d",start); |
||
| 125 | return -1; |
||
| 126 | } |
||
| 127 | |||
| 128 | // set acquisition parameters |
||
| 129 | osc_fpga_set_trigger_delay(delay); |
||
| 130 | g_osc_fpga_reg_mem->data_dec = decimation; |
||
| 131 | osc_fpga_reset(); |
||
| 132 | g_osc_fpga_reg_mem->chb_thr = osc_fpga_cnv_v_to_cnt(threshold_voltage); //sets trigger voltage |
||
| 133 | #endif |
||
| 134 | fprintf(stderr, "%s : %d\n", __FILE__, __LINE__); |
||
| 135 | return 0; |
||
| 136 | } |
||
| 137 | |||
| 138 | int daq_end () { |
||
| 139 | #ifdef DEBUG |
||
| 140 | fprintf (stderr, "Server: end\n"); |
||
| 141 | #endif |
||
| 142 | #ifdef MRP |
||
| 143 | rp_Release(); |
||
| 144 | #else |
||
| 145 | osc_fpga_exit(); |
||
| 146 | #endif |
||
| 147 | return 0; |
||
| 148 | } |
||
| 149 | |||
| 150 | int daq_clear () { |
||
| 151 | #ifdef DEBUG |
||
| 152 | fprintf (stderr, "Server: clear\n"); |
||
| 153 | #endif |
||
| 154 | return 0; |
||
| 155 | } |
||
| 156 | |||
| 157 | |||
| 158 | int16_t chdata[16*1024]; |
||
| 159 | float * chfdata = (float *) chdata; |
||
| 160 | int daq_run (const char *par, char ** data, int *maxlen) |
||
| 161 | |||
| 162 | { |
||
| 163 | |||
| 164 | int *data_buf; |
||
| 165 | int neve; |
||
| 166 | |||
| 167 | unsigned short *sbuff = (unsigned short *) (par); |
||
| 168 | unsigned short maxeve = sbuff[0]; |
||
| 169 | unsigned short nsamples = sbuff[1]; |
||
| 170 | unsigned short tout = sbuff[2]; |
||
| 171 | unsigned char trigger = par[6]; |
||
| 172 | unsigned char chmask = par[7]; |
||
| 173 | clock_t t,t0; |
||
| 174 | neve = 0; |
||
| 175 | |||
| 176 | t0=clock(); |
||
| 177 | int eventsize = 0; |
||
| 178 | if (chmask & 0x1) eventsize += (nsamples+2); |
||
| 179 | if (chmask & 0x2) eventsize += (nsamples+2); |
||
| 180 | eventsize+=4; |
||
| 181 | int required_size = eventsize * maxeve+3; |
||
| 182 | |||
| 183 | #ifdef DEBUG |
||
| 184 | time_t mtime; |
||
| 185 | time(&mtime); |
||
| 186 | fprintf (stderr, "daq_run:\tmaxeve %d\tnsamples=%d\ttimeout=%d\ttrigger=%d\tchmask=%d\t%s", maxeve ,nsamples,tout,trigger,chmask, ctime(&mtime)); // |
||
| 187 | #endif |
||
| 188 | |||
| 189 | |||
| 190 | if (required_size > *maxlen ) { |
||
| 191 | free (*data); |
||
| 192 | *data = (char *) malloc(required_size *sizeof(int)); |
||
| 193 | fprintf(stderr, "New Buffer with size %d allocated. Old size %d\n", required_size, *maxlen); |
||
| 194 | *maxlen = required_size; |
||
| 195 | } |
||
| 196 | |||
| 197 | int *ibuf = (int *) (*data); |
||
| 198 | |||
| 199 | |||
| 200 | data_buf = ibuf + 3; |
||
| 201 | const int sleeptime = 135*nsamples/16386; //135 us for 16386 samples and to fill the 16k ADC buffer/ |
||
| 202 | |||
| 203 | for (int ieve=0; ieve < maxeve; ieve++) |
||
| 204 | { |
||
| 205 | |||
| 206 | #ifdef MRP |
||
| 207 | |||
| 208 | rp_AcqStart(); |
||
| 209 | usleep(sleeptime); |
||
| 210 | rp_AcqSetTriggerSrc(trigger); |
||
| 211 | timer_out = FALSE; |
||
| 212 | tmlnk (tout); |
||
| 213 | rp_acq_trig_src_t source; |
||
| 214 | do { |
||
| 215 | rp_AcqGetTriggerSrc(&source); |
||
| 216 | //printf("TRG %d src %d\n", trigger, source); |
||
| 217 | if (timer_out || ctrl_c) break; |
||
| 218 | } while (source == trigger); |
||
| 219 | |||
| 220 | tmulk (); |
||
| 221 | usleep(sleeptime); |
||
| 222 | |||
| 223 | |||
| 224 | #else |
||
| 225 | |||
| 226 | osc_fpga_arm_trigger(); |
||
| 227 | usleep(sleeptime); |
||
| 228 | osc_fpga_set_trigger(trigger); |
||
| 229 | |||
| 230 | while (g_osc_fpga_reg_mem->trig_source != 0){ |
||
| 231 | if (timer_out || ctrl_c) break; |
||
| 232 | } |
||
| 233 | // with this loop the program waits until the acquistion is completed before continue. |
||
| 234 | int trig_ptr = g_osc_fpga_reg_mem->wr_ptr_trigger; // get pointer to mem. adress where trigger was met |
||
| 235 | int * ch_signal[2]; |
||
| 236 | osc_fpga_get_sig_ptr(&ch_signal[0], &ch_signal[1]); |
||
| 237 | #endif |
||
| 238 | *(data_buf++) = 0x2; |
||
| 239 | *(data_buf++) = chmask; |
||
| 240 | |||
| 241 | for (int id = 0;id<2;id++){ |
||
| 242 | if ( !(chmask & (1 << id)) ) continue; |
||
| 243 | |||
| 244 | *(data_buf++) = id; |
||
| 245 | *(data_buf++) = nsamples; |
||
| 246 | #ifdef MRP |
||
| 247 | const int c[2] = {RP_CH_1, RP_CH_2}; |
||
| 248 | unsigned int isamples = nsamples; |
||
| 249 | rp_AcqGetLatestDataV(c[id], &isamples, (float *) data_buf ); |
||
| 250 | data_buf+=nsamples; |
||
| 251 | #else |
||
| 252 | |||
| 253 | const int BUF = 16*1024; |
||
| 254 | const int offset = 0; |
||
| 255 | if (trig_ptr > (BUF-nsamples)) // Enter logic to transition from end to beginning of cha_signal buffer. |
||
| 256 | { |
||
| 257 | for (int i=trig_ptr;i<BUF;i++) *(data_buf++) = ch_signal[id][i]-offset; |
||
| 258 | for (int i=0;i<nsamples-(BUF-trig_ptr);i++) *(data_buf++) = ch_signal[id][i]-offset; |
||
| 259 | } |
||
| 260 | else // Enter simple logic to send sampleSize from trigger point |
||
| 261 | { |
||
| 262 | for (int i=0;i<nsamples;i++) *(data_buf++) = ch_signal[id][trig_ptr + i]-offset; |
||
| 263 | } |
||
| 264 | #endif |
||
| 265 | } |
||
| 266 | *(data_buf++) = 0x3; |
||
| 267 | *(data_buf++) = neve; |
||
| 268 | neve++; |
||
| 269 | if (ieve+1 % 500 == 0) fprintf(stderr, "Event %d\n", ieve); |
||
| 270 | if (timer_out) break; |
||
| 271 | |||
| 272 | } |
||
| 273 | |||
| 274 | |||
| 275 | |||
| 276 | int *len = ibuf; |
||
| 277 | int *nev = ibuf + 1; |
||
| 278 | float *dt = (float *)(ibuf + 2); |
||
| 279 | |||
| 280 | *len = (data_buf-len)*sizeof(int); |
||
| 281 | *nev = neve; |
||
| 282 | t = clock(); |
||
| 283 | *dt = t-t0; |
||
| 284 | *dt /= CLOCKS_PER_SEC; |
||
| 285 | |||
| 286 | return *len; |
||
| 287 | } |
||
| 288 | |||
| 289 | #define MAXLEN 0XFFFF |
||
| 290 | struct RUNHDR { |
||
| 291 | unsigned short neve; |
||
| 292 | unsigned short nsamples; |
||
| 293 | unsigned short tout; |
||
| 294 | unsigned char trigger; |
||
| 295 | unsigned char mask; |
||
| 296 | int nloops ; |
||
| 297 | int data [MAXLEN]; |
||
| 298 | } ; |
||
| 299 | |||
| 300 | |||
| 301 | struct INIHDR { |
||
| 302 | int delay ; |
||
| 303 | int decimation; |
||
| 304 | int threshold; |
||
| 305 | }; |
||
| 306 | |||
| 307 | |||
| 308 | int daq_help(char *fname, struct INIHDR * i, struct RUNHDR *r, int verbosity){ |
||
| 309 | |||
| 310 | printf("-o filename ... output filename %s\n", fname); |
||
| 311 | printf("-v verbose ... verbosity %d\n", verbosity); |
||
| 312 | printf("-b decimation ... decimation %d\n", i->decimation); |
||
| 313 | printf("-i timeout ... interrupt timeout %d\n", r->tout); |
||
| 314 | printf("-s nsamples ... number of samples %d\n", r->nsamples); |
||
| 315 | printf("-d delay ... delay %d\n", i->delay); |
||
| 316 | printf("-t trigger ... trigger type %d\n", r->trigger); |
||
| 317 | printf("-l level ... trigger level %f\n", i->threshold*0.001); |
||
| 318 | printf("-m mask ... channel mask %d\n", r->mask ); |
||
| 319 | printf("-n neve ... number of events per call %d\n", r->neve); |
||
| 320 | printf("-r nloops ... number of calls %d\n", r->nloops); |
||
| 321 | return 0; |
||
| 322 | } |
||
| 323 | |||
| 324 | |||
| 325 | |||
| 326 | int daq_main( int argc , char ** argv) { |
||
| 327 | // intercept routine |
||
| 328 | if (signal (SIGINT, SigInt) == SIG_ERR) { |
||
| 329 | perror ("sigignore"); |
||
| 330 | } |
||
| 331 | |||
| 332 | |||
| 333 | char filename[0xFF]=""; |
||
| 334 | |||
| 335 | |||
| 336 | struct INIHDR inihdr = { |
||
| 337 | .decimation = 1, |
||
| 338 | .threshold = 100, |
||
| 339 | .delay = 1024 |
||
| 340 | }; |
||
| 341 | |||
| 342 | |||
| 343 | |||
| 344 | struct RUNHDR runhdr; |
||
| 345 | |||
| 346 | |||
| 347 | runhdr.neve =10000; |
||
| 348 | runhdr.nsamples = 1024; |
||
| 349 | runhdr.tout = 1000; |
||
| 350 | runhdr.trigger = 1; |
||
| 351 | runhdr.mask = 0x1; |
||
| 352 | runhdr.nloops = 1; |
||
| 353 | |||
| 354 | int verbose = 0; |
||
| 355 | int argdata = 0; |
||
| 356 | |||
| 357 | if (argc <2) { |
||
| 358 | daq_help(filename, &inihdr, &runhdr, verbose); |
||
| 359 | exit(-1); |
||
| 360 | } |
||
| 361 | |||
| 362 | opterr = 0; |
||
| 363 | int c; |
||
| 364 | while ((c = getopt (argc, argv, "o:v:b:i:s:d:t:l:m:n:r:h")) != -1) |
||
| 365 | switch (c) { |
||
| 366 | case 'o': |
||
| 367 | sprintf(filename,"%s", optarg ); |
||
| 368 | break; // output |
||
| 369 | case 'v': |
||
| 370 | verbose = strtoul (optarg,NULL,0); |
||
| 371 | break; // verbosity |
||
| 372 | case 'b': |
||
| 373 | inihdr.decimation = strtoul (optarg,NULL,0); |
||
| 374 | break; |
||
| 375 | case 'i': |
||
| 376 | runhdr.tout = strtoul (optarg,NULL,0); |
||
| 377 | break; |
||
| 378 | case 's': |
||
| 379 | runhdr.nsamples = strtoul (optarg,NULL,0); |
||
| 380 | break; |
||
| 381 | case 'd': |
||
| 382 | inihdr.delay = strtoul (optarg,NULL,0); |
||
| 383 | break; |
||
| 384 | case 't': |
||
| 385 | runhdr.trigger = strtoul (optarg,NULL,0); |
||
| 386 | break; |
||
| 387 | case 'm': |
||
| 388 | runhdr.mask = strtoul (optarg,NULL,0); |
||
| 389 | break; |
||
| 390 | case 'n': |
||
| 391 | runhdr.neve = atoi (optarg); |
||
| 392 | break; |
||
| 393 | case 'r': |
||
| 394 | runhdr.nloops = atoi (optarg); |
||
| 395 | break; |
||
| 396 | case 'l': |
||
| 397 | inihdr.threshold = (int) (1000*atof (optarg)); |
||
| 398 | break; |
||
| 399 | case 'h': |
||
| 400 | daq_help(filename, &inihdr, &runhdr, verbose); |
||
| 401 | break; |
||
| 402 | case '?': |
||
| 403 | if (optopt == 'c') |
||
| 404 | fprintf (stderr, "Option -%c requires an argument.\n", optopt); |
||
| 405 | else if (isprint (optopt)) |
||
| 406 | fprintf (stderr, "Unknown option `-%c'.\n", optopt); |
||
| 407 | else |
||
| 408 | fprintf (stderr, |
||
| 409 | "Unknown option character `\\x%x'.\n", |
||
| 410 | optopt); |
||
| 411 | return 1; |
||
| 412 | default: |
||
| 413 | abort (); |
||
| 414 | } |
||
| 415 | for (int i=optind; i<argc; i++) argdata = strtoul (argv[i],NULL,0); |
||
| 416 | if (verbose) daq_help(filename, &inihdr, &runhdr, verbose); |
||
| 417 | |||
| 418 | printf("argdata %d nloops %d\n",argdata,runhdr.nloops); |
||
| 419 | |||
| 420 | daq_init((char *)&inihdr); |
||
| 421 | FILE *fp=NULL; |
||
| 422 | if (strlen(filename)>0) fp = fopen(filename, "wb"); |
||
| 423 | |||
| 424 | |||
| 425 | int maxlen = MAXLEN; |
||
| 426 | char *data = (char *) malloc(maxlen * sizeof(int)); |
||
| 427 | time_t t,tstart; |
||
| 428 | time(&tstart); |
||
| 429 | |||
| 430 | for (int i=0;i< runhdr.nloops;i++){ |
||
| 431 | int nb =daq_run((const char*) &runhdr, &data, &maxlen); |
||
| 432 | if (ctrl_c) break; |
||
| 433 | time(&t); |
||
| 434 | fprintf(stderr, "Loop %d dt=%d s\n", i, (int)(t-tstart)); |
||
| 435 | |||
| 436 | if (fp) { |
||
| 437 | fprintf(stderr, "Writing %d to %s", nb, filename); |
||
| 438 | fwrite(data, 1, nb, fp); |
||
| 439 | } |
||
| 440 | |||
| 441 | } |
||
| 442 | time(&t); |
||
| 443 | fprintf(stderr, "Total events %d in %d s\n", runhdr.nloops*runhdr.neve, (int)(t-tstart)); |
||
| 444 | if (fp) fclose(fp); |
||
| 445 | if (data!=NULL) free(data); |
||
| 446 | return 0; |
||
| 447 | } |