Hall-D Software  alpha
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DEVIOWorkerThread.cc
Go to the documentation of this file.
1 /// $Id$
2 //
3 // File: DEVIOWorkerThread.cc
4 // Created: Mon Mar 28 07:40:07 EDT 2016
5 // Creator: davidl (on Darwin harriet.jlab.org 13.4.0 i386)
6 //
7 
8 #include <unistd.h>
9 
10 #include "DEVIOWorkerThread.h"
11 #include "JEventSource_EVIOpp.h"
12 #include "LinkAssociations.h"
13 
14 #include <swap_bank.h>
16 
17 using namespace std;
18 using namespace std::chrono;
19 
20 
21 
22 //---------------------------------
23 // DEVIOWorkerThread (Constructor)
24 //---------------------------------
26  JEventSource_EVIOpp *event_source
27  ,list<DParsedEvent*> &parsed_events
28  ,uint32_t &MAX_PARSED_EVENTS
29  ,mutex &PARSED_EVENTS_MUTEX
30  ,condition_variable &PARSED_EVENTS_CV
31  ,set<uint32_t> &ROCIDS_TO_PARSE
32  ):
33  event_source(event_source)
34  ,parsed_events(parsed_events)
35  ,MAX_PARSED_EVENTS(MAX_PARSED_EVENTS)
36  ,PARSED_EVENTS_MUTEX(PARSED_EVENTS_MUTEX)
37  ,PARSED_EVENTS_CV(PARSED_EVENTS_CV)
38  ,ROCIDS_TO_PARSE(ROCIDS_TO_PARSE)
39  ,done(false)
40  ,thd(&DEVIOWorkerThread::Run,this)
41 {
42  // n.b. in principal, the worker thread is started when the
43  // above constructor is hit and so may already be in Run()
44  // before executing anything below. The "done" variable is
45  // therefore initialized first to guarantee that if that
46  // happens, it gets to the cv.wait() call where it will wait
47  // for someone to notify it. That won't happen before this
48  // constructor completes so we do the remaining initializations
49  // below.
50 
51  VERBOSE = 1;
52  Nrecycled = 0; // Incremented in JEventSource_EVIOpp::Dispatcher()
53  MAX_EVENT_RECYCLES = 1000; // In EVIO events (not L1 trigger events!) overwritten in JEventSource_EVIOpp constructor
54  MAX_OBJECT_RECYCLES = 1000; // overwritten in JEventSource_EVIOpp constructor
55  run_number_seed = 0; // Set in JEventSource_EVIOpp constructor
56 
57  in_use = false;
58  jobtype = JOB_NONE;
59 
60  buff_len = 100; // this will grow as needed
61  buff = new uint32_t[buff_len];
62 
63  PARSE_F250 = true;
64  PARSE_F125 = true;
65  PARSE_F1TDC = true;
66  PARSE_CAEN1290TDC = true;
67  PARSE_CONFIG = true;
68  PARSE_BOR = true;
69  PARSE_EPICS = true;
70  PARSE_EVENTTAG = true;
71  PARSE_TRIGGER = true;
72  PARSE_SSP = true;
73 
74  LINK_TRIGGERTIME = true;
75 }
76 
77 //---------------------------------
78 // ~DEVIOWorkerThread (Destructor)
79 //---------------------------------
81 {
82  if(buff) delete[] buff;
83  for(auto pe : parsed_event_pool) delete pe;
84 }
85 
86 //---------------------------------
87 // Run
88 //---------------------------------
90 {
91  unique_lock<std::mutex> lck(mtx);
92 
93  // Loop waiting for jobs or until told to quit
94  while(!done){
95 
96  cv.wait_for(lck, std::chrono::milliseconds(1));
97 
98  // In principle, in_use should never be false with a jobtype!=JOB_NONE
99  // In practice, this has happened, possibly due to compiler optimization
100  // reordering things in JEventSource_EVIOpp::Dispatcher. That led to
101  // attempting to process a buffer that was being written to. Avoid that
102  // condition by checking the in_use flag is really set.
103  if( !in_use ) continue;
104 
105  try {
106 
107  if( jobtype & JOB_SWAP ) swap_bank(buff, buff, swap32(buff[0])+1 );
108 
110 
112 
113  if( !current_parsed_events.empty() ) PublishEvents();
114 
115  } catch( JExceptionDataFormat &e ){
116  for(auto pe : parsed_event_pool) delete pe; // delete all parsed events any any objects they hold
117  parsed_event_pool.clear();
118  current_parsed_events.clear(); // (these are also in parsed_event_pool so were already deleted)
119  jerr << "Data format error exception caught" << endl;
120  jerr << "Stack trace follows:" << endl;
121  jerr << e.getStackTrace() << endl;
122  jerr << e.what() << endl;
123  japp->Quit(10);
124  } catch (exception &e) {
125  jerr << e.what() << endl;
126  for(auto pe : parsed_event_pool) delete pe; // delete all parsed events any any objects they hold
127  parsed_event_pool.clear();
128  current_parsed_events.clear(); // (these are also in parsed_event_pool so were already deleted)
129  japp->Quit(-1);
130  }
131 
132  // Reset and mark us as available for use
133  jobtype = JOB_NONE;
134  in_use = false;
135 
136  if( jobtype & JOB_QUIT ) break;
137  }
138 
139  in_use = false;
140 }
141 
142 //---------------------------------
143 // Finish
144 //---------------------------------
145 void DEVIOWorkerThread::Finish(bool wait_to_complete)
146 {
147  /// Set the done flag so that the worker thread
148  /// will exit once it is done processing its current
149  /// job. The thread is notified to wake up in case
150  /// it is currently idle. If the wait_to_complete
151  /// flag is set (default), then the worker thread is
152  /// joined to guarantee the current job's processing
153  /// is completed before returning.
154  done = true;
155  cv.notify_all();
156  if(wait_to_complete) {
157  thd.join();
158  } else {
159  thd.detach();
160  }
161 }
162 
163 //---------------------------------
164 // Prune
165 //---------------------------------
167 {
168  /// Delete any DParsedEvent objects not currently in use.
169  /// If the DParsedEvent object pool and their internal
170  /// hit object pools are allowed to continuously grow, it
171  /// will appear as a though there is a memory leak. Occasional
172  /// pruning will reduce the average memory footprint.
173  /// This is called from MakeEvents() every MAX_EVENT_RECYCLES
174  /// EVIO events processed by this worker thread.
175  /// Note that this is in EVIO events (i.e. possibly a block
176  /// of events) not in L1 trigger events.
177  ///
178  /// NOTE: We currently do NOT reduce the size of buff
179  /// here if it is too big. We may wish to do that at some point!
180 
181  // Delete extra parsed events
182  vector<DParsedEvent*> tmp_events = parsed_event_pool;
183  parsed_event_pool.clear();
184  for(auto pe : tmp_events) {
185  if(pe->in_use)
186  parsed_event_pool.push_back(pe);
187  else
188  delete pe;
189 
190  }
191 }
192 
193 //---------------------------------
194 // MakeEvents
195 //---------------------------------
197 {
198 
199  /// Make DParsedEvent objects from data currently in buff.
200  /// This will look at the begining of the EVIO event to see
201  /// how many L1 events are in it. It will then grab that many
202  /// DParsedEvent objects from this threads pool , or create
203  /// new ones and add them all to the current_parsed_events
204  /// vector. These are then filled out later as the data is
205  /// parsed.
206 
207  if(!current_parsed_events.empty()) throw JException("Attempting call to DEVIOWorkerThread::MakeEvents when current_parsed_events not empty!!", __FILE__, __LINE__);
208 
209  uint32_t *iptr = buff;
210 
211  uint32_t M = 1;
212  uint64_t event_num = 0;
213 
214  iptr++;
215  uint32_t mask = 0xFF001000;
216  if( (*iptr)>>16 == 0xFF32){
217 
218  // CDAQ BOR. Leave M=1
219 
220  }else if( (*iptr)>>16 == 0xFF33){
221 
222  // CDAQ Physics event
223  M = iptr[2]&0xFF;
224 
225  // Event number taken from first ROC's trigger bank
226  uint64_t eventnum_lo = iptr[6];
227  uint64_t eventnum_hi = 0; // Only lower 32bits in ROC trigger info.
228  event_num = (eventnum_hi<<32) + (eventnum_lo);
229  }else if( ((*iptr)&mask) == mask ){
230  // CODA Physics event
231  M = *(iptr)&0xFF;
232  uint64_t eventnum_lo = iptr[4];
233  uint64_t eventnum_hi = iptr[5];
234  event_num = (eventnum_hi<<32) + (eventnum_lo);
235  }
236 
237  // Try and get M DParsedEvent objects from this thread's pool.
238  for(auto pe : parsed_event_pool){
239  if(pe->in_use) continue;
240  current_parsed_events.push_back(pe);
241  if( current_parsed_events.size() >= M ) break;
242  }
243 
244  // Create new DParsedEvent objects if needed
245  while( current_parsed_events.size() < M ){
247  current_parsed_events.push_back(pe);
248  parsed_event_pool.push_back(pe);
249  }
250 
251  // Set indexes for the parsed event objects
252  // and flag them as being in use.
253  if( VERBOSE>3 ) cout << " Creating " << current_parsed_events.size() << " parsed events ..." << endl;
254  for(auto pe : current_parsed_events){
255 
256  pe->Clear(); // return previous event's objects to pools and clear vectors
257  pe->buff_len = buff_len;
258  pe->istreamorder = istreamorder;
259  pe->run_number = run_number_seed;
260  pe->event_number = event_num++;
261  pe->sync_flag = false;
262  pe->in_use = true;
263  pe->copied_to_factories = false;
264  pe->event_status_bits = 0;
265  pe->borptrs = NULL; // may be set by either ParseBORbank or JEventSource_EVIOpp::GetEvent
266  }
267 
268  // Parse data in buffer to create data objects
269  ParseBank();
270 
271  // Occasionally prune extra DParsedEvent objects as well as objects
272  // from the existing pools to reduce average memory usage. We do
273  // this after parsing so that not everything is deleted (objects
274  // being used this event will be returned to the pools later.)
275  if(++Nrecycled%MAX_EVENT_RECYCLES == 0) Prune();
276  for(auto pe : current_parsed_events){
277  if( ++pe->Nrecycled%pe->MAX_RECYCLES == 0) pe->Prune();
278  }
279 }
280 
281 //---------------------------------
282 // PublishEvents
283 //---------------------------------
285 {
286  /// Copy our "current_parsed_events" pointers into the global "parsed_events"
287  /// list making them available for consumption.
288 
289  // Lock mutex so other threads can't modify parsed_events
290  unique_lock<mutex> lck(PARSED_EVENTS_MUTEX);
291 
292  // Make sure we don't exceed the maximum number of simultaneous
293  // parsed events. If the done flag is set, go ahead and add
294  // this regardless
295  while( ((current_parsed_events.size()+parsed_events.size())>=MAX_PARSED_EVENTS) && !done ){
297  PARSED_EVENTS_CV.wait_for(lck, std::chrono::milliseconds(1));
298  }
299 
300  // Loop over all elements of parsed_events and insert
301  // these based on istreamorder so that the front element
302  // is the most recent.
303  bool inserted = false;
304  for(auto it = parsed_events.begin(); it!=parsed_events.end(); it++){
305  if( istreamorder < (*it)->istreamorder ){
306  parsed_events.insert(it, current_parsed_events.begin(), current_parsed_events.end());
307  inserted = true;
308  break;
309  }
310  }
311 
312  // In case this should go at end of list
313  if(!inserted) parsed_events.insert(parsed_events.end(), current_parsed_events.begin(), current_parsed_events.end());
314 
315  lck.unlock();
316  PARSED_EVENTS_CV.notify_all();
317 
318  // Any events should now be published
319  current_parsed_events.clear();
320 }
321 
322 //---------------------------------
323 // ParseBank
324 //---------------------------------
326 {
327  uint32_t *iptr = buff;
328  uint32_t *iend = &buff[buff[0]+1];
329 
330  while(iptr < iend){
331  uint32_t event_len = iptr[0];
332  uint32_t event_head = iptr[1];
333  uint32_t tag = (event_head >> 16) & 0xFFFF;
334 
335 //_DBG_ << "0x" << hex << (uint64_t)iptr << dec << ": event_len=" << event_len << "tag=" << hex << tag << dec << endl;
336 
337  switch(tag){
338  case 0x0060: ParseEPICSbank(iptr, iend); break;
339  case 0x0070: ParseBORbank(iptr, iend); break;
340 
341  case 0xFFD0:
342  case 0xFFD1:
343  case 0xFFD2:
344  case 0xFFD3:
345  case 0xFFD4: ParseControlEvent(iptr, iend); break;
346 
347  case 0xFF58:
348  case 0xFF78: current_parsed_events.back()->sync_flag = true;
349  case 0xFF50:
350  case 0xFF70: ParsePhysicsBank(iptr, iend); break;
351  case 0xFF32:
352  case 0xFF33: ParseCDAQBank(iptr, iend); break;
353 
354  default:
355  _DBG_ << "Unknown outer EVIO bank tag: " << hex << tag << dec << endl;
356  iptr = &iptr[event_len+1];
357  if(event_len<1) iptr = iend;
358  }
359  }
360 }
361 
362 //---------------------------------
363 // ParseEventTagBank
364 //---------------------------------
365 void DEVIOWorkerThread::ParseEventTagBank(uint32_t* &iptr, uint32_t *iend)
366 {
367  // skip the bank header
368  // EventTag is stored in a bank of banks with only 1 data bank
369  // so just skip the data bank header for now.
370 
371  iptr++; // data bank length
372  iptr++; // data bank header
373 
374  uint64_t evt_status_lo = *iptr++;
375  uint64_t evt_status_hi = *iptr++;
376  uint64_t l3_status_lo = *iptr++;
377  uint64_t l3_status_hi = *iptr++;
378  auto l3_decision = (DL3Trigger::L3_decision_t)*iptr++;
379  uint32_t l3_algorithm = *iptr++;
380  uint32_t mva_encoded = *iptr++;
381 
382  uint64_t evt_status = evt_status_lo + (evt_status_hi<<32);
383  uint64_t l3_status = l3_status_lo + ( l3_status_hi<<32);
384 
385  DParsedEvent *pe = current_parsed_events.front();
386  pe->NEW_DEventTag(evt_status, l3_decision, l3_status, l3_algorithm, mva_encoded);
387 
388  iptr = iend;
389 }
390 
391 //---------------------------------
392 // ParseEPICSbank
393 //---------------------------------
394 void DEVIOWorkerThread::ParseEPICSbank(uint32_t* &iptr, uint32_t *iend)
395 {
396  if(!PARSE_EPICS){ iptr = iend; return; }
397 
398  time_t timestamp=0;
399 
400  // Outer bank
401  uint32_t *istart = iptr;
402  uint32_t epics_bank_len = *iptr++;
403  if(epics_bank_len < 1){
404  _DBG_ << "bank_len<1 in EPICS event!" << endl;
405  iptr = iend;
406  return;
407  }
408 
409  uint32_t *iend_epics = &iptr[epics_bank_len];
410 
411  // Advance to first daughter bank
412  iptr++;
413 
414  // Get pointer to first DParsedEvent
415  DParsedEvent *pe = current_parsed_events.front();
417 
418  // Loop over daughter banks
419  while( iptr < iend_epics ){
420 
421  uint32_t bank_len = (*iptr)&0xFFFF;
422  uint32_t tag = ((*iptr)>>24)&0xFF;
423  iptr++;
424 
425  if(tag == 0x61){
426  // timestamp bank
427  timestamp = *iptr;
428  }else if(tag == 0x62){
429  // EPICS data value
430  string nameval = (const char*)iptr;
431  pe->NEW_DEPICSvalue(timestamp, nameval);
432  }else{
433  // Unknown tag. Bail
434  _DBG_ << "Unknown tag 0x" << hex << tag << dec << " in EPICS event!" <<endl;
435  DumpBinary(istart, iend_epics, 32, &iptr[-1]);
436  throw JExceptionDataFormat("Unknown tag in EPICS bank", __FILE__, __LINE__);
437  }
438 
439  iptr = &iptr[bank_len];
440  }
441 
442  iptr = iend_epics;
443 }
444 
445 //---------------------------------
446 // ParseBORbank
447 //---------------------------------
448 void DEVIOWorkerThread::ParseBORbank(uint32_t* &iptr, uint32_t *iend)
449 {
450  /// Create BOR config objects from the EVIO bank and store them in
451  /// the event (should only be one since BOR events are not entangled).
452  /// These objects will eventually be inherited by the JEventSource_EVIOpp
453  /// object and passed to all subsequent events.
454 
455  // Upon entry, iptr should point to length word of a bank of banks with tag=0x70
456  // indicating BOR event. Each bank contained within will represent one crate and
457  // will be a bank with tag=0x71 and num the rocid, containing tagsegments. Each tagsegment
458  // represents a single module with the tag containing the module type (bits 0-4) and
459  // slot (bits 5-10). The data in the tagsegments is uint32_t and maps to a data
460  // structure in bor_roc.h depending on the module type. Below is a summary of
461  // how this looks in memory:
462  //
463  // BOR event length
464  // BOR header
465  // crate bank length
466  // crate header
467  // module bank len/header
468  // module data ...
469  // module bank len/header
470  // module data ...
471  // ...
472  // crate bank length
473  // crate header
474  // ...
475 
476  if(!PARSE_BOR){ iptr = &iptr[(*iptr) + 1]; return; }
477  if(VERBOSE>1) jout << "--- Parsing BOR Bank" << endl;
478 
479  // Make sure there is exactly 1 event in current_parsed_events
480  if(current_parsed_events.size() != 1){
481  stringstream ss;
482  ss << "DEVIOWorkerThread::ParseBORbank called for EVIO event with " << current_parsed_events.size() << " events in it. (Should be exactly 1!)";
483  jerr << ss.str() << endl;
484  jerr << "EVIO length=" << hex << iptr[0] << " header=" << iptr[1] << endl;
485  throw JExceptionDataFormat(ss.str(), __FILE__, __LINE__);
486  }
487 
488  // Create new DBORptrs object and set pointer to it in DParsedEvent
489  // (see JEventSource_EVIOpp::GetEvent)
490  DParsedEvent *pe = current_parsed_events.front();
492  pe->borptrs = new DBORptrs();
493  DBORptrs* &borptrs = pe->borptrs;
494 
495  // Make sure we have full event
496  uint32_t borevent_len = *iptr++;
497  uint32_t bank_len = (uint32_t)((uint64_t)iend - (uint64_t)iptr)/sizeof(uint32_t);
498  if(borevent_len > bank_len){
499  stringstream ss;
500  ss << "BOR: Size of bank doesn't match amount of data given (" << borevent_len << " > " << bank_len << ")";
501  throw JExceptionDataFormat(ss.str(), __FILE__, __LINE__);
502  }
503  iend = &iptr[borevent_len]; // in case they give us too much data!
504 
505  // Make sure BOR header word is right
506  uint32_t bor_header = *iptr++;
507  if( (bor_header!=0x700e01) && (bor_header!=0x700e34) ){
508  stringstream ss;
509  ss << "Bad BOR header: 0x" << hex << bor_header;
510  _DBG_<< ss.str() << endl;
511  DumpBinary(&iptr[-4], iend, 32, iptr);
512  throw JExceptionDataFormat(ss.str(), __FILE__, __LINE__);
513  }
514 
515  // Loop over crates
516  while(iptr<iend){
517  uint32_t crate_len = *iptr++;
518  uint32_t *iend_crate = &iptr[crate_len]; // points to first word after this crate
519  uint32_t crate_header = *iptr++;
520 // uint32_t rocid = crate_header&0xFF;
521 
522  // Make sure crate tag is right
523  if( (crate_header>>16) != 0x71 ){
524  stringstream ss;
525  ss << "Bad BOR crate header: 0x" << hex << (crate_header>>16);
526  _DBG_<< ss.str() << endl;
527  throw JExceptionDataFormat(ss.str(), __FILE__, __LINE__);
528  }
529 
530  // Loop over modules
531  while(iptr<iend_crate){
532  uint32_t module_header = *iptr++;
533  uint32_t module_len = module_header&0xFFFF;
534  uint32_t modType = (module_header>>20)&0x1f;
535 // uint32_t slot = (module_header>>25);
536 // uint32_t *iend_module = &iptr[module_len]; // points to first word after this module
537 
538  uint32_t *src = iptr;
539  uint32_t *dest = NULL;
540  uint32_t sizeof_dest = 0;
541 
542  Df250BORConfig *f250conf = NULL;
543  Df125BORConfig *f125conf = NULL;
544  DF1TDCBORConfig *F1TDCconf = NULL;
545  DCAEN1290TDCBORConfig *caen1190conf = NULL;
546  DTSGBORConfig *tsgconf = NULL;
547 
548  switch(modType){
549  case DModuleType::FADC250: // f250
550  f250conf = new Df250BORConfig;
551  dest = (uint32_t*)&f250conf->rocid;
552  sizeof_dest = sizeof(f250config)/sizeof(uint32_t);
553  break;
554  case DModuleType::FADC125: // f125
555  f125conf = new Df125BORConfig;
556  dest = (uint32_t*)&f125conf->rocid;
557  sizeof_dest = sizeof(f125config)/sizeof(uint32_t);
558  break;
559 
560  case DModuleType::F1TDC32: // F1TDCv2
561  case DModuleType::F1TDC48: // F1TDCv3
562  F1TDCconf = new DF1TDCBORConfig;
563  dest = (uint32_t*)&F1TDCconf->rocid;
564  sizeof_dest = sizeof(F1TDCconfig)/sizeof(uint32_t);
565  break;
566 
567  case DModuleType::CAEN1190: // CAEN 1190 TDC
568  case DModuleType::CAEN1290: // CAEN 1290 TDC
569  caen1190conf = new DCAEN1290TDCBORConfig;
570  dest = (uint32_t*)&caen1190conf->rocid;
571  sizeof_dest = sizeof(caen1190config)/sizeof(uint32_t);
572  break;
573  case DModuleType::CDAQTSG: // TSG (from CDAQ)
574  tsgconf = new DTSGBORConfig;
575  // Accomodate variable number of words by copying here
576  tsgconf->rocid = 81; // rocid member must exist for LinkAssociations.h::SortByModule
577  tsgconf->slot = 1; // " " "
578  tsgconf->run_number = src[0];
579  tsgconf->unix_time = src[1];
580  for(uint32_t i=0; i<module_len; i++) tsgconf->misc_words.push_back(src[i]);
581 
582  sizeof_dest = module_len; // prevent error from being thrown below
583  dest = src; // make copy benign. This allows us to keep mechansim used by other modules
584  break;
585 
586  default:
587  {
588  stringstream ss;
589  ss << "Unknown BOR module type: " << modType << " (module_header=0x"<<hex<<module_header<<")";
590  jerr << ss.str() << endl;
591  throw JExceptionDataFormat(ss.str(), __FILE__, __LINE__);
592  }
593  }
594 
595  // Check that the bank size and data structure size match.
596  if( module_len > sizeof_dest ){
597  stringstream ss;
598  ss << "BOR module bank size does not match structure! " << module_len << " > " << sizeof_dest << " for modType " << modType;
599  _DBG_<< ss.str() << endl;
600  throw JExceptionDataFormat(ss.str(), __FILE__, __LINE__);
601  }
602 
603  // Copy bank data, assuming format is the same
604  // Set extra words to "0" at end of structure
605  // in case we are processing data from older firmware
606  for(uint32_t i=0; i<sizeof_dest; i++) *dest++ = i<module_len ? (*src++):0;
607 
608  // Extract certain derived values to fill in convenience members
609  if(f250conf ) f250conf->FillDerived();
610 
611  // Store object for use in this and subsequent events
612  if(f250conf ) borptrs->vDf250BORConfig.push_back(f250conf);
613  if(f125conf ) borptrs->vDf125BORConfig.push_back(f125conf);
614  if(F1TDCconf ) borptrs->vDF1TDCBORConfig.push_back(F1TDCconf);
615  if(caen1190conf) borptrs->vDCAEN1290TDCBORConfig.push_back(caen1190conf);
616  if(tsgconf ) borptrs->vDTSGBORConfig.push_back(tsgconf);
617 
618  iptr = &iptr[module_len];
619  }
620 
621  iptr = iend_crate; // ensure we're pointing past this crate
622  }
623 
624  // Sort the BOR config events now so we don't have to do it for every event
625  borptrs->Sort();
626 }
627 
628 //---------------------------------
629 // ParseTSscalerBank
630 //---------------------------------
631 void DEVIOWorkerThread::ParseTSscalerBank(uint32_t* &iptr, uint32_t *iend)
632 {
633  uint32_t Nwords = ((uint64_t)iend - (uint64_t)iptr)/sizeof(uint32_t);
634  uint32_t Nwords_expected = (6+32+16+32+16);
635  if(Nwords != Nwords_expected){
636  _DBG_ << "TS bank size does not match expected!!" << endl;
637  _DBG_ << "Found " << Nwords << " words. Expected " << Nwords_expected << endl;
638  throw JExceptionDataFormat("TS bank size does not match expected", __FILE__, __LINE__);
639  }else{
640  // n.b. Get the last event here since if this is a block
641  // of events, the last should be the actual sync event.
642  DParsedEvent *pe = current_parsed_events.back();
643  DL1Info *s = pe->NEW_DL1Info();
644  s->nsync = *iptr++;
645  s->trig_number = *iptr++;
646  s->live_time = *iptr++;
647  s->busy_time = *iptr++;
648  s->live_inst = *iptr++;
649  s->unix_time = *iptr++;
650  for(uint32_t i=0; i<32; i++) s->gtp_sc.push_back ( *iptr++ );
651  for(uint32_t i=0; i<16; i++) s->fp_sc.push_back ( *iptr++ );
652  for(uint32_t i=0; i<32; i++) s->gtp_rate.push_back( *iptr++ );
653  for(uint32_t i=0; i<16; i++) s->fp_rate.push_back ( *iptr++ );
654  }
655 
656  iptr = iend;
657 }
658 
659 //---------------------------------
660 // Parsef250scalerBank
661 //---------------------------------
662 void DEVIOWorkerThread::Parsef250scalerBank(uint32_t rocid, uint32_t* &iptr, uint32_t *iend)
663 {
664 
665  uint32_t Nwords = ((uint64_t)iend - (uint64_t)iptr)/sizeof(uint32_t);
666 
667  if(Nwords < 4){
668  _DBG_ << "250Scaler bank size does not match expected!!" << endl;
669  _DBG_ << "Found " << Nwords << endl;
670  throw JExceptionDataFormat("250scaler bank size does not match expected", __FILE__, __LINE__);
671  } else {
672 
673  DParsedEvent *pe = current_parsed_events.back();
674 
675  Df250Scaler *sc = pe->NEW_Df250Scaler();
676 
677  sc->nsync = *iptr++;
678  sc->trig_number = *iptr++;
679  sc->version = *iptr++;
680  sc->crate = rocid;
681 
682  while(iptr < iend){
683  // cout << " " << *iptr << endl;
684  sc->fa250_sc.push_back(*iptr++);
685  }
686 
687  }
688 
689  iptr = iend;
690 
691 }
692 
693 //---------------------------------
694 // ParseControlEvent
695 //---------------------------------
696 void DEVIOWorkerThread::ParseControlEvent(uint32_t* &iptr, uint32_t *iend)
697 {
698 
699  time_t t = (time_t)iptr[2];
700  string tstr = ctime(&t);
701  if(tstr.size()>1) tstr.erase(tstr.size()-1);
702 
703  string type = "Control";
704  switch(iptr[1]>>16){
705  case 0XFFD0: type = "Sync"; break;
706  case 0XFFD1: type = "Prestart"; break;
707  case 0XFFD2: type = "Go"; break;
708  case 0XFFD3: type = "Pause"; break;
709  case 0XFFD4: type = "End"; break;
710  }
711 
712  jout << "Control event: " << type << " - " << tstr << endl;
713 
714  for(auto pe : current_parsed_events) {
715  pe->event_status_bits |= (1<<kSTATUS_CONTROL_EVENT);
716  auto controlevent = pe->NEW_DCODAControlEvent();
717  controlevent->event_type = iptr[1]>>16;
718  controlevent->unix_time = t;
719  for(auto p = iptr; p!=iend; p++) controlevent->words.push_back(*p);
720  }
721 
722  iptr = &iptr[(*iptr) + 1];
723 }
724 
725 //---------------------------------
726 // ParsePhysicsBank
727 //---------------------------------
728 void DEVIOWorkerThread::ParsePhysicsBank(uint32_t* &iptr, uint32_t *iend)
729 {
730 
731  for(auto pe : current_parsed_events) pe->event_status_bits |= (1<<kSTATUS_PHYSICS_EVENT) + (1<<kSTATUS_CODA);
732 
733  uint32_t physics_event_len = *iptr++;
734  uint32_t *iend_physics_event = &iptr[physics_event_len];
735  iptr++;
736 
737  // Built Trigger Bank
738  uint32_t built_trigger_bank_len = *iptr;
739  uint32_t *iend_built_trigger_bank = &iptr[built_trigger_bank_len+1];
740  ParseBuiltTriggerBank(iptr, iend_built_trigger_bank);
741  iptr = iend_built_trigger_bank;
742 
743  // Loop over Data banks
744  while( iptr < iend_physics_event ) {
745 
746  uint32_t data_bank_len = *iptr;
747  uint32_t *iend_data_bank = &iptr[data_bank_len+1];
748 
749  ParseDataBank(iptr, iend_data_bank);
750 
751  iptr = iend_data_bank;
752  }
753 
754  iptr = iend_physics_event;
755 }
756 
757 //---------------------------------
758 // ParseCDAQBank
759 //---------------------------------
760 void DEVIOWorkerThread::ParseCDAQBank(uint32_t* &iptr, uint32_t *iend)
761 {
762 
763  if(VERBOSE>1) jout << "-- Parsing CDAQ Event" << endl;
764 
765  // Check if this is a BOR event
766  if( (iptr[1]&0xFFFF0000) == 0xFF320000 ){
767  iptr += 2;
768  try{
769  ParseBORbank(iptr, iend);
770  }catch(JException &e){
771  cerr << e.what();
772  }
773  return;
774  }
775 
776  // Must be physics event(s)
777  for(auto pe : current_parsed_events) pe->event_status_bits |= (1<<kSTATUS_PHYSICS_EVENT) + (1<<kSTATUS_CDAQ);
778 
779  // Set flag in JEventSource_EVIOpp that this is a CDAQ file
780  event_source->IS_CDAQ_FILE = true;
781 
782  uint32_t physics_event_len = *iptr++;
783  uint32_t *iend_physics_event = &iptr[physics_event_len];
784  iptr++;
785 
786  // Loop over Data banks
787  while( iptr < iend_physics_event ) {
788 
789  uint32_t data_bank_len = *iptr;
790  uint32_t *iend_data_bank = &iptr[data_bank_len+1];
791 
792  ParseDataBank(iptr, iend_data_bank);
793 
794  iptr = iend_data_bank;
795  }
796 
797  iptr = iend_physics_event;
798 }
799 
800 //---------------------------------
801 // ParseBuiltTriggerBank
802 //---------------------------------
803 void DEVIOWorkerThread::ParseBuiltTriggerBank(uint32_t* &iptr, uint32_t *iend)
804 {
805  if(!PARSE_TRIGGER) return;
806 
807  iptr++; // advance past length word
808  uint32_t mask = 0xFF202000;
809  if( ((*iptr) & mask) != mask ){
810  stringstream ss;
811  ss << "Bad header word in Built Trigger Bank: " << hex << *iptr;
812  throw JExceptionDataFormat(ss.str(), __FILE__, __LINE__);
813  }
814 
815  uint32_t tag = (*iptr)>>16; // 0xFF2X
816  uint32_t Nrocs = (*iptr++) & 0xFF;
817  uint32_t Mevents = current_parsed_events.size();
818 
819  // sanity check:
820  if(Mevents == 0) {
821  stringstream ss;
822  ss << "DEVIOWorkerThread::ParseBuiltTriggerBank() called with zero events! "<<endl;
823  throw JExceptionDataFormat(ss.str(), __FILE__, __LINE__);
824  }
825 
826 
827  //-------- Common data (64bit)
828  uint32_t common_header64 = *iptr++;
829  uint32_t common_header64_len = common_header64 & 0xFFFF;
830  uint64_t *iptr64 = (uint64_t*)iptr;
831  iptr = &iptr[common_header64_len];
832 
833  // First event number
834  uint64_t first_event_num = *iptr64++;
835 
836  // Hi and lo 32bit words in 64bit numbers seem to be
837  // switched for events read from ET, but not read from
838  // file. Not sure if this is in the swapping routine
839  if(event_source->source_type==event_source->kETSource) first_event_num = (first_event_num>>32) | (first_event_num<<32);
840 
841  // Average timestamps
842  uint32_t Ntimestamps = (common_header64_len/2)-1;
843  if(tag & 0x2) Ntimestamps--; // subtract 1 for run number/type word if present
844  vector<uint64_t> avg_timestamps;
845  for(uint32_t i=0; i<Ntimestamps; i++) avg_timestamps.push_back(*iptr64++);
846 
847  // run number and run type
848  uint32_t run_number = 0;
849  uint32_t run_type = 0;
850  if(tag & 0x02){
851  run_number = (*iptr64) >> 32;
852  run_type = (*iptr64) & 0xFFFFFFFF;
853  iptr64++;
854  }
855 
856  //-------- Common data (16bit)
857  uint32_t common_header16 = *iptr++;
858  uint32_t common_header16_len = common_header16 & 0xFFFF;
859  uint16_t *iptr16 = (uint16_t*)iptr;
860  iptr = &iptr[common_header16_len];
861 
862  vector<uint16_t> event_types;
863  for(uint32_t i=0; i<Mevents; i++) event_types.push_back(*iptr16++);
864 
865  //-------- ROC data (32bit)
866  for(uint32_t iroc=0; iroc<Nrocs; iroc++){
867  uint32_t common_header32 = *iptr++;
868  uint32_t common_header32_len = common_header32 & 0xFFFF;
869  uint32_t rocid = common_header32 >> 24;
870 
871  uint32_t Nwords_per_event = common_header32_len/Mevents;
872  for(auto pe : current_parsed_events){
873 
874  DCODAROCInfo *codarocinfo = pe->NEW_DCODAROCInfo();
875  codarocinfo->rocid = rocid;
876 
877  uint64_t ts_low = *iptr++;
878  uint64_t ts_high = *iptr++;
879  codarocinfo->timestamp = (ts_high<<32) + ts_low;
880  codarocinfo->misc.clear(); // could be recycled from previous event
881  for(uint32_t i=2; i<Nwords_per_event; i++) codarocinfo->misc.push_back(*iptr++);
882 
883  if(iptr > iend){
884  throw JExceptionDataFormat("Bad data format in ParseBuiltTriggerBank!", __FILE__, __LINE__);
885  }
886  }
887  }
888 
889  //-------- Make DCODAEventInfo objects
890  uint64_t ievent = 0;
891  for(auto pe : current_parsed_events){
892 
893  pe->run_number = run_number; // may be overwritten in JEventSource_EVIOpp::GetEvent()
894 
895  DCODAEventInfo *codaeventinfo = pe->NEW_DCODAEventInfo();
896  codaeventinfo->run_number = run_number;
897  codaeventinfo->run_type = run_type;
898  codaeventinfo->event_number = first_event_num + ievent;
899  codaeventinfo->event_type = event_types.empty() ? 0:event_types[ievent];
900  codaeventinfo->avg_timestamp = avg_timestamps.empty() ? 0:avg_timestamps[ievent];
901  ievent++;
902  }
903 }
904 
905 //---------------------------------
906 // ParseRawTriggerBank
907 //---------------------------------
908 void DEVIOWorkerThread::ParseRawTriggerBank(uint32_t rocid, uint32_t* &iptr, uint32_t *iend)
909 {
910  // CDAQ records the raw trigger bank rather than the built trigger bank.
911  // Create DCODAROCInfo objects for each of these.
912 
913  if(!PARSE_TRIGGER) return;
914 
915  // On entry, iptr points to word after the bank header (i.e. word after the one with 0xFF11)
916 
917  // Loop over events. Should be one segment for each event
918  uint32_t ievent = 0;
919  for(auto pe : current_parsed_events){
920 
921  uint32_t segment_header = *iptr++;
922  uint32_t segment_len = segment_header&0xFFFF;
923  uint32_t *iend_segment = &iptr[segment_len];
924 
925  uint32_t event_number = *iptr++;
926  uint64_t ts_low = *iptr++;
927  uint64_t ts_high = *iptr++;
928 
929  DCODAROCInfo *codarocinfo = pe->NEW_DCODAROCInfo();
930  codarocinfo->rocid = rocid;
931  codarocinfo->timestamp = (ts_high<<32) + ts_low;
932  codarocinfo->misc.clear(); // could be recycled from previous event
933 
934  // rocid=1 is TS and produces 2 extra words for the trigger bits
935  for(uint32_t i=3; i<segment_len; i++) codarocinfo->misc.push_back(*iptr++);
936 
937  if( iptr != iend_segment){
938  throw JExceptionDataFormat("Bad raw trigger bank format", __FILE__, __LINE__);
939  }
940  }
941 }
942 
943 //---------------------------------
944 // ParseDataBank
945 //---------------------------------
946 void DEVIOWorkerThread::ParseDataBank(uint32_t* &iptr, uint32_t *iend)
947 {
948  // Physics Event's Data Bank header
949  iptr++; // advance past data bank length word
950  uint32_t rocid = ((*iptr)>>16) & 0xFFF;
951  iptr++;
952 
953  if(!ROCIDS_TO_PARSE.empty()){
954  if(ROCIDS_TO_PARSE.find(rocid) == ROCIDS_TO_PARSE.end()) return;
955  }
956 
957  // Loop over Data Block Banks
958  while(iptr < iend){
959 
960  uint32_t data_block_bank_len = *iptr++;
961  uint32_t *iend_data_block_bank = &iptr[data_block_bank_len];
962  uint32_t data_block_bank_header = *iptr++;
963 
964  // Not sure where this comes from, but it needs to be skipped if present
965  while( (*iptr==0xF800FAFA) && (iptr<iend) ) iptr++;
966 
967  uint32_t det_id = (data_block_bank_header>>16) & 0xFFF;
968  switch(det_id){
969 
970  case 20:
971  if(VERBOSE>3) jout << " -- CAEN1190 rocid="<< rocid << endl;
972  ParseCAEN1190(rocid, iptr, iend_data_block_bank);
973  break;
974 
975  case 0x55:
976  if(VERBOSE>3) jout <<" -- Module Configuration rocid="<< rocid << endl;
977  ParseModuleConfiguration(rocid, iptr, iend_data_block_bank);
978  break;
979 
980  case 0x56:
981  if(VERBOSE>3) jout <<" -- Event Tag rocid="<< rocid << endl;
982  ParseEventTagBank(iptr, iend_data_block_bank);
983  break;
984 
985  case 0:
986  case 1:
987  case 3:
988  case 6: // flash 250 module, MMD 2014/2/4
989  case 16: // flash 125 module (CDC), DL 2014/6/19
990  case 26: // F1 TDC module (BCAL), MMD 2014-07-31
991  if(VERBOSE>3) jout <<" -- JLab Module rocid="<< rocid << endl;
992  ParseJLabModuleData(rocid, iptr, iend_data_block_bank);
993  break;
994 
995  case 0x123:
996  case 0x28:
997  if(VERBOSE>3) jout <<" -- SSP rocid="<< rocid << endl;
998  ParseSSPBank(rocid, iptr, iend_data_block_bank);
999  break;
1000 
1001  // These were implemented in the ROL for sync events
1002  // as 0xEE02 and 0xEE05. However, that violates the
1003  // spec. which reserves the top 4 bits as status bits
1004  // (the first "E" should really be a "1". We just check
1005  // other 12 bits here.
1006  case 0xE02:
1007  if(VERBOSE>3) jout <<" -- TSscaler rocid="<< rocid << endl;
1008  ParseTSscalerBank(iptr, iend);
1009  break;
1010  case 0xE05:
1011  // Parsef250scalerBank(iptr, iend);
1012  break;
1013  case 0xE10:
1014  Parsef250scalerBank(rocid, iptr, iend_data_block_bank);
1015  break;
1016 
1017  // The CDAQ system leave the raw trigger info in the Physics event data
1018  // bank. Skip it for now.
1019  case 0xF11:
1020  if(VERBOSE>3) jout <<"Raw Trigger bank rocid="<< rocid << endl;
1021  ParseRawTriggerBank(rocid, iptr, iend_data_block_bank);
1022  break;
1023 
1024  // When we write out single events in the offline, we also can save some
1025  // higher level data objects to save disk space and speed up
1026  // specialized processing (e.g. pi0 calibration)
1027  case 0xD01:
1028  ParseDVertexBank(iptr, iend_data_block_bank);
1029  break;
1030  case 0xD02:
1031  ParseDEventRFBunchBank(iptr, iend_data_block_bank);
1032  break;
1033 
1034  case 5:
1035  // old ROL Beni used had this but I don't think its
1036  // been used for years. Run 10390 seems to have
1037  // this though (???)
1038  break;
1039 
1040 
1041  default:
1042  jerr<<"Unknown module type ("<<det_id<<" = 0x" << hex << det_id << dec << " ) encountered" << endl;
1043 // if(VERBOSE>5){
1044  cout << "----- First few words to help with debugging -----" << endl;
1045  cout.flush(); cerr.flush();
1046  DumpBinary(&iptr[-2], iend, 32, &iptr[-1]);
1047 // }
1048  throw JExceptionDataFormat("Unknown bank type in EVIO", __FILE__, __LINE__);
1049 
1050  }
1051 
1052  iptr = iend_data_block_bank;
1053  }
1054 
1055 }
1056 
1057 //----------------
1058 // ParseTIBank
1059 //----------------
1060 void DEVIOWorkerThread::ParseTIBank(uint32_t rocid, uint32_t* &iptr, uint32_t* iend)
1061 {
1062  while(iptr<iend && ((*iptr) & 0xF8000000) != 0x88000000) iptr++; // Skip to JLab block trailer
1063  iptr++; // advance past JLab block trailer
1064  while(iptr<iend && *iptr == 0xF8000000) iptr++; // skip filler words after block trailer
1065  //iptr = iend;
1066 }
1067 
1068 //----------------
1069 // ParseCAEN1190
1070 //----------------
1071 void DEVIOWorkerThread::ParseCAEN1190(uint32_t rocid, uint32_t* &iptr, uint32_t *iend)
1072 {
1073  if(!PARSE_CAEN1290TDC){ iptr = &iptr[(*iptr) + 1]; return; }
1074 
1075  /// Parse data from a CAEN 1190 or 1290 module
1076  /// (See ppg. 72-74 of V1290_REV15.pdf manual)
1077 
1078  uint32_t slot = 0;
1079  uint32_t event_count = 0;
1080  uint32_t word_count = 0;
1081  uint32_t trigger_time_tag = 0;
1082  uint32_t tdc_num = 0;
1083  uint32_t event_id = 0;
1084  uint32_t bunch_id = 0;
1085 
1086  // We need to accomodate multi-event blocks where
1087  // events are entangled (i.e. hits from event 1
1088  // are mixed in between those of event 2,3,4,
1089  // etc... With CAEN modules, we only know which
1090  // event a hit came from by looking at the event_id
1091  // in the TDC header. This value is only 12 bits
1092  // and could roll over within an event block. This
1093  // means we need to keep track of the order we
1094  // encounter them in so it is maintained in the
1095  // "events" container. The event_id order is kept
1096  // in the "event_id_order" vector.
1097  map<uint32_t, DParsedEvent*> events_by_event_id;
1098 
1099  auto pe_iter = current_parsed_events.begin();
1100  DParsedEvent *pe = NULL;
1101 
1102  while(iptr<iend){
1103 
1104  // This word appears to be appended to the data.
1105  // Probably in the ROL. Ignore it if found.
1106  if(*iptr == 0xd00dd00d) {
1107  if(VERBOSE>7) cout << " CAEN skipping 0xd00dd00d word" << endl;
1108  iptr++;
1109  continue;
1110  }
1111 
1112  uint32_t type = (*iptr) >> 27;
1113  uint32_t edge = 0; // 1=trailing, 0=leading
1114  uint32_t channel = 0;
1115  uint32_t tdc = 0;
1116  uint32_t error_flags = 0;
1117  switch(type){
1118  case 0b01000: // Global Header
1119  slot = (*iptr) & 0x1f;
1120  event_count = ((*iptr)>>5) & 0xffffff;
1121  if(VERBOSE>7) cout << " CAEN TDC Global Header (slot=" << slot << " , event count=" << event_count << ")" << endl;
1122  break;
1123  case 0b10000: // Global Trailer
1124  slot = (*iptr) & 0x1f;
1125  word_count = ((*iptr)>>5) & 0x7ffff;
1126  if(VERBOSE>7) cout << " CAEN TDC Global Trailer (slot=" << slot << " , word count=" << word_count << ")" << endl;
1127  slot = event_count = word_count = trigger_time_tag = tdc_num = event_id = bunch_id = 0;
1128  break;
1129  case 0b10001: // Global Trigger Time Tag
1130  trigger_time_tag = ((*iptr)>>5) & 0x7ffffff;
1131  if(VERBOSE>7) cout << " CAEN TDC Global Trigger Time Tag (tag=" << trigger_time_tag << ")" << endl;
1132  break;
1133  case 0b00001: // TDC Header
1134  tdc_num = ((*iptr)>>24) & 0x03;
1135  event_id = ((*iptr)>>12) & 0x0fff;
1136  bunch_id = (*iptr) & 0x0fff;
1137  if(events_by_event_id.find(event_id) == events_by_event_id.end()){
1138  if(pe_iter == current_parsed_events.end()){
1139  _DBG_ << "CAEN1290TDC parser sees more events than CODA header! (>" << current_parsed_events.size() << ")" << endl;
1140  for( auto p : events_by_event_id) cout << "id=" << p.first << endl;
1141  iptr = iend;
1142  throw JExceptionDataFormat("CAEN1290TDC parser sees more events than CODA header", __FILE__, __LINE__);
1143  }
1144  pe = *pe_iter++;
1145  events_by_event_id[event_id] = pe;
1146  }else{
1147  pe = events_by_event_id[event_id];
1148  }
1149  if(VERBOSE>7) cout << " CAEN TDC TDC Header (tdc=" << tdc_num <<" , event id=" << event_id <<" , bunch id=" << bunch_id << ")" << endl;
1150  break;
1151  case 0b00000: // TDC Measurement
1152  edge = ((*iptr)>>26) & 0x01;
1153  channel = ((*iptr)>>21) & 0x1f;
1154  tdc = ((*iptr)>>0) & 0x1fffff;
1155  if(VERBOSE>7) cout << " CAEN TDC TDC Measurement (" << (edge ? "trailing":"leading") << " , channel=" << channel << " , tdc=" << tdc << ")" << endl;
1156 
1157  // Create DCAEN1290TDCHit object
1158  if(pe) pe->NEW_DCAEN1290TDCHit(rocid, slot, channel, 0, edge, tdc_num, event_id, bunch_id, tdc);
1159  break;
1160  case 0b00100: // TDC Error
1161  error_flags = (*iptr) & 0x7fff;
1162  if(VERBOSE>7) cout << " CAEN TDC TDC Error (err flags=0x" << hex << error_flags << dec << ")" << endl;
1163  break;
1164  case 0b00011: // TDC Trailer
1165  tdc_num = ((*iptr)>>24) & 0x03;
1166  event_id = ((*iptr)>>12) & 0x0fff;
1167  word_count = ((*iptr)>>0) & 0x0fff;
1168  if(VERBOSE>7) cout << " CAEN TDC TDC Trailer (tdc=" << tdc_num <<" , event id=" << event_id <<" , word count=" << word_count << ")" << endl;
1169  tdc_num = event_id = bunch_id = 0;
1170  break;
1171  case 0b11000: // Filler Word
1172  if(VERBOSE>7) cout << " CAEN TDC Filler Word" << endl;
1173  break;
1174  default:
1175  cout << "Unknown datatype: 0x" << hex << type << " full word: "<< *iptr << dec << endl;
1176  throw JExceptionDataFormat("Unknown data type for CAEN1190", __FILE__, __LINE__);
1177  }
1178 
1179  iptr++;
1180  }
1181 
1182 }
1183 
1184 //----------------
1185 // ParseModuleConfiguration
1186 //----------------
1187 void DEVIOWorkerThread::ParseModuleConfiguration(uint32_t rocid, uint32_t* &iptr, uint32_t *iend)
1188 {
1189  if(!PARSE_CONFIG){ iptr = &iptr[(*iptr) + 1]; return; }
1190 
1191  /// Parse a bank of module configuration data. These are configuration values
1192  /// programmed into the module at the beginning of the run that may be needed
1193  /// in the offline. For example, the number of samples to sum in a FADC pulse
1194  /// integral.
1195  ///
1196  /// The bank has one or more sections, each describing parameters applicable
1197  /// to a number of modules as indicated by a 24bit slot mask.
1198  ///
1199  /// This bank should appear only once per DAQ event which, if in multi-event
1200  /// block mode, may have multiple L1 events. The parameters here will apply
1201  /// to all L1 events in the block. This method will put the config objects
1202  /// into each event in current_parsed_events. The config objects are duplicated
1203  /// as needed so each event has its own, indepenent set of config object.
1204 
1205  while(iptr < iend){
1206  uint32_t slot_mask = (*iptr) & 0xFFFFFF;
1207  uint32_t Nvals = ((*iptr) >> 24) & 0xFF;
1208  iptr++;
1209 
1210  // Events will be created in the first event (i.e. using its pool)
1211  // but pointers are saved so we can use them to construct identical
1212  // objects in all other event later
1213  DParsedEvent *pe = current_parsed_events.front();
1214 
1215  Df250Config *f250config = NULL;
1216  Df125Config *f125config = NULL;
1217  DF1TDCConfig *f1tdcconfig = NULL;
1218  DCAEN1290TDCConfig *caen1290tdcconfig = NULL;
1219 
1220  // Loop over all parameters in this section
1221  for(uint32_t i=0; i< Nvals; i++){
1222  if( iptr >= iend){
1223  _DBG_ << "DAQ Configuration bank corrupt! slot_mask=0x" << hex << slot_mask << dec << " Nvals="<< Nvals << endl;
1224  throw JExceptionDataFormat("Corrupt DAQ config. bank", __FILE__, __LINE__);
1225  }
1226 
1227  daq_param_type ptype = (daq_param_type)((*iptr)>>16);
1228  uint16_t val = (*iptr) & 0xFFFF;
1229 
1230  if(VERBOSE>6) cout << " DAQ parameter of type: 0x" << hex << ptype << dec << " found with value: " << val << endl;
1231 
1232  // Create config object of correct type if needed and copy
1233  // parameter value into it.
1234  switch(ptype>>8){
1235 
1236  // f250
1237  case 0x05:
1238  if( !f250config ) f250config = pe->NEW_Df250Config(rocid, slot_mask);
1239  switch(ptype){
1240  case kPARAM250_NSA : f250config->NSA = val; break;
1241  case kPARAM250_NSB : f250config->NSB = val; break;
1242  case kPARAM250_NSA_NSB : f250config->NSA_NSB = val; break;
1243  case kPARAM250_NPED : f250config->NPED = val; break;
1244  default: _DBG_ << "UNKNOWN DAQ Config Parameter type: 0x" << hex << ptype << dec << endl;
1245  }
1246  break;
1247 
1248  // f125
1249  case 0x0F:
1250  if( !f125config ) f125config = pe->NEW_Df125Config(rocid, slot_mask);
1251  switch(ptype){
1252  case kPARAM125_NSA : f125config->NSA = val; break;
1253  case kPARAM125_NSB : f125config->NSB = val; break;
1254  case kPARAM125_NSA_NSB : f125config->NSA_NSB = val; break;
1255  case kPARAM125_NPED : f125config->NPED = val; break;
1256  case kPARAM125_WINWIDTH : f125config->WINWIDTH = val; break;
1257  case kPARAM125_PL : f125config->PL = val; break;
1258  case kPARAM125_NW : f125config->NW = val; break;
1259  case kPARAM125_NPK : f125config->NPK = val; break;
1260  case kPARAM125_P1 : f125config->P1 = val; break;
1261  case kPARAM125_P2 : f125config->P2 = val; break;
1262  case kPARAM125_PG : f125config->PG = val; break;
1263  case kPARAM125_IE : f125config->IE = val; break;
1264  case kPARAM125_H : f125config->H = val; break;
1265  case kPARAM125_TH : f125config->TH = val; break;
1266  case kPARAM125_TL : f125config->TL = val; break;
1267  case kPARAM125_IBIT : f125config->IBIT = val; break;
1268  case kPARAM125_ABIT : f125config->ABIT = val; break;
1269  case kPARAM125_PBIT : f125config->PBIT = val; break;
1270  default: _DBG_ << "UNKNOWN DAQ Config Parameter type: 0x" << hex << ptype << dec << endl;
1271  }
1272  break;
1273 
1274  // F1TDC
1275  case 0x06:
1276  if( !f1tdcconfig ) f1tdcconfig = pe->NEW_DF1TDCConfig(rocid, slot_mask);
1277  switch(ptype){
1278  case kPARAMF1_REFCNT : f1tdcconfig->REFCNT = val; break;
1279  case kPARAMF1_TRIGWIN : f1tdcconfig->TRIGWIN = val; break;
1280  case kPARAMF1_TRIGLAT : f1tdcconfig->TRIGLAT = val; break;
1281  case kPARAMF1_HSDIV : f1tdcconfig->HSDIV = val; break;
1282  case kPARAMF1_BINSIZE : f1tdcconfig->BINSIZE = val; break;
1283  case kPARAMF1_REFCLKDIV : f1tdcconfig->REFCLKDIV = val; break;
1284  default: _DBG_ << "UNKNOWN DAQ Config Parameter type: 0x" << hex << ptype << dec << endl;
1285  }
1286  break;
1287 
1288  // caen1290
1289  case 0x10:
1290  if( !caen1290tdcconfig ) caen1290tdcconfig = pe->NEW_DCAEN1290TDCConfig(rocid, slot_mask);
1291  switch(ptype){
1292  case kPARAMCAEN1290_WINWIDTH : caen1290tdcconfig->WINWIDTH = val; break;
1293  case kPARAMCAEN1290_WINOFFSET : caen1290tdcconfig->WINOFFSET = val; break;
1294  default: _DBG_ << "UNKNOWN DAQ Config Parameter type: 0x" << hex << ptype << dec << endl;
1295  }
1296  break;
1297 
1298  default:
1299  _DBG_ << "Unknown module type: 0x" << hex << (ptype>>8) << endl;
1300  throw JExceptionDataFormat("Unknown module type in configuration bank", __FILE__, __LINE__);
1301  }
1302 
1303 
1304  iptr++;
1305  }
1306 
1307  // Make copies of all config objects for all other events
1308  for(auto tpe : current_parsed_events){
1309 
1310  if(tpe == pe) continue; // first event already owns objects so skip it
1311 
1312  if(f250config ) tpe->NEW_Df250Config(f250config);
1313  if(f125config ) tpe->NEW_Df125Config(f125config);
1314  if(f1tdcconfig ) tpe->NEW_DF1TDCConfig(f1tdcconfig);
1315  if(caen1290tdcconfig) tpe->NEW_DCAEN1290TDCConfig(caen1290tdcconfig);
1316  }
1317  }
1318 }
1319 
1320 //----------------
1321 // ParseJLabModuleData
1322 //----------------
1323 void DEVIOWorkerThread::ParseJLabModuleData(uint32_t rocid, uint32_t* &iptr, uint32_t *iend)
1324 {
1325 
1326  while(iptr<iend){
1327 
1328  // Get module type from next word (bits 18-21)
1329  uint32_t mod_id = ((*iptr) >> 18) & 0x000F;
1330  MODULE_TYPE type = (MODULE_TYPE)mod_id;
1331  //cout << " rocid=" << rocid << " Encountered module type: " << type << " (=" << DModuleType::GetModule(type).GetName() << ") word=" << hex << (*iptr) << dec << endl;
1332 
1333  switch(type){
1334  case DModuleType::FADC250:
1335  Parsef250Bank(rocid, iptr, iend);
1336  break;
1337 
1338  case DModuleType::FADC125:
1339  Parsef125Bank(rocid, iptr, iend);
1340  break;
1341 
1342  case DModuleType::F1TDC32:
1343  ParseF1TDCBank(rocid, iptr, iend);
1344  break;
1345 
1346  case DModuleType::F1TDC48:
1347  ParseF1TDCBank(rocid, iptr, iend);
1348  break;
1349 
1350  case DModuleType::TID:
1351  ParseTIBank(rocid, iptr, iend);
1352  /*
1353  // Ignore this data and skip over it
1354  while(iptr<iend && ((*iptr) & 0xF8000000) != 0x88000000) iptr++; // Skip to JLab block trailer
1355  iptr++; // advance past JLab block trailer
1356  while(iptr<iend && *iptr == 0xF8000000) iptr++; // skip filler words after block trailer
1357  break;
1358  */
1359  break;
1360 
1361  case DModuleType::UNKNOWN:
1362  default:
1363  jerr<<"Unknown module type ("<<mod_id<<") iptr=0x" << hex << iptr << dec << endl;
1364 
1365  while(iptr<iend && ((*iptr) & 0xF8000000) != 0x88000000) iptr++; // Skip to JLab block trailer
1366  iptr++; // advance past JLab block trailer
1367  while(iptr<iend && *iptr == 0xF8000000) iptr++; // skip filler words after block trailer
1368  throw JExceptionDataFormat("Unknown JLab module type", __FILE__, __LINE__);
1369  break;
1370  }
1371  }
1372 
1373 }
1374 
1375 //----------------
1376 // Parsef250Bank
1377 //----------------
1378 void DEVIOWorkerThread::Parsef250Bank(uint32_t rocid, uint32_t* &iptr, uint32_t *iend)
1379 {
1380  if(!PARSE_F250){ iptr = &iptr[(*iptr) + 1]; return; }
1381 
1382  auto pe_iter = current_parsed_events.begin();
1383  DParsedEvent *pe = NULL;
1384 
1385  uint32_t slot = 0;
1386  uint32_t itrigger = -1;
1387 
1388  // Loop over data words
1389  for(; iptr<iend; iptr++){
1390 
1391  // Skip all non-data-type-defining words at this
1392  // level. When we do encounter one, the appropriate
1393  // case block below should handle parsing all of
1394  // the data continuation words and advance the iptr.
1395  if(((*iptr>>31) & 0x1) == 0)continue;
1396 
1397  uint32_t data_type = (*iptr>>27) & 0x0F;
1398  switch(data_type){
1399  case 0: // Block Header
1400  slot = (*iptr>>22) & 0x1F;
1401  if(VERBOSE>7) cout << " FADC250 Block Header: slot="<<slot<<" (0x"<<hex<<*iptr<<dec<<")"<<endl;
1402  break;
1403  case 1: // Block Trailer
1404  pe_iter = current_parsed_events.begin();
1405  pe = NULL;
1406  if(VERBOSE>7) cout << " FADC250 Block Trailer"<<" (0x"<<hex<<*iptr<<dec<<") iptr=0x"<<hex<<iptr<<dec<<endl;
1407  break;
1408  case 2: // Event Header
1409  itrigger = (*iptr>>0) & 0x3FFFFF;
1410  pe = *pe_iter++;
1411  if(VERBOSE>7) cout << " FADC250 Event Header: itrigger="<<itrigger<<", rocid="<<rocid<<", slot="<<slot<<")" <<" (0x"<<hex<<*iptr<<dec<<")" <<endl;
1412  break;
1413  case 3: // Trigger Time
1414  {
1415  uint64_t t = ((*iptr)&0xFFFFFF)<<0;
1416  if(VERBOSE>7) cout << " FADC250 Trigger time low word="<<(((*iptr)&0xFFFFFF))<<" (0x"<<hex<<*iptr<<dec<<")"<<endl;
1417  iptr++;
1418  if(((*iptr>>31) & 0x1) == 0){
1419  t += ((*iptr)&0xFFFFFF)<<24; // from word on the street: second trigger time word is optional!!??
1420  if(VERBOSE>7) cout << " FADC250 Trigger time high word="<<(((*iptr)&0xFFFFFF))<<" (0x"<<hex<<*iptr<<dec<<") iptr=0x"<<hex<<iptr<<dec<<endl;
1421  }else{
1422  iptr--;
1423  }
1424  if(VERBOSE>7) cout << " FADC250 Trigger Time: t="<<t<<endl;
1425  if(pe) pe->NEW_Df250TriggerTime(rocid, slot, itrigger, t);
1426  }
1427  break;
1428  case 4: // Window Raw Data
1429  // iptr passed by reference and so will be updated automatically
1430  if(VERBOSE>7) cout << " FADC250 Window Raw Data"<<" (0x"<<hex<<*iptr<<dec<<")"<<endl;
1431  if(pe) MakeDf250WindowRawData(pe, rocid, slot, itrigger, iptr);
1432  break;
1433  case 5: // Window Sum
1434  {
1435  uint32_t channel = (*iptr>>23) & 0x0F;
1436  uint32_t sum = (*iptr>>0) & 0x3FFFFF;
1437  uint32_t overflow = (*iptr>>22) & 0x1;
1438  if(VERBOSE>7) cout << " FADC250 Window Sum"<<" (0x"<<hex<<*iptr<<dec<<")"<<endl;
1439  if(pe) pe->NEW_Df250WindowSum(rocid, slot, channel, itrigger, sum, overflow);
1440  }
1441  break;
1442  case 6: // Pulse Raw Data
1443 // MakeDf250PulseRawData(objs, rocid, slot, itrigger, iptr);
1444  if(VERBOSE>7) cout << " FADC250 Pulse Raw Data"<<" (0x"<<hex<<*iptr<<dec<<")"<<endl;
1445  break;
1446  case 7: // Pulse Integral
1447  {
1448  uint32_t channel = (*iptr>>23) & 0x0F;
1449  uint32_t pulse_number = (*iptr>>21) & 0x03;
1450  uint32_t quality_factor = (*iptr>>19) & 0x03;
1451  uint32_t sum = (*iptr>>0) & 0x7FFFF;
1452  uint32_t nsamples_integral = 0; // must be overwritten later in GetObjects with value from Df125Config value
1453  uint32_t nsamples_pedestal = 1; // The firmware returns an already divided pedestal
1454  uint32_t pedestal = 0; // This will be replaced by the one from Df250PulsePedestal in GetObjects
1455  if(VERBOSE>7) cout << " FADC250 Pulse Integral: chan="<<channel<<" pulse_number="<<pulse_number<<" sum="<<sum<<" (0x"<<hex<<*iptr<<dec<<")"<<endl;
1456  if(pe) pe->NEW_Df250PulseIntegral(rocid, slot, channel, itrigger, pulse_number, quality_factor, sum, pedestal, nsamples_integral, nsamples_pedestal);
1457  }
1458  break;
1459  case 8: // Pulse Time
1460  {
1461  uint32_t channel = (*iptr>>23) & 0x0F;
1462  uint32_t pulse_number = (*iptr>>21) & 0x03;
1463  uint32_t quality_factor = (*iptr>>19) & 0x03;
1464  uint32_t pulse_time = (*iptr>>0) & 0x7FFFF;
1465  if(VERBOSE>7) cout << " FADC250 Pulse Time: chan="<<channel<<" pulse_number="<<pulse_number<<" pulse_time="<<pulse_time<<" (0x"<<hex<<*iptr<<dec<<")"<<endl;
1466  if(pe) pe->NEW_Df250PulseTime(rocid, slot, channel, itrigger, pulse_number, quality_factor, pulse_time);
1467  }
1468  break;
1469  case 9: // Pulse Data (firmware instroduce in Fall 2016)
1470  {
1471  // from word 1
1472  uint32_t event_number_within_block = (*iptr>>19) & 0xFF;
1473  uint32_t channel = (*iptr>>15) & 0x0F;
1474  bool QF_pedestal = (*iptr>>14) & 0x01;
1475  uint32_t pedestal = (*iptr>>0 ) & 0x3FFF;
1476  if(VERBOSE>7) cout << " FADC250 Pulse Data (0x"<<hex<<*iptr<<dec<<") channel=" << channel << " pedestal="<<pedestal << " event within block=" << event_number_within_block <<endl;
1477 
1478  // event_number_within_block=0 indicates error
1479  if(event_number_within_block==0){
1480  _DBG_<<"event_number_within_block==0. This indicates a bug in firmware." << endl;
1481  exit(-1);
1482  }
1483 
1484  // Event headers may be supressed so determine event from hit data
1485  if( (event_number_within_block > current_parsed_events.size()) ) { jerr << "Bad f250 event number for rocid="<<rocid<<" slot="<<slot<<" channel="<<channel<<endl; throw JException("Bad f250 event number", __FILE__, __LINE__);}
1486  pe_iter = current_parsed_events.begin();
1487  advance( pe_iter, event_number_within_block-1 );
1488  pe = *pe_iter++;
1489 
1490  itrigger = event_number_within_block; // is this right?
1491  uint32_t pulse_number = 0;
1492 
1493  while( (*++iptr>>31) == 0 ){
1494 
1495  if( (*iptr>>30) != 0x01) { jerr << "Bad f250 Pulse Data for rocid="<<rocid<<" slot="<<slot<<" channel="<<channel<<endl; throw JException("Bad f250 Pulse Data!", __FILE__, __LINE__);}
1496 
1497  // from word 2
1498  uint32_t integral = (*iptr>>12) & 0x3FFFF;
1499  bool QF_NSA_beyond_PTW = (*iptr>>11) & 0x01;
1500  bool QF_overflow = (*iptr>>10) & 0x01;
1501  bool QF_underflow = (*iptr>>9 ) & 0x01;
1502  uint32_t nsamples_over_threshold = (*iptr>>0 ) & 0x1FF;
1503  if(VERBOSE>7) cout << " FADC250 Pulse Data word 2(0x"<<hex<<*iptr<<dec<<") integral="<<integral<<endl;
1504 
1505  iptr++;
1506  if( (*iptr>>30) != 0x00) throw JException("Bad f250 Pulse Data!", __FILE__, __LINE__);
1507 
1508  // from word 3
1509  uint32_t course_time = (*iptr>>21) & 0x1FF;//< 4 ns/count
1510  uint32_t fine_time = (*iptr>>15) & 0x3F;//< 0.0625 ns/count
1511  uint32_t pulse_peak = (*iptr>>3 ) & 0xFFF;
1512  bool QF_vpeak_beyond_NSA = (*iptr>>2 ) & 0x01;
1513  bool QF_vpeak_not_found = (*iptr>>1 ) & 0x01;
1514  bool QF_bad_pedestal = (*iptr>>0 ) & 0x01;
1515  if(VERBOSE>7) cout << " FADC250 Pulse Data word 3(0x"<<hex<<*iptr<<dec<<") course_time="<<course_time<<" fine_time="<<fine_time<<" pulse_peak="<<pulse_peak<<endl;
1516 
1517  if( pe ) {
1518  pe->NEW_Df250PulseData(rocid, slot, channel, itrigger
1519  , event_number_within_block
1520  , QF_pedestal
1521  , pedestal
1522  , integral
1523  , QF_NSA_beyond_PTW
1524  , QF_overflow
1525  , QF_underflow
1526  , nsamples_over_threshold
1527  , course_time
1528  , fine_time
1529  , pulse_peak
1530  , QF_vpeak_beyond_NSA
1531  , QF_vpeak_not_found
1532  , QF_bad_pedestal
1533  , pulse_number++);
1534  }
1535  }
1536  iptr--; // backup so when outer loop advances, it points to next data defining word
1537 
1538  }
1539  break;
1540  case 10: // Pulse Pedestal
1541  {
1542  uint32_t channel = (*iptr>>23) & 0x0F;
1543  uint32_t pulse_number = (*iptr>>21) & 0x03;
1544  uint32_t pedestal = (*iptr>>12) & 0x1FF;
1545  uint32_t pulse_peak = (*iptr>>0) & 0xFFF;
1546  if(VERBOSE>7) cout << " FADC250 Pulse Pedestal chan="<<channel<<" pulse_number="<<pulse_number<<" pedestal="<<pedestal<<" pulse_peak="<<pulse_peak<<" (0x"<<hex<<*iptr<<dec<<")"<<endl;
1547  if(pe) pe->NEW_Df250PulsePedestal(rocid, slot, channel, itrigger, pulse_number, pedestal, pulse_peak);
1548  }
1549  break;
1550  case 13: // Event Trailer
1551  // This is marked "suppressed for normal readout – debug mode only" in the
1552  // current manual (v2). It does not contain any data so the most we could do here
1553  // is return early. I'm hesitant to do that though since it would mean
1554  // different behavior for debug mode data as regular data.
1555  case 14: // Data not valid (empty module)
1556  case 15: // Filler (non-data) word
1557  if(VERBOSE>7) cout << " FADC250 Event Trailer, Data not Valid, or Filler word ("<<data_type<<")"<<" (0x"<<hex<<*iptr<<dec<<")"<<endl;
1558  break;
1559  default:
1560  if(VERBOSE>7) cout << " FADC250 unknown data type ("<<data_type<<")"<<" (0x"<<hex<<*iptr<<dec<<")"<<endl;
1561  throw JExceptionDataFormat("Unexpected word type in fADC125 block!", __FILE__, __LINE__);
1562  }
1563  }
1564 
1565  // Chop off filler words
1566  for(; iptr<iend; iptr++){
1567  if(((*iptr)&0xf8000000) != 0xf8000000) break;
1568  }
1569 }
1570 
1571 //----------------
1572 // MakeDf250WindowRawData
1573 //----------------
1574 void DEVIOWorkerThread::MakeDf250WindowRawData(DParsedEvent *pe, uint32_t rocid, uint32_t slot, uint32_t itrigger, uint32_t* &iptr)
1575 {
1576  uint32_t channel = (*iptr>>23) & 0x0F;
1577  uint32_t window_width = (*iptr>>0) & 0x0FFF;
1578 
1579  Df250WindowRawData *wrd = pe->NEW_Df250WindowRawData(rocid, slot, channel, itrigger);
1580 
1581  for(uint32_t isample=0; isample<window_width; isample +=2){
1582 
1583  // Advance to next word
1584  iptr++;
1585 
1586  // Make sure this is a data continuation word, if not, stop here
1587  if(((*iptr>>31) & 0x1) != 0x0){
1588  iptr--; // calling method expects us to point to last word in block
1589  break;
1590  }
1591 
1592  bool invalid_1 = (*iptr>>29) & 0x1;
1593  bool invalid_2 = (*iptr>>13) & 0x1;
1594  uint16_t sample_1 = 0;
1595  uint16_t sample_2 = 0;
1596  if(!invalid_1)sample_1 = (*iptr>>16) & 0x1FFF;
1597  if(!invalid_2)sample_2 = (*iptr>>0) & 0x1FFF;
1598 
1599  // Sample 1
1600  wrd->samples.push_back(sample_1);
1601  wrd->invalid_samples |= invalid_1;
1602  wrd->overflow |= (sample_1>>12) & 0x1;
1603 
1604  if(((isample+2) == window_width) && invalid_2)break; // skip last sample if flagged as invalid
1605 
1606  // Sample 2
1607  wrd->samples.push_back(sample_2);
1608  wrd->invalid_samples |= invalid_2;
1609  wrd->overflow |= (sample_2>>12) & 0x1;
1610  }
1611 }
1612 
1613 //----------------
1614 // Parsef125Bank
1615 //----------------
1616 void DEVIOWorkerThread::Parsef125Bank(uint32_t rocid, uint32_t* &iptr, uint32_t *iend)
1617 {
1618  if(!PARSE_F125){ iptr = &iptr[(*iptr) + 1]; return; }
1619 
1620  auto pe_iter = current_parsed_events.begin();
1621  DParsedEvent *pe = NULL;
1622 
1623  uint32_t slot=0;
1624  uint32_t itrigger = -1;
1625  uint32_t last_itrigger = -2;
1626  uint32_t last_pulse_time_channel=0;
1627  uint32_t last_slot = -1;
1628  uint32_t last_channel = -1;
1629 
1630  // Loop over data words
1631  for(; iptr<iend; iptr++){
1632 
1633  // Skip all non-data-type-defining words at this
1634  // level. When we do encounter one, the appropriate
1635  // case block below should handle parsing all of
1636  // the data continuation words and advance the iptr.
1637  if(((*iptr>>31) & 0x1) == 0)continue;
1638 
1639  uint32_t data_type = (*iptr>>27) & 0x0F;
1640  switch(data_type){
1641  case 0: // Block Header
1642  slot = (*iptr>>22) & 0x1F;
1643  if(VERBOSE>7) cout << " FADC125 Block Header: slot="<<slot<<endl;
1644  break;
1645  case 1: // Block Trailer
1646  pe_iter = current_parsed_events.begin();
1647  pe = NULL;
1648  break;
1649  case 2: // Event Header
1650  //slot_event_header = (*iptr>>22) & 0x1F;
1651  itrigger = (*iptr>>0) & 0x3FFFFFF;
1652  pe = *pe_iter++;
1653  if(VERBOSE>7) cout << " FADC125 Event Header: itrigger="<<itrigger<<" last_itrigger="<<last_itrigger<<", rocid="<<rocid<<", slot="<<slot <<endl;
1654  break;
1655  case 3: // Trigger Time
1656  {
1657  uint64_t t = ((*iptr)&0xFFFFFF)<<0;
1658  iptr++;
1659  if(((*iptr>>31) & 0x1) == 0){
1660  t += ((*iptr)&0xFFFFFF)<<24; // from word on the street: second trigger time word is optional!!??
1661  }else{
1662  iptr--;
1663  }
1664  if(VERBOSE>7) cout << " FADC125 Trigger Time (t="<<t<<")"<<endl;
1665  if(pe) pe->NEW_Df125TriggerTime(rocid, slot, itrigger, t);
1666  }
1667  break;
1668  case 4: // Window Raw Data
1669  // iptr passed by reference and so will be updated automatically
1670  if(VERBOSE>7) cout << " FADC125 Window Raw Data"<<endl;
1671  if(pe) MakeDf125WindowRawData(pe, rocid, slot, itrigger, iptr);
1672  break;
1673 
1674  case 5: // CDC pulse data (new) (GlueX-doc-2274-v8)
1675  {
1676  // Word 1:
1677  uint32_t word1 = *iptr;
1678  uint32_t channel = (*iptr>>20) & 0x7F;
1679  uint32_t pulse_number = (*iptr>>15) & 0x1F;
1680  uint32_t pulse_time = (*iptr>>4 ) & 0x7FF;
1681  uint32_t quality_factor = (*iptr>>3 ) & 0x1; //time QF bit
1682  uint32_t overflow_count = (*iptr>>0 ) & 0x7;
1683  if(VERBOSE>7){
1684  cout << " FADC125 CDC Pulse Data word1: " << hex << (*iptr) << dec << endl;
1685  cout << " FADC125 CDC Pulse Data (chan="<<channel<<" pulse="<<pulse_number<<" time="<<pulse_time<<" QF="<<quality_factor<<" OC="<<overflow_count<<")"<<endl;
1686  }
1687 
1688  // Word 2:
1689  ++iptr;
1690  if(iptr>=iend){
1691  jerr << " Truncated f125 CDC hit (block ends before continuation word!)" << endl;
1692  continue;
1693  }
1694  if( ((*iptr>>31) & 0x1) != 0 ){
1695  jerr << " Truncated f125 CDC hit (missing continuation word!)" << endl;
1696  continue;
1697  }
1698  uint32_t word2 = *iptr;
1699  uint32_t pedestal = (*iptr>>23) & 0xFF;
1700  uint32_t sum = (*iptr>>9 ) & 0x3FFF;
1701  uint32_t pulse_peak = (*iptr>>0 ) & 0x1FF;
1702  if(VERBOSE>7){
1703  cout << " FADC125 CDC Pulse Data word2: " << hex << (*iptr) << dec << endl;
1704  cout << " FADC125 CDC Pulse Data (pedestal="<<pedestal<<" sum="<<sum<<" peak="<<pulse_peak<<")"<<endl;
1705  }
1706 
1707  // Create hit objects
1708  uint32_t nsamples_integral = 0; // must be overwritten later in GetObjects with value from Df125Config value
1709  uint32_t nsamples_pedestal = 1; // The firmware pedestal divided by 2^PBIT where PBIT is a config. parameter
1710 
1711  if( pe ) {
1712  pe->NEW_Df125CDCPulse(rocid, slot, channel, itrigger
1713  , pulse_number // NPK
1714  , pulse_time // le_time
1715  , quality_factor // time_quality_bit
1716  , overflow_count // overflow_count
1717  , pedestal // pedestal
1718  , sum // integral
1719  , pulse_peak // first_max_amp
1720  , word1 // word1
1721  , word2 // word2
1722  , nsamples_pedestal // nsamples_pedestal
1723  , nsamples_integral // nsamples_integral
1724  , false); // emulated
1725  }
1726  }
1727  break;
1728 
1729  case 6: // FDC pulse data-integral (new) (GlueX-doc-2274-v8)
1730  {
1731  // Word 1:
1732  uint32_t word1 = *iptr;
1733  uint32_t channel = (*iptr>>20) & 0x7F;
1734  uint32_t pulse_number = (*iptr>>15) & 0x1F;
1735  uint32_t pulse_time = (*iptr>>4 ) & 0x7FF;
1736  uint32_t quality_factor = (*iptr>>3 ) & 0x1; //time QF bit
1737  uint32_t overflow_count = (*iptr>>0 ) & 0x7;
1738  if(VERBOSE>7){
1739  cout << " FADC125 FDC Pulse Data(integral) word1: " << hex << (*iptr) << dec << endl;
1740  cout << " FADC125 FDC Pulse Data (chan="<<channel<<" pulse="<<pulse_number<<" time="<<pulse_time<<" QF="<<quality_factor<<" OC="<<overflow_count<<")"<<endl;
1741  }
1742 
1743  // Word 2:
1744  ++iptr;
1745  if(iptr>=iend){
1746  jerr << " Truncated f125 FDC hit (block ends before continuation word!)" << endl;
1747  continue;
1748  }
1749  if( ((*iptr>>31) & 0x1) != 0 ){
1750  jerr << " Truncated f125 FDC hit (missing continuation word!)" << endl;
1751  continue;
1752  }
1753  uint32_t word2 = *iptr;
1754  uint32_t pulse_peak = 0;
1755  uint32_t sum = (*iptr>>19) & 0xFFF;
1756  uint32_t peak_time = (*iptr>>11) & 0xFF;
1757  uint32_t pedestal = (*iptr>>0 ) & 0x7FF;
1758  if(VERBOSE>7){
1759  cout << " FADC125 FDC Pulse Data(integral) word2: " << hex << (*iptr) << dec << endl;
1760  cout << " FADC125 FDC Pulse Data (integral="<<sum<<" time="<<peak_time<<" pedestal="<<pedestal<<")"<<endl;
1761  }
1762 
1763  // Create hit objects
1764  uint32_t nsamples_integral = 0; // must be overwritten later in GetObjects with value from Df125Config value
1765  uint32_t nsamples_pedestal = 1; // The firmware pedestal divided by 2^PBIT where PBIT is a config. parameter
1766 
1767  if( pe ) {
1768  pe->NEW_Df125FDCPulse(rocid, slot, channel, itrigger
1769  , pulse_number // NPK
1770  , pulse_time // le_time
1771  , quality_factor // time_quality_bit
1772  , overflow_count // overflow_count
1773  , pedestal // pedestal
1774  , sum // integral
1775  , pulse_peak // peak_amp
1776  , peak_time // peak_time
1777  , word1 // word1
1778  , word2 // word2
1779  , nsamples_pedestal // nsamples_pedestal
1780  , nsamples_integral // nsamples_integral
1781  , false); // emulated
1782  }
1783  }
1784  break;
1785 
1786  case 7: // Pulse Integral
1787  {
1788  if(VERBOSE>7) cout << " FADC125 Pulse Integral"<<endl;
1789  uint32_t channel = (*iptr>>20) & 0x7F;
1790  uint32_t sum = (*iptr>>0) & 0xFFFFF;
1791  uint32_t quality_factor = 0;
1792  uint32_t nsamples_integral = 0; // must be overwritten later in GetObjects with value from Df125Config value
1793  uint32_t nsamples_pedestal = 1; // The firmware returns an already divided pedestal
1794  uint32_t pedestal = 0; // This will be replaced by the one from Df250PulsePedestal in GetObjects
1795  uint32_t pulse_number = 0;
1796  if (last_slot == slot && last_channel == channel) pulse_number = 1;
1797  last_slot = slot;
1798  last_channel = channel;
1799  if( pe ) pe->NEW_Df125PulseIntegral(rocid, slot, channel, itrigger, pulse_number, quality_factor, sum, pedestal, nsamples_integral, nsamples_pedestal);
1800  }
1801  break;
1802  case 8: // Pulse Time
1803  {
1804  if(VERBOSE>7) cout << " FADC125 Pulse Time"<<endl;
1805  uint32_t channel = (*iptr>>20) & 0x7F;
1806  uint32_t pulse_number = (*iptr>>18) & 0x03;
1807  uint32_t pulse_time = (*iptr>>0) & 0xFFFF;
1808  uint32_t quality_factor = 0;
1809  if( pe ) pe->NEW_Df125PulseTime(rocid, slot, channel, itrigger, pulse_number, quality_factor, pulse_time);
1810  last_pulse_time_channel = channel;
1811  }
1812  break;
1813 
1814  case 9: // FDC pulse data-peak (new) (GlueX-doc-2274-v8)
1815  {
1816  // Word 1:
1817  uint32_t word1 = *iptr;
1818  uint32_t channel = (*iptr>>20) & 0x7F;
1819  uint32_t pulse_number = (*iptr>>15) & 0x1F;
1820  uint32_t pulse_time = (*iptr>>4 ) & 0x7FF;
1821  uint32_t quality_factor = (*iptr>>3 ) & 0x1; //time QF bit
1822  uint32_t overflow_count = (*iptr>>0 ) & 0x7;
1823  if(VERBOSE>7){
1824  cout << " FADC125 FDC Pulse Data(peak) word1: " << hex << (*iptr) << dec << endl;
1825  cout << " FADC125 FDC Pulse Data (chan="<<channel<<" pulse="<<pulse_number<<" time="<<pulse_time<<" QF="<<quality_factor<<" OC="<<overflow_count<<")"<<endl;
1826  }
1827 
1828  // Word 2:
1829  ++iptr;
1830  if(iptr>=iend){
1831  jerr << " Truncated f125 FDC hit (block ends before continuation word!)" << endl;
1832  continue;
1833  }
1834  if( ((*iptr>>31) & 0x1) != 0 ){
1835  jerr << " Truncated f125 FDC hit (missing continuation word!)" << endl;
1836  continue;
1837  }
1838  uint32_t word2 = *iptr;
1839  uint32_t pulse_peak = (*iptr>>19) & 0xFFF;
1840  uint32_t sum = 0;
1841  uint32_t peak_time = (*iptr>>11) & 0xFF;
1842  uint32_t pedestal = (*iptr>>0 ) & 0x7FF;
1843  if(VERBOSE>7){
1844  cout << " FADC125 FDC Pulse Data(peak) word2: " << hex << (*iptr) << dec << endl;
1845  cout << " FADC125 FDC Pulse Data (integral="<<sum<<" time="<<peak_time<<" pedestal="<<pedestal<<")"<<endl;
1846  }
1847 
1848  // Create hit objects
1849  uint32_t nsamples_integral = 0; // must be overwritten later in GetObjects with value from Df125Config value
1850  uint32_t nsamples_pedestal = 1; // The firmware pedestal divided by 2^PBIT where PBIT is a config. parameter
1851 
1852  if( pe ) {
1853 
1854  // The following is a temporary fix. In late 2017 the CDC group started
1855  // using data type 9 (i.e. FDC pulse peak). This caused many conflicts
1856  // with plugins downstream that were built around there being a Df125CDCPulse
1857  // object associated with the DCDCDigiHit. In order to quickly solve
1858  // the issue as the run was starting, this fix was made to produce Df125CDCPulse
1859  // object from this data iff rocid<30 indicating the data came from the
1860  // CDC.
1861  if( rocid<30 ){
1862 
1863  pe->NEW_Df125CDCPulse(rocid, slot, channel, itrigger
1864  , pulse_number // NPK
1865  , pulse_time // le_time
1866  , quality_factor // time_quality_bit
1867  , overflow_count // overflow_count
1868  , pedestal // pedestal
1869  , sum // integral
1870  , pulse_peak // peak_amp
1871  , word1 // word1
1872  , word2 // word2
1873  , nsamples_pedestal // nsamples_pedestal
1874  , nsamples_integral // nsamples_integral
1875  , false); // emulated
1876 
1877  }else{
1878 
1879  pe->NEW_Df125FDCPulse(rocid, slot, channel, itrigger
1880  , pulse_number // NPK
1881  , pulse_time // le_time
1882  , quality_factor // time_quality_bit
1883  , overflow_count // overflow_count
1884  , pedestal // pedestal
1885  , sum // integral
1886  , pulse_peak // peak_amp
1887  , peak_time // peak_time
1888  , word1 // word1
1889  , word2 // word2
1890  , nsamples_pedestal // nsamples_pedestal
1891  , nsamples_integral // nsamples_integral
1892  , false); // emulated
1893  }
1894  }
1895  }
1896  break;
1897 
1898  case 10: // Pulse Pedestal (consistent with Beni's hand-edited version of Cody's document)
1899  {
1900  if(VERBOSE>7) cout << " FADC125 Pulse Pedestal"<<endl;
1901  //channel = (*iptr>>20) & 0x7F;
1902  uint32_t channel = last_pulse_time_channel; // not enough bits to hold channel number so rely on proximity to Pulse Time in data stream (see "FADC125 dataformat 250 modes.docx")
1903  uint32_t pulse_number = (*iptr>>21) & 0x03;
1904  uint32_t pedestal = (*iptr>>12) & 0x1FF;
1905  uint32_t pulse_peak = (*iptr>>0) & 0xFFF;
1906  uint32_t nsamples_pedestal = 1; // The firmware returns an already divided pedestal
1907  if( pe ) pe->NEW_Df125PulsePedestal(rocid, slot, channel, itrigger, pulse_number, pedestal, pulse_peak, nsamples_pedestal);
1908  }
1909  break;
1910 
1911  case 13: // Event Trailer
1912  case 14: // Data not valid (empty module)
1913  case 15: // Filler (non-data) word
1914  if(VERBOSE>7) cout << " FADC125 ignored data type: " << data_type <<endl;
1915  break;
1916  default:
1917  if(VERBOSE>7) cout << " FADC125 unknown data type ("<<data_type<<")"<<" (0x"<<hex<<*iptr<<dec<<")"<<endl;
1918  throw JExceptionDataFormat("Unexpected word type in fADC125 block!", __FILE__, __LINE__);
1919 
1920  }
1921  }
1922 
1923  // Chop off filler words
1924  for(; iptr<iend; iptr++){
1925  if(((*iptr)&0xf8000000) != 0xf8000000) break;
1926  }
1927 }
1928 
1929 //----------------
1930 // MakeDf125WindowRawData
1931 //----------------
1932 void DEVIOWorkerThread::MakeDf125WindowRawData(DParsedEvent *pe, uint32_t rocid, uint32_t slot, uint32_t itrigger, uint32_t* &iptr)
1933 {
1934  uint32_t channel = (*iptr>>20) & 0x7F;
1935  uint32_t window_width = (*iptr>>0) & 0x0FFF;
1936 
1937  Df125WindowRawData *wrd = pe->NEW_Df125WindowRawData(rocid, slot, channel, itrigger);
1938 
1939  for(uint32_t isample=0; isample<window_width; isample +=2){
1940 
1941  // Advance to next word
1942  iptr++;
1943 
1944  // Make sure this is a data continuation word, if not, stop here
1945  if(((*iptr>>31) & 0x1) != 0x0)break;
1946 
1947  bool invalid_1 = (*iptr>>29) & 0x1;
1948  bool invalid_2 = (*iptr>>13) & 0x1;
1949  uint16_t sample_1 = 0;
1950  uint16_t sample_2 = 0;
1951  if(!invalid_1)sample_1 = (*iptr>>16) & 0x1FFF;
1952  if(!invalid_2)sample_2 = (*iptr>>0) & 0x1FFF;
1953 
1954  // Sample 1
1955  wrd->samples.push_back(sample_1);
1956  wrd->invalid_samples |= invalid_1;
1957  wrd->overflow |= (sample_1>>12) & 0x1;
1958 
1959  if((isample+2) == window_width && invalid_2)break; // skip last sample if flagged as invalid
1960 
1961  // Sample 2
1962  wrd->samples.push_back(sample_2);
1963  wrd->invalid_samples |= invalid_2;
1964  wrd->overflow |= (sample_2>>12) & 0x1;
1965  }
1966 }
1967 
1968 //----------------
1969 // ParseF1TDCBank
1970 //----------------
1971 void DEVIOWorkerThread::ParseF1TDCBank(uint32_t rocid, uint32_t* &iptr, uint32_t *iend)
1972 {
1973  if(!PARSE_F1TDC){ iptr = &iptr[(*iptr) + 1]; return; }
1974 
1975  uint32_t *istart = iptr;
1976 
1977  auto pe_iter = current_parsed_events.begin();
1978  DParsedEvent *pe = NULL;
1979 
1980  uint32_t slot = 0;
1981  uint32_t modtype = 0;
1982  uint32_t itrigger = -1;
1983  uint32_t trig_time_f1header = 0;
1984 
1985  // Some early data had a marker word at just before the actual F1 data
1986  if(*iptr == 0xf1daffff) iptr++;
1987 
1988  // Loop over data words
1989  for(; iptr<iend; iptr++){
1990 
1991  // Skip all non-data-type-defining words at this
1992  // level. When we do encounter one, the appropriate
1993  // case block below should handle parsing all of
1994  // the data continuation words and advance the iptr.
1995  if(((*iptr>>31) & 0x1) == 0)continue;
1996 
1997  uint32_t data_type = (*iptr>>27) & 0x0F;
1998  switch(data_type){
1999  case 0: // Block Header
2000  slot = (*iptr)>>22 & 0x001F;
2001  modtype = (*iptr)>>18 & 0x000F; // should match a DModuleType::type_id_t
2002  if(VERBOSE>7) cout << " F1 Block Header: slot=" << slot << " modtype=" << modtype << endl;
2003  break;
2004 
2005  case 1: // Block Trailer
2006  pe_iter = current_parsed_events.begin();
2007  pe = NULL;
2008  if(VERBOSE>7) cout << " F1 Block Trailer" << endl;
2009  break;
2010 
2011  case 2: // Event Header
2012  {
2013  pe = *pe_iter++;
2014  itrigger = (*iptr)>>0 & 0x0003FFFFF;
2015  if(VERBOSE>7) {
2016  uint32_t slot_event_header = (*iptr)>>22 & 0x00000001F;
2017  cout << " F1 Event Header: slot=" << slot_event_header << " itrigger=" << itrigger << endl;
2018  }
2019  }
2020  break;
2021 
2022  case 3: // Trigger time
2023  {
2024  uint64_t t = ((*iptr)&0xFFFFFF)<<0;
2025  iptr++;
2026  if(((*iptr>>31) & 0x1) == 0){
2027  t += ((*iptr)&0xFFFFFF)<<24; // from word on the street: second trigger time word is optional!!??
2028  }else{
2029  iptr--;
2030  }
2031  if(VERBOSE>7) cout << " F1TDC Trigger Time (t="<<t<<")"<<endl;
2032  if(pe) pe->NEW_DF1TDCTriggerTime(rocid, slot, itrigger, t);
2033  }
2034  break;
2035 
2036  case 8: // F1 Chip Header
2037  trig_time_f1header = ((*iptr)>> 7) & 0x1FF;
2038  if(VERBOSE>7) {
2039  uint32_t chip_f1header = ((*iptr)>> 3) & 0x07;
2040  uint32_t chan_on_chip_f1header = ((*iptr)>> 0) & 0x07; // this is always 7 in real data!
2041  uint32_t itrigger_f1header = ((*iptr)>>16) & 0x3F;
2042  cout << " Found F1 header: chip=" << chip_f1header << " chan=" << chan_on_chip_f1header << " itrig=" << itrigger_f1header << " trig_time=" << trig_time_f1header << endl;
2043  }
2044  break;
2045 
2046  case 7: // F1 Data
2047  {
2048  uint32_t chip = (*iptr>>19) & 0x07;
2049  uint32_t chan_on_chip = (*iptr>>16) & 0x07;
2050  uint32_t time = (*iptr>> 0) & 0xFFFF;
2051  uint32_t channel = F1TDC_channel(chip, chan_on_chip, modtype);
2052  if(VERBOSE>7) cout << " Found F1 data : chip=" << chip << " chan=" << chan_on_chip << " time=" << time << endl;
2053  if(pe){
2054  auto hit = pe->NEW_DF1TDCHit(rocid, slot, channel, itrigger, trig_time_f1header, time, *iptr, MODULE_TYPE(modtype));
2055  if(hit->res_status==0){
2056  static uint32_t Nwarnings=0;
2057  if(Nwarnings<10) jerr << "ERROR: F1 TDC chip \"unlocked\" flag set!" << ((++Nwarnings == 10) ? " -- last warning":"") << endl;
2058  }
2059  }
2060  }
2061  break;
2062 
2063  case 15: // Filler word
2064  if(VERBOSE>7) cout << " F1 filler word" << endl;
2065  case 14: // Data not valid (how to handle this?)
2066  break;
2067 
2068  default:
2069  cerr<<endl;
2070  cout.flush(); cerr.flush();
2071  _DBG_<<"Unknown data word in F1TDC block. Dumping for debugging:" << endl;
2072  for(const uint32_t *iiptr = istart; iiptr<iend; iiptr++){
2073  _DBG_<<"0x"<<hex<<*iiptr<<dec;
2074  if(iiptr == iptr)cerr<<" <----";
2075  switch( (*iiptr) & 0xF8000000 ){
2076  case 0x80000000: cerr << " F1 Block Header"; break;
2077  case 0x90000000: cerr << " F1 Event Header"; break;
2078  case 0x98000000: cerr << " F1 Trigger time"; break;
2079  case 0xC0000000: cerr << " F1 Header"; break;
2080  case 0xB8000000: cerr << " F1 Data"; break;
2081  case 0x88000000: cerr << " F1 Block Trailer"; break;
2082  case 0xF8000000: cerr << " Filler word"; break;
2083  case 0xF0000000: cerr << " <module has no valid data>"; break;
2084  default: break;
2085  }
2086  cerr<<endl;
2087  if(iiptr > (iptr+4)) break;
2088  }
2089  throw JExceptionDataFormat("Unexpected word type in F1TDC block!", __FILE__, __LINE__);
2090  break;
2091  }
2092  }
2093 
2094  // Skip filler words
2095  while(iptr<iend && (*iptr&0xF8000000)==0xF8000000)iptr++;
2096 }
2097 
2098 //----------------
2099 // ParseSSPBank
2100 //----------------
2101 void DEVIOWorkerThread::ParseSSPBank(uint32_t rocid, uint32_t* &iptr, uint32_t *iend)
2102 {
2103  if(!PARSE_SSP){ iptr = &iptr[(*iptr) + 1]; return; }
2104 
2105  auto pe_iter = current_parsed_events.begin();
2106  DParsedEvent *pe = NULL;
2107 
2108  uint32_t slot_bh = 0xFFFFFFFF; //< slot number from block header
2109  uint32_t slot = 0xFFFFFFFF; //< slot number from event header
2110  uint32_t itrigger = 0xFFFFFFFF;
2111  uint32_t dev_id = 0xFFFFFFFF;
2112  uint32_t ievent_cnt = 0xFFFFFFFF;
2113  //uint32_t last_itrigger = itrigger;
2114  for( ; iptr<iend; iptr++){
2115  if(((*iptr>>31) & 0x1) == 0)continue;
2116 
2117  uint32_t data_type = (*iptr>>27) & 0x0F;
2118  switch(data_type){
2119  case 0: // Block Header
2120  {
2121  slot_bh = ((*iptr)>>22) & 0x1F;
2122  uint32_t block_num = ((*iptr)>> 8) & 0x3FF;
2123  uint32_t block_size = ((*iptr)>> 0) & 0xFF;
2124  if(VERBOSE>7) cout << " SSP/DIRC Block Header: slot=" << slot_bh << " block_num="<<block_num << " block_size=" << block_size << endl;
2125  }
2126  break;
2127  case 1: // Block Trailer
2128  pe_iter = current_parsed_events.begin();
2129  pe = NULL;
2130  if(VERBOSE>7) cout << " SSP/DIRC Block Trailer" << endl;
2131  break;
2132  case 2: // Event Header
2133  slot = ((*iptr)>>22) & 0x1F;
2134  itrigger = ((*iptr)>> 0) & 0x3FFFFF;
2135  pe = *pe_iter++;
2136  //if(itrigger != last_itrigger) pe = *pe_iter++;
2137  //last_itrigger = itrigger;
2138  if(VERBOSE>7) cout << " SSP/DIRC Event Header: slot=" << slot << " itrigger=" << itrigger << endl;
2139  if( slot != slot_bh ){
2140  jerr << "Slot from SSP/DIRC event header does not match slot from last block header (" <<slot<<" != " << slot_bh << ")" <<endl;
2141  }
2142  break;
2143  case 3: // Trigger Time
2144  {
2145  uint64_t t = ((*iptr)&0xFFFFFF)<<0;
2146  if(VERBOSE>7) cout << " SSP Trigger time low word="<<(((*iptr)&0xFFFFFF))<<" (0x"<<hex<<*iptr<<dec<<")"<<endl;
2147  iptr++;
2148  if(((*iptr>>31) & 0x1) == 0){ // Confirm that continuation word is present
2149  t += ((*iptr)&0xFFFFFF)<<24;
2150  if(VERBOSE>7) cout << " SSP Trigger time high word="<<(((*iptr)&0xFFFFFF))<<" (0x"<<hex<<*iptr<<dec<<") iptr=0x"<<hex<<iptr<<dec<<endl;
2151  }else{
2152  iptr--;
2153  }
2154  if(VERBOSE>7) cout << " SSP Trigger Time: t="<<t<<endl;
2155  if(pe) pe->NEW_DDIRCTriggerTime(rocid, slot, itrigger, t);
2156  }
2157  break;
2158  case 4: // Reserved
2159  case 5: // Reserved
2160  case 6: // Reserved
2161  case 10: // Reserved
2162  case 11: // Reserved
2163  case 12: // Reserved
2164  case 13: // Reserved
2165  if(VERBOSE>7) cout << " SSP/DIRC Reserved Word" << endl;
2166  break;
2167  case 7: // Device ID
2168  dev_id = ((*iptr)>>22) & 0x1F;
2169  ievent_cnt = ((*iptr)>>0 ) & 0x3FFFFF;
2170  if(VERBOSE>7) cout << " SSP/DIRC Device ID: dev_id=" << dev_id << " ievent_cnt=" << ievent_cnt << endl;
2171  break;
2172  case 8: // TDC Hit (single channel)
2173  {
2174  uint32_t edge = (*iptr>>26) & 0x01;
2175  uint32_t channel_fpga = (*iptr>>16) & 0xFF;
2176  uint32_t time = (*iptr>>0 ) & 0xFFFF;
2177  uint32_t channel = (dev_id<<8) + channel_fpga;
2178  if(VERBOSE>7) cout << " SSP/DIRC TDC Hit: edge=" << edge << "channel_fpga=" << channel_fpga << "time=" << time << " channel=" << channel << endl;
2179  if( pe ) pe->NEW_DDIRCTDCHit(rocid, slot, channel, itrigger, dev_id, ievent_cnt, channel_fpga, edge, time);
2180  }
2181  break;
2182  case 9: // ADC (64 channels, currently only used for bench testing and may not be supported by all firmware versions)
2183  {
2184  if(VERBOSE>7) cout << " SSP/DIRC ADC data"<<endl;
2185  uint32_t adc_hold2 = (*iptr>>16) & 0xFF;
2186  uint32_t adc_hold1 = (*iptr>>8 ) & 0xFF;
2187  uint32_t adc_max_bits = (*iptr>>4 ) & 0x0F;
2188  uint32_t maroc_id = (*iptr>>0 ) & 0x03;
2189  for(uint32_t i=0; i<32; i++){
2190  if(((*++iptr>>31) & 0x1) != 0){ iptr--; break;}
2191  uint32_t channel_lower = (dev_id<<8) + (maroc_id<<6) + (i*2 + 0); // ADC_LOWER
2192  uint32_t channel_upper = (dev_id<<8) + (maroc_id<<6) + (i*2 + 1); // ADC_UPPER
2193  uint32_t adc_lower = (*iptr>>0 ) & 0xFFF;
2194  uint32_t adc_upper = (*iptr>>16 ) & 0xFFF;
2195  switch(adc_max_bits){
2196  case 11:
2197  break;
2198  case 9:
2199  adc_lower >>= 2;
2200  adc_upper >>= 2;
2201  break;
2202  case 7:
2203  adc_lower >>= 4;
2204  adc_upper >>= 4;
2205  break;
2206  default:
2207  jerr << "Bad value for adc_max_bits (" << adc_max_bits << ") from SSP/DIRC with rocid=" << rocid << " slot=" << slot << "channel=" << channel_lower << "," << channel_upper << endl;
2208  break;
2209  }
2210  if( pe ) {
2211  pe->NEW_DDIRCADCHit(rocid, slot, channel_lower, itrigger, dev_id, ievent_cnt, adc_hold1, adc_hold2, adc_max_bits, maroc_id, adc_lower);
2212  pe->NEW_DDIRCADCHit(rocid, slot, channel_upper, itrigger, dev_id, ievent_cnt, adc_hold1, adc_hold2, adc_max_bits, maroc_id, adc_upper);
2213  }
2214  }
2215  }
2216  break;
2217  case 14: // Data not Valid
2218  if(VERBOSE>7) cout << " SSP/DIRC Data not Valid" << endl;
2219  break;
2220  case 15: // Filler Word
2221  if(VERBOSE>7) cout << " SSP/DIRC Filler Word" << endl;
2222  break;
2223  }
2224  }
2225 
2226  iptr =iend;
2227 }
2228 
2229 //----------------
2230 // ParseDEventRFBunchBank
2231 //----------------
2232 void DEVIOWorkerThread::ParseDEventRFBunchBank(uint32_t* &iptr, uint32_t *iend)
2233 {
2234  uint32_t Nwords = ((uint64_t)iend - (uint64_t)iptr)/sizeof(uint32_t);
2235  uint32_t Nwords_expected = 6;
2236  if(Nwords != Nwords_expected){
2237  _DBG_ << "RFTime size does not match expected!!" << endl;
2238  _DBG_ << "Found " << Nwords << " words. Expected " << Nwords_expected << endl;
2239  }else{
2240  DParsedEvent *pe = current_parsed_events.back();
2241  DEventRFBunch *the_rftime = pe->NEW_DEventRFBunch();
2242 
2243  the_rftime->dTimeSource = static_cast<DetectorSystem_t>(*iptr++);
2244  the_rftime->dNumParticleVotes = *iptr++;
2245 
2246  uint64_t in_word = *iptr++; // 1st word, lo word; 2nd word, hi word
2247  uint64_t in_word_hi = *iptr++;
2248  in_word |= in_word_hi<<32;
2249  double rftime;
2250  memcpy(&rftime, &in_word, sizeof(double));
2251  in_word = *iptr++; in_word_hi = *iptr++;
2252  in_word |= in_word_hi<<32;
2253  double rftime_var;
2254  memcpy(&rftime_var, &in_word, sizeof(double));
2255 
2256  the_rftime->dTime = rftime;
2257  the_rftime->dTimeVariance = rftime_var;
2258  }
2259 }
2260 
2261 
2262 //----------------
2263 // ParseDVertexBank
2264 //----------------
2265 void DEVIOWorkerThread::ParseDVertexBank(uint32_t* &iptr, uint32_t *iend)
2266 {
2267  uint32_t Nwords = ((uint64_t)iend - (uint64_t)iptr)/sizeof(uint32_t);
2268  uint32_t Nwords_expected = 11;
2269  if(Nwords != Nwords_expected){
2270  _DBG_ << "DVertex size does not match expected!!" << endl;
2271  _DBG_ << "Found " << Nwords << " words. Expected " << Nwords_expected << endl;
2272  }else{
2273  DParsedEvent *pe = current_parsed_events.back();
2274  DVertex *the_vertex = pe->NEW_DVertex();
2275 
2276  uint64_t in_word = *iptr++; // 1st word, lo word; 2nd word, hi word
2277  uint64_t in_word_hi = *iptr++;
2278  in_word |= in_word_hi<<32;
2279  //uint64_t hi_word = *iptr++;
2280  double vertex_x_pos;
2281  memcpy(&vertex_x_pos, &in_word, sizeof(double));
2282  in_word = *iptr++; in_word_hi = *iptr++;
2283  in_word |= in_word_hi<<32;
2284  double vertex_y_pos;
2285  memcpy(&vertex_y_pos, &in_word, sizeof(double));
2286  in_word = *iptr++; in_word_hi = *iptr++;
2287  in_word |= in_word_hi<<32;
2288  double vertex_z_pos;
2289  memcpy(&vertex_z_pos, &in_word, sizeof(double));
2290  in_word = *iptr++; in_word_hi = *iptr++;
2291  in_word |= in_word_hi<<32;
2292  double vertex_t;
2293  memcpy(&vertex_t, &in_word, sizeof(double));
2294 
2295  DVector3 vertex_position(vertex_x_pos, vertex_y_pos, vertex_z_pos);
2296  the_vertex->dSpacetimeVertex = DLorentzVector(vertex_position, vertex_t);
2297  the_vertex->dKinFitNDF = *iptr++;
2298 
2299  in_word = *iptr++; in_word_hi = *iptr++;
2300  in_word |= in_word_hi<<32;
2301  memcpy(&(the_vertex->dKinFitChiSq), &in_word, sizeof(double));
2302  }
2303 }
2304 
2305 
2306 //----------------
2307 // LinkAllAssociations
2308 //----------------
2310 {
2311 
2312  /// Find objects that should be linked as "associated objects"
2313  /// of one another and add to each other's list.
2314  for( auto pe : current_parsed_events){
2315 
2316  //----------------- Sort hit objects
2317 
2318  // fADC250 (n.b. Df250PulseData values overwritten in JEventSource_EVIOpp::LinkBORassociations)
2319  if(pe->vDf250PulseData.size()>1 ) sort(pe->vDf250PulseData.begin(), pe->vDf250PulseData.end(), SortByPulseNumber<Df250PulseData> );
2320  if(pe->vDf250PulseIntegral.size()>1) sort(pe->vDf250PulseIntegral.begin(), pe->vDf250PulseIntegral.end(), SortByPulseNumber<Df250PulseIntegral> );
2321  if(pe->vDf250PulseTime.size()>1 ) sort(pe->vDf250PulseTime.begin(), pe->vDf250PulseTime.end(), SortByPulseNumber<Df250PulseTime> );
2322  if(pe->vDf250PulsePedestal.size()>1) sort(pe->vDf250PulsePedestal.begin(), pe->vDf250PulsePedestal.end(), SortByPulseNumber<Df250PulsePedestal> );
2323  if(pe->vDf250WindowRawData.size()>1) sort(pe->vDf250WindowRawData.begin(), pe->vDf250WindowRawData.end(), SortByChannel<Df250WindowRawData> );
2324 
2325  // fADC125
2326  if(pe->vDf125PulseIntegral.size()>1) sort(pe->vDf125PulseIntegral.begin(), pe->vDf125PulseIntegral.end(), SortByPulseNumber<Df125PulseIntegral> );
2327  if(pe->vDf125CDCPulse.size()>1 ) sort(pe->vDf125CDCPulse.begin(), pe->vDf125CDCPulse.end(), SortByChannel<Df125CDCPulse> );
2328  if(pe->vDf125FDCPulse.size()>1 ) sort(pe->vDf125FDCPulse.begin(), pe->vDf125FDCPulse.end(), SortByChannel<Df125FDCPulse> );
2329  if(pe->vDf125PulseTime.size()>1 ) sort(pe->vDf125PulseTime.begin(), pe->vDf125PulseTime.end(), SortByPulseNumber<Df125PulseTime> );
2330  if(pe->vDf125PulsePedestal.size()>1) sort(pe->vDf125PulsePedestal.begin(), pe->vDf125PulsePedestal.end(), SortByPulseNumber<Df125PulsePedestal> );
2331  if(pe->vDf125WindowRawData.size()>1) sort(pe->vDf125WindowRawData.begin(), pe->vDf125WindowRawData.end(), SortByChannel<Df125WindowRawData> );
2332 
2333  // F1TDC
2334  if(pe->vDF1TDCHit.size()>1 ) sort(pe->vDF1TDCHit.begin(), pe->vDF1TDCHit.end(), SortByModule<DF1TDCHit> );
2335 
2336  // CAEN1290TDC
2337  if(pe->vDCAEN1290TDCHit.size()>1 ) sort(pe->vDCAEN1290TDCHit.begin(), pe->vDCAEN1290TDCHit.end(), SortByModule<DCAEN1290TDCHit> );
2338 
2339 
2340  //----------------- Link hit objects
2341 
2342  // Connect Df250 pulse objects
2343  LinkPulse(pe->vDf250PulseTime, pe->vDf250PulseIntegral);
2344  LinkPulsePedCopy(pe->vDf250PulsePedestal, pe->vDf250PulseIntegral);
2345 
2346  // Connect Df125 pulse objects
2347  LinkPulse(pe->vDf125PulseTime, pe->vDf125PulseIntegral);
2348  LinkPulsePedCopy(pe->vDf125PulsePedestal, pe->vDf125PulseIntegral);
2349 
2350  // Connect Df250 window raw data objects
2351  if(!pe->vDf250WindowRawData.empty()){
2352  LinkConfig(pe->vDf250Config, pe->vDf250WindowRawData);
2353  LinkModule(pe->vDf250TriggerTime, pe->vDf250WindowRawData);
2354  LinkChannel(pe->vDf250WindowRawData, pe->vDf250PulseIntegral);
2355  LinkChannel(pe->vDf250WindowRawData, pe->vDf250PulseTime);
2356  LinkChannel(pe->vDf250WindowRawData, pe->vDf250PulsePedestal);
2357  LinkChannel(pe->vDf250WindowRawData, pe->vDf250PulseData);
2358  }
2359 
2360  // Connect Df125 window raw data objects
2361  if(!pe->vDf125WindowRawData.empty()){
2362  LinkConfig(pe->vDf125Config, pe->vDf125WindowRawData);
2363  LinkModule(pe->vDf125TriggerTime, pe->vDf125WindowRawData);
2364  LinkChannel(pe->vDf125WindowRawData, pe->vDf125PulseIntegral);
2365  LinkChannel(pe->vDf125WindowRawData, pe->vDf125PulseTime);
2366  LinkChannel(pe->vDf125WindowRawData, pe->vDf125PulsePedestal);
2367  LinkChannel(pe->vDf125WindowRawData, pe->vDf125CDCPulse);
2368  LinkChannel(pe->vDf125WindowRawData, pe->vDf125FDCPulse);
2369  }
2370 
2371  //----------------- Optionally link config objects (on by default)
2372  if(LINK_CONFIG){
2373  if(pe->vDf250Config.size()>1 ) sort(pe->vDf250Config.begin(), pe->vDf250Config.end(), SortByROCID<Df250Config> );
2374  if(pe->vDf125Config.size()>1 ) sort(pe->vDf125Config.begin(), pe->vDf125Config.end(), SortByROCID<Df125Config> );
2375  if(pe->vDF1TDCConfig.size()>1 ) sort(pe->vDF1TDCConfig.begin(), pe->vDF1TDCConfig.end(), SortByROCID<DF1TDCConfig> );
2376  if(pe->vDCAEN1290TDCConfig.size()>1) sort(pe->vDCAEN1290TDCConfig.begin(), pe->vDCAEN1290TDCConfig.end(), SortByROCID<DCAEN1290TDCConfig> );
2377 
2378  LinkConfigSamplesCopy(pe->vDf250Config, pe->vDf250PulseIntegral);
2379  LinkConfigSamplesCopy(pe->vDf250Config, pe->vDf250PulseData);
2380  LinkConfigSamplesCopy(pe->vDf125Config, pe->vDf125PulseIntegral);
2381  LinkConfigSamplesCopy(pe->vDf125Config, pe->vDf125CDCPulse);
2382  LinkConfigSamplesCopy(pe->vDf125Config, pe->vDf125FDCPulse);
2383  LinkConfig(pe->vDF1TDCConfig, pe->vDF1TDCHit);
2384  LinkConfig(pe->vDCAEN1290TDCConfig, pe->vDCAEN1290TDCHit);
2385  }
2386 
2387  //----------------- Optionally link trigger time objects (off by default)
2388  if(LINK_TRIGGERTIME){
2389  if(pe->vDf250TriggerTime.size()>1 ) sort(pe->vDf250TriggerTime.begin(), pe->vDf250TriggerTime.end(), SortByModule<Df250TriggerTime> );
2390  if(pe->vDf125TriggerTime.size()>1 ) sort(pe->vDf125TriggerTime.begin(), pe->vDf125TriggerTime.end(), SortByModule<Df125TriggerTime> );
2391  if(pe->vDF1TDCTriggerTime.size()>1 ) sort(pe->vDF1TDCTriggerTime.begin(), pe->vDF1TDCTriggerTime.end(), SortByModule<DF1TDCTriggerTime> );
2392 
2393  LinkModule(pe->vDf250TriggerTime, pe->vDf250PulseIntegral);
2394  LinkModule(pe->vDf125TriggerTime, pe->vDf125PulseIntegral);
2395  LinkModule(pe->vDf125TriggerTime, pe->vDf125CDCPulse);
2396  LinkModule(pe->vDf125TriggerTime, pe->vDf125FDCPulse);
2397  LinkModule(pe->vDF1TDCTriggerTime, pe->vDF1TDCHit);
2398  }
2399  }
2400 
2401 }
2402 
2403 //----------------
2404 // DumpBinary
2405 //----------------
2406 void DEVIOWorkerThread::DumpBinary(const uint32_t *iptr, const uint32_t *iend, uint32_t MaxWords, const uint32_t *imark)
2407 {
2408  /// This is used for debugging. It will print to the screen the words
2409  /// starting at the address given by iptr and ending just before iend
2410  /// or for MaxWords words, whichever comes first. If iend is NULL,
2411  /// then MaxWords will be printed. If MaxWords is zero then it is ignored
2412  /// and only iend is checked. If both iend==NULL and MaxWords==0, then
2413  /// only the word at iptr is printed.
2414 
2415  cout << "Dumping binary: istart=" << hex << iptr << " iend=" << iend << " MaxWords=" << dec << MaxWords << endl;
2416 
2417  if(iend==NULL && MaxWords==0) MaxWords=1;
2418  if(MaxWords==0) MaxWords = (uint32_t)0xffffffff;
2419 
2420  uint32_t Nwords=0;
2421  while(iptr!=iend && Nwords<MaxWords){
2422 
2423  // line1 is hex and line2 is decimal
2424  stringstream line1, line2;
2425 
2426  // print words in columns 8 words wide. First part is
2427  // reserved for word number
2428  uint32_t Ncols = 8;
2429  line1 << setw(5) << Nwords;
2430  line2 << string(5, ' ');
2431 
2432  // Loop over columns
2433  for(uint32_t i=0; i<Ncols; i++, iptr++, Nwords++){
2434 
2435  if(iptr == iend) break;
2436  if(Nwords>=MaxWords) break;
2437 
2438  stringstream iptr_hex;
2439  iptr_hex << hex << "0x" << *iptr;
2440 
2441  string mark = (iptr==imark ? "*":" ");
2442 
2443  line1 << setw(12) << iptr_hex.str() << mark;
2444  line2 << setw(12) << *iptr << mark;
2445  }
2446 
2447  cout << line1.str() << endl;
2448  cout << line2.str() << endl;
2449  cout << endl;
2450  }
2451 }
2452 
2453 
uint32_t live_inst
Definition: DL1Info.h:24
uint16_t NSB
Definition: Df250Config.h:22
uint16_t NPED
Definition: Df250Config.h:24
void Finish(bool wait_to_complete=true)
uint32_t version
Definition: Df250Scaler.h:16
void ParseRawTriggerBank(uint32_t rocid, uint32_t *&iptr, uint32_t *iend)
uint32_t swap_bank(uint32_t *outbuff, uint32_t *inbuff, uint32_t len)
Definition: swap_bank.cc:15
const int Ncols
uint32_t F1TDC_channel(uint32_t chip, uint32_t chan_on_chip, int modtype)
L3_decision_t
The DL3Trigger object is used to tell the level-3 trigger process whether or not to discard the event...
Definition: DL3Trigger.h:68
uint32_t rocid
Definition: DTSGBORConfig.h:31
uint16_t NSA_NSB
Definition: Df125Config.h:29
uint64_t timestamp
Definition: DCODAROCInfo.h:22
uint16_t IBIT
Definition: Df125Config.h:44
uint16_t NSA
Definition: Df250Config.h:21
TVector3 DVector3
Definition: DVector3.h:14
unsigned int dKinFitNDF
Definition: DVertex.h:31
atomic< bool > in_use
set< uint32_t > & ROCIDS_TO_PARSE
DEVIOWorkerThread(JEventSource_EVIOpp *event_source, list< DParsedEvent * > &parsed_events, uint32_t &MAX_PARSED_EVENTS, mutex &PARSED_EVENTS_MUTEX, condition_variable &PARSED_EVENTS_CV, set< uint32_t > &ROCIDS_TO_PARSE)
char string[256]
DModuleType::type_id_t MODULE_TYPE
Definition: DModuleType.h:153
vector< uint32_t > fp_sc
Definition: DL1Info.h:28
uint16_t NPED
Definition: Df125Config.h:30
vector< uint32_t > fa250_sc
Definition: Df250Scaler.h:20
void ParseDataBank(uint32_t *&iptr, uint32_t *iend)
uint64_t event_status_bits
Definition: DParsedEvent.h:144
uint32_t nsync
Definition: Df250Scaler.h:14
daq_param_type
int event_num
uint16_t event_type
void FillDerived(void)
Extract values as read from config registers and fill in the derived members defined above...
uint32_t & MAX_PARSED_EVENTS
This is a subclass of JException that is used to indicate a parsing error. This was motivated by hdmo...
condition_variable & PARSED_EVENTS_CV
uint16_t PBIT
Definition: Df125Config.h:46
void ParseControlEvent(uint32_t *&iptr, uint32_t *iend)
uint16_t IE
Definition: Df125Config.h:40
uint16_t TRIGWIN
Definition: DF1TDCConfig.h:22
uint32_t unix_time
Definition: DTSGBORConfig.h:34
uint16_t ABIT
Definition: Df125Config.h:45
uint32_t rocid
Definition: DCODAROCInfo.h:21
DetectorSystem_t
Definition: GlueX.h:15
vector< uint16_t > samples
TLorentzVector DLorentzVector
JApplication * japp
uint16_t P2
Definition: Df125Config.h:38
vector< uint32_t > misc_words
Definition: DTSGBORConfig.h:35
list< DParsedEvent * > & parsed_events
void ParseDEventRFBunchBank(uint32_t *&iptr, uint32_t *iend)
void ParseSSPBank(uint32_t rocid, uint32_t *&iptr, uint32_t *iend)
uint16_t TRIGLAT
Definition: DF1TDCConfig.h:23
TEllipse * e
uint16_t P1
Definition: Df125Config.h:37
uint64_t avg_timestamp
uint32_t rocid
Definition: bor_roc.h:138
JEventSource_EVIOpp * event_source
void Parsef250scalerBank(uint32_t rocid, uint32_t *&iptr, uint32_t *iend)
void ParseCDAQBank(uint32_t *&iptr, uint32_t *iend)
uint32_t nsync
Definition: DL1Info.h:20
void ParseDVertexBank(uint32_t *&iptr, uint32_t *iend)
void ParsePhysicsBank(uint32_t *&iptr, uint32_t *iend)
uint32_t run_number
#define swap32(x)
Definition: HDEVIO.h:36
How this Event Source Works
void ParseEventTagBank(uint32_t *&iptr, uint32_t *iend)
vector< uint16_t > samples
void MakeDf250WindowRawData(DParsedEvent *pe, uint32_t rocid, uint32_t slot, uint32_t itrigger, uint32_t *&iptr)
uint16_t WINWIDTH
Definition: Df125Config.h:31
void DumpBinary(const uint32_t *iptr, const uint32_t *iend, uint32_t MaxWords=0, const uint32_t *imark=NULL)
uint16_t BINSIZE
Definition: DF1TDCConfig.h:25
#define _DBG_
Definition: HDEVIO.h:12
void Sort(void)
Definition: DBORptrs.h:66
uint16_t HSDIV
Definition: DF1TDCConfig.h:24
void ParseTIBank(uint32_t rocid, uint32_t *&iptr, uint32_t *iend)
uint32_t slot
Definition: DTSGBORConfig.h:32
uint32_t trig_number
Definition: Df250Scaler.h:15
void LinkAllAssociations(void)
void ParseCAEN1190(uint32_t rocid, uint32_t *&iptr, uint32_t *iend)
void MakeDf125WindowRawData(DParsedEvent *pe, uint32_t rocid, uint32_t slot, uint32_t itrigger, uint32_t *&iptr)
DLorentzVector dSpacetimeVertex
Definition: DVertex.h:28
double dTimeVariance
Definition: DEventRFBunch.h:31
void ParseF1TDCBank(uint32_t rocid, uint32_t *&iptr, uint32_t *iend)
void Parsef125Bank(uint32_t rocid, uint32_t *&iptr, uint32_t *iend)
void ParseJLabModuleData(uint32_t rocid, uint32_t *&iptr, uint32_t *iend)
DBORptrs * borptrs
Definition: DParsedEvent.h:147
void ParseBuiltTriggerBank(uint32_t *&iptr, uint32_t *iend)
uint32_t unix_time
Definition: DL1Info.h:25
uint16_t NW
Definition: Df125Config.h:35
EVIOSourceType source_type
uint32_t busy_time
Definition: DL1Info.h:23
vector< uint32_t > gtp_sc
Definition: DL1Info.h:27
void ParseTSscalerBank(uint32_t *&iptr, uint32_t *iend)
uint16_t PG
Definition: Df125Config.h:39
uint16_t NSA
Definition: Df125Config.h:27
static const size_t block_size
Definition: src/md5.cpp:54
vector< DParsedEvent * > parsed_event_pool
uint16_t TL
Definition: Df125Config.h:43
uint16_t REFCLKDIV
Definition: DF1TDCConfig.h:26
uint16_t NSA_NSB
Definition: Df250Config.h:23
uint32_t live_time
Definition: DL1Info.h:22
DetectorSystem_t dTimeSource
Definition: DEventRFBunch.h:28
uint32_t run_number
Definition: DTSGBORConfig.h:33
static TH1I * pedestal[nChan]
uint16_t TH
Definition: Df125Config.h:42
atomic< bool > done
set< uint32_t > ROCIDS_TO_PARSE
double dKinFitChiSq
Definition: DVertex.h:32
virtual ~DEVIOWorkerThread()
uint32_t trig_number
Definition: DL1Info.h:21
vector< uint32_t > misc
Definition: DCODAROCInfo.h:23
unsigned int dNumParticleVotes
Definition: DEventRFBunch.h:32
list< DParsedEvent * > current_parsed_events
uint32_t run_type
vector< uint32_t > fp_rate
Definition: DL1Info.h:30
void ParseModuleConfiguration(uint32_t rocid, uint32_t *&iptr, uint32_t *iend)
void ParseBORbank(uint32_t *&iptr, uint32_t *iend)
uint32_t rocid
Definition: bor_roc.h:70
uint16_t REFCNT
Definition: DF1TDCConfig.h:21
void ParseEPICSbank(uint32_t *&iptr, uint32_t *iend)
uint32_t rocid
Definition: bor_roc.h:114
uint16_t H
Definition: Df125Config.h:41
vector< uint32_t > gtp_rate
Definition: DL1Info.h:29
std::atomic< uint_fast64_t > NPARSER_STALLED
uint16_t PL
Definition: Df125Config.h:34
uint16_t NPK
Definition: Df125Config.h:36
void Parsef250Bank(uint32_t rocid, uint32_t *&iptr, uint32_t *iend)
condition_variable cv
uint64_t MAX_OBJECT_RECYCLES
uint64_t event_number
uint32_t rocid
Definition: bor_roc.h:152
uint16_t NSB
Definition: Df125Config.h:28