Subversion Repositories f9daq

Rev

Rev 197 | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. /*
  2.    Name:           read_binary.cpp
  3.    Created by:     Stefan Ritt <stefan.ritt@psi.ch>
  4.    Date:           July 30th, 2014
  5.  
  6.    Purpose:        Example file to read binary data saved by DRSOsc.
  7.  
  8.    Compile and run it with:
  9.  
  10.       gcc -o read_binary read_binary.cpp
  11.  
  12.       ./read_binary <filename>
  13.  
  14.    This program assumes that a pulse from a signal generator is split
  15.    and fed into channels #1 and #2. It then calculates the time difference
  16.    between these two pulses to show the performance of the DRS board
  17.    for time measurements.
  18.  
  19.    $Id: read_binary.cpp 22321 2016-08-25 12:26:12Z ritt $
  20. */
  21.  
  22. #include <stdio.h>
  23. #include <fcntl.h>
  24. #include <unistd.h>
  25. #include <string.h>
  26. #include <math.h>
  27.  
  28. typedef struct {
  29.    char           tag[3];
  30.    char           version;
  31. } FHEADER;
  32.  
  33. typedef struct {
  34.    char           time_header[4];
  35. } THEADER;
  36.  
  37. typedef struct {
  38.    char           bn[2];
  39.    unsigned short board_serial_number;
  40. } BHEADER;
  41.  
  42. typedef struct {
  43.    char           event_header[4];
  44.    unsigned int   event_serial_number;
  45.    unsigned short year;
  46.    unsigned short month;
  47.    unsigned short day;
  48.    unsigned short hour;
  49.    unsigned short minute;
  50.    unsigned short second;
  51.    unsigned short millisecond;
  52.    unsigned short range;
  53. } EHEADER;
  54.  
  55. typedef struct {
  56.    char           tc[2];
  57.    unsigned short trigger_cell;
  58. } TCHEADER;
  59.  
  60. typedef struct {
  61.    char           c[1];
  62.    char           cn[3];
  63. } CHEADER;
  64.  
  65. /*-----------------------------------------------------------------------------*/
  66.  
  67. int main(int argc, const char * argv[])
  68. {
  69.    FHEADER  fh;
  70.    THEADER  th;
  71.    BHEADER  bh;
  72.    EHEADER  eh;
  73.    TCHEADER tch;
  74.    CHEADER  ch;
  75.    
  76.    unsigned int scaler;
  77.    unsigned short voltage[1024];
  78.    double waveform[16][4][1024], time[16][4][1024];
  79.    float bin_width[16][4][1024];
  80.    int i, j, b, chn, n, chn_index, n_boards;
  81.    double t1, t2, dt;
  82.    char filename[256];
  83.  
  84.    int ndt;
  85.    double threshold, sumdt, sumdt2;
  86.    
  87.    if (argc > 1)
  88.       strcpy(filename, argv[1]);
  89.    else {
  90.       printf("Usage: read_binary <filename>\n");
  91.       return 0;
  92.    }
  93.    
  94.    // open the binary waveform file
  95.    FILE *f = fopen(filename, "rb");
  96.    if (f == NULL) {
  97.       printf("Cannot find file \'%s\'\n", filename);
  98.       return 0;
  99.    }
  100.  
  101.    // read file header
  102.    fread(&fh, sizeof(fh), 1, f);
  103.    if (fh.tag[0] != 'D' || fh.tag[1] != 'R' || fh.tag[2] != 'S') {
  104.       printf("Found invalid file header in file \'%s\', aborting.\n", filename);
  105.       return 0;
  106.    }
  107.    
  108.    if (fh.version != '2') {
  109.       printf("Found invalid file version \'%c\' in file \'%s\', should be \'2\', aborting.\n", fh.version, filename);
  110.       return 0;
  111.    }
  112.  
  113.    // read time header
  114.    fread(&th, sizeof(th), 1, f);
  115.    if (memcmp(th.time_header, "TIME", 4) != 0) {
  116.       printf("Invalid time header in file \'%s\', aborting.\n", filename);
  117.       return 0;
  118.    }
  119.  
  120.    for (b = 0 ; ; b++) {
  121.       // read board header
  122.       fread(&bh, sizeof(bh), 1, f);
  123.       if (memcmp(bh.bn, "B#", 2) != 0) {
  124.          // probably event header found
  125.          fseek(f, -4, SEEK_CUR);
  126.          break;
  127.       }
  128.      
  129.       printf("Found data for board #%d\n", bh.board_serial_number);
  130.      
  131.       // read time bin widths
  132.       memset(bin_width[b], sizeof(bin_width[0]), 0);
  133.       for (chn=0 ; chn<5 ; chn++) {
  134.          fread(&ch, sizeof(ch), 1, f);
  135.          if (ch.c[0] != 'C') {
  136.             // event header found
  137.             fseek(f, -4, SEEK_CUR);
  138.             break;
  139.          }
  140.          i = ch.cn[2] - '0' - 1;
  141.          printf("Found timing calibration for channel #%d\n", i+1);
  142.          fread(&bin_width[b][i][0], sizeof(float), 1024, f);
  143.          // fix for 2048 bin mode: double channel
  144.          if (bin_width[b][i][1023] > 10 || bin_width[b][i][1023] < 0.01) {
  145.             for (j=0 ; j<512 ; j++)
  146.                bin_width[b][i][j+512] = bin_width[b][i][j];
  147.          }
  148.       }
  149.    }
  150.    n_boards = b;
  151.    
  152.    // initialize statistics
  153.    ndt = 0;
  154.    sumdt = sumdt2 = 0;
  155.    
  156.    // loop over all events in the data file
  157.    for (n=0 ; ; n++) {
  158.       // read event header
  159.       i = (int)fread(&eh, sizeof(eh), 1, f);
  160.       if (i < 1)
  161.          break;
  162.      
  163.       printf("Found event #%d %d %d\n", eh.event_serial_number, eh.second, eh.millisecond);
  164.      
  165.       // loop over all boards in data file
  166.       for (b=0 ; b<n_boards ; b++) {
  167.          
  168.          // read board header
  169.          fread(&bh, sizeof(bh), 1, f);
  170.          if (memcmp(bh.bn, "B#", 2) != 0) {
  171.             printf("Invalid board header in file \'%s\', aborting.\n", filename);
  172.             return 0;
  173.          }
  174.          
  175.          // read trigger cell
  176.          fread(&tch, sizeof(tch), 1, f);
  177.          if (memcmp(tch.tc, "T#", 2) != 0) {
  178.             printf("Invalid trigger cell header in file \'%s\', aborting.\n", filename);
  179.             return 0;
  180.          }
  181.  
  182.          if (n_boards > 1)
  183.             printf("Found data for board #%d\n", bh.board_serial_number);
  184.          
  185.          // reach channel data
  186.          for (chn=0 ; chn<4 ; chn++) {
  187.            
  188.             // read channel header
  189.             fread(&ch, sizeof(ch), 1, f);
  190.             if (ch.c[0] != 'C') {
  191.                // event header found
  192.                fseek(f, -4, SEEK_CUR);
  193.                break;
  194.             }
  195.             chn_index = ch.cn[2] - '0' - 1;
  196.             fread(&scaler, sizeof(int), 1, f);
  197.             fread(voltage, sizeof(short), 1024, f);
  198.            
  199.             for (i=0 ; i<1024 ; i++) {
  200.                // convert data to volts
  201.                waveform[b][chn_index][i] = (voltage[i] / 65536. + eh.range/1000.0 - 0.5);
  202.                
  203.                // calculate time for this cell
  204.                for (j=0,time[b][chn_index][i]=0 ; j<i ; j++)
  205.                   time[b][chn_index][i] += bin_width[b][chn_index][(j+tch.trigger_cell) % 1024];
  206.             }
  207.          }
  208.          
  209.          // align cell #0 of all channels
  210.          t1 = time[b][0][(1024-tch.trigger_cell) % 1024];
  211.          for (chn=1 ; chn<4 ; chn++) {
  212.             t2 = time[b][chn][(1024-tch.trigger_cell) % 1024];
  213.             dt = t1 - t2;
  214.             for (i=0 ; i<1024 ; i++)
  215.                time[b][chn][i] += dt;
  216.          }
  217.          
  218.          t1 = t2 = 0;
  219.          threshold = 0.3;
  220.          
  221.          // find peak in channel 1 above threshold
  222.          for (i=0 ; i<1022 ; i++)
  223.             if (waveform[b][0][i] < threshold && waveform[b][0][i+1] >= threshold) {
  224.                t1 = (threshold-waveform[b][0][i])/(waveform[b][0][i+1]-waveform[b][0][i])*(time[b][0][i+1]-time[b][0][i])+time[b][0][i];
  225.                break;
  226.             }
  227.          
  228.          // find peak in channel 2 above threshold
  229.          for (i=0 ; i<1022 ; i++)
  230.             if (waveform[b][1][i] < threshold && waveform[b][1][i+1] >= threshold) {
  231.                t2 = (threshold-waveform[b][1][i])/(waveform[b][1][i+1]-waveform[b][1][i])*(time[b][1][i+1]-time[b][1][i])+time[b][1][i];
  232.                break;
  233.             }
  234.          
  235.          // calculate distance of peaks with statistics
  236.          if (t1 > 0 && t2 > 0) {
  237.             ndt++;
  238.             dt = t2 - t1;
  239.             sumdt += dt;
  240.             sumdt2 += dt*dt;
  241.          }
  242.       }
  243.    }
  244.    
  245.    // print statistics
  246.    printf("dT = %1.3lfns +- %1.1lfps\n", sumdt/ndt, 1000*sqrt(1.0/(ndt-1)*(sumdt2-1.0/ndt*sumdt*sumdt)));
  247.    
  248.    return 1;
  249. }
  250.  
  251.