ROOTANA
Loading...
Searching...
No Matches
UnpackVF48A.cxx
Go to the documentation of this file.
1// UnpackVF48A.cxx
2
3#include <stdio.h>
4#include <string.h>
5#include <stdlib.h>
6#include <assert.h>
7#include <stdint.h>
8#include <math.h>
9#include <time.h>
10#include <sys/time.h>
11
12#include "UnpackVF48A.h"
13
15{
16 unit = i;
17 trigger = 0;
18 error = 0;
19 for (int i=0; i<VF48_MAX_GROUPS; i++) {
20 trigno[i] = 0;
21 timestamp64[i] = 0;
22 timestamps[i] = 0;
23 }
24 for (int i=0; i<VF48_MAX_GROUPS; i++) {
25 presentMask[i] = 0;
26 hitMask[i] = 0;
27 }
28 complete = false;
31 tgroup = 0;
32 groupMask = 0;
33 //numSamples = 0;
34 //numChannels = 0;
35 for (int i=0; i<VF48_MAX_CHANNELS; i++)
36 {
37 channels[i].channel = -1;
38 channels[i].numSamples = 0;
39 channels[i].complete = false;
40 }
41}
42
44{
45 printf("Unit %d, trigger %d, timestamp %.3fms, tgroup %d, grpmask 0x%02x 0x%02x, complete %d, error %d\n",
46 unit,
47 trigger,
48 timestamps[tgroup]*1000.0, // convert sec to msec
49 tgroup,
53 error);
54
55 for (int i=0; i<VF48_MAX_GROUPS; i++) {
56 printf("Group %d: ts64: 0x%016llx, %.3fms, trigno: %d, hit masks: 0x%02x 0x%02x\n", i, (unsigned long long)timestamp64[i], timestamps[i]*1000.0, trigno[i], presentMask[i], hitMask[i]);
57 }
58}
59
60VF48event::VF48event(int xeventNo) // ctor
61{
62 eventNo = xeventNo;
63 timestamp = 0;
64 complete = 0;
65 error = 0;
66 modulesMask = 0;
67 for (int i=0; i<VF48_MAX_MODULES; i++)
68 modules[i] = NULL;
69}
70
72{
73 eventNo = 0;
74 timestamp = 0;
75 for (int i=0; i<VF48_MAX_MODULES; i++)
76 if (modules[i])
77 {
78 delete modules[i];
79 modules[i] = NULL;
80 }
81}
82
84{
85 int max = 0;
86
87 for (int i=0; i<VF48_MAX_MODULES; i++)
88 if (modules[i])
89 max = i+1;
90
91 printf("VF48 event: %6d, ", eventNo);
92 printf("Triggers: ");
93 for (int i=0; i<max; i++)
94 if (modules[i])
95 printf(" %4d", modules[i]->trigger);
96 else
97 printf(" null");
98 printf(", Timestamps: ");
99 for (int i=0; i<max; i++)
100 if (modules[i])
101 printf(" %.3f", modules[i]->timestamps[modules[i]->tgroup]*1000.0);
102 else
103 printf(" (null)");
104 printf(" complete %d, error %d", complete, error);
105 printf("\n");
106}
107
109{
110 PrintSummary();
111
112 for (int i=0; i<VF48_MAX_MODULES; i++)
113 if (modules[i])
114 modules[i]->PrintModule();
115}
116
117//static double GetTimeSec()
118//{
119// struct timeval tv;
120// gettimeofday(&tv,NULL);
121// return tv.tv_sec + 0.000001*tv.tv_usec;
122//}
123
124void PrintEvent(const VF48event* e)
125{
126 printf("VF48 event: %d\n", e->eventNo);
127 printf("Timestamps: \n");
128 for (int i=0; i<VF48_MAX_MODULES; i++)
129 {
130 printf("Unit %d: ", i);
131 for (int j=0; j<VF48_MAX_GROUPS; j++)
132 printf(" %u", e->modules[i]->trigno[j]);
133 for (int j=0; j<VF48_MAX_GROUPS; j++)
134 printf(" %.3fms", e->modules[i]->timestamps[j]*1000.0);
135 //printf(" freq %fMHz", gVF48freq[i]/1e6);
136 printf("\n");
137 }
138}
139
141{
142 fNumModules = 0;
143 fModulesMask = 0;
144
145 for (int i=0; i<VF48_MAX_MODULES; i++) {
146 fGroupEnabled[i] = 0x3F;
147 fNumSamples[i] = 1000;
148 fFreq[i] = 60.0e6; // 60MHz VF48 ADC clock
149 for (int j=0; j<VF48_MAX_CHANNELS; j++)
150 fChanEnabled[i][j] = true;
151 }
152
153 fCoinc = 0.000100; // in seconds
154
156
157 fDisasmStream = false;
158 fDisasmStructure = false;
159 fDisasmSamples = false;
160
162
163 fEventNo = 0;
164 fBadDataCount = 0;
165
166 for (int i=0; i<VF48_MAX_MODULES; i++)
167 for (int j=0; j<VF48_MAX_GROUPS; j++)
168 wbuf[i][j] = NULL;
169
170 Reset();
171}
172
174{
177 for (int i=0; i<VF48_MAX_MODULES; i++)
178 for (int j=0; j<VF48_MAX_GROUPS; j++)
179 if (wbuf[i][j]) {
180 free(wbuf[i][j]);
181 wbuf[i][j] = NULL;
182 }
183}
184
186{
187 printf("--- all buffered events ---\n");
188 for (unsigned i=0; i<fBuffer.size(); i++)
189 fBuffer[i]->PrintSummary();
190 printf("--- end ---\n");
191}
192
193void UnpackVF48::SetCoincTime(double time_sec)
194{
195 fCoinc = time_sec;
196}
197
199{
200 fTimestampResyncEnable = enable;
201}
202
203void UnpackVF48::SetNumModules(int num_modules)
204{
205 assert(num_modules > 0);
206 assert(num_modules < VF48_MAX_MODULES);
207 fNumModules = num_modules;
208 fModulesMask = 0;
209 for (int i=0; i<fNumModules; i++) {
210 fModulesMask |= (1<<i);
211 }
212}
213
214void UnpackVF48::SetModulesMask(uint32_t mask)
215{
216 //fNumModules = num_modules;
217 fModulesMask = mask;
218}
219
220void UnpackVF48::SetGroupEnableMask(int unit, int groupMask)
221{
222 for (int i=0; i<fNumModules; i++)
223 if (i==unit || unit<0)
224 fGroupEnabled[i] = groupMask;
225}
226
227void UnpackVF48::SetNumSamples(int unit, int num_samples)
228{
229 for (int i=0; i<fNumModules; i++)
230 if (i==unit || unit<0)
231 fNumSamples[i] = num_samples;
232}
233
234void UnpackVF48::SetChanEnable(int unit, int grp, int chan_enable_mask)
235{
236 assert(unit >= 0);
237 assert(unit < fNumModules);
238 assert(grp >= 0);
239 assert(grp < VF48_MAX_GROUPS);
240 for (int i=0; i<VF48_MAX_CHANNELS/VF48_MAX_GROUPS; i++)
241 if (chan_enable_mask & (1<<i))
242 fChanEnabled[unit][grp*VF48_MAX_CHANNELS/VF48_MAX_GROUPS + i] = true;
243 else
244 fChanEnabled[unit][grp*VF48_MAX_CHANNELS/VF48_MAX_GROUPS + i] = false;
245}
246
247void UnpackVF48::SetTsFreq(int unit, double ts_freq_hz)
248{
249 for (int i=0; i<fNumModules; i++)
250 if (i==unit || unit<0)
251 fFreq[unit] = ts_freq_hz;
252}
253
254double UnpackVF48::GetTsFreq(int unit)
255{
256 assert(unit >= 0);
257 assert(unit < fNumModules);
258 return fFreq[unit];
259}
260
262{
263 fFlushIncompleteThreshold = threshold;
264}
265
266VF48event* UnpackVF48::FindEvent(int unit, double timestamp, bool dup)
267{
268 for (unsigned i=0; i<fBuffer.size(); i++) {
269 VF48event* e = fBuffer[i];
270 if (fabs(e->timestamp - timestamp) < fCoinc)
271 if (e->modules[unit] == NULL || dup)
272 return e;
273 }
274
275 VF48event* e = new VF48event(++fEventNo);
276 e->timestamp = timestamp;
277 fBuffer.push_back(e);
278 return e;
279}
280
282{
283 // if buffer is empty, return nothing
284
285 if (fBuffer.size() < 1)
286 return NULL;
287
288 VF48event* e = fBuffer[0];
289
290 if (!e->complete)
291 CompleteEvent(e);
292
293 // if buffer has a complete event
294 // or we are flushing out anything remaing after
295 // the end of file or end of run, return it
296
297 if (e->complete || flush) {
298 fBuffer.pop_front();
299 return e;
300 }
301
302 // we have an incomplete event
303 //
304 // look at the buffer, if there are complete
305 // events after this incomplete event, push this
306 // incomplete event out.
307
308 for (unsigned i=0; i<fBuffer.size(); i++) {
309
310 VF48event* ee = fBuffer[i];
311 if (!ee->complete)
312 CompleteEvent(ee);
313
314 if (ee->complete) {
315 fBuffer.pop_front();
316 return e;
317 }
318 }
319
320 // the buffer only has incomplete events
321 //
322 // one possibility is if one VF48 module died
323 // and does not produce any data and there will
324 // be no complete events ever again. To avoid
325 // fill the buffer with an infinite number of
326 // incomplete events and running out of memory,
327 // we start flushing incomplete events and let
328 // the user deal with it.
329
330 if (fBuffer.size() > fFlushIncompleteThreshold) {
331 fBuffer.pop_front();
332 return e;
333 }
334
335 // maybe more data will arrive later to complete
336 // the current event or some events after it.
337
338 return NULL;
339}
340
342{
345
346 fBadDataCount = 0;
347 fEventNo = 0;
348
349 for (int unit=0; unit<VF48_MAX_MODULES; unit++) {
350 for (int grp=0; grp<VF48_MAX_GROUPS; grp++) {
351 ts_first[unit][grp] = 0;
352 ts_last[unit][grp] = 0;
353 }
354 }
355
356 // which modules and channels are enabled?
357 for (int unit=0; unit<VF48_MAX_MODULES; unit++)
358 {
359 int count = 0;
360 for (int i=0; i<VF48_MAX_GROUPS; i++)
361 for (int j=0; j<8; j++)
362 {
363 if (fGroupEnabled[unit] & (1<<i))
364 {
365 fChanEnabled[unit][i*8+j] = true;
366 count ++;
367 }
368 else
369 {
370 fChanEnabled[unit][i*8+j] = false;
371 }
372 }
373
374
375 //printf("VF48: module %d, groups enabled: 0x%x, channels enabled: %d, num samples: %d\n", unit, gGroupEnabled[unit], count, gNumSamples);
376 }
377}
378
380{
381 if (m->groupMask == 0)
382 {
383 // empty event
384 m->complete = true;
385 return;
386 }
387
388 for (int i=0; i<VF48_MAX_CHANNELS; i++)
389 {
390 if (!fChanEnabled[m->unit][i])
391 continue;
392
393 // no data for this channel
394 if (m->channels[i].channel==(-1) && m->channels[i].numSamples==0)
395 continue;
396
397 // channel is suppressed
398 if (m->channels[i].numSamples==0)
399 continue;
400
401 if (m->channels[i].numSamples != fNumSamples[m->unit])
402 {
403 printf("*** Unit %d, trigger %d: Channel %d %d has %4d samples, should be %3d\n", m->unit, m->trigger, i, m->channels[i].channel, m->channels[i].numSamples, fNumSamples[m->unit]), fBadDataCount++;
404 m->error = 1;
405 }
406
409 }
410
411 uint32_t tn = m->trigno[m->tgroup];
412 double t = m->timestamps[m->tgroup];
413 for (int i=0; i<VF48_MAX_GROUPS; i++)
414 if (fGroupEnabled[m->unit] & (1<<i))
415 {
416 if (!(m->groupMask & (1<<i)))
417 {
418 printf("*** Unit %d, trigger %d: No data for group %d\n", m->unit, m->trigger, i), fBadDataCount++;
419 m->error = 1;
420 }
421 else if (!(m->timestampGroupMask & (1<<i)))
422 {
423 printf("*** Unit %d, trigger %d: No timestamp for group %d\n", m->unit, m->trigger, i), fBadDataCount++;
424 m->error = 1;
425 }
426 else if (fabs(m->timestamps[i] - t) > 0.010)
427 {
428 printf("*** Unit %d, trigger %d: Internal timestamp mismatch: group %d timestamp %.6fs should be %.6fs\n", m->unit, m->trigger, i, m->timestamps[i], t), fBadDataCount++;
429 printf("groups 0x%x\n", m->groupMask);
430 m->PrintModule();
431 m->error = 1;
432 }
433
434 if (m->trigno[i] != tn)
435 {
436 printf("*** Unit %d, trigger %d: Internal trigno mismatch: group %d trigno %u should be %u\n", m->unit, m->trigger, i, m->trigno[i], tn), fBadDataCount++;
437 printf("groups 0x%x\n", m->groupMask);
438 m->PrintModule();
439 m->error = 1;
440 }
441 }
442
443 m->complete = true;
444
445 //printf("Complete: "); Print();
446}
447
449{
450 if (fModulesMask == 0) {
451 // empty event
452 e->complete = true;
453 return;
454 }
455
456 for (int i=0; i<fNumModules; i++)
457 if (e->modules[i]) {
458 if (e->modules[i]->error > e->error)
459 e->error = e->modules[i]->error;
460 if (e->modules[i]->complete)
461 e->modulesMask |= (1<<i);
462 }
463
464 //printf("complete event: mask 0x%04x vs 0x%04x\n", e->modulesMask, fModulesMask);
465
466 if (e->modulesMask == fModulesMask)
467 e->complete = true;
468}
469
471{
472 VF48event* e = FindEvent(m->unit, m->timestamps[m->tgroup]); // find event corresponding to this time, if not found create new event
473 //printf("For unit %d, trigger %d, ts %f, Find event: ", m->unit, m->trigger, m->timestamps[m->tgroup]); e->PrintSummary();
474
475 if (e->modules[m->unit] != NULL)
476 {
477 printf("*** Unit %d has duplicate data for trigger %d timestamp %.6f ms: FindEvent yelds trigger %d timestamp %.6f ms, diff %.6f ms\n", m->unit, m->trigger, m->timestamps[m->tgroup]*1000.0, e->modules[m->unit]->trigger, e->timestamp*1000.0, (m->timestamps[m->tgroup] - e->timestamp)*1000.0), fBadDataCount++;
478
480
481#if 1
482 m->PrintModule();
483 printf("to event:\n");
484 e->PrintSummary();
485#endif
486 // we are not adding this module to this event,
487 // but somebody has to delete the module data.
488 // We do it here.
489 delete m;
490 return;
491 }
492
493 e->modules[m->unit] = m;
494
495 if (m->error > e->error)
496 e->error = m->error;
497
498 // PrintAllEvents();
499}
500
501void PrintVF48word(int unit, int i, uint32_t w)
502{
503 switch (w & 0xF0000000)
504 {
505 default: // unexpected data
506 {
507 printf("unit %d, word %5d: 0x%08x: Unknown data\n", unit, i, w);
508 break;
509 }
510 case 0x80000000: // event header
511 {
512 uint32_t trigNo = w & 0x00FFFFFF;
513 printf("unit %d, word %5d: 0x%08x: Event header: unit %d, trigger %d\n", unit, i, w, unit, trigNo);
514 break;
515 }
516 case 0xA0000000: // time stamp
517 {
518 uint32_t ts = w&0x00FFFFFF;
519 printf("unit %d, word %5d: 0x%08x: Timestamp %d\n", unit, i, w, ts);
520 break;
521 }
522 case 0xC0000000: // channel header
523 {
524 int group = (w&0x70)>>4;
525 int chan = (w&0x7) | (group<<3);
526 printf("unit %d, word %5d: 0x%08x: Group %d, Channel %2d\n", unit, i, w, group, chan);
527 break;
528 }
529 case 0x00000000: // adc samples
530 {
531 if (w==0) // 64-bit padding
532 {
533 printf("unit %d, word %5d: 0x%08x: 64-bit padding\n", unit, i, w);
534 break;
535 }
536
537 int sample1 = w & 0x3FFF;
538 int sample2 = (w>>16) & 0x3FFF;
539 printf("unit %d, word %5d: 0x%08x: samples 0x%04x 0x%04x (%d %d)\n", unit, i, w, sample1, sample2, sample1, sample2);
540 break;
541 }
542 case 0x40000000: // time analysis
543 {
544 int t = w & 0x00FFFFFF;
545 printf("unit %d, word %5d: 0x%08x: Time %d\n", unit, i, w, t);
546 break;
547 }
548 case 0x50000000: // charge analysis
549 {
550 int c = w & 0x00FFFFFF;
551 printf("unit %d, word %5d: 0x%08x: Charge %d\n", unit, i, w, c);
552 break;
553 }
554 case 0xE0000000: // event trailer
555 {
556 uint32_t trigNo2 = w & 0x00FFFFFF;
557 printf("unit %d, word %5d: 0x%08x: Event trailer: unit %d, trigger %d\n", unit, i, w, unit, trigNo2);
558 break;
559 }
560 }
561}
562
564{
565 for (int i=0; i<VF48_MAX_MODULES; i++) {
566 wgrp[i] = 0;
567 wdiscarded[i] = 0;
568 for (int j=0; j<VF48_MAX_GROUPS; j++) {
569 wmax[i][j] = 0;
570 wptr[i][j] = 0;
571 wacc[i][j] = 0;
572 }
573 }
574}
575
577{
578 //PrintAllEvents();
579
580 for (unsigned i=0; i<fBuffer.size(); i++) {
581 VF48event *e = fBuffer[i];
582 delete e;
583 }
584 fBuffer.clear();
585}
586
587VF48module* UnpackVF48::FindModule(int unit, int group, double timestamp)
588{
589 //printf("find module %d, group %d, timestamp %f\n", unit, group, timestamp);
590
591 VF48event* e = FindEvent(unit, timestamp, true);
592
593 if (e) {
594 //printf("e %p, module %d is %p\n", e, unit, e->modules[unit]);
595 if (e->modules[unit])
596 return e->modules[unit];
597
598 VF48module* m = new VF48module(unit);
599 e->modules[unit] = m;
600 return m;
601 }
602
603 VF48module* m = new VF48module(unit);
604 AddToEvent(m);
605 return m;
606}
607
608static void DumpWords(const uint32_t* wptr, int wcount)
609{
610 for (int i=0; i<wcount; i++)
611 printf("word[%d]: 0x%08x\n", i, wptr[i]);
612}
613
614void UnpackVF48::UnpackEvent(int unit, int group, const uint32_t data[], int wcount)
615{
616 #define SWAP 0
617 #if SWAP
618 static bool swap = SWAP;
619 #endif
620 assert(unit>=0);
621 assert(unit<VF48_MAX_MODULES);
622
623 assert(group>=0);
624 assert(group<VF48_MAX_GROUPS);
625
626 if (fDisasmStream) {
627 printf("UnpackVF48A: UnpackEvent unit %d, group %d, wcount %d, first word: 0x%08x, last word: 0x%08x\n", unit, group, wcount, data[0], data[wcount-1]);
628 }
629
630 bool disasm = fDisasmStructure;
631 bool disasmSamples = fDisasmSamples;
632
633 bool doexit = false;
634
635 VF48module* m = NULL;
636
637 int chan = -1;
638 int headerTrigNo = -1;
639 int trailerTrigNo = -1;
640
641 int timestampCount = 0;
642 int timestampFlag = 0;
643 uint32_t timestamp1 = 0;
644 uint32_t timestamp2 = 0;
645
646 for (int i=0; i<wcount; i++)
647 {
648 uint32_t w = data[i];
649
650#if SWAP
651 if (((w&0xF0FFFFFF)==0xF0FFFFFF) && (w != 0xFFFFFFFF))
652 swap = true;
653
654 if (swap && (w != 0xdeadbeef)) {
655 uint32_t w0 = w&0x000000FF;
656 uint32_t w1 = w&0x0000FF00;
657 uint32_t w2 = w&0x00FF0000;
658 uint32_t w3 = w&0xFF000000;
659 w = (w0<<(16+8)) | (w1<<8) | (w2>>8) | (w3>>(16+8));
660 //printf("swap 0x%08x -> 0x%08x\n", data32[i], w);
661 }
662#endif
663
664 switch (w & 0xF0000000)
665 {
666 default: // unexpected data
667 {
668 if (w == 0xdeaddead) // skip the buffer padding
669 {
670 if (disasm)
671 printf("unit %d, word %5d: 0x%08x: reading from empty EB FIFO\n", unit, i, w);
672 break;
673 }
674
675 if (w == 0xdeadbeef) // dma marker
676 {
677 if (disasm)
678 printf("unit %d, word %5d: 0x%08x: DMA marker\n", unit, i, w);
679 break;
680 }
681
682 if (m)
683 if (!m->channels[chan].complete)
684 if (disasm)
685 printf("unit %d, adc samples: %d\n", unit, m->channels[chan].numSamples);
686
687 if (disasm)
688 printf("unit %d, word %5d: 0x%08x: unexpected data\n", unit, i, w);
689
690 if (m)
691 m->error = 1;
692
694 printf("*** Unit %d, group %d, trigger %d: Unexpected data at %5d: 0x%08x, skipping to next event header\n", unit, group, headerTrigNo, i, w);
695
696 //accept = false;
697 break;
698 }
699 case 0xF0000000: // switch to data from different group
700 {
701 int group = (w & 0x00000007);
702
703 if (disasm)
704 printf("unit %d, word %5d: 0x%08x: switch to data from group %d\n", unit, i, w, group);
705
706 // do nothing - should not encounter these - we are here after the demuxer
707 break;
708 }
709 case 0x80000000: // event header
710 {
711 uint32_t trigNo = w & 0x00FFFFFF;
712
713 if (disasm)
714 printf("unit %d, word %5d: 0x%08x: Event header: unit %d, group %d, trigger %d\n", unit, i, w, unit, group, trigNo);
715
716#if 0
717 if (0 && trigNo > 1) {
718 if (trigNo != c->headerTrigNo+1) {
719 printf("*** Unit %d, group %d, trigger %d: Out of sequence trigger %d should be %d\n", unit, group, trigNo, trigNo, c->headerTrigNo+1);
721 }
722 }
723#endif
724
725 headerTrigNo = trigNo;
726
727 //printf("*** Unit %d, group %d, trigger %d: Event header for trigger %d without an event trailer for previous trigger %d, group %d\n", unit, group, trigNo, trigNo, c->headerTrigNo, c->group);
728 //fBadDataCount++;
729
730 break;
731 }
732 case 0xA0000000: // time stamp
733 {
734 uint32_t ts = w&0x00FFFFFF;
735
736 if (disasm)
737 printf("unit %d, word %5d: 0x%08x: Timestamp %d, count %d\n", unit, i, w, ts, timestampCount);
738
739 if (timestampCount == 0)
740 timestamp1 = ts;
741 else if (timestampCount == 1)
742 timestamp2 = ts;
743 else {
744 printf("*** Unit %d, group %d, trigger %d: Unexpected timestamp count: %d\n", unit, group, headerTrigNo, timestampCount);
746 if (m)
747 m->error = 1;
748 }
749
750 timestampCount++;
751 timestampFlag = 1;
752 }
753 break;
754 case 0xC0000000: // channel header
755 {
756 int merror = 0;
757
758 int cgroup = (w&0x70)>>4;
759
760 if (group != 0) { // definitely new mode
761 if (cgroup != 0) { // group number in 0xC header is always zero for new data
763 merror = 1;
764 printf("*** Unit %d, group %d, trigger %d: data at %5d: 0x%08x, Invalid cgroup number %d should be zero\n", unit, group, headerTrigNo, i, w, cgroup);
765 }
766 }
767
768 if (cgroup != 0) { // definitely old data
769 if (group != 0) { // old data should always come from data buffer for group 0
771 merror = 1;
772 printf("*** Unit %d, group %d, trigger %d: data at %5d: 0x%08x, Invalid group number %d should be zero\n", unit, group, headerTrigNo, i, w, group);
773 }
774 }
775
776 if (cgroup == 0)
777 cgroup = group;
778
779 chan = (w&0x7) | (cgroup<<3);
780
781 if (disasm)
782 printf("unit %d, word %5d: 0x%08x: Group %d, Channel %2d\n", unit, i, w, cgroup, chan);
783
784 if ((chan < 0) || (chan >= VF48_MAX_CHANNELS)) {
785 printf("*** Unit %d, group %d, trigger %d: data at %5d: 0x%08x, Bad channel number %d\n", unit, group, headerTrigNo, i, w, chan);
786 merror = 1;
788 break;
789 }
790
791 if (timestampCount) {
792 uint64_t ts48 = timestamp1 | (((uint64_t)timestamp2) << 24);
793
794 if (ts48 == 0 && headerTrigNo == 1 && ts_first[unit][group] != 0) {
795 printf("*** Unit %d, group %d, trigger %d: Group %d unexpected event counter and timestamp reset!\n", unit, group, headerTrigNo, group);
797 merror = 1;
798 ts_first[unit][group] = 0;
799 }
800
802 if (ts48 == 0 && headerTrigNo == 1)
803 {
804 timestamp1 = 1;
805 ts48 = 1;
806 }
807
808 if (!ts_first[unit][group])
809 {
810 ts_first[unit][group] = ts48;
811 }
812 }
813
814 if (ts48 == ts_last[unit][cgroup])
815 {
816 printf("*** Unit %d, group %d, trigger %d: Group %d has invalid timestamp %d, should be more than %d\n", unit, group, headerTrigNo, group, (int)ts48, (int)ts_last[unit][cgroup]);
818 merror = 1;
819 ts48 = ts_last[unit][cgroup] + (int)(fCoinc*fFreq[unit])+1;
820 }
821
822 ts_last[unit][cgroup] = ts48;
823
824 double timestamp = (ts48 - ts_first[unit][group])/fFreq[unit];
825
826 if (!m) {
827 m = FindModule(unit, group, timestamp);
828
829 m->unit = unit;
830 m->trigger = headerTrigNo;
831
832 //if (fDisasmStream)
833 //printf("unit %d, group %d, timestamp %f -> module %p\n", unit, group, timestamp, m);
834 }
835
836#if 0
837 if (headerTrigNo < 4) {
838 printf("AAA unit %d, group %d, trigNo %d, ts 0x%x 0x%x, base 0x%08x, ts %f\n", unit, group, headerTrigNo, timestamp2, timestamp1, (uint32_t)(ts_first[unit][group]&0xFFFFFFFF), timestamp);
839
840 if (headerTrigNo == 2)
841 exit(123);
842 }
843#endif
844
845 m->trigno[cgroup] = headerTrigNo;
846 m->timestamp64[cgroup] = ts48;
847 m->timestamps[cgroup] = timestamp;
848 m->tgroup = cgroup;
849 if (merror)
850 m->error = merror;
851 }
852
853 if (m->channels[chan].numSamples != 0)
854 {
855 printf("*** Unit %d, group %d, trigger %d: Duplicate data for channel %d: already have %d samples\n", unit, group, headerTrigNo, chan, m->channels[chan].numSamples);
857 m->error = 1;
858 }
859
860 timestampCount = 0;
861 m->groupMask |= (1<<cgroup);
862 if (timestampFlag)
863 m->timestampGroupMask |= (1<<cgroup);
864 timestampFlag = 0;
865 m->channels[chan].complete = false;
866 m->channels[chan].numSamples = 0;
867 m->channels[chan].channel = chan;
868
869 m->completeGroupMask |= (1<<cgroup);
870 }
871 break;
872 case 0x00000000: // adc samples
873 {
874 if (!m || (chan<0) || (chan>=VF48_MAX_CHANNELS))
875 {
876 if (disasm)
877 printf("unit %d, word %5d: 0x%08x: out of sequence adc samples\n", unit, i, w);
878
879 if (m)
880 m->error = 1;
882 printf("*** Unit %d, group %d, trigger %d: Unexpected adc samples data at %5d: 0x%08x (no module %p or bad channel number %d)\n", unit, group, headerTrigNo, i, w, m, chan);
883
884 //accept[unit] = false;
885 break;
886 }
887
888 VF48channel *cc = &m->channels[chan];
889
890 int sample1 = w & 0x3FFF;
891 int sample2 = (w>>16) & 0x3FFF;
892
893 if (disasmSamples)
894 printf("unit %d, word %5d: 0x%08x: samples %4d: 0x%04x 0x%04x (%d %d)\n", unit, i, w, cc->numSamples, sample1, sample2, sample1, sample2);
895
896 if (m->channels[chan].complete)
897 {
898 if (1)
899 {
901 m->error = 1;
902
903 static int xi = 0;
904 static int xc = 0;
905
906 if (xi+1 != i)
907 {
908 if (xc > 0)
909 printf("*** Previously ignored %d out of sequence adc samples\n", xc);
910
911 printf("*** Unit %d, group %d, trigger %d: Out of sequence adc samples for channel %d at %d, word 0x%08x\n", unit, group, headerTrigNo, cc->channel, i, w);
912 xc = 0;
913 }
914
915 xi = i;
916 xc ++;
917 }
918 }
919 else if (cc->numSamples < VF48_MAX_SAMPLES-2)
920 {
921 cc->samples[cc->numSamples++] = sample1;
922 cc->samples[cc->numSamples++] = sample2;
923
924 m->presentMask[chan>>3] |= (1<<(chan&7));
925 }
926 else
927 {
928 printf("*** Unit %d group %d channel %d has too many samples: %d\n", unit, group, chan, cc->numSamples);
930 cc->numSamples += 2;
931 m->error = 1;
932 }
933 }
934 break;
935 case 0x40000000: // time analysis
936 {
937 if (!m || (chan<0) || (chan>=VF48_MAX_CHANNELS))
938 {
939 if (disasm)
940 printf("unit %d, word %5d: 0x%08x: out of sequence data\n", unit, i, w);
941
942 if (m)
943 m->error = 1;
945 printf("*** Unit %d, group %d, trigger %d: Unexpected time data at %5d: 0x%08x (no module %p or bad channel number %d)\n", unit, group, headerTrigNo, i, w, m, chan);
946
947 //accept[unit] = false;
948 break;
949 }
950
951 if (!m->channels[chan].complete)
952 if (disasm)
953 printf("unit %d, adc samples: %d\n", unit, m->channels[chan].numSamples);
954
955 int t = w & 0x00FFFFFF;
956 if (disasm)
957 printf("unit %d, word %5d: 0x%08x: Time %d\n", unit, i, w, t);
958 m->channels[chan].time = t;
959 m->channels[chan].complete = true;
960 }
961 break;
962 case 0x50000000: // charge analysis
963 {
964 if (!m || (chan<0) || (chan>=VF48_MAX_CHANNELS))
965 {
966 if (disasm)
967 printf("unit %d, word %5d: 0x%08x: out of sequence data\n", unit, i, w);
968
969 if (m)
970 m->error = 1;
972 printf("*** Unit %d, group %d, trigger %d: Unexpected charge data at %5d: 0x%08x (no module %p or bad channel number %d)\n", unit, group, headerTrigNo, i, w, m, chan);
973
974 //accept[unit] = false;
975 break;
976 }
977
978 if (!m->channels[chan].complete)
979 if (disasm)
980 printf("unit %d, adc samples: %d\n", unit, m->channels[chan].numSamples);
981 int charge = w & 0x00FFFFFF;
982 if (disasm)
983 printf("unit %d, word %5d: 0x%08x: Charge %d\n", unit, i, w, charge);
984
985 if ((w & 0x0F000000) == 0x00000000)
986 m->hitMask[chan>>3] = w & 0xFF;
987
988 m->channels[chan].charge = charge;
989 m->channels[chan].complete = true;
990 }
991 break;
992 case 0xE0000000: // event trailer
993 {
994 if (!m || (chan<0) || (chan>=VF48_MAX_CHANNELS))
995 {
996 if (disasm)
997 printf("unit %d, word %5d: 0x%08x: out of sequence data\n", unit, i, w);
998
999 if (m)
1000 m->error = 1;
1001 fBadDataCount++;
1002 printf("*** Unit %d, group %d, trigger %d: Unexpected event trailer at %5d: 0x%08x (no module %p or bad channel number %d)\n", unit, group, headerTrigNo, i, w, m, chan);
1003
1004 //DumpWords(data, wcount);
1005 //exit(123);
1006
1007 //accept[unit] = false;
1008 break;
1009 }
1010
1011 if (!m->channels[chan].complete)
1012 if (disasm)
1013 printf("unit %d, adc samples: %d\n", unit, m->channels[chan].numSamples);
1014
1015 uint32_t trigNo = w & 0x00FFFFFF;
1016
1017 trailerTrigNo = trigNo;
1018
1019 if (disasm)
1020 printf("unit %d, word %5d: 0x%08x: Event trailer: unit %d, group %d, trigger %d, module complete mask 0x%x\n", unit, i, w, unit, group, trailerTrigNo, m->completeGroupMask);
1021
1022 m->channels[chan].complete = true;
1023
1024 if (trigNo != (uint32_t)headerTrigNo)
1025 {
1026 printf("*** Unit %d, group %d, trigger %d: event trailer trigger mismatch: see %d, should be %d\n", unit, group, headerTrigNo, trigNo, m->trigger);
1027 fBadDataCount++;
1028 m->error = 1;
1029 }
1030
1031 if (m->completeGroupMask == fGroupEnabled[unit]) {
1032 CompleteModule(m);
1033 m = NULL;
1034 }
1035 }
1036 break;
1037 }
1038 }
1039
1040 if (doexit)
1041 exit(123);
1042}
1043
1045{
1046 int grp = wgrp[unit];
1047 assert(grp>=0 && grp<VF48_MAX_GROUPS);
1048
1049 if (!wbuf[unit][grp]) {
1050 wmax[unit][grp] = VF48_MAX_SAMPLES*2*VF48_MAX_CHANNELS + 1024;
1051 wbuf[unit][grp] = (uint32_t*)malloc(wmax[unit][grp]);
1052 assert(wbuf[unit][grp]);
1053 wptr[unit][grp] = 0;
1054 wacc[unit][grp] = false;
1055 wdiscarded[unit] = 0;
1056 }
1057
1058 return grp;
1059}
1060
1061void UnpackVF48::UnpackStream(int unit, const void* data, int size)
1062{
1063 int size32 = size;
1064 const uint32_t *data32 = (const uint32_t*)data;
1065
1066 //printf("UnpackVF48: unit %d, size %d\n", unit, size);
1067
1068 bool doDump = false;
1069
1070 assert(unit>=0);
1071 assert(unit<VF48_MAX_MODULES);
1072
1073 int grp = NewGroup(unit);
1074
1075 for (int i=0; i<size32; i++)
1076 {
1077 uint32_t w = data32[i];
1078
1079 //printf("unit %d, at %d, word 0x%08x\n", unit, i, w);
1080
1081 if ((w & 0xFFFFFFF0) == 0xFFFFFFF0) // group marker
1082 {
1083 int group = (w & 0x00000007);
1084
1085 //if (fDisasmStream)
1086 //printf("unit %d, word %5d: 0x%08x: switch to data from group %d\n", unit, i, w, group);
1087
1088 wgrp[unit] = group;
1089 grp = NewGroup(unit);
1090
1091 //if (wptr[unit][grp] == 0)
1092 //wbuf[unit][grp][wptr[unit][grp]++] = w;
1093 }
1094 else if ((w & 0xF0000000) == 0x80000000) // event header
1095 {
1096 if (wdiscarded[unit]) {
1097 printf("*** Unit %d, group %d, at word %d, skipped %d words preceeding event header 0x%08x\n", unit, grp, i, wdiscarded[unit], w);
1098 doDump = true;
1099 }
1100
1101 if (fDisasmStream) {
1102 printf("UnpackVF48A: Header 0x%08x, unit %d, group %d, at word %d\n", w, unit, grp, i);
1103 }
1104
1105 if (wptr[unit][grp] > 1) {
1106 UnpackEvent(unit, grp, wbuf[unit][grp], wptr[unit][grp]);
1107 wptr[unit][grp] = 0;
1108 }
1109
1110 wacc[unit][grp] = true;
1111 wdiscarded[unit] = 0;
1112
1113 wbuf[unit][grp][wptr[unit][grp]++] = w;
1114 }
1115 else if ((w & 0xF0000000) == 0xE0000000) // event trailer
1116 {
1117 wbuf[unit][grp][wptr[unit][grp]++] = w;
1118
1119 if (fDisasmStream) {
1120 printf("UnpackVF48A: Trailer 0x%08x, unit %d, group %d, at word %d\n", w, unit, grp, i);
1121 }
1122
1123 if (0 && wptr[unit][grp] == 1) {
1124 printf("*** Unit %d, group %d, at word %d, lonely event trailer 0x%08x\n", unit, grp, i, w);
1125 doDump = true;
1126 }
1127
1128 if (wacc[unit][grp]) {
1129 UnpackEvent(unit, grp, wbuf[unit][grp], wptr[unit][grp]);
1130 } else {
1131 printf("*** Unit %d, group %d, at word %d, missing event header for trailer 0x%08x, %d data words were discarded\n", unit, grp, i, w, wdiscarded[unit]);
1132 wdiscarded[unit] = 0;
1133 }
1134
1135 wptr[unit][grp] = 0;
1136 wacc[unit][grp] = false;
1137 }
1138 else if (wacc[unit][grp])
1139 {
1140 wbuf[unit][grp][wptr[unit][grp]++] = w;
1141 }
1142 else
1143 {
1144 //if (fDisasmStream)
1145 //printf("unit %d, word %5d: 0x%08x - skipped waiting for event header\n", unit, i, w);
1146
1147 if (w != 0xdeadbeef) // DMA marker, do not count as skipped
1148 if (w != 0xdeaddead) {
1149 wdiscarded[unit]++;
1150 //printf("*** Unit %d, group %d, at word %d, skipped word 0x%08x\n", unit, grp, i, w);
1151 }
1152 }
1153 }
1154
1155 if (0 && doDump) {
1156 printf("*** Unit %d, bank dump, %d words:\n", unit, size32);
1157 DumpWords(data32, size32);
1158 }
1159}
1160
1161// end
1162
void PrintEvent(const VF48event *e)
#define SWAP
static void DumpWords(const uint32_t *wptr, int wcount)
void PrintVF48word(int unit, int i, uint32_t w)
#define VF48_MAX_SAMPLES
Definition UnpackVF48A.h:12
#define VF48_MAX_MODULES
Definition UnpackVF48A.h:9
#define VF48_MAX_CHANNELS
Definition UnpackVF48A.h:11
#define VF48_MAX_GROUPS
Definition UnpackVF48A.h:10
void SetNumModules(int num_modules)
bool fDisasmStream
void UnpackEvent(int module, int group, const uint32_t *data, int wcount)
void SetTsFreq(int module, double ts_freq_hz)
bool wacc[VF48_MAX_MODULES][VF48_MAX_GROUPS]
bool fChanEnabled[VF48_MAX_MODULES][VF48_MAX_CHANNELS]
Definition UnpackVF48A.h:95
unsigned fFlushIncompleteThreshold
Definition UnpackVF48A.h:99
void CompleteModule(VF48module *m)
bool fDisasmSamples
VF48event * FindEvent(int unit, double timestamp, bool dup=false)
void SetChanEnable(int module, int grp, int chan_enable)
void CompleteEvent(VF48event *e)
void SetNumSamples(int module, int num_samples)
int wgrp[VF48_MAX_MODULES]
int NewGroup(int unit)
VF48module * FindModule(int unit, int group, double timestamp)
double fCoinc
Definition UnpackVF48A.h:98
int wdiscarded[VF48_MAX_MODULES]
void SetModulesMask(uint32_t mask)
void SetTimestampResync(bool enable)
int wptr[VF48_MAX_MODULES][VF48_MAX_GROUPS]
double GetTsFreq(int module)
bool fTimestampResyncEnable
void SetFlushIncompleteThreshold(int threshold)
void PrintAllEvents()
void UnpackStream(int module, const void *data_ptr, int data_size)
int fNumModules
Definition UnpackVF48A.h:92
uint32_t fModulesMask
Definition UnpackVF48A.h:93
uint64_t ts_first[VF48_MAX_MODULES][VF48_MAX_GROUPS]
void ResetStreamBuffer()
void SetCoincTime(double time_sec)
double fFreq[VF48_MAX_MODULES]
Definition UnpackVF48A.h:97
int fNumSamples[VF48_MAX_MODULES]
Definition UnpackVF48A.h:96
uint32_t fGroupEnabled[VF48_MAX_MODULES]
Definition UnpackVF48A.h:94
void AddToEvent(VF48module *m)
uint32_t * wbuf[VF48_MAX_MODULES][VF48_MAX_GROUPS]
bool fDisasmStructure
void SetGroupEnableMask(int module, int grp_enable_mask)
void ResetEventBuffer()
uint64_t ts_last[VF48_MAX_MODULES][VF48_MAX_GROUPS]
VF48event * GetEvent(bool flush=false)
int fBadDataCount
std::deque< VF48event * > fBuffer
int wmax[VF48_MAX_MODULES][VF48_MAX_GROUPS]
uint32_t time
Definition UnpackVF48A.h:17
uint32_t charge
Definition UnpackVF48A.h:18
uint16_t samples[VF48_MAX_SAMPLES]
Definition UnpackVF48A.h:21
void PrintSummary() const
VF48module * modules[VF48_MAX_MODULES]
Definition UnpackVF48A.h:55
VF48event(int eventNo)
double timestamp
Definition UnpackVF48A.h:54
void PrintEvent() const
uint32_t modulesMask
Definition UnpackVF48A.h:53
VF48channel channels[VF48_MAX_CHANNELS]
Definition UnpackVF48A.h:41
VF48module(int i)
uint32_t completeGroupMask
Definition UnpackVF48A.h:35
uint64_t timestamp64[VF48_MAX_GROUPS]
Definition UnpackVF48A.h:31
double timestamps[VF48_MAX_GROUPS]
Definition UnpackVF48A.h:32
int presentMask[VF48_MAX_GROUPS]
Definition UnpackVF48A.h:39
uint32_t timestampGroupMask
Definition UnpackVF48A.h:30
int hitMask[VF48_MAX_GROUPS]
Definition UnpackVF48A.h:40
void PrintModule() const
uint32_t trigno[VF48_MAX_GROUPS]
Definition UnpackVF48A.h:33
uint32_t trigger
Definition UnpackVF48A.h:27
uint32_t groupMask
Definition UnpackVF48A.h:34
bool complete
Definition UnpackVF48A.h:36