ROOTANA
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 
14 VF48module::VF48module(int i) // ctor
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,
50  groupMask,
52  complete,
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 
60 VF48event::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 
124 void 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 
161  fTimestampResyncEnable = true;
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 
193 void UnpackVF48::SetCoincTime(double time_sec)
194 {
195  fCoinc = time_sec;
196 }
197 
199 {
200  fTimestampResyncEnable = enable;
201 }
202 
203 void 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 
214 void UnpackVF48::SetModulesMask(uint32_t mask)
215 {
216  //fNumModules = num_modules;
217  fModulesMask = mask;
218 }
219 
220 void 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 
227 void 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 
234 void 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 
247 void 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 
254 double 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 
266 VF48event* 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 
479  PrintAllEvents();
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 
501 void 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 
587 VF48module* 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 
608 static 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 
614 void 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 
693  fBadDataCount++;
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);
720  fBadDataCount++;
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);
745  fBadDataCount++;
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
762  fBadDataCount++;
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
770  fBadDataCount++;
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;
787  fBadDataCount++;
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);
796  fBadDataCount++;
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]);
817  fBadDataCount++;
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);
856  fBadDataCount++;
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;
881  fBadDataCount++;
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  {
900  fBadDataCount++;
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);
929  fBadDataCount++;
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;
944  fBadDataCount++;
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;
971  fBadDataCount++;
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 
1061 void 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
Definition: UnpackVF48A.h:101
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]
Definition: UnpackVF48A.h:118
bool fChanEnabled[VF48_MAX_MODULES][VF48_MAX_CHANNELS]
Definition: UnpackVF48A.h:95
unsigned fFlushIncompleteThreshold
Definition: UnpackVF48A.h:99
void CompleteModule(VF48module *m)
bool fDisasmSamples
Definition: UnpackVF48A.h:103
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]
Definition: UnpackVF48A.h:114
int NewGroup(int unit)
VF48module * FindModule(int unit, int group, double timestamp)
double fCoinc
Definition: UnpackVF48A.h:98
int wdiscarded[VF48_MAX_MODULES]
Definition: UnpackVF48A.h:119
void SetModulesMask(uint32_t mask)
void SetTimestampResync(bool enable)
int wptr[VF48_MAX_MODULES][VF48_MAX_GROUPS]
Definition: UnpackVF48A.h:116
double GetTsFreq(int module)
bool fTimestampResyncEnable
Definition: UnpackVF48A.h:105
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]
Definition: UnpackVF48A.h:122
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]
Definition: UnpackVF48A.h:117
bool fDisasmStructure
Definition: UnpackVF48A.h:102
void SetGroupEnableMask(int module, int grp_enable_mask)
void ResetEventBuffer()
uint64_t ts_last[VF48_MAX_MODULES][VF48_MAX_GROUPS]
Definition: UnpackVF48A.h:123
VF48event * GetEvent(bool flush=false)
int fBadDataCount
Definition: UnpackVF48A.h:108
std::deque< VF48event * > fBuffer
Definition: UnpackVF48A.h:111
void Reset()
int wmax[VF48_MAX_MODULES][VF48_MAX_GROUPS]
Definition: UnpackVF48A.h:115
bool complete
Definition: UnpackVF48A.h:19
int numSamples
Definition: UnpackVF48A.h:20
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
Definition: UnpackVF48A.cxx:83
VF48module * modules[VF48_MAX_MODULES]
Definition: UnpackVF48A.h:55
VF48event(int eventNo)
Definition: UnpackVF48A.cxx:60
int eventNo
Definition: UnpackVF48A.h:50
double timestamp
Definition: UnpackVF48A.h:54
int complete
Definition: UnpackVF48A.h:51
void PrintEvent() const
uint32_t modulesMask
Definition: UnpackVF48A.h:53
VF48channel channels[VF48_MAX_CHANNELS]
Definition: UnpackVF48A.h:41
VF48module(int i)
Definition: UnpackVF48A.cxx:14
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
Definition: UnpackVF48A.cxx:43
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