1 | #include <DAQ/Df250EmulatorAlgorithm_v2.h> |
2 | |
3 | Df250EmulatorAlgorithm_v2::Df250EmulatorAlgorithm_v2(JEventLoop *loop){ |
4 | |
5 | FORCE_DEFAULT = 0; |
6 | |
7 | NSA_DEF = 20; |
8 | NSB_DEF = 5; |
9 | THR_DEF = 120; |
10 | NPED_DEF = 4; |
11 | MAXPED_DEF = 512; |
12 | NSAT_DEF = 2; |
13 | |
14 | |
15 | VERBOSE = 0; |
16 | |
17 | if(gPARMS){ |
18 | gPARMS->SetDefaultParameter("EMULATION250:FORCE_DEFAULT", FORCE_DEFAULT,"Set to >0 to force use of default values"); |
19 | gPARMS->SetDefaultParameter("EMULATION250:NSA", NSA_DEF,"Set NSA for firmware emulation, will be overwritten by BORConfig if present"); |
20 | gPARMS->SetDefaultParameter("EMULATION250:NSB", NSB_DEF,"Set NSB for firmware emulation, will be overwritten by BORConfig if present"); |
21 | gPARMS->SetDefaultParameter("EMULATION250:THR", THR_DEF,"Set threshold for firmware emulation, will be overwritten by BORConfig if present"); |
22 | gPARMS->SetDefaultParameter("EMULATION250:NPED", NPED_DEF,"Set NPED for firmware emulation, will be overwritten by BORConfig if present"); |
23 | gPARMS->SetDefaultParameter("EMULATION250:MAXPED", MAXPED_DEF,"Set MAXPED for firmware emulation, will be overwritten by BORConfig if present"); |
24 | gPARMS->SetDefaultParameter("EMULATION250:NSAT", NSAT_DEF,"Set NSAT for firmware emulation, will be overwritten by BORConfig if present"); |
25 | gPARMS->SetDefaultParameter("EMULATION250:VERBOSE", VERBOSE,"Set verbosity for f250 emulation"); |
26 | } |
27 | } |
28 | |
29 | void Df250EmulatorAlgorithm_v2::EmulateFirmware(const Df250WindowRawData* rawData, |
30 | std::vector<Df250PulseData*> &pdat_objs) |
31 | { |
32 | |
33 | if (VERBOSE > 0) { |
| |
34 | jout << " Df250EmulatorAlgorithm_v2::EmulateFirmware ==> Starting emulation <==" << endl; |
35 | jout << "rocid : " << rawData->rocid << " slot: " << rawData->slot << " channel: " << rawData->channel << endl; |
36 | } |
37 | |
38 | |
39 | if (rawData == NULL__null) { |
| |
40 | jout << " ERROR: Df250EmulatorAlgorithm_v2::EmulateFirmware - raw sample data is missing" << endl; |
41 | jout << " Contact mstaib@jlab.org" << endl; |
42 | } |
43 | |
44 | |
45 | uint32_t channel = rawData->channel; |
46 | |
47 | |
48 | |
49 | |
50 | const Df250BORConfig *f250BORConfig = NULL__null; |
51 | rawData->GetSingle(f250BORConfig); |
52 | |
53 | uint32_t NSA; |
54 | int32_t NSB; |
55 | uint32_t NPED, MAXPED; |
56 | uint16_t THR; |
57 | uint16_t NSAT; |
58 | |
59 | if (f250BORConfig == NULL__null || FORCE_DEFAULT){ |
60 | static int counter = 0; |
61 | NSA = NSA_DEF; |
62 | NSB = NSB_DEF; |
63 | THR = THR_DEF; |
64 | NPED = NPED_DEF; |
| 3 | | Value assigned to 'NPED' | |
|
65 | MAXPED = MAXPED_DEF; |
66 | NSAT = NSAT_DEF; |
67 | if (counter < 10){ |
| |
68 | counter++; |
69 | if (counter == 10) jout << " WARNING Df250EmulatorAlgorithm_v2::EmulateFirmware No Df250BORConfig == Using default values == LAST WARNING" << endl; |
| |
70 | else jout << " WARNING Df250EmulatorAlgorithm_v2::EmulateFirmware No Df250BORConfig == Using default values " << endl; |
71 | |
72 | } |
73 | } |
74 | else{ |
75 | NSA = f250BORConfig->NSA; |
76 | NSB = f250BORConfig->NSB; |
77 | THR = f250BORConfig->adc_thres[channel]; |
78 | NPED = f250BORConfig->NPED; |
79 | MAXPED = f250BORConfig->MaxPed; |
80 | NSAT = f250BORConfig->NSAT; |
81 | |
82 | } |
83 | |
84 | if (VERBOSE > 0) jout << "Df250EmulatorAlgorithm_v2::EmulateFirmware NSA: " << NSA << " NSB: " << NSB << " THR: " << THR << endl; |
| |
85 | |
86 | |
87 | |
88 | |
89 | |
90 | bool bad_pedestal = false; |
91 | bool bad_timing_pedestal = false; |
92 | bool no_timing_calculation = false; |
93 | |
94 | |
95 | |
96 | |
97 | |
98 | |
99 | vector<uint16_t> samples = rawData->samples; |
100 | uint16_t NW = samples.size(); |
101 | uint32_t npulses = 0; |
102 | const int max_pulses = 3; |
103 | uint32_t TC[max_pulses] = {}; |
104 | uint32_t TMIN[max_pulses] = {3}; |
105 | uint32_t pulse_integral[max_pulses] = {}; |
106 | bool has_overflow_samples[max_pulses] = {false}; |
107 | bool has_underflow_samples[max_pulses] = {false}; |
108 | uint32_t number_samples_above_threshold[max_pulses] = {0}; |
109 | bool NSA_beyond_PTW[max_pulses] = {false}; |
110 | bool vpeak_beyond_NSA[max_pulses] = {false}; |
111 | bool vpeak_not_found[max_pulses] = {false}; |
112 | |
113 | |
114 | if(VERBOSE > 0) { |
| |
115 | for (unsigned int i=0; i < NW; i++) { |
116 | if(VERBOSE > 2) { |
117 | if(samples[i] == 0x1fff) |
118 | jout << "Overflow at sample " << i << endl; |
119 | if(samples[i] == 0x1000) |
120 | jout << "Underflow at sample " << i << endl; |
121 | } |
122 | if (VERBOSE > 5) jout << "Df250EmulatorAlgorithm_v2::EmulateFirmware samples[" << i << "]: " << samples[i] << endl; |
123 | } |
124 | } |
125 | |
126 | |
127 | for (unsigned int i=0; i < (NW-NSAT); i++) { |
| 8 | | Loop condition is false. Execution continues on line 184 | |
|
128 | if ((samples[i] & 0xfff) > THR) { |
129 | if (VERBOSE > 1) { |
130 | jout << "threshold crossing at " << i << endl; |
131 | } |
132 | TC[npulses] = i+1; |
133 | |
134 | |
135 | if( (NSAT>1) && (i>0) ){ |
136 | int samples_over_threshold = 1; |
137 | for(unsigned int j=1; j < NSAT; j++) { |
138 | if ((samples[i+j] & 0xfff) > THR) { |
139 | samples_over_threshold++; |
140 | if( samples_over_threshold == NSAT ) |
141 | break; |
142 | } else { |
143 | break; |
144 | } |
145 | } |
146 | |
147 | if( samples_over_threshold != NSAT ) |
148 | continue; |
149 | } |
150 | unsigned int ibegin; |
151 | if(NSB > 0) |
152 | ibegin = i > uint32_t(NSB) ? (i - NSB) : 0; |
153 | else { |
154 | ibegin = i - NSB; |
155 | if(ibegin > uint32_t(NW)) |
156 | break; |
157 | } |
158 | unsigned int iend = (i + NSA) < uint32_t(NW) ? (i + NSA) : NW; |
159 | |
160 | NSA_beyond_PTW[npulses] = (i + NSA - 1) >= uint32_t(NW); |
161 | for (i = ibegin; i < iend; ++i) { |
162 | pulse_integral[npulses] += (samples[i] & 0xfff); |
163 | |
164 | if(samples[i] == 0x1fff) { |
165 | has_overflow_samples[npulses] = true; |
166 | } |
167 | if(samples[i] == 0x1000) { |
168 | has_underflow_samples[npulses] = true; |
169 | } |
170 | |
171 | if( (i+1>=TC[npulses]) && ((samples[i] & 0xfff) > THR) ) |
172 | number_samples_above_threshold[npulses]++; |
173 | } |
174 | for (; i < NW && (samples[i] & 0xfff) >= THR; ++i) {} |
175 | if (++npulses == max_pulses) |
176 | break; |
177 | TMIN[npulses] = i; |
178 | } |
179 | } |
180 | |
181 | |
182 | |
183 | |
184 | uint32_t VPEAK[max_pulses] = {}; |
185 | uint32_t TPEAK[max_pulses] = {}; |
186 | uint16_t TMID[max_pulses] = {}; |
187 | uint16_t VMID[max_pulses] = {}; |
188 | uint16_t TFINE[max_pulses] = {}; |
189 | uint32_t pulse_time[max_pulses] = {}; |
190 | |
191 | |
192 | uint32_t pedestal = 0; |
193 | uint32_t VMIN = 0; |
194 | for (unsigned int i=0; i < NPED; i++) { |
| 9 | | Assuming 'i' is >= 'NPED' | |
|
| 10 | | Loop condition is false. Execution continues on line 208 | |
|
195 | pedestal += (samples[i] & 0xfff); |
196 | if(i<4) |
197 | VMIN += (samples[i] & 0xfff); |
198 | |
199 | |
200 | if ((samples[i] & 0xfff) > MAXPED) { |
201 | bad_pedestal = true; |
202 | } |
203 | |
204 | if( (samples[i] == 0x1fff) || (samples[i] == 0x1000) ) { |
205 | bad_pedestal = true; |
206 | } |
207 | } |
208 | VMIN /= NPED; |
| |
209 | |
210 | |
211 | bool pedestal_underflow = false; |
212 | for (unsigned int i=0; i < 5; i++) { |
213 | |
214 | if ( ((samples[i] & 0xfff) > MAXPED) || ((samples[i] & 0xfff) > THR) ) { |
215 | bad_timing_pedestal = true; |
216 | } |
217 | |
218 | if ( (samples[i] == 0x1000) || (samples[i] == 0x1fff) ) { |
219 | bad_timing_pedestal = true; |
220 | } |
221 | |
222 | |
223 | if( (samples[i] & 0xfff) > THR ) { |
224 | no_timing_calculation = true; |
225 | } |
226 | } |
227 | |
228 | for (unsigned int p=0; p < npulses; ++p) { |
229 | |
230 | |
231 | |
232 | |
233 | if(no_timing_calculation) { |
234 | TMID[p] = TC[p]; |
235 | TFINE[p] = 0; |
236 | VPEAK[p] = 0; |
237 | vpeak_not_found[p] = true; |
238 | |
239 | } |
240 | |
241 | |
242 | |
243 | |
244 | |
245 | while ( (!no_timing_calculation) && true) { |
246 | |
247 | |
248 | |
249 | |
250 | |
251 | |
252 | |
253 | |
254 | |
255 | |
256 | unsigned int ipeak; |
257 | for (ipeak = TC[p]; ipeak < NW-1; ++ipeak) { |
258 | if ((samples[ipeak] & 0xfff) < (samples[ipeak-1] & 0xfff)) { |
259 | VPEAK[p] = (samples[ipeak-1] & 0xfff); |
260 | TPEAK[p] = ipeak-1; |
261 | break; |
262 | } |
263 | } |
264 | |
265 | |
266 | if(ipeak > TC[p]+NSA) |
267 | vpeak_beyond_NSA[p] = true; |
268 | |
269 | if (VERBOSE > 1) { |
270 | jout << " pulse " << p << ": VMIN: " << VMIN |
271 | << " TC: " << TC[p] << " VPEAK: " << VPEAK[p] << endl; |
272 | } |
273 | |
274 | |
275 | if (VPEAK[p] == 0) { |
276 | TMID[p] = TC[p]; |
277 | TFINE[p] = 0; |
278 | VPEAK[p] = 0; |
279 | vpeak_beyond_NSA[p] = true; |
280 | vpeak_not_found[p] = true; |
281 | break; |
282 | } |
283 | |
284 | |
285 | VMID[p] = (VMIN + VPEAK[p]) >> 1; |
286 | |
287 | |
288 | |
289 | |
290 | |
291 | |
292 | |
293 | |
294 | |
295 | |
296 | |
297 | |
298 | |
299 | |
300 | |
301 | for (unsigned int i = TPEAK[p]; i >= 1; --i) { |
302 | if ( ((samples[i-1] & 0xfff) <= VMID[p]) && ((samples[i] & 0xfff) > VMID[p]) ) { |
303 | |
304 | |
305 | TMID[p] = i; |
306 | break; |
307 | } |
308 | } |
309 | |
310 | if (TMID[p] == 0) { |
311 | TFINE[p] = 0; |
312 | } |
313 | else { |
314 | |
315 | int Vnext = (samples[TMID[p]] & 0xfff); |
316 | int Vlast = (samples[TMID[p]-1] & 0xfff); |
317 | if (VERBOSE > 2) { |
318 | jout << " TMIN = " << TMIN[p] << " TMID = " << TMID[p] << " TPEAK = " << TPEAK[p] << endl |
319 | << " VMID = " << VMID[p] << " Vnext = " << Vnext << " Vlast = " << Vlast << endl; |
320 | } |
321 | if (Vnext > Vlast && VMID[p] >= Vlast) |
322 | TFINE[p] = 64 * (VMID[p] - Vlast) / (Vnext - Vlast); |
323 | else |
324 | TFINE[p] = 62; |
325 | if(TFINE[p] == 64) |
326 | TFINE[p] = 0; |
327 | } |
328 | pulse_time[p] = ((TMID[p]-1) << 6) + TFINE[p]; |
329 | break; |
330 | } |
331 | VMIN = (VMIN < 99999)? VMIN : 0; |
332 | |
333 | if (VERBOSE > 1) { |
334 | jout << " pulse " << p << ": VMID: " << VMID[p] << " TMID: " << TMID[p] |
335 | << " TFINE: " << TFINE[p] << " time: " << pulse_time[p] |
336 | << " integral: " << pulse_integral[p] << endl; |
337 | } |
338 | |
339 | |
340 | Df250PulseData* f250PulseData; |
341 | if( p < pdat_objs.size() ) { |
342 | f250PulseData = pdat_objs[p]; |
343 | |
344 | if(f250PulseData == NULL__null) { |
345 | jerr << " NULL f250PulseData object!" << endl; |
346 | continue; |
347 | } |
348 | } else { |
349 | |
350 | f250PulseData = new Df250PulseData; |
351 | |
352 | f250PulseData->rocid = rawData->rocid; |
353 | f250PulseData->slot = rawData->slot; |
354 | f250PulseData->channel = rawData->channel; |
355 | f250PulseData->itrigger = rawData->itrigger; |
356 | |
357 | f250PulseData->event_within_block = 1; |
358 | f250PulseData->QF_pedestal = bad_pedestal; |
359 | f250PulseData->pedestal = pedestal; |
360 | |
361 | f250PulseData->integral = pulse_integral[p]; |
362 | f250PulseData->QF_NSA_beyond_PTW = NSA_beyond_PTW[p]; |
363 | f250PulseData->QF_overflow = has_overflow_samples[p]; |
364 | f250PulseData->QF_underflow = has_underflow_samples[p]; |
365 | f250PulseData->nsamples_over_threshold = number_samples_above_threshold[p]; |
366 | |
367 | f250PulseData->course_time = TMID[p]; |
368 | f250PulseData->fine_time = TFINE[p]; |
369 | f250PulseData->QF_vpeak_beyond_NSA = vpeak_beyond_NSA[p]; |
370 | f250PulseData->QF_vpeak_not_found = vpeak_not_found[p]; |
371 | f250PulseData->QF_bad_pedestal = bad_timing_pedestal; |
372 | |
373 | f250PulseData->pulse_number = p; |
374 | f250PulseData->nsamples_integral = NSA + NSB; |
375 | f250PulseData->nsamples_pedestal = NPED; |
376 | f250PulseData->emulated = true; |
377 | |
378 | f250PulseData->AddAssociatedObject(rawData); |
379 | const_cast<Df250WindowRawData*>(rawData)->AddAssociatedObject(f250PulseData); |
380 | pdat_objs.push_back(f250PulseData); |
381 | } |
382 | |
383 | |
384 | f250PulseData->integral_emulated = pulse_integral[p]; |
385 | f250PulseData->pedestal_emulated = pedestal; |
386 | f250PulseData->pulse_peak_emulated = VPEAK[p]; |
387 | f250PulseData->course_time_emulated = TMID[p]; |
388 | f250PulseData->fine_time_emulated = TFINE[p]; |
389 | |
390 | |
391 | uint32_t QF = 0; |
392 | if( bad_pedestal ) QF |= (1<<0); |
393 | if( NSA_beyond_PTW[p] ) QF |= (1<<1); |
394 | if( has_overflow_samples[p] ) QF |= (1<<2); |
395 | if( has_underflow_samples[p] ) QF |= (1<<3); |
396 | if( vpeak_beyond_NSA[p] ) QF |= (1<<4); |
397 | if( vpeak_not_found[p] ) QF |= (1<<5); |
398 | if( bad_timing_pedestal ) QF |= (1<<6); |
399 | f250PulseData->QF_emulated = QF; |
400 | |
401 | if(VERBOSE > 3) { |
402 | cout << boolalpha; |
403 | cout << "bad_pedestal = " << bad_pedestal << endl; |
404 | cout << "NSA_beyond_PTW = " << NSA_beyond_PTW[p] << endl; |
405 | cout << "has_overflow_samples = " << has_overflow_samples[p] << endl; |
406 | cout << "has_underflow_samples = " << has_underflow_samples[p] << endl; |
407 | cout << "vpeak_beyond_NSA = " << vpeak_beyond_NSA[p] << endl; |
408 | cout << "vpeak_not_found = " << vpeak_not_found[p] << endl; |
409 | cout << "bad_timing_pedestal = " << bad_timing_pedestal << endl; |
410 | cout << "total QF = " << QF << endl; |
411 | } |
412 | |
413 | |
414 | if( f250PulseData->emulated ) { |
415 | f250PulseData->integral = f250PulseData->integral_emulated; |
416 | f250PulseData->pedestal = f250PulseData->pedestal_emulated; |
417 | f250PulseData->pulse_peak = f250PulseData->pulse_peak_emulated; |
418 | f250PulseData->course_time = f250PulseData->course_time_emulated; |
419 | f250PulseData->fine_time = f250PulseData->fine_time_emulated; |
420 | } |
421 | |
422 | } |
423 | |
424 | if (VERBOSE > 0) jout << " Df250EmulatorAlgorithm_v2::EmulateFirmware ==> Emulation complete <==" << endl; |
425 | return; |
426 | } |