Subversion Repositories f9daq

Rev

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

Rev Author Line No. Line
195 f9daq 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