Bug Summary

File:libraries/DAQ/JEventSource_EVIO.cc
Location:line 2144, column 9
Description:Called C++ object pointer is null

Annotated Source Code

1// $Id$
2// $HeadURL$
3//
4// File: JEventSource_EVIO.cc
5// Created: Tue Aug 7 15:22:29 EDT 2012
6// Creator: davidl (on Darwin harriet.jlab.org 11.4.0 i386)
7//
8
9// See comments in JEventSource_EVIO.h for overview description
10
11#include <unistd.h>
12#include <stdint.h>
13
14#include <string>
15#include <cmath>
16#include <iomanip>
17using namespace std;
18
19
20// This flag allows us to switch back and forth from using HDEVIO and
21// the CODA-supplied EVIO
22#define USE_HDEVIO1 1
23
24//#define ENABLE_UPSAMPLING
25
26#ifdef HAVE_EVIO1
27
28#if USE_HDEVIO1 == 0
29#include <evioFileChannel.hxx>
30#endif
31
32extern "C" uint32_t *swap_int32_t(uint32_t *data, unsigned int length, uint32_t *dest);
33#endif // HAVE_EVIO
34
35#ifdef HAVE_ET
36//#include <evioETChannel.hxx>
37#include <et.h>
38#endif // HAVE_ET
39
40#include "JEventSourceGenerator_EVIO.h"
41//#include "JFactoryGenerator_DAQ.h"
42#include "JEventSource_EVIO.h"
43
44using namespace jana;
45
46#include <DANA/DStatusBits.h>
47#include <TTAB/DTranslationTable.h>
48#include <TTAB/DTranslationTable_factory.h>
49#include <DAQ/Df125EmulatorAlgorithm_factory.h>
50#include <DAQ/Df250EmulatorAlgorithm_factory.h>
51
52#define _DBG_DAQ(A)cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<":"<<
52<<" 0x"<<hex<<A<<" cntrl:0x"<<
(A&0xF0000000)<<dec<<" slot:"<<((A>>
22)&0x1F)<<endl
cerr<<__FILE__"libraries/DAQ/JEventSource_EVIO.cc"<<":"<<__LINE__52<<" 0x"<<hex<<A<<" cntrl:0x"<<(A&0xF0000000)<<dec<<" slot:"<<((A>>22)&0x1F)<<endl
53
54// Make us a plugin
55#include <JANA/JApplication.h>
56//extern "C"{
57// void InitPlugin(JApplication *app){
58// InitJANAPlugin(app);
59// app->AddEventSourceGenerator(new JEventSourceGenerator_EVIO());
60// app->AddFactoryGenerator(new JFactoryGenerator_DAQ());
61// }
62//} // "C"
63
64// if we don't find a run number in the file, then it's nice to let the user know
65static bool WARN_USER_RUN_FILENAME = false;
66
67set<uint32_t> ROCIDS_TO_PARSE;
68
69//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
70// If EVIO support is not available, define dummy methods
71#ifndef HAVE_EVIO1
72JEventSource_EVIO::JEventSource_EVIO(const char* source_name):JEventSource(source_name){
73 cerr << endl;
74 cerr << "You are trying to use code requiring EVIO when support" << endl;
75 cerr << "for EVIO was not built into this binary. Set your" << endl;
76 cerr << "EVIOROOT *and* your ETROOT environment variables to" << endl;
77 cerr << "point to your EVIO installation and recompile." << endl;
78 cerr << endl;
79 exit(-1);
80}
81 JEventSource_EVIO::~JEventSource_EVIO(){}
82jerror_t JEventSource_EVIO::GetEvent(jana::JEvent &event){return NOERROR;}
83 void JEventSource_EVIO::FreeEvent(jana::JEvent &event){}
84jerror_t JEventSource_EVIO::GetObjects(jana::JEvent &event, jana::JFactory_base *factory){return NOERROR;}
85jerror_t JEventSource_EVIO::ReadEVIOEvent(uint32_t* &buf){return NOERROR;}
86//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
87
88#else // HAVE_EVIO
89
90//----------------
91// Constructor
92//----------------
93JEventSource_EVIO::JEventSource_EVIO(const char* source_name):JEventSource(source_name)
94{
95 // Initialize connection objects and flags to NULL
96 et_connected = false;
97 //chan = NULL;
98 hdevio = NULL__null;
99 source_type = kNoSource;
100 quit_on_next_ET_timeout = false;
101
102 // Initialize dedicated JStreamLog used for debugging messages
103 evioout.SetTag("--- EVIO ---: ");
104 evioout.SetTimestampFlag();
105 evioout.SetThreadstampFlag();
106
107 // Define base set of status bits
108 if(japp) DStatusBits::SetStatusBitDescriptions(japp);
109
110 // Get configuration parameters
111 AUTODETECT_MODULE_TYPES = true;
112 DUMP_MODULE_MAP = false;
113 MAKE_DOM_TREE = true;
114 PARSE_EVIO_EVENTS = true;
115 PARSE_F250 = true;
116 PARSE_F125 = true;
117 PARSE_F1TDC = true;
118 PARSE_CAEN1290TDC = true;
119 PARSE_CONFIG = true;
120 PARSE_BOR = true;
121 PARSE_EPICS = true;
122 PARSE_EVENTTAG = true;
123 PARSE_TRIGGER = true;
124 BUFFER_SIZE = 20000000; // in bytes
125 ET_STATION_NEVENTS = 10;
126 ET_STATION_CREATE_BLOCKING = false;
127 ET_DEBUG_WORDS_TO_DUMP = 0;
128 LOOP_FOREVER = false;
129 VERBOSE = 0;
130 TIMEOUT = 2.0;
131 MODTYPE_MAP_FILENAME = "modtype.map";
132 ENABLE_DISENTANGLING = true;
133 EVIO_SPARSE_READ = false;
134 EVENT_MASK = "";
135
136 F125_EMULATION_MODE = kEmulationAuto;
137 F250_EMULATION_MODE = kEmulationAuto;
138
139 USER_RUN_NUMBER = 0;
140 F125PULSE_NUMBER_FILTER = 1000;
141 F250PULSE_NUMBER_FILTER = 1000;
142
143 if(gPARMS){
144 // JANA doesn't know about EmulationModeType so we use temporary variables
145 uint32_t f250_emulation_mode = F250_EMULATION_MODE;
146 uint32_t f125_emulation_mode = F125_EMULATION_MODE;
147
148 gPARMS->SetDefaultParameter("EVIO:AUTODETECT_MODULE_TYPES", AUTODETECT_MODULE_TYPES, "Try and guess the module type tag,num values for which there is no module map entry.");
149 gPARMS->SetDefaultParameter("EVIO:DUMP_MODULE_MAP", DUMP_MODULE_MAP, "Write module map used to file when source is destroyed. n.b. If more than one input file is used, the map file will be overwritten!");
150 gPARMS->SetDefaultParameter("EVIO:MAKE_DOM_TREE", MAKE_DOM_TREE, "Set this to 0 to disable generation of EVIO DOM Tree and parsing of event. (for benchmarking/debugging)");
151 gPARMS->SetDefaultParameter("EVIO:PARSE_EVIO_EVENTS", PARSE_EVIO_EVENTS, "Set this to 0 to disable parsing of event but still make the DOM tree, so long as MAKE_DOM_TREE isn't set to 0. (for benchmarking/debugging)");
152 gPARMS->SetDefaultParameter("EVIO:PARSE_F250", PARSE_F250, "Set this to 0 to disable parsing of data from F250 ADC modules (for benchmarking/debugging)");
153 gPARMS->SetDefaultParameter("EVIO:PARSE_F125", PARSE_F125, "Set this to 0 to disable parsing of data from F125 ADC modules (for benchmarking/debugging)");
154 gPARMS->SetDefaultParameter("EVIO:PARSE_F1TDC", PARSE_F1TDC, "Set this to 0 to disable parsing of data from F1TDC modules (for benchmarking/debugging)");
155 gPARMS->SetDefaultParameter("EVIO:PARSE_CAEN1290TDC", PARSE_CAEN1290TDC, "Set this to 0 to disable parsing of data from CAEN 1290 TDC modules (for benchmarking/debugging)");
156 gPARMS->SetDefaultParameter("EVIO:PARSE_CONFIG", PARSE_CONFIG, "Set this to 0 to disable parsing of ROC configuration data in the data stream (for benchmarking/debugging)");
157 gPARMS->SetDefaultParameter("EVIO:PARSE_BOR", PARSE_BOR, "Set this to 0 to disable parsing of BOR events from the data stream (for benchmarking/debugging)");
158 gPARMS->SetDefaultParameter("EVIO:PARSE_EPICS", PARSE_EPICS, "Set this to 0 to disable parsing of EPICS events from the data stream (for benchmarking/debugging)");
159 gPARMS->SetDefaultParameter("EVIO:PARSE_EVENTTAG", PARSE_EVENTTAG, "Set this to 0 to disable parsing of event tag data in the data stream (for benchmarking/debugging)");
160 gPARMS->SetDefaultParameter("EVIO:PARSE_TRIGGER", PARSE_TRIGGER, "Set this to 0 to disable parsing of the built trigger bank from CODA (for benchmarking/debugging)");
161
162 gPARMS->SetDefaultParameter("EVIO:BUFFER_SIZE", BUFFER_SIZE, "Size in bytes to allocate for holding a single EVIO event.");
163 gPARMS->SetDefaultParameter("EVIO:ET_STATION_NEVENTS", ET_STATION_NEVENTS, "Number of events to use if we have to create the ET station. Ignored if station already exists.");
164 gPARMS->SetDefaultParameter("EVIO:ET_STATION_CREATE_BLOCKING", ET_STATION_CREATE_BLOCKING, "Set this to 0 to create station in non-blocking mode (default is to create it in blocking mode). Ignored if station already exists.");
165 gPARMS->SetDefaultParameter("EVIO:ET_DEBUG_WORDS_TO_DUMP", ET_DEBUG_WORDS_TO_DUMP, "Number of words to dump to screen from ET buffer (useful for debugging only).");
166 gPARMS->SetDefaultParameter("EVIO:LOOP_FOREVER", LOOP_FOREVER, "If reading from EVIO file, keep re-opening file and re-reading events forever (only useful for debugging) If reading from ET, this is ignored.");
167 gPARMS->SetDefaultParameter("EVIO:VERBOSE", VERBOSE, "Set verbosity level for processing and debugging statements while parsing. 0=no debugging messages. 10=all messages");
168 gPARMS->SetDefaultParameter("ET:TIMEOUT", TIMEOUT, "Set the timeout in seconds for each attempt at reading from ET system (repeated attempts will still be made indefinitely until program quits or the quit_on_et_timeout flag is set.");
169 gPARMS->SetDefaultParameter("EVIO:MODTYPE_MAP_FILENAME", MODTYPE_MAP_FILENAME, "Optional module type conversion map for use with files generated with the non-standard module types");
170 gPARMS->SetDefaultParameter("EVIO:ENABLE_DISENTANGLING", ENABLE_DISENTANGLING, "Enable/disable disentangling of multi-block events. Enabled by default. Set to 0 to disable.");
171 gPARMS->SetDefaultParameter("EVIO:SPARSE_READ", EVIO_SPARSE_READ, "Set to true to enable sparse reading of the EVIO file. This will take some time to map out the entire file prior to event processing. It is typically only useful if the EVIO:EVENT_MASK variable is set.");
172 gPARMS->SetDefaultParameter("EVIO:EVENT_MASK", EVENT_MASK, "Commas separated list used to set the mask that selects the type of events to read in. Other types will be skipped. Valid values are EPICS,BOR and PHYSICS");
173
174 gPARMS->SetDefaultParameter("EVIO:F250_EMULATION_MODE", f250_emulation_mode, "Set f250 emulation mode. 0=no emulation, 1=always, 2=auto. Default is 2 (auto).");
175 gPARMS->SetDefaultParameter("EVIO:F125_EMULATION_MODE", f125_emulation_mode, "Set f125 emulation mode. 0=no emulation, 1=always, 2=auto. Default is 2 (auto).");
176
177 gPARMS->SetDefaultParameter("EVIO:RUN_NUMBER", USER_RUN_NUMBER, "User-supplied run number. Override run number from other sources with this.(will be ignored if set to zero)");
178 gPARMS->SetDefaultParameter("EVIO:F125PULSE_NUMBER_FILTER", F125PULSE_NUMBER_FILTER, "Ignore data for DF125XXX objects with a pulse number equal or greater than this.");
179 gPARMS->SetDefaultParameter("EVIO:F250PULSE_NUMBER_FILTER", F250PULSE_NUMBER_FILTER, "Ignore data for DF250XXX objects with a pulse number equal or greater than this.");
180
181 F250_EMULATION_MODE = (EmulationModeType)f250_emulation_mode;
182 F125_EMULATION_MODE = (EmulationModeType)f125_emulation_mode;
183 }
184
185 // Try to open the file.
186 try {
187
188 if(VERBOSE>0) evioout << "Attempting to open \""<<this->source_name<<"\" as EVIO file..." <<endl;
189
190#if USE_HDEVIO1
191 //---------- HDEVIO ------------
192 hdevio = new HDEVIO(this->source_name);
193 if( ! hdevio->is_open ) throw std::exception(); // throw exception if unable to open
194 if(EVENT_MASK.length()!=0) hdevio->SetEventMask(EVENT_MASK);
195 if(EVIO_SPARSE_READ) hdevio->PrintFileSummary();
196#else // USE_HDEVIO
197 //-------- CODA EVIO -----------
198 jerr << "You are attempting to use the CODA Channels library for reading" << endl;
199 jerr << "and EVIO file and this mechanism has been disabled from in the" << endl;
200 jerr << "DAQ library. Contact davidl@jlab.org if you need this to be" << endl;
201 jerr << "reinstated." << endl;
202 quit(0);
203 //chan = new evioFileChannel(this->source_name, "r", BUFFER_SIZE);
204 //chan->open(); // open the file. Throws exception if not successful
205
206#endif // USE_HDEVIO
207
208 source_type = kFileSource;
209
210 } catch (std::exception &e) {
211
212#ifdef HAVE_ET
213 // Could not open file. Check if name starts with "ET:"
214 //chan = NULL;
215 if(this->source_name.substr(0,3) == "ET:"){
216 if(VERBOSE>0) evioout << "Attempting to open \""<<this->source_name<<"\" as ET (network) source..." <<endl;
217 ConnectToET(source_name);
218 }
219
220 if(!et_connected) throw JException("Failed to open ET system: " + this->source_name);
221
222 // open the channel. Throws exception if not successful
223 // chan->open(); // evioETchannel no longer used
224 source_type = kETSource;
225
226#else // HAVE_ET
227
228 // No ET and the file didn't work so re-throw the exception
229 if(this->source_name.substr(0,3) == "ET:"){
230 cerr << endl;
231 cerr << "=== ERROR: ET source specified and this was compiled without ===" << endl;
232 cerr << "=== ET support. You need to install ET and set your ===" << endl;
233 cerr << "=== ETROOT environment variable appropriately before ===" << endl;
234 cerr << "=== recompiling. ===" << endl;
235 cerr << endl;
236 }
237 throw e;
238
239#endif // HAVE_ET
240 }
241 if(VERBOSE>0) evioout << "Success opening event source \"" << this->source_name << "\"!" <<endl;
242
243
244 // Create list of data types this event source can provide
245 // (must match what is returned by JObject::className() )
246 // n.b. there is an ugly hack down in GetObjects that will
247 // probably also need a line added for each data type added
248 // here.
249 event_source_data_types.insert("Df250Config");
250 event_source_data_types.insert("Df250PulseIntegral");
251 event_source_data_types.insert("Df250StreamingRawData");
252 event_source_data_types.insert("Df250WindowSum");
253 event_source_data_types.insert("Df250PulseRawData");
254 event_source_data_types.insert("Df250TriggerTime");
255 event_source_data_types.insert("Df250PulseTime");
256 event_source_data_types.insert("Df250PulsePedestal");
257 event_source_data_types.insert("Df250WindowRawData");
258 event_source_data_types.insert("Df125Config");
259 event_source_data_types.insert("Df125PulseIntegral");
260 event_source_data_types.insert("Df125TriggerTime");
261 event_source_data_types.insert("Df125PulseTime");
262 event_source_data_types.insert("Df125PulsePedestal");
263 event_source_data_types.insert("Df125WindowRawData");
264 event_source_data_types.insert("Df125CDCPulse");
265 event_source_data_types.insert("Df125FDCPulse");
266 event_source_data_types.insert("DF1TDCConfig");
267 event_source_data_types.insert("DF1TDCHit");
268 event_source_data_types.insert("DF1TDCTriggerTime");
269 event_source_data_types.insert("DCAEN1290TDCConfig");
270 event_source_data_types.insert("DCAEN1290TDCHit");
271 event_source_data_types.insert("DCODAEventInfo");
272 event_source_data_types.insert("DCODAROCInfo");
273 event_source_data_types.insert("DTSscalers");
274 event_source_data_types.insert("DEPICSvalue");
275 event_source_data_types.insert("DEventTag");
276 event_source_data_types.insert("DL1Info");
277
278 // Read in optional module type translation map if it exists
279 ReadOptionalModuleTypeTranslation();
280
281 last_run_number = 0;
282 filename_run_number = 0;
283 current_event_count = 0;
284
285 // Try extracting the run number from the filename. (This is
286 // only used if the run number is not found in the EVIO data.)
287 size_t pos2 = this->source_name.find_last_of('_');
288 if(pos2 != string::npos){
289 size_t pos1 = this->source_name.find_last_of('_', pos2-1);
290 if(pos1 != string::npos){
291 pos1++;
292 string runstr = this->source_name.substr(pos1, pos2-pos1);
293 if(runstr.length()>0) filename_run_number = atoi(runstr.c_str());
294 }
295 }
296
297 pthread_mutex_init(&evio_buffer_pool_mutex, NULL__null);
298 pthread_mutex_init(&stored_events_mutex, NULL__null);
299 pthread_mutex_init(&current_event_count_mutex, NULL__null);
300 pthread_rwlock_init(&BOR_lock, NULL__null);
301}
302
303//----------------
304// Destructor
305//----------------
306JEventSource_EVIO::~JEventSource_EVIO()
307{
308 // close event source here
309// if(chan){
310// if(VERBOSE>0) evioout << "Closing event source \"" << this->source_name << "\"" <<endl;
311// chan->close();
312// delete chan;
313// }
314
315#ifdef HAVE_ET
316 if(et_connected){
317 if(VERBOSE>0) evioout << "Closing ET connection \"" << this->source_name << "\"" <<endl;
318 et_close(sys_id);
319 et_connected = false;
320 }
321#endif
322
323 if(hdevio){
324 if(VERBOSE>0) evioout << "Closing hdevio event source \"" << this->source_name << "\"" <<endl;
325 hdevio->PrintStats();
326 delete hdevio;
327 }
328
329 // Release memory used for the event buffer pool
330 while(!evio_buffer_pool.empty()){
331 free(evio_buffer_pool.front());
332 evio_buffer_pool.pop_front();
333 }
334
335 // Delete any BOR config objects
336 for(uint32_t i=0; i<BORobjs.size(); i++) delete BORobjs[i];
337 BORobjs.clear();
338
339 // Optionally dump the module map
340 if(DUMP_MODULE_MAP)DumpModuleMap();
341}
342
343//---------------------------------
344// ReadOptionalModuleTypeTranslation
345//---------------------------------
346void JEventSource_EVIO::ReadOptionalModuleTypeTranslation(void)
347{
348 // Some data may be taken with bad ROLs or drivers that
349 // write module type values that are non-standard. This
350 // allows the user to specify a simple text file that
351 // can be read in to translate the types found in the
352 // file to another type so that they can be properly parsed.
353 ifstream ifs(MODTYPE_MAP_FILENAME.c_str());
354 if(!ifs.is_open()) return;
355
356 cout << "Opened JLab module type translation map: " << endl;
357 cout << " " << MODTYPE_MAP_FILENAME << endl;
358 while(ifs.good()){
359 char line[256];
360 ifs.getline(line, 256);
361 if(ifs.gcount() < 1) break;
362 if(line[0] == '#') continue;
363
364 stringstream ss(line);
365 uint32_t from=10000, to=10000;
366 ss >> from >> to; // from=evio to=TT
367 if( to==10000 ){
368 if( from!=10000){
369 cout << "unable to convert line:" << endl;
370 cout << " " << line;
371 }
372 }else{
373 modtype_translate[(MODULE_TYPE)from] = (MODULE_TYPE)to;
374 }
375 }
376 ifs.close();
377
378 cout << " Read " << modtype_translate.size() << " entries" << endl;
379 map<MODULE_TYPE,MODULE_TYPE>::iterator iter;
380 for(iter=modtype_translate.begin(); iter != modtype_translate.end(); iter++){
381 cout << " type " << iter->first << " -> type " << iter->second << endl;
382 }
383}
384
385//----------------
386// ConnectToET
387//----------------
388void JEventSource_EVIO::ConnectToET(const char* source_name)
389{
390#ifdef HAVE_ET
391
392 /// Format for ET source strings is:
393 ///
394 /// ET:session:station:host:port
395 ///
396 /// The session is used to form the filename of the ET
397 /// system. For example, if an session of "eb" is specified,
398 /// then a file named "/tmp/et_sys_eb" is assumed to be
399 /// what should be opened. If no session is specified (or
400 /// an empty session name) then "none" is used as the session.
401 ///
402 /// If the station name specified does not exist, it will
403 /// be created. If it does exist, the existing station will
404 /// be used. If no station is specified, then the station
405 /// name "DANA" will be used. Any station created will be
406 /// set to "blocking" *unless* the configuration paramter
407 /// EVIO:ET_STATION_CREATE_BLOCKING is set to "0"
408 /// in which case it will be set to non-blocking.
409 ///
410 /// If the host is specified, then an attempt will be made
411 /// to open that system. If it is not specified, then
412 /// it will attempt to open an ET system on the local machine.
413 ///
414 /// If port is specified, it is used as the TCP port number
415 /// on the remote host to attach to. If the host is not
416 /// specified (i.e. by having two colons and therefore
417 /// an empty string) then the port is ignored. If the
418 /// port is omitted or specified as "0", then the default
419 /// port is used.
420 ///
421
422 // Split source name into session, station, etc...
423 vector<string> fields;
424 string str = source_name;
425 size_t startpos=0, endpos=0;
426 while((endpos = str.find(":", startpos)) != str.npos){
427 size_t len = endpos-startpos;
428 fields.push_back(len==0 ? "":str.substr(startpos, len));
429 startpos = endpos+1;
430 }
431 if(startpos<str.length()) fields.push_back(str.substr(startpos, str.npos));
432
433 string session = fields.size()>1 ? fields[1]:"";
434 string station = fields.size()>2 ? fields[2]:"";
435 string host = fields.size()>3 ? fields[3]:"localhost";
436 int port = fields.size()>4 ? atoi(fields[4].c_str()):ET_SERVER_PORT;
437
438 if(session == "") session = "none";
439 if(station == "") station = "DANA";
440 if(host == "") host = "localhost";
441 string fname = session.at(0)=='/' ? session:(string("/tmp/et_sys_") + session);
442
443 // Report to user what we're doing
444 jout << " Opening ET system:" << endl;
445 if(session!=fname) jout << " session: " << session << endl;
446 jout << " station: " << station << endl;
447 jout << " system file: " << fname << endl;
448 jout << " host: " << host << endl;
449 if(port !=0) jout << " port: " << port << endl;
450
451 // connect to the ET system
452 et_openconfig openconfig;
453 et_open_config_init(&openconfig);
454 if(host != ""){
455 if(host.find("239.")==0){
456 cout<<__FILE__"libraries/DAQ/JEventSource_EVIO.cc"<<":"<<__LINE__456<<" Configuring input ET for multicast" << endl;
457 et_open_config_setcast(openconfig, ET_MULTICAST);
458 et_open_config_addmulticast(openconfig, host.c_str());
459 et_open_config_sethost(openconfig, ET_HOST_ANYWHERE);
460 et_open_config_setport(openconfig, port);
461 struct timespec tspec={5,5};
462 et_open_config_settimeout(openconfig, tspec);
463 et_open_config_setwait(openconfig, ET_OPEN_WAIT);
464 }else{
465 cout<<__FILE__"libraries/DAQ/JEventSource_EVIO.cc"<<":"<<__LINE__465<<" Configuring input ET for direct connection" << endl;
466 et_open_config_setcast(openconfig, ET_DIRECT);
467 et_open_config_setmode(openconfig, ET_HOST_AS_LOCAL); // ET_HOST_AS_LOCAL or ET_HOST_AS_REMOTE
468 et_open_config_sethost(openconfig, host.c_str());
469 et_open_config_setport(openconfig, ET_BROADCAST_PORT);
470 if(port != 0)et_open_config_setserverport(openconfig, port);
471 }
472 }
473 int err = et_open(&sys_id,fname.c_str(),openconfig);
474 if(err != ET_OK){
475 cerr << __FILE__"libraries/DAQ/JEventSource_EVIO.cc"<<":"<<__LINE__475<<" Problem opening ET system"<<endl;
476 cerr << et_perror(err);
477 return;
478 }
479
480 // create station config in case no station exists
481 et_statconfig et_station_config;
482 et_station_config_init(&et_station_config);
483 et_station_config_setblock(et_station_config, ET_STATION_CREATE_BLOCKING ? ET_STATION_BLOCKING:ET_STATION_NONBLOCKING);
484 et_station_config_setselect(et_station_config,ET_STATION_SELECT_ALL);
485 et_station_config_setuser(et_station_config,ET_STATION_USER_MULTI);
486 et_station_config_setrestore(et_station_config,ET_STATION_RESTORE_OUT);
487 et_station_config_setcue(et_station_config,ET_STATION_NEVENTS);
488 et_station_config_setprescale(et_station_config,1);
489 cout<<"ET station configured\n";
490
491 // create station if not already created
492 int status=et_station_create(sys_id,&sta_id,station.c_str(),et_station_config);
493 if((status!=ET_OK)&&(status!=ET_ERROR_EXISTS)) {
494 et_close(sys_id);
495 cerr << "Unable to create station " << station << endl;
496 cerr << et_perror(status);
497
498 // Check that the number of events in the ET system is not
499 // less than the number of events we specified for the station CUE.
500 int Nevents = 0;
501 et_system_getnumevents(sys_id, &Nevents);
502 if(Nevents <= ET_STATION_NEVENTS){
503 jerr << "NOTE: The number of events specified for the station cue is equal to" << endl;
504 jerr << "or greater than the number of events in the entire ET system:" << endl;
505 jerr << endl;
506 jerr << " " << ET_STATION_NEVENTS << " >= " << Nevents << endl;
507 jerr << endl;
508 jerr << "Try re-running with: " << endl;
509 jerr << endl;
510 jerr << " -PEVIO:ET_STATION_NEVENTS=" << (Nevents+1)/2 << endl;
511 jerr << endl;
512 }
513 return;
514 }
515 if(status==ET_ERROR_EXISTS){
516 jout << " Using existing ET station " << station << endl;
517 }else{
518 jout << " ET station " << station << " created\n";
519 }
520
521 // Attach to the ET station
522 status=et_station_attach(sys_id,sta_id,&att_id);
523 if(status!=ET_OK) {
524 et_close(sys_id);
525 jerr << "Unable to attach to station " << station << endl;
526 return;
527 }
528
529 jout << "...now connected to ET system: " << fname
530 << ", station: " << station << " (station id=" << sta_id << ", attach id=" << att_id <<")" << endl;
531
532 et_connected = true;
533 // chan = new evioETChannel(sys_id, att_id);
534
535 // Make sure the size of event buffers we will allocate are at least as big
536 // as the event size used in the ET system
537 size_t eventsize;
538 et_system_geteventsize(sys_id, &eventsize);
539 if((uint32_t)eventsize > BUFFER_SIZE){
540 jout<<" Events in ET system are larger than currently set buffer size:"<<endl;
541 jout<<" "<<eventsize<<" > "<<BUFFER_SIZE<<endl;
542 jout<<" Setting BUFFER_SIZE to "<<eventsize<<endl;
543 BUFFER_SIZE = (uint32_t)eventsize;
544 }else{
545 jout<<" ET system event size:"<<eventsize<<" JEventSource_EVIO.BUFFER_SIZE:"<<BUFFER_SIZE<<endl;
546 }
547
548#else
549 jerr << endl;
550 jerr << "You are attempting to connect to an ET system using a binary that" <<endl;
551 jerr << "was compiled without ET support. Please reconfigure and recompile" <<endl;
552 jerr << "To get ET support." << endl;
553 jerr << endl;
554 throw exception();
555#endif // HAVE_ET
556}
557
558//----------------
559// Cleanup
560//----------------
561void JEventSource_EVIO::Cleanup(void)
562{
563 /// This is called internally by the JEventSource_EVIO class
564 /// once all events have been read in. Its purpose is to
565 /// free the hidden memory in all of the container class
566 /// members of the JEventSource_EVIO class. This is needed
567 /// for jobs that process a lot of input files and therefore
568 /// create a lot JEventSource_EVIO objects. JANA does not delete
569 /// these objects until the end of the job so this tends to
570 /// act like a memory leak. The data used can be substantial
571 /// (nearly 1GB per JEventSource_EVIO object).
572 if(hdevio) delete hdevio;
573 hdevio = NULL__null;
574 //if(chan) delete chan;
575 //chan = NULL;
576#ifdef HAVE_ET
577 if(et_connected) et_close(sys_id);
578 et_connected = false;
579#endif // HAVE_ET
580
581 module_type.clear();
582 modtype_translate.clear();
583
584 for(uint32_t i=0; i<hit_objs.size(); i++) hit_objs[i].resize(0);
585 hit_objs.resize(0);
586
587 while(!stored_events.empty()){
588 delete stored_events.front();
589 stored_events.pop();
590 }
591 while(!evio_buffer_pool.empty()) {
592 delete evio_buffer_pool.back();
593 evio_buffer_pool.pop_back();
594 }
595 while(!event_source_data_types.empty()){
596 event_source_data_types.erase(event_source_data_types.begin());
597 }
598}
599
600//----------------
601// GetEvent
602//----------------
603jerror_t JEventSource_EVIO::GetEvent(JEvent &event)
604{
605 if(VERBOSE>1) evioout << "GetEvent called for &event = " << hex << &event << dec << endl;
606
607 // If we couldn't even open the source, then there's nothing to do
608 bool no_source = true;
609#if USE_HDEVIO1
610 if(source_type==kFileSource && hdevio->is_open) no_source = false;
611#endif
612 if(source_type==kETSource && et_connected) no_source = false;
613 if(no_source)throw JException(string("Unable to open EVIO channel for \"") + source_name + "\"");
614
615
616 // This may not be a long term solution, but here goes:
617 // We need to write single events out in EVIO format, possibly
618 // with new information attached. The easiest way to do this
619 // is to keep the DOM tree when the event is read in and modify
620 // it if needed before writing it out. The complication comes
621 // in that entangled events will not have a dedicated DOM tree
622 // for every event. This is only an issue if disentangling is
623 // not done upstream. How this is handled now is that the DOM
624 // tree pointer is copied into the ObjList object for the first
625 // physics event found in the DAQ event. The DOM tree is freed
626 // in FreeEvent (if the pointer is non-NULL). Note that for
627 // single event blocks (i.e. already disentangled events) the
628 // stored_events list will always be empty so "evt" is always
629 // set.
630
631 // Check for event stored from parsing a previously read in
632 // DAQ event
633 ObjList *objs_ptr = NULL__null;
634 pthread_mutex_lock(&stored_events_mutex);
635 if(!stored_events.empty()){
636 objs_ptr = stored_events.front();
637 stored_events.pop();
638
639 // If this is a stored event then it almost certainly
640 // came from a multi-event block of physics events.
641 // Set the physics event status bit.
642 event.SetStatusBit(kSTATUS_PHYSICS_EVENT);
643 }
644 pthread_mutex_unlock(&stored_events_mutex);
645
646 // If no events are currently stored in the buffer, then
647 // read in another event block.
648 if(objs_ptr == NULL__null){
649 uint32_t *buff = NULL__null; // ReadEVIOEvent will allocate memory from pool for this
650 double t1 = GetTime();
651 jerror_t err = ReadEVIOEvent(buff);
652 double t2 = GetTime();
653 if(err != NOERROR) return err;
654 if(buff == NULL__null) return MEMORY_ALLOCATION_ERROR;
655 uint32_t buff_size = ((*buff) + 1)*4; // first word in EVIO buffer is total bank size in words
656
657 objs_ptr = new ObjList();
658 objs_ptr->time_evio_read = t2 - t1;
659 objs_ptr->eviobuff = buff;
660 objs_ptr->eviobuff_size = buff_size;
661 objs_ptr->run_number = FindRunNumber(buff);
662 objs_ptr->event_number = FindEventNumber(buff);
663
664 // Increment counter that keeps track of how many events
665 // are currently being processed.
666 pthread_mutex_lock(&current_event_count_mutex);
667 current_event_count++;
668 pthread_mutex_unlock(&current_event_count_mutex);
669 }
670
671 // Store a pointer to the ObjList object for this event in the
672 // JEvent as the Reference value. Parsing will be done later
673 // in GetObjects() -> ParseEvents() using the eviobuff pointer.
674 event.SetJEventSource(this);
675 event.SetEventNumber((uint64_t)objs_ptr->event_number);
676 event.SetRunNumber(objs_ptr->run_number);
677 event.SetRef(objs_ptr);
678 event.SetStatusBit(kSTATUS_EVIO);
679 if( source_type == kFileSource ) event.SetStatusBit(kSTATUS_FROM_FILE);
680 if( source_type == kETSource ) event.SetStatusBit(kSTATUS_FROM_ET);
681 if(objs_ptr)
682 if(objs_ptr->eviobuff) FindEventType(objs_ptr->eviobuff, event);
683
684 // EPICS and BOR events are barrier events
685 if(event.GetStatusBit(kSTATUS_EPICS_EVENT) || event.GetStatusBit(kSTATUS_BOR_EVENT) ){
686 event.SetSequential();
687 }
688
689 Nevents_read++;
690
691 return NOERROR;
692}
693
694//----------------
695// FreeEvent
696//----------------
697void JEventSource_EVIO::FreeEvent(JEvent &event)
698{
699 if(VERBOSE>1) evioout << "FreeEvent called for event: " << event.GetEventNumber() << endl;
700
701 ObjList *objs_ptr = (ObjList*)event.GetRef();
702 if(objs_ptr){
703
704 // If a DAQ event was read in but GetObjects never called
705 // then the buffer will never have been parsed. Since the
706 // DAQ event could hold multiple Physics events, we parse
707 // it now to ensure all physics events are presented by
708 // the event source. The ParseEvents call will copy the
709 // first event's parameters into our objs_ptr object, but
710 // any additional ones will be placed in stored_events.
711 if(!objs_ptr->eviobuff_parsed) ParseEvents(objs_ptr);
712
713 if(objs_ptr->own_objects){
714
715 for(unsigned int i=0; i<objs_ptr->hit_objs.size(); i++){
716 delete objs_ptr->hit_objs[i];
717 }
718
719 for(unsigned int i=0; i<objs_ptr->config_objs.size(); i++){
720 delete objs_ptr->config_objs[i];
721 }
722
723 for(unsigned int i=0; i<objs_ptr->misc_objs.size(); i++){
724 delete objs_ptr->misc_objs[i];
725 }
726 }
727
728 if(objs_ptr->DOMTree != NULL__null) delete objs_ptr->DOMTree;
729 if(objs_ptr->eviobuff){
730
731 // If we have not already stopped reading events from
732 // the source then return this buffer to the pool. Otherwise,
733 // delete the buffer.
734 if(hdevio){
735 // Return EVIO buffer to pool for recycling
736 pthread_mutex_lock(&evio_buffer_pool_mutex);
737 evio_buffer_pool.push_front(objs_ptr->eviobuff);
738 pthread_mutex_unlock(&evio_buffer_pool_mutex);
739 }else{
740 free(objs_ptr->eviobuff);
741 }
742 }
743
744 delete objs_ptr;
745
746 // Decrement counter that keeps track of how many events
747 // are currently being processed.
748 pthread_mutex_lock(&current_event_count_mutex);
749 current_event_count--;
750 bool last_event = (hdevio==NULL__null) && (current_event_count==0);
751 pthread_mutex_unlock(&current_event_count_mutex);
752
753 // If we are the last event, then clean up as much memory as
754 // possible.
755 if(last_event) Cleanup();
756 }
757}
758
759//----------------
760// ParseEvents
761//----------------
762jerror_t JEventSource_EVIO::ParseEvents(ObjList *objs_ptr)
763{
764 /// This is the high-level entry point for parsing the
765 /// DAQ event in order to create one or more Physics
766 /// events. It will be called from either GetObjects
767 /// or FreeEvent, the latter being done only if needed
768 /// to ensure the event does eventually get parsed.
769 /// The grunt work of actually parsing the data starts
770 /// in ParseEVIOEvent().
771 ///
772 /// This method is here so that the DOM Tree creation
773 /// and data parsing can be deferred from the EventBuffer
774 /// thread (of which there is only one) to an event
775 /// processor thread (or which there may be many). Since
776 /// the DOM tree creating and data parsing represent the
777 /// larger time cost of getting the event into memory,
778 /// a siginificant performance increase can be gained
779 /// using this slightly more complicated method.
780
781 if(VERBOSE>2) evioout << " Entering ParseEvents() with objs_ptr=" << hex << objs_ptr << dec << endl;
782
783 // Double check that we're not re-parsing an event
784 if(objs_ptr->eviobuff_parsed){
785 jerr << " DAQ event already parsed!! Bug in code. Contact davidl@jlab.org" << endl;
786 return UNKNOWN_ERROR;
787 }
788
789 // Bomb-proof against getting a NULL buffer
790 uint32_t *buff = objs_ptr->eviobuff;
791 if(buff == NULL__null){
792 jerr << " Bad buffer pointer passed to JEventSource_EVIO::ParseEvent()!!" << endl;
793 return RESOURCE_UNAVAILABLE;
794 }
795
796 // This container will be used to hold all of the individual
797 // Physics (L1 triggered) events for this DAQ event. This includes
798 // both dientangling multi-event blocks and separating multi-event
799 // ET events.
800 list<ObjList*> full_events;
801
802 // Setup up iptr and iend to point to the start of the first event
803 // and the word just after the end of the last event respectively.
804 // Initialize them for the case of reading from a file and not a
805 // CODA-produced ET event
806 uint32_t *iptr = &buff[0];
807 uint32_t *iend = &buff[buff[0]+1]; // EVIO length word is exclusive so +1
808
809 // If the "event" was read from ET, then it may (and likely
810 // will) contain several DAQ events. (Each DAQ event may itself
811 // contain many L1 trigger events.) In addition, the ET event
812 // will have a Network Transport Header (NTH) that must be skipped
813 // but only if read from CODA. Events put into the ET system
814 // by other means will not include the NTH. To decide whether
815 // there is an NTH, we look at the magic word and the header length.
816 // Note that byteswapping should already have occured.
817 if(source_type==kETSource && buff[7]==0xc0da0100 && buff[2]==8){
818 // This buffer read from ET. Redefine iptr and iend
819 iptr = &buff[8];
820 iend = &buff[buff[0]]; // EVIO length word in NTH is inclusive so don't add 1
821 }
822
823 if(VERBOSE>5) evioout << " Looping event stack with " << *iptr << " words" << endl;
824
825 // Loop over events in buffer until entire buffer is parsed.
826 // When reading from a file, this loop should only get executed once.
827 int Nevents_in_stack=0;
828 while(iptr < iend){
829
830 double time_dom_tree = 0;
831 double time_evio_parse = 0;
832
833 // Make a evioDOMTree for this DAQ event
834 evioDOMTree *evt = NULL__null;
835 if(MAKE_DOM_TREE){
836 try{
837 double tstart = GetTime();
838 evt = new evioDOMTree(iptr);
839 time_dom_tree = GetTime() - tstart;
840 }catch(evioException &e){
841 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<841<<" "
<< "Problem creating EVIO DOM Tree!!" << endl;
842 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<842<<" "
<< e.what() << endl;
843 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<843<<" "
<< "Binary dump of first 160 words follows:" << endl;
844 DumpBinary(iptr, iend, 160);
845 exit(-1);
846 }
847 }
848
849 if(evt){
850 // Parse event, making other ObjList objects
851 list<ObjList*> my_full_events;
852 //bool skipped_parsing = true;
853 if(PARSE_EVIO_EVENTS){
854 try{
855 double tstart = GetTime();
856 ParseEVIOEvent(evt, my_full_events);
857 time_evio_parse = GetTime() - tstart;
858 }catch(JException &jexception){
859 jerr << "Exception thrown from ParseEVIOEvent!" << endl;
860 jerr << jexception.toString() << endl;
861 }
862 }
863
864 // Append physics events found for this DAQ event to the list of all physics events
865 if(!my_full_events.empty()) {
866 my_full_events.front()->DOMTree = evt; // keep DOMTree pointer with first event from this DAQ event
867 my_full_events.front()->time_dom_tree = time_dom_tree;
868 my_full_events.front()->time_evio_parse = time_evio_parse;
869 full_events.insert( full_events.end(), my_full_events.begin(), my_full_events.end() );
870 }else{
871 delete evt;
872 }
873 }else{
874 // No DOM tree made for this buffer. Insert an empty event into
875 // the list so we can keep track of the number of events seen
876 // even when DOMTree creation is turned off.
877 ObjList *objs = new ObjList;
878 full_events.push_back(objs);
879 }
880
881 // Advance pointer to next event in buffer
882 iptr += iptr[0]+1;
883 Nevents_in_stack++; // number of events processed in this buffer (for debugging)
884 }
885
886 if(VERBOSE>5) evioout << " Loop finished. " << full_events.size() << " events total found (" << Nevents_in_stack << " events in stack)" << endl;
887
888 // At this point, we have parsed the DAQ event and extracted all physics
889 // events into the full_events list. In the case of a prestart or go event
890 // read from an EVIO file, the full_events list may actually be empty at
891 // this point. For these cases, we need to add an empty event for the
892 // current thread to "process".
893 bool empty_event = full_events.empty();
894 if(empty_event) full_events.push_back(new ObjList());
895
896 // Whether we actually parsed the events or not, we mark them as being
897 // parsed since it is really just used as a flag to tell whether this
898 // method should be called or not.
899 list<ObjList*>::iterator iter = full_events.begin();
900 for( ; iter != full_events.end(); iter++ ) (*iter)->eviobuff_parsed = true;
901
902 // Copy the first event's objects obtained from parsing into this event's ObjList
903 ObjList *objs = full_events.front();
904 full_events.pop_front();
905 //objs_ptr->run_number = empty_event ? objs_ptr->run_number:objs->run_number;
906 objs_ptr->own_objects = objs->own_objects;
907 objs_ptr->hit_objs = objs->hit_objs;
908 objs_ptr->config_objs = objs->config_objs;
909 objs_ptr->misc_objs = objs->misc_objs;
910 objs_ptr->eviobuff_parsed = objs->eviobuff_parsed;
911 objs_ptr->time_dom_tree = objs->time_dom_tree;
912 objs_ptr->time_evio_parse = objs->time_evio_parse;
913 //objs_ptr->eviobuff = objs->eviobuff; // Don't copy this! (it causes memory leak)
914 //objs_ptr->eviobuff_size = objs->eviobuff_size;
915 objs_ptr->DOMTree = objs->DOMTree;
916 delete objs;
917
918 // Config objects come from banks that are created when a block
919 // of events is read out. Thus, a single set of config. objects
920 // will be created when parsing a multi-event block. Here, we duplicate
921 // all config objects for the first event for every other event in the
922 // block. To make this a little more compact and maintainable, we use a
923 // #define. This allows us to write the class type once and guarantee
924 // that it shows up the same in all places. For example, using
925 // CloneConfigObject(Df125Config) will expand to something like:
926 //
927 // if(confobj->className() == string("Df125Config")){
928 // c = new Df125Config(confobj->rocid,confobj->slot_mask);
929 // *((Df125Config*)c) = *((Df125Config*)confobj);
930 // }
931#define CloneConfigObject(T){ if(confobj->className() == string("T")){ c = new T(confobj
->rocid,confobj->slot_mask); *((T*)c) = *((T*)confobj);
} }
{ if(confobj->className() == string(#T)){ c = new T(confobj->rocid,confobj->slot_mask); *((T*)c) = *((T*)confobj);} }
932 list<ObjList*>::iterator feiter = full_events.begin();
933 for(; feiter!=full_events.end(); feiter++){
934 ObjList *objs = *feiter;
935 for(uint32_t j=0; j<objs_ptr->config_objs.size(); j++){
936 DDAQConfig *confobj = objs_ptr->config_objs[j];
937 DDAQConfig *c = NULL__null;
938 CloneConfigObject(Df250Config){ if(confobj->className() == string("Df250Config")){ c = new
Df250Config(confobj->rocid,confobj->slot_mask); *((Df250Config
*)c) = *((Df250Config*)confobj);} }
;
939 CloneConfigObject(Df125Config){ if(confobj->className() == string("Df125Config")){ c = new
Df125Config(confobj->rocid,confobj->slot_mask); *((Df125Config
*)c) = *((Df125Config*)confobj);} }
;
940 CloneConfigObject(DF1TDCConfig){ if(confobj->className() == string("DF1TDCConfig")){ c = new
DF1TDCConfig(confobj->rocid,confobj->slot_mask); *((DF1TDCConfig
*)c) = *((DF1TDCConfig*)confobj);} }
;
941 CloneConfigObject(DCAEN1290TDCConfig){ if(confobj->className() == string("DCAEN1290TDCConfig"))
{ c = new DCAEN1290TDCConfig(confobj->rocid,confobj->slot_mask
); *((DCAEN1290TDCConfig*)c) = *((DCAEN1290TDCConfig*)confobj
);} }
;
942 if(c)objs->config_objs.push_back(c);
943 }
944 }
945
946 // Copy remaining events into the stored_events container
947 pthread_mutex_lock(&stored_events_mutex);
948 while(!full_events.empty()){
949 objs = full_events.front();
950 full_events.pop_front();
951 stored_events.push(objs);
952
953 // Copy run number from first event
954 objs->run_number = objs_ptr->run_number;
955 }
956 pthread_mutex_unlock(&stored_events_mutex);
957
958 if(VERBOSE>2) evioout << " Leaving ParseEvents()" << endl;
959
960 return NOERROR;
961}
962
963//----------------
964// GetPoolBuffer
965//----------------
966uint32_t* JEventSource_EVIO::GetPoolBuffer(void)
967{
968 // Get buffer from pool or allocate new one if needed
969 uint32_t *buff = NULL__null;
970 pthread_mutex_lock(&evio_buffer_pool_mutex);
971 if(evio_buffer_pool.empty()){
972 // Allocate new block of memory
973 if(VERBOSE>5) evioout << " evio_buffer_pool empty. Allocating new buffer of size: " << BUFFER_SIZE << " bytes" << endl;
974 buff = (uint32_t*)malloc(BUFFER_SIZE);
975 }else{
976 if(VERBOSE>5) evioout << " evio_buffer_pool not empty(size=" << evio_buffer_pool.size() << "). using buffer from pool" << endl;
977 buff = evio_buffer_pool.front();
978 evio_buffer_pool.pop_front();
979 }
980 pthread_mutex_unlock(&evio_buffer_pool_mutex);
981
982 return buff;
983}
984
985//----------------
986// ReadEVIOEvent
987//----------------
988jerror_t JEventSource_EVIO::ReadEVIOEvent(uint32_t* &buff)
989{
990 /// This method will read an event from the source (file or ET system)
991 /// copying the data into "buff". No parsing of the data is done at
992 /// this level except that if the event comes from ET and needs to be
993 /// byte-swapped, the byte swapping is done during the copy.
994 ///
995 /// This is called from the GetEvent method and therefore run in
996 /// the event reader thread. Events read from ET may contain several DAQ
997 /// events in a single buffer (and each of those may contain several
998 /// physics events if read in multi-event blocks). Separating the multiple
999 /// DAQ events is left to the ParseEvents method which gets called later
1000 /// from the event processing threads to improve efficiency.
1001
1002 if(VERBOSE>1) evioout << " ReadEVIOEvent() called with &buff=" << hex << &buff << dec << endl;
1003
1004 try{
1005 if(source_type==kFileSource){
1006 if(VERBOSE>3) evioout << " attempting read from EVIO file source ..." << endl;
1007
1008#if USE_HDEVIO1
1009
1010 bool done = false;
1011 buff = GetPoolBuffer(); // Get (or allocate) a new buffer from the pool
1012 uint32_t buff_size = BUFFER_SIZE;
1013 while(!done){
1014 bool isok = true;
1015 if(EVIO_SPARSE_READ)
1016 isok= hdevio->readSparse(buff, buff_size);
1017 else
1018 isok= hdevio->read(buff, buff_size);
1019 if(isok){
1020 done = true;
1021 }else{
1022 string mess = hdevio->err_mess.str();
1023
1024 switch(hdevio->err_code){
1025 case HDEVIO::HDEVIO_OK:
1026 done = true;
1027 break;
1028 case HDEVIO::HDEVIO_USER_BUFFER_TOO_SMALL:
1029 if(VERBOSE>0) evioout << "EVIO buffer too small (" << buff_size << " bytes) . Reallocating to " << hdevio->last_event_len<< endl;
1030 if(buff) delete[] buff;
1031 buff_size = hdevio->last_event_len;
1032 buff = new uint32_t[buff_size];
1033 continue;
1034 break;
1035 case HDEVIO::HDEVIO_EVENT_BIGGER_THAN_BLOCK:
1036 case HDEVIO::HDEVIO_BANK_TRUNCATED:
1037 case HDEVIO::HDEVIO_UNKNOWN_BANK_TYPE:
1038 if(VERBOSE>0) cout << endl << mess << endl;
1039 continue;
1040 break;
1041 case HDEVIO::HDEVIO_EOF:
1042 if(hdevio) delete hdevio;
1043 hdevio = NULL__null;
1044 if(LOOP_FOREVER && Nevents_read>=1){
1045 cout << "LOOP_FOREVER: reopening " << this->source_name <<endl;
1046 hdevio = new HDEVIO(this->source_name);
1047 if( hdevio->is_open ) continue;
1048 }
1049 return NO_MORE_EVENTS_IN_SOURCE;
1050 break;
1051 default:
1052 cout << endl << "err_code=" << hdevio->err_code << endl;
1053 cout << endl << mess << endl;
1054 if(hdevio) delete hdevio;
1055 hdevio = NULL__null;
1056 return NO_MORE_EVENTS_IN_SOURCE;
1057 break;
1058 }
1059 }
1060 } // while(!done)
1061
1062#else
1063 // ( removed old evio library code )
1064#endif // USE_HDEVIO
1065
1066 }else if(source_type==kETSource){
1067
1068#ifdef HAVE_ET
1069
1070 if(VERBOSE>3) evioout << " attempting read from EVIO ET source ..." << endl;
1071
1072
1073 // Loop until we get an event or are told to stop
1074 struct timespec timeout;
1075 timeout.tv_sec = (unsigned int)floor(TIMEOUT); // set ET timeout
1076 timeout.tv_nsec = (unsigned int)floor(1.0E9*(TIMEOUT-(float)timeout.tv_sec));
1077 et_event *pe=NULL__null;
1078 while(! japp->GetQuittingStatus() ){
1079 int err = et_event_get(sys_id, att_id, &pe, ET_TIMED , &timeout);
1080
1081 if( err == ET_OK && pe!=NULL__null) break; // got an event. break out of while loop
1082
1083 if( err == ET_OK && pe==NULL__null){
1084 evioout << " !!! ET returned no error, but event pointer is NULL!!!" << endl;
1085 return NO_MORE_EVENTS_IN_SOURCE;
1086 }
1087
1088 if( err==ET_ERROR_TIMEOUT ){
1089 if(quit_on_next_ET_timeout)return NO_MORE_EVENTS_IN_SOURCE;
1090 }else if( err!=ET_OK){
1091 evioout << " Error reading from ET. This probably means the ET" << endl;
1092 evioout << "system has gone away (possibly due to run ending or" << endl;
1093 evioout << "DAQ crashing). At any rate, we are quitting now as this" << endl;
1094 evioout << "error is currently unrecoverable." << endl;
1095 return NO_MORE_EVENTS_IN_SOURCE;
1096 }
1097
1098 usleep(10);
1099 }
1100
1101 if(japp->GetQuittingStatus() && pe==NULL__null) return NO_MORE_EVENTS_IN_SOURCE;
1102
1103 // Get pointer to event buffer in the ET-owned memory
1104 uint32_t *et_buff=NULL__null;
1105 et_event_getdata(pe, (void**)&et_buff);
1106 if(et_buff == NULL__null){
1107 jerr << " Got event from ET, but pointer to data is NULL!" << endl;
1108 return NO_MORE_EVENTS_IN_SOURCE;
1109 }
1110
1111 // If user specified to dump words from ET event, do it right away
1112 if(ET_DEBUG_WORDS_TO_DUMP) DumpBinary(et_buff, &et_buff[ET_DEBUG_WORDS_TO_DUMP], ET_DEBUG_WORDS_TO_DUMP, NULL__null);
1113
1114 // A single ET event may have multiple EVIO blocks in it
1115 // Each block may have several EVIO events in it.
1116 //
1117 // (note that "block" here is not the same as the CODA
1118 // "block number". That one determines the number of
1119 // entangled events within the EVIO event and is dealt
1120 // with later while parsing the EVIO event itself.)
1121 //
1122 // We need to loop over EVIO blocks in this ET event
1123 // and then loop over EVIO events within the block.
1124
1125 // Get total size of ET event
1126 size_t et_len=0;
1127 size_t et_idx=0;
1128 et_event_getlength(pe, &et_len);
1129 if(VERBOSE>3)evioout << " ET event length: " << et_len << " (=" << et_len/4 << " words)"<<endl;
1130
1131 // Loop over EVIO blocks in ET event
1132 vector<uint32_t*> buffs;
1133 while(et_idx < et_len/4){
1134
1135 // Pointer to start of EVIO block header
1136 if(VERBOSE>3)evioout << " Looking for EVIO block header at et_idx=" << et_idx << endl;
1137 uint32_t *evio_block = &et_buff[et_idx];
1138
1139 // Check byte order of event by looking at magic #
1140 bool swap_needed = false;
1141 uint32_t magic = evio_block[7];
1142 switch(magic){
1143 case 0xc0da0100: swap_needed = false; break;
1144 case 0x0001dac0: swap_needed = true; break;
1145 default:
1146 evioout << "EVIO magic word not present!" << endl;
1147 return NO_MORE_EVENTS_IN_SOURCE;
1148 }
1149 uint32_t len = evio_block[0];
1150 if(swap_needed) len = EVIO_SWAP32(len)( (((len) >> 24) & 0x000000FF) | (((len) >> 8
) & 0x0000FF00) | (((len) << 8) & 0x00FF0000) |
(((len) << 24) & 0xFF000000) )
;
1151 if(VERBOSE>3){
1152 evioout << "Swapping is " << (swap_needed ? "":"not ") << "needed" << endl;
1153 evioout << " Num. words in EVIO buffer: "<<len<<endl;
1154 }
1155
1156 bool is_last_evio_block = (evio_block[5]>>(9+8))&0x1;
1157 if(VERBOSE>3)evioout << " Is last EVIO block?: " << is_last_evio_block << endl;
1158
1159 // Loop over all evio events in ET event
1160 uint32_t idx = 8; // point to first EVIO event
1161 while(idx<len){
1162
1163 // Size of events in bytes
1164 uint32_t mylen = swap_needed ? EVIO_SWAP32(evio_block[idx])( (((evio_block[idx]) >> 24) & 0x000000FF) | (((evio_block
[idx]) >> 8) & 0x0000FF00) | (((evio_block[idx]) <<
8) & 0x00FF0000) | (((evio_block[idx]) << 24) &
0xFF000000) )
:evio_block[idx];
1165 uint32_t bufsize_bytes = (mylen+1)*sizeof(uint32_t); // +1 is for buffer length word
1166 if(bufsize_bytes > BUFFER_SIZE){
1167 jerr<<" ET event larger than our BUFFER_SIZE!!!"<<endl;
1168 jerr<<" " << bufsize_bytes << " > " << BUFFER_SIZE << endl;
1169 jerr<<" Will stop reading from this source now. Try restarting"<<endl;
1170 jerr<<" with -PEVIO:BUFFER_SIZE=X where X is greater than "<<bufsize_bytes<<endl;
1171 if(VERBOSE>3){
1172 evioout << "First few words in case you are trying to debug:" << endl;
1173 for(unsigned int j=0; j<3; j++){
1174 char str[512];
1175 for(unsigned int i=0; i<5; i++){
1176 sprintf(str, " %08x", evio_block[i+j*5]);
1177 evioout << str;
1178 }
1179 evioout << endl;
1180 }
1181 }
1182 return NO_MORE_EVENTS_IN_SOURCE;
1183 }
1184
1185 // Check that EVIO event length doesn't claim to
1186 // extend past ET buffer.
1187 if( (idx+mylen) > len ){
1188 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<1188<<" "
<< "Bad word count while swapping events in ET event stack!" << endl;
1189 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<1189<<" "
<< "idx="<<idx<<" mylen="<<mylen<<" len="<<len<<endl;
1190 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<1190<<" "
<< "This indicates a problem either with the DAQ system"<<endl;
1191 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<1191<<" "
<< "or this parser code! Contact davidl@jlab.org x5567 " <<endl;
1192 break;
1193 }
1194
1195 // Get new buffer for this EVIO event
1196 buff = GetPoolBuffer();
1197
1198 // Copy event into "buff", byte swapping if needed.
1199 // If no swapping is needed, we just copy it all over
1200 // in one go.
1201 if(!swap_needed){
1202 memcpy(buff, &evio_block[idx], bufsize_bytes);
1203 }else{
1204 swap_int32_t(&evio_block[idx], mylen+1, buff);
1205 }
1206
1207 // Update pointer to next EVIO event in stack (if any)
1208 idx += mylen+1;
1209 buffs.push_back(buff);
1210 }
1211
1212 // bump index to next EVIO block
1213 et_idx += idx;
1214 if(VERBOSE>3)evioout << " EVIO events found so far: " << buffs.size() << endl;
1215 if(is_last_evio_block){
1216 if(VERBOSE>3) evioout << " Block flagged as last in ET event. Ignoring last " << (et_len/4 - et_idx) << " words" <<endl;
1217 break;
1218 }
1219 }
1220
1221 // Put ET event back since we're done with it
1222 et_event_put(sys_id, att_id, pe);
1223
1224 if(VERBOSE>3) evioout << " Found " << buffs.size() << " events in the ET event stack." << endl;
1225
1226 // The first EVIO event should be returned via "buff".
1227 buff = buffs.empty() ? NULL__null:buffs[0];
1228
1229 // Additional EVIO events need to be placed in
1230 // the "stored_events" deque so they can be
1231 // used in subsequent calls to GetEvent()
1232 pthread_mutex_lock(&stored_events_mutex);
1233 for(uint32_t i=1; i<buffs.size(); i++){
1234 ObjList *objs = new ObjList();
1235 objs->eviobuff = buffs[i];
1236 objs->eviobuff_size = BUFFER_SIZE;
1237 objs->run_number = FindRunNumber(buffs[i]);
1238 objs->event_number = FindEventNumber(buffs[i]);
1239 stored_events.push(objs);
1240 }
1241 pthread_mutex_unlock(&stored_events_mutex);
1242
1243#else // HAVE_ET
1244
1245 japp->Quit();
1246 evioout << "Attempting to read from ET system using binary that" << endl;
1247 evioout << "does not have ET support built in! Try recompiling" << endl;
1248 evioout << "programs/Utilities/plugins/DAQ with ETROOT defined" << endl;
1249 evioout << "and pointing to an ET installation." << endl;
1250
1251#endif //HAVE_ET
1252
1253 }
1254 } catch (evioException &e) {
1255 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<1255<<" "
<<e.what()<<endl;
1256 if(e.type == S_EVFILE_TRUNC0x40730001){
1257 jerr << "-- Event buffer truncated --" <<endl;
1258 jerr << "---- this could be because the events are too large " << endl;
1259 jerr << "---- for the buffer provided (" << BUFFER_SIZE << " bytes)" <<endl;
1260 jerr << "---- you can try giving a larger buffer size by setting" << endl;
1261 jerr << "---- the EVIO:BUFFER_SIZE configuration parameter by " << endl;
1262 jerr << "---- adding this argument to your command line:" << endl;
1263 jerr << "---- -PEVIO:BUFFER_SIZE=X (where X is in bytes)" << endl;
1264 }
1265 }
1266
1267 if(VERBOSE>2) evioout << " Leaving ReadEVIOEvent()" << endl;
1268
1269 return NOERROR;
1270}
1271
1272//----------------
1273// GetObjects
1274//----------------
1275jerror_t JEventSource_EVIO::GetObjects(JEvent &event, JFactory_base *factory)
1276{
1277 if(VERBOSE>2) evioout << " GetObjects() called for &event = " << hex << &event << dec << endl;
1278
1279 // This will get called when the first object of the event is
1280 // requested (regardless of the type of object). Instead of
1281 // pulling out objects only of the type requested, we instead
1282 // take the data for all objects and copy them into the respective
1283 // factories. Subsequent requests for objects for this same
1284 // event will get them from the factories. Thus, this should
1285 // only get called once per event.
1286 // O.K. that is not actually true. If objects of a type we don't
1287 // supply are requested, then the corresponding factory's evnt_called
1288 // flag will not have been set and it will come here first to see
1289 // if the source can supply those objects. In those cases, we should
1290 // just return OBJECT_NOT_AVAILABLE so it can revert to the factory
1291 // algorithm. We use the "own_objects" flag here to test if we have
1292 // already copied the low-level objects to the factories and so
1293 // should return right away.
1294 ObjList *objs_ptr = (ObjList*)event.GetRef();
1295 if(!objs_ptr)return RESOURCE_UNAVAILABLE;
1296 if(!objs_ptr->own_objects) return OBJECT_NOT_AVAILABLE; // if objects were already copied ...
1297
1298 // If any translation tables exist, we will use them at the end of this
1299 // method. However, the TTab plugin has an option to specify parsing of
1300 // only certain detector systems. It does this by copying values into
1301 // this JEventSource_EVIO object via the AddROCIDtoParseList method
1302 // while in the brun method. The brun method won't get called until
1303 // we ask for the DTranslationTable objects, thus, we must ask for them
1304 // here, prior to calling ParseEvents.
1305 // Note that we have to use the GetFromFactory() method here since
1306 // if we just use Get() or GetSingle(), it will call us (the event
1307 // source) again in an infinite loop!
1308 // Also note that we use static_cast here instead of dynamic_cast
1309 // since the latter requires that the type_info structure for
1310 // the DTranslationTable_factory be present. It is not in this
1311 // plugin (it is in the TTab plugin). Thus, with dynamic_cast there
1312 // is an unresolved symbol error if the TTab plugin is not also
1313 // present. (Make sense?)
1314 vector<const DTranslationTable*> translationTables;
1315 JEventLoop *loop = event.GetJEventLoop();
1316 DTranslationTable_factory *ttfac = static_cast<DTranslationTable_factory*>(loop->GetFactory("DTranslationTable"));
1317 if(ttfac) ttfac->Get(translationTables);
1318
1319 // We use a deferred parsing scheme for efficiency. If the event
1320 // is not flagged as having already been parsed, then parse it
1321 // now, creating objects for one or more events. The first event's
1322 // parameters will be copied into our ObjList object and any additional
1323 // ones stored in the stored_events queue.
1324 if(!objs_ptr->eviobuff_parsed) ParseEvents(objs_ptr);
1325
1326 // Get name of class which is actually being requested by caller
1327 string dataClassName = (factory==NULL__null ? "N/A":factory->GetDataClassName());
1328
1329 // Make list of data(hit) types we have. Keep list of
1330 // pointers to hit objects of each type
1331 map<string, vector<JObject*> > hit_objs_by_type;
1332 vector<DDAQAddress*> &hit_objs = objs_ptr->hit_objs;
1333 for(unsigned int i=0; i<hit_objs.size(); i++){
1334 JObject *hit_obj = hit_objs[i];
1335 hit_objs_by_type[hit_obj->className()].push_back(hit_obj);
1336 }
1337
1338 // Make list of config objects of each type
1339 map<string, vector<JObject*> > config_objs_by_type;
1340 vector<DDAQConfig*> &config_objs = objs_ptr->config_objs;
1341 for(unsigned int i=0; i<config_objs.size(); i++){
1342 JObject *config_obj = config_objs[i];
1343 config_objs_by_type[config_obj->className()].push_back(config_obj);
1344 }
1345
1346 // Make list of misc objects of each type
1347 map<string, vector<JObject*> > misc_objs_by_type;
1348 vector<JObject*> &misc_objs = objs_ptr->misc_objs;
1349 for(unsigned int i=0; i<misc_objs.size(); i++){
1350 JObject *jobj = misc_objs[i];
1351 misc_objs_by_type[jobj->className()].push_back(jobj);
1352 }
1353
1354 // Associate any DDAQConfig objects with hit objects to which they should apply.
1355 // If the objects are emulated, we will add this association later.
1356 for(unsigned int j=0; j<config_objs.size(); j++){
1357 DDAQConfig *config = config_objs[j];
1358 for(unsigned int i=0; i<hit_objs.size(); i++){
1359 DDAQAddress *hit = hit_objs[i];
1360 if(hit->rocid != config->rocid) continue;
1361 if( (1<<hit->slot) & config->slot_mask){
1362 hit->AddAssociatedObject(config);
1363 }
1364 }
1365 }
1366
1367 // Copy pointers to BOR objects
1368 CopyBOR(loop, hit_objs_by_type);
1369
1370 // In order for the janadot plugin to properly display the callgraph, we need to
1371 // make entries for each of the object types that we generated from data in the file.
1372 // Actually, we need to do it for all of the data objects we supply, but if any objects
1373 // are emulated (e.g. Df250PulseIntegral) they need to be added differently so the correct
1374 // dependence is shown. The first step is to add entries for all of the hit objects we
1375 // actually did find in the file. Do that here.
1376 map<string, vector<JObject*> >::iterator hoiter;
1377 for(hoiter=hit_objs_by_type.begin(); hoiter!=hit_objs_by_type.end(); hoiter++){
1378 AddSourceObjectsToCallStack(loop, hoiter->first);
1379 }
1380
1381 // Get references to various objects
1382 vector<JObject*> &f250_wrd_objs = hit_objs_by_type["Df250WindowRawData"];
1383 vector<JObject*> &f250_pt_objs = hit_objs_by_type["Df250PulseTime"];
1384 vector<JObject*> &f250_pp_objs = hit_objs_by_type["Df250PulsePedestal"];
1385 vector<JObject*> &f250_pi_objs = hit_objs_by_type["Df250PulseIntegral"];
1386
1387 vector<JObject*> &f125_wrd_objs = hit_objs_by_type["Df125WindowRawData"];
1388 vector<JObject*> &f125_pt_objs = hit_objs_by_type["Df125PulseTime"];
1389 vector<JObject*> &f125_pp_objs = hit_objs_by_type["Df125PulsePedestal"];
1390 vector<JObject*> &f125_pi_objs = hit_objs_by_type["Df125PulseIntegral"];
1391 vector<JObject*> &f125_cp_objs = hit_objs_by_type["Df125CDCPulse"];
1392 vector<JObject*> &f125_fp_objs = hit_objs_by_type["Df125FDCPulse"];
1393
1394 // Firmware Emulation
1395
1396 if( F250_EMULATION_MODE != kEmulationNone ){
1397 EmulateDf250Firmware(event, f250_wrd_objs, f250_pt_objs, f250_pp_objs, f250_pi_objs);
1398 }
1399 // Repeat for f125
1400 if( F125_EMULATION_MODE != kEmulationNone ){
1401 EmulateDf125Firmware(event, f125_wrd_objs, f125_cp_objs, f125_fp_objs);
1402 }
1403
1404 // Make PulseTime, PulsePedstal, and PulseIntegral objects associated objects of one another
1405 vector<Df250PulseIntegral*> f250_ppi_objs;
1406 vector<Df250PulseTime*> f250_ppt_objs;
1407 vector<Df250PulsePedestal*> f250_ppp_objs;
1408 CopyContainerElementsWithCast(f250_pi_objs, f250_ppi_objs);
1409 CopyContainerElementsWithCast(f250_pt_objs, f250_ppt_objs);
1410 CopyContainerElementsWithCast(f250_pp_objs, f250_ppp_objs);
1411 LinkAssociationsWithPulseNumber(f250_ppt_objs, f250_ppi_objs);
1412 LinkAssociationsWithPulseNumber(f250_ppp_objs, f250_ppi_objs);
1413 LinkAssociationsWithPulseNumber(f250_ppp_objs, f250_ppt_objs);
1414
1415 vector<Df125WindowRawData*> f125_pwrd_objs;
1416 vector<Df125PulseIntegral*> f125_ppi_objs;
1417 vector<Df125PulseTime*> f125_ppt_objs;
1418 vector<Df125PulsePedestal*> f125_ppp_objs;
1419 vector<Df125CDCPulse*> f125_pcp_objs;
1420 vector<Df125FDCPulse*> f125_pfp_objs;
1421 CopyContainerElementsWithCast(f125_wrd_objs, f125_pwrd_objs);
1422 CopyContainerElementsWithCast(f125_pi_objs, f125_ppi_objs);
1423 CopyContainerElementsWithCast(f125_pt_objs, f125_ppt_objs);
1424 CopyContainerElementsWithCast(f125_pp_objs, f125_ppp_objs);
1425 CopyContainerElementsWithCast(f125_cp_objs, f125_pcp_objs);
1426 CopyContainerElementsWithCast(f125_fp_objs, f125_pfp_objs);
1427 LinkAssociationsWithPulseNumber(f125_ppt_objs, f125_ppi_objs);
1428 LinkAssociationsWithPulseNumber(f125_ppp_objs, f125_ppi_objs);
1429 LinkAssociationsWithPulseNumber(f125_ppp_objs, f125_ppt_objs);
1430 LinkAssociations(f125_pcp_objs, f125_pwrd_objs);
1431 LinkAssociations(f125_pfp_objs, f125_pwrd_objs);
1432
1433 // Add data objects to call stack for the classes we can provide, but for which
1434 // there are no objects for this event. Again, this is so janadot will display things
1435 // properly.
1436 set<string>::iterator siter;
1437 for(siter=event_source_data_types.begin(); siter!=event_source_data_types.end(); siter++){
1438 if(hit_objs_by_type.find(*siter) == hit_objs_by_type.end()){
1439 AddSourceObjectsToCallStack(loop, *siter);
1440 }
1441 }
1442
1443 // The f125 firmware used for the 2014 and Spring 2015 commissioning
1444 // data was hardwired to report pedestals that were an average of
1445 // 4 samples. Since only the average was reported, the number of
1446 // samples used for this data was always "1". For the firmware
1447 // implemented in late 2015, configuration parameters were introduced
1448 // to allow a different number of samples to be used for the pedestal
1449 // and a different divisor as well. Here, we need to replace the
1450 // nsamples field of the PulsePedestal objects (which should be set to
1451 // a default value of "1") with values determined by the config.
1452 // parameters. We use the value NPED which should be calculated in
1453 // the coda_config code on the ROCs when the data was taken.
1454 vector<JObject*> &vpp125 = hit_objs_by_type["Df125PulsePedestal"];
1455 for(unsigned int i=0; i<vpp125.size(); i++){
1456 Df125PulsePedestal *pp = (Df125PulsePedestal*)vpp125[i];
1457 if(!pp->emulated){
1458 const Df125Config*conf = NULL__null;
1459 pp->GetSingle(conf);
1460 if(conf!=NULL__null){
1461 if(conf->NPED != 0xFFFF){
1462 pp->nsamples = conf->NPED;
1463 }
1464 }
1465 }
1466 }
1467
1468 // Initially, the F250, F125 firmware does not include the
1469 // pedestal measurement in the pulse integral data
1470 // (it is an add-on Pulse Pedestal word) We want the
1471 // pedestal field of the Df250PulseIntegral objects
1472 // to contain the measured pedestals in both cases.
1473 // Check all Df250PulseIntegral objects for an associated
1474 // Df250PulsePedestal object. If it has one, copy the
1475 // pedestal from it into the Df250PulseIntegral.
1476 vector<JObject*> &vpi250 = hit_objs_by_type["Df250PulseIntegral"];
1477 for(unsigned int i=0; i<vpi250.size(); i++){
1478
1479 Df250PulseIntegral *pi = (Df250PulseIntegral*)vpi250[i];
1480 const Df250Config*conf = NULL__null;
1481 const Df250BORConfig*BORconf = NULL__null;
1482 const Df250PulsePedestal*pp = NULL__null;
1483 pi->GetSingle(conf);
1484 pi->GetSingle(BORconf);
1485 pi->GetSingle(pp);
1486
1487 // If a Df250PulsePedestal object is associated with this
1488 // then copy its pedestal into the pedestal member of this
1489 // pulse integral object. Furthermore, if the pedestal is
1490 // *not* emulated and we have a configuration parameter from
1491 // the datastream for the number of samples the pedestal
1492 // represents, then copy this into the nsamples_pedestal.
1493 if(pp){
1494 pi->pedestal = pp->pedestal;
1495 if(!pp->emulated){
1496 if(conf!=NULL__null){
1497 if(conf->NPED != 0xFFFF){
1498 pi->nsamples_pedestal = conf->NPED;
1499 }
1500 }
1501 }
1502 }
1503
1504 // If this pulse integral is *not* emulated AND there is
1505 // a configuration object from the data stream associated,
1506 // then copy the number of samples for the integral from it.
1507 if(!pi->emulated){
1508 if (BORconf!=NULL__null){
1509 uint16_t NSB = BORconf->adc_nsb & 0x7F;
1510 uint16_t NSA = BORconf->adc_nsa & 0x7F;
1511 pi->nsamples_integral = NSB + NSA;
1512 }
1513 else if(conf){
1514 pi->nsamples_integral = conf->NSA_NSB;
1515 }
1516 }
1517 }
1518 vector<JObject*> &vpi125 = hit_objs_by_type["Df125PulseIntegral"];
1519 for(unsigned int i=0; i<vpi125.size(); i++){
1520
1521 Df125PulseIntegral *pi = (Df125PulseIntegral*)vpi125[i];
1522 const Df125Config*conf = NULL__null;
1523 const Df125PulsePedestal*pp = NULL__null;
1524 pi->GetSingle(conf);
1525 pi->GetSingle(pp);
1526
1527 // If a Df125PulsePedestal object is associated with this
1528 // then copy its pedestal into the pedestal member of this
1529 // pulse integral object. Furthermore, if the pedestal is
1530 // *not* emulated then copy the number of pedestal samples.
1531 // (n.b. the value of nsamples should have been set based
1532 // on the configuration parameter in a separate loop over
1533 // Df125PulsePedestal objects above.)
1534 if(pp){
1535 pi->pedestal = pp->pedestal;
1536 if(!pp->emulated) pi->nsamples_pedestal = pp->nsamples;
1537 }
1538
1539 // If this pulse integral is *not* emulated AND there is
1540 // a configuration object from the data stream associated,
1541 // then copy the number of samples for the integral from it.
1542 if(!pi->emulated){
1543 if(conf){
1544 pi->nsamples_integral = conf->NSA_NSB;
1545 }
1546 }
1547 }
1548 vector<JObject*> &vcdcp125 = hit_objs_by_type["Df125CDCPulse"];
1549 for(unsigned int i=0; i<vcdcp125.size(); i++){
1550
1551 Df125CDCPulse *cdcp = (Df125CDCPulse*)vcdcp125[i];
1552 const Df125Config*conf = NULL__null;
1553 cdcp->GetSingle(conf);
1554
1555 // If this CDCpulse is *not* emulated AND there is
1556 // a configuration object from the data stream associated,
1557 // then copy the number of samples for the integral from it.
1558 if(!cdcp->emulated){
1559 if(conf){
1560
1561 int timesample = (int)cdcp->le_time/10;
1562 int END = ( (timesample + conf->IE) > (conf->NW - 20) ) ? (conf->NW - 20) : (timesample + conf->IE) ;
1563 int nsamp = END - timesample;
1564 if (nsamp>0){
1565 cdcp->nsamples_integral = nsamp;
1566 } else {
1567 cdcp->nsamples_integral = 0; //integral is 0 if timesample >= NW-20
1568 }
1569
1570 }
1571 }
1572 }
1573
1574 vector<JObject*> &vfdcp125 = hit_objs_by_type["Df125FDCPulse"];
1575 for(unsigned int i=0; i<vfdcp125.size(); i++){
1576
1577 Df125FDCPulse *fdcp = (Df125FDCPulse*)vfdcp125[i];
1578 const Df125Config*conf = NULL__null;
1579 fdcp->GetSingle(conf);
1580
1581 // If this FDCpulse is *not* emulated AND there is
1582 // a configuration object from the data stream associated,
1583 // then copy the number of samples for the integral from it.
1584 if(!fdcp->emulated){
1585 if(conf){
1586
1587 int timesample = (int)fdcp->le_time/10;
1588 int END = ( (timesample + conf->IE) > (conf->NW - 20) ) ? (conf->NW - 20) : (timesample + conf->IE) ;
1589 int nsamp = END - timesample;
1590
1591 if (nsamp>0){
1592 fdcp->nsamples_integral = nsamp;
1593 } else {
1594 fdcp->nsamples_integral = 0; //integral is 0 if timesample >= NW-20
1595 }
1596
1597 }
1598 }
1599 }
1600
1601 // Loop over types of config objects, copying to appropriate factory
1602 map<string, vector<JObject*> >::iterator config_iter = config_objs_by_type.begin();
1603 for(; config_iter!=config_objs_by_type.end(); config_iter++){
1604 JFactory_base *fac = loop->GetFactory(config_iter->first, "", false); // false= don't allow default tag replacement
1605 if(fac) fac->CopyTo(config_iter->second);
1606 }
1607
1608 // Loop over types of hit objects, copying to appropriate factory
1609 map<string, vector<JObject*> >::iterator iter = hit_objs_by_type.begin();
1610 for(; iter!=hit_objs_by_type.end(); iter++){
1611 JFactory_base *fac = loop->GetFactory(iter->first, "", false); // false= don't allow default tag replacement
1612 fac->CopyTo(iter->second);
1613 }
1614
1615 // Loop over types of misc objects, copying to appropriate factory
1616 map<string, vector<JObject*> >::iterator misc_iter = misc_objs_by_type.begin();
1617 for(; misc_iter!=misc_objs_by_type.end(); misc_iter++){
1618 JFactory_base *fac = loop->GetFactory(misc_iter->first, "", false); // false= don't allow default tag replacement
1619 fac->CopyTo(misc_iter->second);
1620 }
1621 objs_ptr->own_objects = false;
1622
1623 // Copy pointers to BOR objects
1624 //CopyBOR(loop, hit_objs_by_type);
1625
1626 // Returning OBJECT_NOT_AVAILABLE tells JANA that this source cannot
1627 // provide the type of object requested and it should try and generate
1628 // it via a factory algorithm. Returning NOERROR on the other hand
1629 // tells JANA that we can provide this type of object and any that
1630 // are present have already been copied into the appropriate factory.
1631 jerror_t err = OBJECT_NOT_AVAILABLE;
1632 if(strlen(factory->Tag()) == 0){ // We do not supply any tagged factory data here
1633 if(event_source_data_types.find(dataClassName) != event_source_data_types.end()) err = NOERROR;
1634 }
1635
1636 // If it turns out there are no objects of one of the types we supply
1637 // then the CopyTo method for that factory never gets called and subsequent
1638 // requests for that object type will end up calling this method again.
1639 // (For the case when this is done from the ApplyTranslationTable call
1640 // below, it results in an infinite loop!). To prevent this, we need to
1641 // mark all factories of the data types we supply as having had their
1642 // evnt method called.
1643 set<string>::iterator dtiter = event_source_data_types.begin();
1644 for(; dtiter!=event_source_data_types.end(); dtiter++){
1645 JFactory_base *fac = loop->GetFactory(*dtiter);
1646 if(fac) {
1647 // The DAQ_WRD2PI plugin wants to generate some objects from
1648 // the waveform data, overiding anything found in the file.
1649 // It this case, the factory's use_factory flag is set and
1650 // we should NOT mark the factory as having it's event method
1651 // called. Furthermore, we should delete any objects in the
1652 // factory.
1653 // Now, another complication is that the only way to check
1654 // the use_factory flag is to have a pointer to the JFactory
1655 // not the JFactory_base. This means we have to check the data
1656 // type of the factory and make the appropriate cast
1657 string dataClassName = fac->GetDataClassName();
1658 int checkSourceFirst = 1;
1659 if( dataClassName == "Df250Config") checkSourceFirst = ((JFactory<Df250Config >*)fac)->GetCheckSourceFirst();
1660 else if(dataClassName == "Df250PulseIntegral") checkSourceFirst = ((JFactory<Df250PulseIntegral >*)fac)->GetCheckSourceFirst();
1661 else if(dataClassName == "Df250StreamingRawData") checkSourceFirst = ((JFactory<Df250StreamingRawData>*)fac)->GetCheckSourceFirst();
1662 else if(dataClassName == "Df250WindowSum") checkSourceFirst = ((JFactory<Df250WindowSum >*)fac)->GetCheckSourceFirst();
1663 else if(dataClassName == "Df250PulseRawData") checkSourceFirst = ((JFactory<Df250PulseRawData >*)fac)->GetCheckSourceFirst();
1664 else if(dataClassName == "Df250TriggerTime") checkSourceFirst = ((JFactory<Df250TriggerTime >*)fac)->GetCheckSourceFirst();
1665 else if(dataClassName == "Df250PulseTime") checkSourceFirst = ((JFactory<Df250PulseTime >*)fac)->GetCheckSourceFirst();
1666 else if(dataClassName == "Df250PulsePedestal") checkSourceFirst = ((JFactory<Df250PulsePedestal >*)fac)->GetCheckSourceFirst();
1667 else if(dataClassName == "Df250WindowRawData") checkSourceFirst = ((JFactory<Df250WindowRawData >*)fac)->GetCheckSourceFirst();
1668 else if(dataClassName == "Df125Config") checkSourceFirst = ((JFactory<Df125Config >*)fac)->GetCheckSourceFirst();
1669 else if(dataClassName == "Df125PulseIntegral") checkSourceFirst = ((JFactory<Df125PulseIntegral >*)fac)->GetCheckSourceFirst();
1670 else if(dataClassName == "Df125TriggerTime") checkSourceFirst = ((JFactory<Df125TriggerTime >*)fac)->GetCheckSourceFirst();
1671 else if(dataClassName == "Df125PulseTime") checkSourceFirst = ((JFactory<Df125PulseTime >*)fac)->GetCheckSourceFirst();
1672 else if(dataClassName == "Df125PulsePedestal") checkSourceFirst = ((JFactory<Df125PulsePedestal >*)fac)->GetCheckSourceFirst();
1673 else if(dataClassName == "Df125WindowRawData") checkSourceFirst = ((JFactory<Df125WindowRawData >*)fac)->GetCheckSourceFirst();
1674 else if(dataClassName == "Df125CDCPulse") checkSourceFirst = ((JFactory<Df125CDCPulse >*)fac)->GetCheckSourceFirst();
1675 else if(dataClassName == "Df125FDCPulse") checkSourceFirst = ((JFactory<Df125FDCPulse >*)fac)->GetCheckSourceFirst();
1676 else if(dataClassName == "DF1TDCConfig") checkSourceFirst = ((JFactory<DF1TDCConfig >*)fac)->GetCheckSourceFirst();
1677 else if(dataClassName == "DF1TDCHit") checkSourceFirst = ((JFactory<DF1TDCHit >*)fac)->GetCheckSourceFirst();
1678 else if(dataClassName == "DF1TDCTriggerTime") checkSourceFirst = ((JFactory<DF1TDCTriggerTime >*)fac)->GetCheckSourceFirst();
1679 else if(dataClassName == "DCAEN1290TDCConfig") checkSourceFirst = ((JFactory<DCAEN1290TDCConfig >*)fac)->GetCheckSourceFirst();
1680 else if(dataClassName == "DCAEN1290TDCHit") checkSourceFirst = ((JFactory<DCAEN1290TDCHit >*)fac)->GetCheckSourceFirst();
1681 else if(dataClassName == "DCODAEventInfo") checkSourceFirst = ((JFactory<DCODAEventInfo >*)fac)->GetCheckSourceFirst();
1682 else if(dataClassName == "DCODAROCInfo") checkSourceFirst = ((JFactory<DCODAROCInfo >*)fac)->GetCheckSourceFirst();
1683 else if(dataClassName == "DTSscalers") checkSourceFirst = ((JFactory<DTSscalers >*)fac)->GetCheckSourceFirst();
1684 else if(dataClassName == "Df250BORConfig") checkSourceFirst = ((JFactory<Df250BORConfig >*)fac)->GetCheckSourceFirst();
1685 else if(dataClassName == "Df125BORConfig") checkSourceFirst = ((JFactory<Df125BORConfig >*)fac)->GetCheckSourceFirst();
1686 else if(dataClassName == "DF1TDCBORConfig") checkSourceFirst = ((JFactory<DF1TDCBORConfig >*)fac)->GetCheckSourceFirst();
1687 else if(dataClassName == "DCAEN1290TDCBORConfig") checkSourceFirst = ((JFactory<DCAEN1290TDCBORConfig>*)fac)->GetCheckSourceFirst();
1688
1689 if(checkSourceFirst) {
1690 fac->Set_evnt_called();
1691 }else{
1692 // Factory wants to generate these so delete any read
1693 // from source.
1694 fac->Reset();
1695 }
1696 }
1697 }
1698
1699 // If a translation table object is available, use it to create
1700 // detector hits from the low-level DAQ objects we just created.
1701 for(unsigned int i=0; i<translationTables.size(); i++){
1702 translationTables[i]->ApplyTranslationTable(loop);
1703 if(translationTables[i]->IsSuppliedType(dataClassName))
1704 if(strlen(factory->Tag()) == 0)err = NOERROR; // Don't allow tagged factories from Translation table
1705 }
1706
1707 if(VERBOSE>2) evioout << " Leaving GetObjects()" << endl;
1708
1709 return err;
1710}
1711
1712//----------------
1713// CopyBOR
1714//----------------
1715void JEventSource_EVIO::CopyBOR(JEventLoop *loop, map<string, vector<JObject*> > &hit_objs_by_type)
1716{
1717 /// Copy pointers to BOR (Beginning Of Run) objects into the
1718 /// appropriate factories for this event. The objects are flagged
1719 /// so that the factories won't delete them and the objects
1720 /// may be reused on subsequent events.
1721
1722 pthread_rwlock_rdlock(&BOR_lock);
1723
1724 // Make list of BOR objects of each type
1725 map<string, vector<JObject*> > bor_objs_by_type;
1726 for(unsigned int i=0; i<BORobjs.size(); i++){
1727 JObject *jobj = BORobjs[i];
1728 bor_objs_by_type[jobj->className()].push_back(jobj);
1729 }
1730
1731 // Loop over types of BOR objects, copying to appropriate factory
1732 map<string, vector<JObject*> >::iterator iter = bor_objs_by_type.begin();
1733 for(; iter!=bor_objs_by_type.end(); iter++){
1734 const string &bor_obj_name = iter->first;
1735 vector<JObject*> &bors = iter->second;
1736 JFactory_base *fac = loop->GetFactory(bor_obj_name, "", false); // false= don't allow default tag replacement
1737 if(fac){
1738 fac->CopyTo(bors);
1739 fac->SetFactoryFlag(JFactory_base::NOT_OBJECT_OWNER);
1740 }
1741
1742 // Associate with hit objects from this type of module
1743 if(bor_obj_name == "Df250BORConfig"){
1744 LinkAssociationsModuleOnlyWithCast<Df250BORConfig,Df250PulseIntegral>(bors, hit_objs_by_type["Df250PulseIntegral"]);
1745 LinkAssociationsModuleOnlyWithCast<Df250BORConfig,Df250PulsePedestal>(bors, hit_objs_by_type["Df250PulsePedestal"]);
1746 LinkAssociationsModuleOnlyWithCast<Df250BORConfig,Df250PulseTime>(bors, hit_objs_by_type["Df250PulseTime"]);
1747 LinkAssociationsModuleOnlyWithCast<Df250BORConfig,Df250WindowRawData>(bors, hit_objs_by_type["Df250WindowRawData"]);
1748 }
1749 if(bor_obj_name == "Df125BORConfig"){
1750 LinkAssociationsModuleOnlyWithCast<Df125BORConfig,Df125CDCPulse>(bors, hit_objs_by_type["Df125CDCPulse"]);
1751 LinkAssociationsModuleOnlyWithCast<Df125BORConfig,Df125FDCPulse>(bors, hit_objs_by_type["Df125FDCPulse"]);
1752 LinkAssociationsModuleOnlyWithCast<Df125BORConfig,Df125PulseIntegral>(bors, hit_objs_by_type["Df125PulseIntegral"]);
1753 LinkAssociationsModuleOnlyWithCast<Df125BORConfig,Df125PulsePedestal>(bors, hit_objs_by_type["Df125PulsePedestal"]);
1754 LinkAssociationsModuleOnlyWithCast<Df125BORConfig,Df125PulseTime>(bors, hit_objs_by_type["Df125PulseTime"]);
1755 LinkAssociationsModuleOnlyWithCast<Df125BORConfig,Df125WindowRawData>(bors, hit_objs_by_type["Df125WindowRawData"]);
1756 }
1757 if(bor_obj_name == "DF1TDCBORConfig"){
1758 LinkAssociationsModuleOnlyWithCast<DF1TDCBORConfig,Df250PulseIntegral>(bors, hit_objs_by_type["DF1TDCHit"]);
1759 }
1760 if(bor_obj_name == "DCAEN1290TDCBORConfig"){
1761 LinkAssociationsModuleOnlyWithCast<DCAEN1290TDCBORConfig,Df250PulseIntegral>(bors, hit_objs_by_type["DCAEN1290TDCHit"]);
1762 }
1763 }
1764
1765 pthread_rwlock_unlock(&BOR_lock);
1766}
1767
1768//----------------
1769// AddSourceObjectsToCallStack
1770//----------------
1771void JEventSource_EVIO::AddSourceObjectsToCallStack(JEventLoop *loop, string className)
1772{
1773 /// This is used to give information to JANA regarding the origin of objects
1774 /// that *should* come from the source. We add them in explicitly because
1775 /// the file may not have any, but factories may ask for them. We want those
1776 /// links to indicate that the "0" objects in the factory came from the source
1777 /// so that janadot draws these objects correctly.
1778
1779 JEventLoop::call_stack_t cs;
1780 cs.caller_name = "<ignore>"; // tells janadot this object wasn't actually requested by anybody
1781 cs.caller_tag = "";
1782 cs.callee_name = className;
1783 cs.callee_tag = "";
1784 cs.start_time = 0.0;
1785 cs.end_time = 0.0;
1786 cs.data_source = JEventLoop::DATA_FROM_SOURCE;
1787 loop->AddToCallStack(cs);
1788}
1789
1790//----------------
1791// AddEmulatedObjectsToCallStack
1792//----------------
1793void JEventSource_EVIO::AddEmulatedObjectsToCallStack(JEventLoop *loop, string caller, string callee)
1794{
1795 /// This is used to give information to JANA regarding the relationship and
1796 /// origin of some of these data objects. This is really just needed so that
1797 /// the janadot program can be used to produce the correct callgraph. Because
1798 /// of how this plugin works, JANA can't record the correct call stack (at
1799 /// least not easily!) Therefore, we have to give it a little help here.
1800
1801 JEventLoop::call_stack_t cs;
1802 cs.caller_name = caller;
1803 cs.callee_name = callee;
1804 cs.data_source = JEventLoop::DATA_FROM_SOURCE;
1805 loop->AddToCallStack(cs);
1806 cs.callee_name = cs.caller_name;
1807 cs.caller_name = "<ignore>";
1808 cs.data_source = JEventLoop::DATA_FROM_FACTORY;
1809 loop->AddToCallStack(cs);
1810}
1811
1812//----------------
1813// EmulateDf250Firmware
1814//----------------
1815void JEventSource_EVIO::EmulateDf250Firmware(JEvent &event, vector<JObject*> &wrd_objs, vector<JObject*> &pt_objs, vector<JObject*> &pp_objs, vector<JObject*> &pi_objs)
1816{
1817 // Cant emulate without the raw data
1818 if(wrd_objs.size() == 0) return;
1819 if(VERBOSE>3) evioout << " Entering EmulateDf250Firmware ..." <<endl;
1820
1821 vector <const Df250EmulatorAlgorithm*> f250Emulator_const;
1822 Df250EmulatorAlgorithm *f250Emulator = NULL__null;
1823 JEventLoop *loop = event.GetJEventLoop();
1824 Df250EmulatorAlgorithm_factory *f250EmFac = static_cast<Df250EmulatorAlgorithm_factory*>(loop->GetFactory("Df250EmulatorAlgorithm"));
1825 if (f250EmFac) {
1826 f250EmFac->Get(f250Emulator_const);
1827 // Drop const
1828 if (f250Emulator_const.size() != 0) f250Emulator = const_cast<Df250EmulatorAlgorithm*>(f250Emulator_const[0]);
1829 }
1830
1831 if(VERBOSE>3) evioout << " Looping over raw data ..." <<endl;
1832 // Loop over all window raw data objects
1833 for(unsigned int i=0; i<wrd_objs.size(); i++){
1834 const Df250WindowRawData *f250WindowRawData = (Df250WindowRawData*)wrd_objs[i];
1835 Df250PulseTime *f250PulseTime = NULL__null;
1836 Df250PulsePedestal *f250PulsePedestal = NULL__null;
1837 Df250PulseIntegral *f250PulseIntegral = NULL__null;
1838
1839 // When raw data exists, we will always do the emulation
1840 // Grab the existing Pulse data, up to three of each type
1841 // for each WindowRawData object.
1842 for(uint32_t j=0; j<pt_objs.size(); j++){
1843 Df250PulseTime *pt = (Df250PulseTime*)pt_objs[j];
1844 if(pt->rocid == f250WindowRawData->rocid){
1845 if(pt->slot == f250WindowRawData->slot){
1846 if(pt->channel == f250WindowRawData->channel){
1847 f250PulseTime = pt;
1848 f250PulseTime->AddAssociatedObject(f250WindowRawData);
1849 if(pt->emulated){
1850 jerr << "Emulating channel that already has emulated objects!" << endl;
1851 jerr << "This likely means there is a bug in JEventSource_EVIO.cc" <<endl;
1852 jerr << "PulseTime: rocid="<<pt->rocid<<" slot="<<pt->slot<<" channel="<<pt->channel<<endl;
1853 jerr << "please report error to davidl@jlab.org" << endl;
1854 exit(-1);
1855 }
1856 }
1857 }
1858 }
1859 }
1860
1861 // Ditto for pulse pedestal objects
1862 for(uint32_t j=0; j<pp_objs.size(); j++){
1863 Df250PulsePedestal *pp = (Df250PulsePedestal*)pp_objs[j];
1864 if(pp->rocid == f250WindowRawData->rocid){
1865 if(pp->slot == f250WindowRawData->slot){
1866 if(pp->channel == f250WindowRawData->channel){
1867 f250PulsePedestal = pp;
1868 f250PulsePedestal->AddAssociatedObject(f250WindowRawData);
1869 if(pp->emulated){
1870 jerr << "Emulating channel that already has emulated objects!" << endl;
1871 jerr << "This likely means there is a bug in JEventSource_EVIO.cc" <<endl;
1872 jerr << "PulsePedestal: rocid="<<pp->rocid<<" slot="<<pp->slot<<" channel="<<pp->channel<<endl;
1873 jerr << "please report error to davidl@jlab.org" << endl;
1874 exit(-1);
1875 }
1876 }
1877 }
1878 }
1879 }
1880
1881 // Ditto for pulse integral objects
1882 for(uint32_t j=0; j<pi_objs.size(); j++){
1883 Df250PulseIntegral *pi = (Df250PulseIntegral*)pi_objs[j];
1884 if(pi->rocid == f250WindowRawData->rocid){
1885 if(pi->slot == f250WindowRawData->slot){
1886 if(pi->channel == f250WindowRawData->channel){
1887 f250PulseIntegral = pi;
1888 f250PulseIntegral->AddAssociatedObject(f250WindowRawData);
1889 if(pi->emulated){
1890 jerr << "Emulating channel that already has emulated objects!" << endl;
1891 jerr << "This likely means there is a bug in JEventSource_EVIO.cc" <<endl;
1892 jerr << "PulseIntegral: rocid="<<pi->rocid<<" slot="<<pi->slot<<" channel="<<pi->channel<<endl;
1893 jerr << "please report error to davidl@jlab.org" << endl;
1894 exit(-1);
1895 }
1896 }
1897 }
1898 }
1899 }
1900
1901 // Emulate firmware
1902 uint32_t pt_emulated = pt_objs.size();
1903 uint32_t pp_emulated = pp_objs.size();
1904 uint32_t pi_emulated = pi_objs.size();
1905 if(VERBOSE>3) evioout << " Calling EmulateFirmware ..." << endl;
1906 f250Emulator->EmulateFirmware(f250WindowRawData, pt_objs, pp_objs, pi_objs);
1907
1908 // Find all new objects generated by emulation and match with hw originals, if any
1909 uint32_t pt_hardware = 0;
1910 for (uint32_t i = pt_emulated; i < pt_objs.size(); i++) {
1911 const Df250WindowRawData *rd;
1912 Df250PulseTime *pt_em = dynamic_cast<Df250PulseTime*>(pt_objs[i]);
1913 pt_em->GetSingle(rd);
1914 if (rd != f250WindowRawData) {
1915 jerr << "Emulated object found that does not belong to WindowRawData object!" << endl;
1916 jerr << "This likely means there is a bug in JEventSource_EVIO.cc PulseTime emulation." << endl;
1917 jerr << "rocid=" << pt_em->rocid << " slot=" << pt_em->slot << " channel=" << pt_em->channel << endl;
1918 jerr << "Please report error to davidl@jlab.org" << endl;
1919 exit(-1);
1920 }
1921 for (uint32_t j = pt_hardware; j < pt_emulated; j++) {
1922 Df250PulseTime *pt_hw = dynamic_cast<Df250PulseTime*>(pt_objs[j]);
1923 pt_hw->GetSingle(rd);
1924 if (rd == f250WindowRawData && pt_hw->pulse_number == pt_em->pulse_number) {
1925 pt_hardware = j + 1;
1926 if (F250_EMULATION_MODE == kEmulationAlways) {
1927 *pt_hw = *pt_em;
1928 }
1929 else {
1930 pt_hw->time_emulated = pt_em->time_emulated;
1931 pt_hw->quality_factor_emulated = pt_em->quality_factor_emulated;
1932 }
1933 if ((VERBOSE > 0 && pt_hw->time != pt_hw->time_emulated) || VERBOSE > 3) {
1934 // implement special exceptions for early pulse times in mode 8 data
1935 if (VERBOSE > 3 || !(pt_hw->time == 0 &&
1936 (pt_hw->time_emulated == 64 || pt_hw->time_emulated == 128 ||
1937 pt_hw->time_emulated == 192 || pt_hw->time_emulated == 256)) )
1938 {
1939 jout << " comparing f250 hw and emulation pulse times for ROC/slot/chan "
1940 << pt_hw->rocid << "/" << pt_hw->slot << "/" << pt_hw->channel << ": "
1941 << pt_hw->time << " vs " << pt_hw->time_emulated << endl;
1942 }
1943 }
1944 pt_objs.erase(pt_objs.begin() + i);
1945 delete pt_em;
1946 pt_em = 0;
1947 --i;
1948 break;
1949 }
1950 }
1951 if (pt_em != 0 && VERBOSE > 3) {
1952 jout << " new f250 emulation PulseTime generated for ROC/slot/chan "
1953 << pt_em->rocid << "/" << pt_em->slot << "/" << pt_em->channel << ": "
1954 << "pulse " << pt_em->pulse_number << ", time " << pt_em->time << endl;
1955 }
1956 }
1957
1958 uint32_t pp_hardware = 0;
1959 for (uint32_t i = pp_emulated; i < pp_objs.size(); i++) {
1960 Df250PulsePedestal *pp_em = dynamic_cast<Df250PulsePedestal*>(pp_objs[i]);
1961 const Df250WindowRawData *rd;
1962 pp_em->GetSingle(rd);
1963 if (rd != f250WindowRawData) {
1964 jerr << "Emulated object found that does not belong to WindowRawData object!" << endl;
1965 jerr << "This likely means there is a bug in JEventSource_EVIO.cc PulsePedestal emulation." << endl;
1966 jerr << "rocid=" << pp_em->rocid << " slot=" << pp_em->slot << " channel=" << pp_em->channel << endl;
1967 jerr << "Please report error to davidl@jlab.org" << endl;
1968 exit(-1);
1969 }
1970 for (uint32_t j=pp_hardware; j < pp_emulated; j++) {
1971 Df250PulsePedestal *pp_hw = dynamic_cast<Df250PulsePedestal*>(pp_objs[j]);
1972 pp_hw->GetSingle(rd);
1973 if (rd == f250WindowRawData && pp_hw->pulse_number == pp_em->pulse_number) {
1974 pp_hardware = j + 1;
1975 if (F250_EMULATION_MODE == kEmulationAlways) {
1976 *pp_hw = *pp_em;
1977 }
1978 else {
1979 pp_hw->pedestal_emulated = pp_em->pedestal_emulated;
1980 pp_hw->pulse_peak_emulated = pp_em->pulse_peak_emulated;
1981 }
1982 if ((VERBOSE > 0 && pp_hw->pulse_peak != pp_hw->pulse_peak_emulated) || VERBOSE > 3)
1983 jout << " comparing f250 hw and emulation pulse peaks for ROC/slot/chan "
1984 << pp_hw->rocid << "/" << pp_hw->slot << "/" << pp_hw->channel << ": "
1985 << pp_hw->pulse_peak << " vs " << pp_hw->pulse_peak_emulated << endl;
1986 pp_objs.erase(pp_objs.begin() + i);
1987 delete pp_em;
1988 pp_em = 0;
1989 --i;
1990 break;
1991 }
1992 }
1993 if (pp_em != 0 && VERBOSE > 3) {
1994 jout << " new f250 emulation PulsePedestal generated for ROC/slot/chan "
1995 << pp_em->rocid << "/" << pp_em->slot << "/" << pp_em->channel << ": "
1996 << "pulse " << pp_em->pulse_number << ", pedestal " << pp_em->pedestal
1997 << ", peak " << pp_em->pulse_peak << endl;
1998 }
1999 }
2000
2001 uint32_t pi_hardware = 0;
2002 for (uint32_t i = pi_emulated; i < pi_objs.size(); i++) {
2003 Df250PulseIntegral *pi_em = dynamic_cast<Df250PulseIntegral*>(pi_objs[i]);
2004 const Df250WindowRawData *rd;
2005 pi_em->GetSingle(rd);
2006 if (rd != f250WindowRawData) {
2007 jerr << "Emulated object found that does not belong to WindowRawData object!" << endl;
2008 jerr << "This likely means there is a bug in JEventSource_EVIO.cc PulseIntegral emulation." << endl;
2009 jerr << "rocid=" << pi_em->rocid << " slot=" << pi_em->slot << " channel=" << pi_em->channel << endl;
2010 jerr << "Please report error to davidl@jlab.org" << endl;
2011 exit(-1);
2012 }
2013 for (uint32_t j=pi_hardware; j < pi_emulated; j++) {
2014 Df250PulseIntegral *pi_hw = dynamic_cast<Df250PulseIntegral*>(pi_objs[j]);
2015 pi_hw->GetSingle(rd);
2016 if (rd == f250WindowRawData && pi_hw->pulse_number == pi_em->pulse_number) {
2017 pi_hardware = j + 1;
2018 if (F250_EMULATION_MODE == kEmulationAlways) {
2019 *pi_hw = *pi_em;
2020 }
2021 else {
2022 pi_hw->integral_emulated = pi_em->integral_emulated;
2023 pi_hw->pedestal_emulated = pi_em->pedestal_emulated;
2024 }
2025 if ((VERBOSE > 0 && pi_hw->integral != pi_hw->integral_emulated) || VERBOSE > 3)
2026 jout << " comparing f250 hw and emulation pulse integrals for ROC/slot/chan "
2027 << pi_hw->rocid << "/" << pi_hw->slot << "/" << pi_hw->channel << ": "
2028 << pi_hw->integral << " vs " << pi_hw->integral_emulated << endl;
2029 pi_objs.erase(pi_objs.begin() + i);
2030 delete pi_em;
2031 pi_em = 0;
2032 i--;
2033 break;
2034 }
2035 }
2036 if (pi_em != 0 && VERBOSE > 3) {
2037 jout << " new f250 emulation PulseIntegral generated for ROC/slot/chan "
2038 << pi_em->rocid << "/" << pi_em->slot << "/" << pi_em->channel << ": "
2039 << "pulse " << pi_em->pulse_number << ", integral " << pi_em->integral
2040 << ", pedestal " << pi_em->pedestal << endl;
2041 }
2042 }
2043 }
2044
2045 // PulseTime, PulsePedestal, PulseIntegral objects are associated to one another in GetObjects
2046 if(VERBOSE>3) evioout << " Leaving EmulateDf250Firmware" <<endl;
2047}
2048
2049//----------------
2050// EmulateDf125Firmware
2051//----------------
2052void JEventSource_EVIO::EmulateDf125Firmware( JEvent &event, vector<JObject*> &wrd_objs, vector<JObject*> &cp_objs, vector<JObject*> &fp_objs)
2053{
2054 /// This code implements an upsampling technique developed by Naomi Jarvis at
2055 /// CMU. This was not implemented in the firmware for the 2014-2015 commissioning
2056 /// run, but was implemented for later runs.
2057 ///
2058 /// Removed f250 style emulation of f125 firmware. Keep in mind if for some reason old
2059 /// mode 8 data is processed, it will return the new style words with 1/10
2060 /// sample resolution. It is doubtful anyone will be using these in the future so nbd. 3/18/2016 MS
2061
2062 if(wrd_objs.size() == 0) return; // Can't do anything without the raw data
1
Taking false branch
2063 if(VERBOSE>3) evioout << " Entering EmulateDf125Firmware ..." <<endl;
2
Taking false branch
2064
2065 vector <const Df125EmulatorAlgorithm*> f125Emulator_const;
2066 Df125EmulatorAlgorithm *f125Emulator = NULL__null;
3
'f125Emulator' initialized to a null pointer value
2067 JEventLoop *loop = event.GetJEventLoop();
2068 Df125EmulatorAlgorithm_factory *f125EmFac = static_cast<Df125EmulatorAlgorithm_factory*>(loop->GetFactory("Df125EmulatorAlgorithm"));
2069 if (f125EmFac) {
4
Assuming 'f125EmFac' is null
5
Taking false branch
2070 f125EmFac->Get(f125Emulator_const);
2071 // Drop const
2072 if (f125Emulator_const.size() != 0) f125Emulator = const_cast<Df125EmulatorAlgorithm*>(f125Emulator_const[0]);
2073 }
2074
2075 // Loop over all window raw data objects
2076 for(unsigned int i=0; i<wrd_objs.size(); i++){
6
Loop condition is true. Entering loop body
2077 const Df125WindowRawData *f125WindowRawData = (Df125WindowRawData*)wrd_objs[i];
2078 Df125CDCPulse *f125CDCPulse = NULL__null;
2079 Df125FDCPulse *f125FDCPulse = NULL__null;
2080
2081 //search for existing CDCPulse
2082 for(uint32_t j=0; j<cp_objs.size(); j++){
7
Loop condition is false. Execution continues on line 2096
2083 Df125CDCPulse *cp = (Df125CDCPulse*)cp_objs[j];
2084 if(cp->rocid == f125WindowRawData->rocid){
2085 if(cp->slot == f125WindowRawData->slot){
2086 if(cp->channel == f125WindowRawData->channel){
2087 f125CDCPulse = cp;
2088 f125CDCPulse->AddAssociatedObject(f125WindowRawData);
2089 break;
2090 }
2091 }
2092 }
2093 }
2094
2095 // search for existing FDCPulse
2096 for(uint32_t j=0; j<fp_objs.size(); j++){
8
Loop condition is false. Execution continues on line 2117
2097 Df125FDCPulse *fp = (Df125FDCPulse*)fp_objs[j];
2098 if(fp->rocid == f125WindowRawData->rocid){
2099 if(fp->slot == f125WindowRawData->slot){
2100 if(fp->channel == f125WindowRawData->channel){
2101 f125FDCPulse = fp;
2102 f125FDCPulse->AddAssociatedObject(f125WindowRawData);
2103 break;
2104 }
2105 }
2106 }
2107 }
2108
2109 // If the the pulse objects do not exist, create new ones to go with our raw data
2110 // This should rarely happen since CDC_long and FDC_long have the raw data
2111 // along with the calculated quantities in a pulse word. Pure raw mode would be the only time
2112 // when this would not be the case. Since this is so infrequently used (if ever),
2113 // the ROCID check for CDC/FDC determination is hard coded...
2114 // ROCID CDC: 25-28
2115 // ROCID FDC Cathode: 52,53,55-62
2116
2117 if(f125CDCPulse == NULL__null && ( f125WindowRawData->rocid < 30 ) ){
9
Taking false branch
2118 f125CDCPulse = new Df125CDCPulse;
2119 f125CDCPulse->rocid = f125WindowRawData->rocid;
2120 f125CDCPulse->slot = f125WindowRawData->slot;
2121 f125CDCPulse->channel = f125WindowRawData->channel;
2122 f125CDCPulse->emulated = true;
2123 f125CDCPulse->AddAssociatedObject(f125WindowRawData);
2124 cp_objs.push_back(f125CDCPulse);
2125 }
2126
2127 else if(f125FDCPulse == NULL__null && ( f125WindowRawData->rocid > 30 ) ){
10
Taking false branch
2128 f125FDCPulse = new Df125FDCPulse;
2129 f125FDCPulse->rocid = f125WindowRawData->rocid;
2130 f125FDCPulse->slot = f125WindowRawData->slot;
2131 f125FDCPulse->channel = f125WindowRawData->channel;
2132 f125FDCPulse->emulated = true;
2133 f125FDCPulse->AddAssociatedObject(f125WindowRawData);
2134 cp_objs.push_back(f125FDCPulse);
2135 }
2136
2137 // Flag all objects as emulated and their values will be replaced with emulated quantities
2138 if (F125_EMULATION_MODE == kEmulationAlways){
11
Taking false branch
2139 if(f125CDCPulse!=NULL__null) f125CDCPulse->emulated = 1;
2140 if(f125FDCPulse!=NULL__null) f125FDCPulse->emulated = 1;
2141 }
2142
2143 // Perform the emulation
2144 f125Emulator->EmulateFirmware(f125WindowRawData, f125CDCPulse, f125FDCPulse);
12
Called C++ object pointer is null
2145 }
2146
2147 if(VERBOSE>3) evioout << " Leaving EmulateDf125Firmware" <<endl;
2148}
2149
2150//----------------
2151// GetRunNumber
2152//----------------
2153int32_t JEventSource_EVIO::GetRunNumber(evioDOMTree *evt)
2154{
2155 // Note: This is currently not used. Preference is
2156 // now given to the run number found in FindRunNumber
2157 // which is called from GetEvent. This makes things
2158 // a little simpler and ensures the run number originally
2159 // presented to the processor/factory does not change.
2160 // 2/15/2016 DL
2161
2162 // This is called during event parsing to get the
2163 // run number for the event.
2164 // Look through event to try and extract the run number.
2165 // We do this by looking for all uint64_t nodes. Then
2166 // check for a parent with one of the magic values for
2167 // the tag indicating it has run number information.
2168 if(USER_RUN_NUMBER>0) return USER_RUN_NUMBER;
2169 if(!evt) return last_run_number;
2170
2171 evioDOMNodeListP bankList = evt->getNodeList(typeIs<uint64_t>());
2172 evioDOMNodeList::iterator iter = bankList->begin();
2173 const uint64_t *run_number_and_type = NULL__null;
2174 for(; iter!=bankList->end(); iter++){
2175 evioDOMNodeP bankPtr = *iter;
2176 evioDOMNodeP physics_event_built_trigger_bank = bankPtr->getParent();
2177 if(physics_event_built_trigger_bank == NULL__null) continue;
2178 uint32_t tag = physics_event_built_trigger_bank->tag;
2179 const vector<uint64_t> *vec;
2180 switch(tag){
2181 case 0xFF22:
2182 case 0xFF23:
2183 case 0xFF26:
2184 case 0xFF27:
2185 vec = bankPtr->getVector<uint64_t>();
2186 if(!vec) continue;
2187 if(vec->size()<1) continue;
2188 run_number_and_type = &((*vec)[vec->size()-1]);
2189 break;
2190 }
2191 if(run_number_and_type != NULL__null) break;
2192 }
2193
2194 if(run_number_and_type != NULL__null) last_run_number = (*run_number_and_type)>>32;
2195
2196 return last_run_number;
2197}
2198
2199//----------------
2200// FindRunNumber
2201//----------------
2202int32_t JEventSource_EVIO::FindRunNumber(uint32_t *iptr)
2203{
2204 /// This is called from GetEvent() to quickly look for the run number
2205 /// at the time the event is read in so it can be passed into
2206 /// JEvent. It is what will be used for accessing the CCDB.
2207 /// from this event. If a bank containing the run number is found,
2208 /// use it to provide the run number. Otherwise, return whatever run
2209 /// number we were able to extract from the file name.
2210
2211 if(VERBOSE>1) evioout << " .. Searching for run number ..." <<endl;
2212 if(USER_RUN_NUMBER>0){
2213 if(VERBOSE>1) evioout << " returning user-supplied run number: " << USER_RUN_NUMBER << endl;
2214 return last_run_number=USER_RUN_NUMBER;
2215 }
2216
2217 // Assume first word is number of words in bank
2218 uint32_t *iend = &iptr[*iptr - 1];
2219 if(*iptr > 2048) iend = &iptr[2048];
2220 bool has_timestamps = false;
2221 while(iptr<iend){
2222 iptr++;
2223
2224 // EPICS event
2225 if( (*iptr & 0xff000f) == 0x600001){
2226 if(VERBOSE>2) evioout << " Found EPICS header. Looking for HD:coda:daq:run_number ..." << endl;
2227 const char *cptr = (const char*)&iptr[1];
2228 const char *cend = (const char*)iend;
2229 const char *needle = "HD:coda:daq:run_number=";
2230 while(cptr<cend){
2231 if(VERBOSE>4) evioout << " \""<<cptr<<"\"" << endl;
2232 if(!strncmp(cptr, needle, strlen(needle))){
2233 if(VERBOSE>2) evioout << " Found it!" << endl;
2234 return last_run_number = atoi(&cptr[strlen(needle)]);
2235 }
2236 cptr+=4; // should only start on 4-byte boundary!
2237 }
2238 }
2239
2240 // BOR event
2241 if( (*iptr & 0xffffffff) == 0x00700E01){
2242 // OK, this looks like a BOR event which does not include the
2243 // run number. In this case, we have a couple of options:
2244 //
2245 // 1. If we are reading from a file then look further into
2246 // the file to see if we can find another event with the
2247 // run number in it.
2248 //
2249 // 2. Return the run number found from the filename.
2250 //
2251 if(source_type==kFileSource){
2252 int32_t run_number = EpicQuestForRunNumber();
2253 if(run_number != 0){
2254 if(VERBOSE>1) evioout << " Found run number " << run_number << " from Epic Quest." <<endl;
2255 return last_run_number = run_number;
2256 }
2257 }
2258 break; // return filename_run_number with warning message
2259 }
2260
2261 // PHYSICS event
2262 switch((*iptr)>>16){
2263 case 0xFF10:
2264 case 0xFF11:
2265 case 0xFF20:
2266 case 0xFF21:
2267 case 0xFF24:
2268 case 0xFF25:
2269 case 0xFF30:
2270 // These Trigger Bank Tag values have no run number info in them
2271 if(VERBOSE>2) evioout << " ... Trigger bank tag (0x" << hex << ((*iptr)>>16) << dec << ") does not contain run number" <<endl;
2272 if(!WARN_USER_RUN_FILENAME) {
2273 jout << "WARNING: setting run number " << filename_run_number << " based on file name" << endl;
2274 WARN_USER_RUN_FILENAME = true;
2275 }
2276 return last_run_number = filename_run_number;
2277 case 0xFF23:
2278 case 0xFF27:
2279 has_timestamps = true;
2280 case 0xFF22:
2281 case 0xFF26:
2282 if(VERBOSE>2) evioout << " ... Trigger bank tag (0x" << hex << ((*iptr)>>16) << dec << ") does contain run number" <<endl;
2283 // Nrocs = (*iptr) & 0x0F;
2284 break;
2285 default:
2286 continue;
2287 }
2288 iptr++;
2289 if( ((*iptr)&0x00FF0000) != 0x000A0000) { iptr--; continue; }
2290 uint32_t M = iptr[-3] & 0x000000FF; // Number of events from Physics Event header
2291 if(VERBOSE>2) evioout << " ... Trigger bank " << (has_timestamps ? "does":"doesn't") << " have timestamps. Nevents in block M=" << M <<endl;
2292 iptr++;
2293 uint64_t *iptr64 = (uint64_t*)iptr;
2294
2295 uint64_t event_num = *iptr64;
2296 if(source_type==kETSource) event_num = ((*iptr64)>>32) | ((*iptr64)<<32);
2297 if(VERBOSE>3) evioout << " .... Event num: " << event_num <<endl;
2298 iptr64++;
2299 if(has_timestamps) iptr64 = &iptr64[M]; // advance past timestamps
2300
2301 // I'm not sure I fully understand this, but if we read from
2302 // ET, then the run number is in the low 32 bits of *iptr64.
2303 // If we are reading from a file, it is in the high 32 bits.
2304 // No byte swapping is needed (it has already been done, though
2305 // perhaps incorrectly). We handle this here by checking if
2306 // this is an ET source or not.
2307 uint64_t run64 = (*iptr64)>>32;
2308 if(source_type==kETSource){
2309 run64 = (*iptr64)&0xffffffff;
2310 }
2311 int32_t run = (int32_t)run64;
2312 if(VERBOSE>1) evioout << " .. Found run number: " << run <<endl;
2313
2314 return last_run_number = run;
2315 }
2316
2317 // if we're not sure what else to do, try a more comprehensive search
2318 if(source_type==kFileSource){
2319 int32_t run_number = EpicQuestForRunNumber();
2320 if(run_number != 0){
2321 if(VERBOSE>1) evioout << " Found run number " << run_number << " from Epic Quest." <<endl;
2322 return last_run_number = run_number;
2323 }
2324 }
2325
2326 if(!WARN_USER_RUN_FILENAME) {
2327 jout << "WARNING: setting run number " << filename_run_number << " based on file name" << endl;
2328 WARN_USER_RUN_FILENAME = true;
2329 }
2330
2331 return last_run_number = filename_run_number;
2332}
2333
2334//----------------
2335// EpicQuestForRunNumber
2336//----------------
2337int32_t JEventSource_EVIO::EpicQuestForRunNumber(void)
2338{
2339 /// This is called when an event is encountered that does
2340 /// not have a run number in it. (e.g. a BOR event encountered
2341 /// in FindRunNumber() ). This is a last hope of finding the
2342 /// run number in the file by looking for other events that
2343 /// may contain it. Specifically, EPICS or PHYSICS events.
2344 /// This only works if it is a file source so that it can open
2345 /// the file and read in past the first event.
2346 ///
2347 /// Note that this is extremely inefficient so should not be
2348 /// called very often. As a precaution, this will look to see
2349 /// if last_run_number is not set to 0 first and will just
2350 /// return it if it is. Only if it is not will the epic quest
2351 /// commence.
2352
2353 if(source_type!=kFileSource) return 0;
2354 if(last_run_number != 0) return last_run_number;
2355
2356 uint32_t buff_len = 4000000;
2357 uint32_t *buff = new uint32_t[buff_len];
2358 HDEVIO *hdevio = new HDEVIO(source_name);
2359 while(hdevio->read(buff, buff_len)){
2360
2361 // Assume first word is number of words in bank
2362 uint32_t *iptr = buff;
2363 uint32_t *iend = &iptr[*iptr - 1];
2364 if(*iptr > 2048) iend = &iptr[2048];
2365 bool has_timestamps = false;
2366 while(iptr<iend){
2367 iptr++;
2368
2369 // EPICS event
2370 if( (*iptr & 0xff000f) == 0x600001){
2371 if(VERBOSE>2) evioout << " Found EPICS header. Looking for HD:coda:daq:run_number ..." << endl;
2372 const char *cptr = (const char*)&iptr[1];
2373 const char *cend = (const char*)iend;
2374 const char *needle = "HD:coda:daq:run_number=";
2375 while(cptr<cend){
2376 if(VERBOSE>4) evioout << " \""<<cptr<<"\"" << endl;
2377 if(!strncmp(cptr, needle, strlen(needle))){
2378 if(VERBOSE>2) evioout << " Found it!" << endl;
2379 int32_t run_number = atoi(&cptr[strlen(needle)]);
2380 if(hdevio) delete hdevio;
2381 if(buff) delete[] buff;
2382 return run_number;
2383 }
2384 cptr+=4; // should only start on 4-byte boundary!
2385 }
2386 }
2387
2388 // BOR event
2389 if( (*iptr & 0xffffffff) == 0x00700E01) continue;
2390
2391 // PHYSICS event
2392 bool not_in_this_buffer = false;
2393 switch((*iptr)>>16){
2394 case 0xFF10:
2395 case 0xFF11:
2396 case 0xFF20:
2397 case 0xFF21:
2398 case 0xFF24:
2399 case 0xFF25:
2400 case 0xFF30:
2401 not_in_this_buffer = true;
2402 break;
2403 case 0xFF23:
2404 case 0xFF27:
2405 has_timestamps = true;
2406 case 0xFF22:
2407 case 0xFF26:
2408 break;
2409 default:
2410 continue;
2411 }
2412
2413 if(not_in_this_buffer) break; // go to next EVIO buffer
2414
2415 iptr++;
2416 if( ((*iptr)&0x00FF0000) != 0x000A0000) { iptr--; continue; }
2417 uint32_t M = iptr[-3] & 0x000000FF; // Number of events from Physics Event header
2418 if(VERBOSE>2) evioout << " ...(epic quest) Trigger bank " << (has_timestamps ? "does":"doesn't") << " have timestamps. Nevents in block M=" << M <<endl;
2419 iptr++;
2420 uint64_t *iptr64 = (uint64_t*)iptr;
2421
2422 uint64_t event_num = *iptr64;
2423 if(source_type==kETSource) event_num = ((*iptr64)>>32) | ((*iptr64)<<32);
2424 if(VERBOSE>3) evioout << " ....(epic quest) Event num: " << event_num <<endl;
2425 iptr64++;
2426 if(has_timestamps) iptr64 = &iptr64[M]; // advance past timestamps
2427
2428 // I'm not sure I fully understand this, but if we read from
2429 // ET, then the run number is in the low 32 bits of *iptr64.
2430 // If we are reading from a file, it is in the high 32 bits.
2431 // No byte swapping is needed (it has already been done, though
2432 // perhaps incorrectly). We handle this here by checking if
2433 // this is an ET source or not.
2434 uint64_t run64 = (*iptr64)>>32;
2435 if(source_type==kETSource){
2436 run64 = (*iptr64)&0xffffffff;
2437 }
2438 int32_t run = (int32_t)run64;
2439 if(VERBOSE>1) evioout << " .. (epic quest) Found run number: " << run <<endl;
2440
2441 if(hdevio) delete hdevio;
2442 if(buff) delete[] buff;
2443 return run;
2444
2445 } // while(iptr<iend)
2446
2447 if(hdevio->Nevents > 500) break;
2448 } // while(hdevio->read(buff, buff_len))
2449
2450 if(hdevio) delete hdevio;
2451 if(buff) delete[] buff;
2452
2453 return 0;
2454}
2455
2456//----------------
2457// FindEventNumber
2458//----------------
2459uint64_t JEventSource_EVIO::FindEventNumber(uint32_t *iptr)
2460{
2461 /// This is called from GetEvent() to quickly look for the event number
2462 /// at the time the event is read in so it can be passed into JEvent.
2463 /// (See comments for FindRunNumber above.)
2464 if(VERBOSE>1) evioout << " .. Searching for event number ..." <<endl;
2465
2466 if(*iptr < 6){
2467 if(VERBOSE>1) evioout << " Word count(="<<*iptr<<")<6. Returning Nevents_read+1(=" << Nevents_read+1 << ") as event number" <<endl;
2468 return Nevents_read+1;
2469 }
2470
2471 // Check header of Trigger bank
2472 uint32_t mask = 0xFF202000;
2473 if( (iptr[3]&mask) != mask ){
2474 if(VERBOSE>1){
2475 evioout << " iptr[3]=" << hex << iptr[3] << " does not look like trigger bank tag (" << (iptr[3]&mask) << " != " << mask << ")" << dec <<endl;
2476 evioout << " Returning Nevents_read+1(=" << Nevents_read+1 << ") as event number" <<endl;
2477 }
2478 return Nevents_read+1;
2479 }
2480
2481 uint64_t loevent_num = iptr[5];
2482 uint64_t hievent_num = iptr[6];
2483 if(source_type==kETSource) {
2484 loevent_num = iptr[6];
2485 hievent_num = iptr[5];
2486 }
2487 uint64_t event_num = loevent_num + (hievent_num<<32);
2488 if(VERBOSE>1) evioout << " .. Found event number: " << event_num <<endl;
2489
2490 return event_num;
2491}
2492
2493//----------------
2494// FindEventType
2495//----------------
2496void JEventSource_EVIO::FindEventType(uint32_t *iptr, JEvent &event)
2497{
2498 /// This is called from GetEvent to quickly determine the type of
2499 /// event this is (Physics, EPICS, SYNC, BOR, ...)
2500 uint32_t head = iptr[1];
2501 if( (head & 0xff000f) == 0x600001){
2502 event.SetStatusBit(kSTATUS_EPICS_EVENT);
2503 }else if( (head & 0xffffffff) == 0x00700E01){
2504 event.SetStatusBit(kSTATUS_BOR_EVENT);
2505 }else if( (head & 0xffffff00) == 0xff501000){
2506 event.SetStatusBit(kSTATUS_PHYSICS_EVENT);
2507 }else if( (head & 0xffffff00) == 0xff701000){
2508 event.SetStatusBit(kSTATUS_PHYSICS_EVENT);
2509 }else if( (head & 0xfff000ff) == 0xffd00000){
2510 event.SetStatusBit(kSTATUS_CONTROL_EVENT);
2511 if( (head>>16) == 0xffd0 ) event.SetStatusBit(kSTATUS_SYNC_EVENT);
2512 }else{
2513 DumpBinary(iptr, &iptr[16]);
2514 }
2515}
2516
2517//----------------
2518// MergeObjLists
2519//----------------
2520void JEventSource_EVIO::MergeObjLists(list<ObjList*> &events1, list<ObjList*> &events2)
2521{
2522 if(VERBOSE>5) evioout << " Entering MergeObjLists(). "
2523 << " &events1=" << hex << &events1 << dec << "(" << events1.size() << " events) "
2524 << " &events2=" << hex << &events2 << dec << "(" << events2.size() << " events) " << endl;
2525
2526 /// Merge the events referenced in events2 into the events1 list.
2527 ///
2528 /// This will append the object lists for each type of data object
2529 /// stored in events2 onto the appropriate list in events1. It does this
2530 /// event-by-event. The idea being that each entry in the queue represents a
2531 /// partial list of the objects for the event. The two queues are most likely
2532 /// filled from different EVIO banks orginiating from different ROCs.
2533 ///
2534 /// Before the merging is done, it is checked that both lists either have the
2535 /// same number of events, or one list is empty. One list is allowed to be
2536 /// empty since it is possible it was "filled" from a bank that contains no
2537 /// data at all which may not neccessarily be an error. If both queues have
2538 /// at least one event, but they do not contain an equal number of events,
2539 /// then an exception is thrown.
2540 ///
2541 /// The contents of event2 will be erased before returning. Ownership of all
2542 /// ObjList objects pointed to by event2 upon entry should be considered
2543 /// owned by event1 upon return.
2544
2545 // Allow a list of 1 event with only config objects in test below
2546 bool justconfig = false;
2547 if(events1.size()==1){
2548 ObjList *objs1 = events1.front();
2549 justconfig = objs1->hit_objs.size()==0 && objs1->misc_objs.size()==0 && objs1->config_objs.size()!=0;
2550 }else if(events2.size()==1){
2551 ObjList *objs2 = events2.front();
2552 justconfig = objs2->hit_objs.size()==0 && objs2->misc_objs.size()==0 && objs2->config_objs.size()!=0;
2553 }
2554
2555 // Check number of events and throw exception if appropriate
2556 unsigned int Nevents1 = events1.size();
2557 unsigned int Nevents2 = events2.size();
2558 if(Nevents1>0 && Nevents2>0 && !justconfig){
2559 if(Nevents1 != Nevents2){
2560 evioout << "Mismatch of number of events passed to MergeObjLists. Throwing exception." << endl;
2561 evioout << "Nevents1="<<Nevents1<<" Nevents2="<<Nevents2<<endl;
2562 throw JException("Number of events in JEventSource_EVIO::MergeObjLists do not match!");
2563 }
2564 }
2565
2566 // Handle cases when one or both lists are empty
2567 if(Nevents1==0 && Nevents2==0)return;
2568 if(Nevents1==0){
2569 events1 = events2;
2570 events2.clear(); // clear queue
2571 return;
2572 }
2573 if(Nevents2==0)return;
2574
2575 // If we get here it means both events1 and events2 have events
2576 list<ObjList*>::iterator iter = events1.begin();
2577 for(; iter!=events1.end(); iter++){
2578 if(events2.empty()) break; // in case one has just config objects in a single event
2579 ObjList *objs1 = *iter;
2580 ObjList *objs2 = events2.front();
2581 events2.pop_front();
2582
2583 objs1->hit_objs.insert(objs1->hit_objs.end(), objs2->hit_objs.begin(), objs2->hit_objs.end());
2584 objs1->config_objs.insert(objs1->config_objs.end(), objs2->config_objs.begin(), objs2->config_objs.end());
2585 objs1->misc_objs.insert(objs1->misc_objs.end(), objs2->misc_objs.begin(), objs2->misc_objs.end());
2586
2587 // Delete the objs2 container
2588 delete objs2;
2589 }
2590
2591 // Clear out any references to objects in event2 (this should be redundant)
2592 events2.clear(); // clear queue
2593
2594 if(VERBOSE>5) evioout << " Leaving MergeObjLists(). &events1=" << hex << &events1 << " &events2=" << &events2 << dec << endl;
2595}
2596
2597//----------------
2598// ParseEVIOEvent
2599//----------------
2600void JEventSource_EVIO::ParseEVIOEvent(evioDOMTree *evt, list<ObjList*> &full_events)
2601{
2602 if(VERBOSE>5) evioout << " Entering ParseEVIOEvent() with evt=" << hex << evt << dec << endl;
2603
2604 if(!evt)throw RESOURCE_UNAVAILABLE;
2605
2606 // Since each bank contains parts of many events, have them fill in
2607 // the "tmp_events" list and then merge those into the "full_events".
2608 // It is done this way so each bank can grow tmp_events to the appropriate
2609 // size to hold the number of events it discovers in the bank. A check
2610 // can then be made that this is consistent with the number of event
2611 // fragments found in the other banks.
2612 //list<ObjList*> full_events;
2613 list<ObjList*> tmp_events;
2614
2615 // The Physics Event bank is the outermost bank of the event and
2616 // it is a bank of banks. One of those banks is the
2617 // "Built Trigger Bank" which is a bank of segments. The others
2618 // are the "Data Bank" banks which in turn contain the
2619 // "Data Block Bank" banks which hold the actual data. For the
2620 // mc2coda generated data files (and presumably the real data)
2621 // these Data Block Banks are banks of ints. More specifically,
2622 // uint32_t.
2623 //
2624 // The "Physics Event's Built Trigger Bank" is a bank of segments.
2625 // This contains 3 segments, one each of type uint64, uint16, and
2626 // unit32. The first two are "common data" which contains information
2627 // common to all rocs. The last (uint32) has information specific to each
2628 // event and for each ROC.
2629 //
2630 // For now, we skip parseing the Built Trigger Bank and just
2631 // look for Data Block Banks. We do this by getting a list of
2632 // all uint32_t banks in the enitries DOM Tree (at all levels
2633 // of the heirachy) and checking the parent banks for depth
2634 // and additional info.
2635
2636 // Loop over list of all EVIO banks at all levels of the tree and parse
2637 // them, creating data objects and adding them to the overall list.
2638 evioDOMNodeListP bankList = evt->getNodeList();
2639 evioDOMNodeList::iterator iter = bankList->begin();
2640 if(VERBOSE>7) evioout << " Looping over " << bankList->size() << " banks in EVIO event" << endl;
2641 for(int ibank=1; iter!=bankList->end(); iter++, ibank++){ // ibank only used for debugging messages
2642
2643 if(VERBOSE>7) evioout << " -------- bank " << ibank << "/" << bankList->size() << " --------" << endl;
2644
2645 // The data banks we want should have exactly two parents:
2646 // - Data Bank bank <-- parent
2647 // - Physics Event bank <-- grandparent
2648 //
2649 // other types of events may be inserted in the datastream though so we
2650 // check for those first.
2651
2652 // BOR event
2653 // BOR events will have an outermost
2654 // bank with tag=0x70 and num=1. If this is the outermost bank of
2655 // a BOR event, then parse it. If it is a inner BOR bank then ignore it.
2656 evioDOMNodeP outermostBankPtr = *iter;
2657 while(outermostBankPtr->getParent()) outermostBankPtr = outermostBankPtr->getParent();
2658 if(outermostBankPtr->tag==0x70 && outermostBankPtr->num==1){
2659 // This is a BOR bank
2660 if(VERBOSE>9) evioout << " bank is part of BOR event ... " << endl;
2661 if(outermostBankPtr == *iter){
2662 if(VERBOSE>9) evioout << " bank is outermost EVIO bank. Parsing BOR event ..." << endl;
2663 ParseBORevent(outermostBankPtr);
2664 }else{
2665 if(VERBOSE>9) evioout << " bank is not outermost EVIO bankin BOR event skipping ..." << endl;
2666 }
2667 continue; // no further processing of this bank is needed
2668 }
2669
2670 // EPICS event
2671 evioDOMNodeP bankPtr = *iter;
2672 evioDOMNodeP data_bank = bankPtr->getParent();
2673 if( data_bank==NULL__null ) {
2674
2675 if(VERBOSE>9) evioout << " bank has no parent. Checking if it's an EPICS event ... " << endl;
2676 if(bankPtr->tag==96 && bankPtr->num==1){
2677 // This looks like an EPICS event. Hand it over to EPICS parser
2678 ParseEPICSevent(bankPtr, full_events);
2679 }else{
2680 if(VERBOSE>9) evioout << " Not an EPICS event bank. skipping ... " << endl;
2681 }
2682
2683 continue;
2684 }
2685
2686 // Trigger Bank
2687 evioDOMNodeP physics_event_bank = data_bank->getParent();
2688
2689 // TS scalers for SYNC events. Currently us phys event tag
2690 // Don't use the parent tag in the future, to be checked
2691 if((physics_event_bank != NULL__null) && (bankPtr != NULL__null)){
2692 if( (physics_event_bank->tag == 0xff70) && (bankPtr->tag == 0xEE02)){
2693 const vector<uint32_t> *vec = bankPtr->getVector<uint32_t>();
2694 if(vec->size() < 102){
2695 evioout << " TS record for SYNC event is inconsistent. Don't parse " << endl;
2696 } else {
2697 ParseTSSync(bankPtr, full_events);
2698 // MergeObjLists(full_events, tmp_events);
2699 }
2700 }
2701 }
2702
2703
2704 if( physics_event_bank==NULL__null ){
2705 if(VERBOSE>6) evioout << " bank has no grandparent. Checking if this is a trigger bank ... " << endl;
2706
2707 // Check if this is a CODA Reserved Bank Tag. If it is, then
2708 // this probably is part of the built trigger bank and not
2709 // the ROC data we're looking to parse here.
2710 if((bankPtr->tag & 0xFF00) == 0xFF00){
2711 if(VERBOSE>6) evioout << " Bank tag="<<hex<<data_bank->tag<<dec<<" is in reserved CODA range and has correct lineage. Assuming it's a built trigger bank."<< endl;
2712 ParseBuiltTriggerBank(bankPtr, tmp_events);
2713 if(VERBOSE>5) evioout << " Merging objects in ParseEVIOEvent" << endl;
2714 MergeObjLists(full_events, tmp_events);
2715
2716 // Check if this is a DEventTag bank
2717 }else if(bankPtr->tag == 0x0056){
2718 const vector<uint32_t> *vec = bankPtr->getVector<uint32_t>();
2719 if(vec){
2720 const uint32_t *iptr = &(*vec)[0];
2721 const uint32_t *iend = &(*vec)[vec->size()];
2722 ParseEventTag(iptr, iend, tmp_events);
2723 if(VERBOSE>5) evioout << " Merging DEventTag objects in ParseEVIOEvent" << endl;
2724 MergeObjLists(full_events, tmp_events);
2725 }
2726 }
2727
2728 continue; // if this wasn't a trigger bank, then it has the wrong lineage to be a data bank
2729 }
2730 if( physics_event_bank->getParent() != NULL__null ){
2731 if(VERBOSE>9) evioout << " bank DOES have great-grandparent. skipping ... " << endl;
2732 continue; // physics event bank should have no parent!
2733 }
2734 if(VERBOSE>9){
2735 evioout << " Physics Event Bank: tag=" << hex << physics_event_bank->tag << " num=" << (int)physics_event_bank->num << dec << endl;
2736 evioout << " Data Bank: tag=" << hex << data_bank->tag << " num=" << (int)data_bank->num << dec << endl;
2737 }
2738
2739 if(VERBOSE>9) evioout << " bank lineage check OK. Continuing with parsing ... " << endl;
2740
2741 // Extract ROC id (crate number) from bank's parent
2742 uint32_t rocid = data_bank->tag & 0x0FFF;
2743
2744 // Get data from bank in the form of a vector of uint32_t
2745 const vector<uint32_t> *vec = bankPtr->getVector<uint32_t>();
2746 if(!vec){
2747 if(VERBOSE>6) evioout << " bank is not uint32_t. Skipping..." << endl;
2748 continue;
2749 }
2750 const uint32_t *iptr = &(*vec)[0];
2751 const uint32_t *iend = &(*vec)[vec->size()];
2752 if(VERBOSE>6) evioout << " uint32_t bank has " << vec->size() << " words" << endl;
2753
2754 // If there are rocid's specified that we wish to parse, make sure this one
2755 // is in the list. Otherwise, skip it.
2756 if(!ROCIDS_TO_PARSE.empty()){
2757 if(VERBOSE>4) evioout << " Skipping parsing of rocid="<<rocid<<" due to it being in ROCIDS_TO_PARSE set." << endl;
2758 if(ROCIDS_TO_PARSE.find(rocid) == ROCIDS_TO_PARSE.end()) continue;
2759 }
2760
2761 // Check if this is a CODA Reserved Bank Tag.
2762 if((data_bank->tag & 0xFF00) == 0xFF00){
2763 if(VERBOSE>6) evioout << " Data Bank tag="<<hex<<data_bank->tag<<dec<<" is in reserved CODA range. This is probably not ROC data"<< endl;
2764 continue;
2765 }
2766
2767 // Check if this is a TS Bank.
2768 if(bankPtr->tag == 0xEE02){
2769 if(VERBOSE>4) evioout << " TS bank tag="<<hex<<bankPtr->tag<<dec<< endl;
2770 ParseTSBank(rocid, iptr, iend, full_events);
2771 continue;
2772 }
2773
2774 // Check if this is a f250 Pedestal Bank.
2775 if(bankPtr->tag == 0xEE05){
2776 if(VERBOSE>6) evioout << " SYNC event - f250 pedestals not currently handled"<< endl;
2777 continue;
2778 }
2779
2780 // Check if this is additional sync data
2781 if(bankPtr->tag == 0xEE10){
2782 if(VERBOSE>6) evioout << " SYNC event - ignoring undocumented sync bank"<< endl; // only somov@jlab.org knows what this is
2783 continue;
2784 }
2785
2786 // The number of events in block is stored in lower 8 bits
2787 // of header word (aka the "num") of Data Bank. This should
2788 // be at least 1.
2789 uint32_t NumEvents = data_bank->num & 0xFF;
2790 if( NumEvents<1 ){
2791 if(VERBOSE>9) evioout << " bank has less than 1 event (Data Bank num or \"M\" = 0) skipping ... " << endl;
2792 continue;
2793 }
2794
2795 // At this point iptr and iend indicate the data that came
2796 // from the ROC itself (all CODA headers have been stripped
2797 // away). Here, we need to decide what type of data this
2798 // bank contains. All JLab modules have a common block
2799 // header format and so are handled in a common way. Other
2800 // modules (e.g. CAEN) will have to appear in their own
2801 // EVIO bank and should be identified by their own det_id
2802 // value in the Data Block Bank.
2803 //
2804 // Current, preliminary thinking includes writing the type
2805 // of data into the 12-bit detector id contained in the
2806 // Data Block Bank of the DAQ group's "Event Building EVIO
2807 // Scheme". (This is the lower 12 bits of the "tag"). We
2808 // use this to decide if it is JLab module data or somehting
2809 // else.
2810 uint32_t det_id = bankPtr->tag & 0x0FFF;
2811 // Call appropriate parsing method
2812 bool bank_parsed = true; // will be set to false if default case is entered
2813 switch(det_id){
2814 case 0:
2815 case 1:
2816 case 3:
2817 case 6: // flash 250 module, MMD 2014/2/4
2818 case 16: // flash 125 module (CDC), DL 2014/6/19
2819 case 26: // F1 TDC module (BCAL), MMD 2014-07-31
2820 ParseJLabModuleData(rocid, iptr, iend, tmp_events);
2821 break;
2822
2823 case 20:
2824 ParseCAEN1190(rocid, iptr, iend, tmp_events);
2825 break;
2826
2827 case 0x55:
2828 ParseModuleConfiguration(rocid, iptr, iend, tmp_events);
2829 break;
2830
2831 case 5:
2832 // Beni's original CDC ROL used for the stand-alone CDC DAQ
2833 // had the following for the TS readout list (used in the TI):
2834 // *dma_dabufp++ = 0xcebaf111;
2835 // *dma_dabufp++ = tsGetIntCount();
2836 // *dma_dabufp++ = 0xdead;
2837 // *dma_dabufp++ = 0xcebaf222;
2838 // We skip this here, but put in the case so that we avoid errors
2839 break;
2840
2841
2842 default:
2843 jerr<<"Unknown module type ("<<det_id<<") encountered for tag="<<bankPtr->tag<<" num="<< (int)bankPtr->num << endl;
2844 bank_parsed = false;
2845 if(VERBOSE>5){
2846 cerr << endl;
2847 cout << "----- First few words to help with debugging -----" << endl;
2848 cout.flush(); cerr.flush();
2849 int i=0;
2850 for(const uint32_t *iiptr = iptr; iiptr<iend; iiptr++, i++){
2851 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<2851<<" "
<< "0x" << hex << *iiptr << dec << endl;
2852 if(i>=8) break;
2853 }
2854
2855 }
2856 }
2857
2858 // Merge this bank's partial events into the full events
2859 if(bank_parsed){
2860 if(VERBOSE>5) evioout << " Merging objects in ParseEVIOEvent" << endl;
2861 MergeObjLists(full_events, tmp_events);
2862 }
2863 }
2864
2865 // The following disabled in preference for keeping the
2866 // run number found by FindRunNumber called from
2867 // GetEvent() 2/15/2016
2868
2869 // // Set the run number for all events
2870 // uint32_t run_number = GetRunNumber(evt);
2871 // list<ObjList*>::iterator evt_iter = full_events.begin();
2872 // for(; evt_iter!=full_events.end(); evt_iter++){
2873 // ObjList *objs = *evt_iter;
2874 // objs->run_number = run_number;
2875 // }
2876
2877 if(VERBOSE>5) evioout << " Leaving ParseEVIOEvent()" << endl;
2878}
2879
2880//----------------
2881// ParseBuiltTriggerBank
2882//----------------
2883void JEventSource_EVIO::ParseBuiltTriggerBank(evioDOMNodeP trigbank, list<ObjList*> &events)
2884{
2885 if(!PARSE_TRIGGER) return;
2886
2887 if(VERBOSE>5) evioout << " Entering ParseBuiltTriggerBank()" << endl;
2888
2889 uint32_t Mevents = 1; // number of events in block (will be overwritten below)
2890 uint32_t Nrocs = (uint32_t)trigbank->num; // number of rocs providing data in this bank
2891 evioDOMNodeP physics_event_bank = trigbank->getParent();
2892 if(physics_event_bank) Mevents = (uint32_t)physics_event_bank->num;
2893
2894 if(VERBOSE>6) evioout << " Mevents=" << Mevents << " Nrocs=" << Nrocs << endl;
2895
2896 // Some values to fill in while parsing the banks that will be used later to create objects
2897 vector<uint64_t> avg_timestamps;
2898 uint32_t run_number = 0;
2899 uint32_t run_type = 0;
2900 uint64_t first_event_num = 1;
2901 vector<uint16_t> event_types;
2902 map<uint32_t, vector<DCODAROCInfo*> > rocinfos; // key=event (from 0 to Mevents-1)
2903 //vector<map<uint32_t, DCODAROCInfo*> > rocinfos; // key=rocid
2904
2905 // Loop over children of built trigger bank
2906 evioDOMNodeListP bankList = trigbank->getChildren();
2907 evioDOMNodeList::iterator iter = bankList->begin();
2908 for(int ibank=1; iter!=bankList->end(); iter++, ibank++){
2909
2910 if(VERBOSE>7) evioout << " Looking for data in child banks ..." << endl;
2911
2912 evioDOMNodeP bankPtr = *iter;
2913
2914 // The "Physics Event's Built Trigger Bank" is a bank of segments that
2915 // may contain banks of 3 data types: uint64_t, uint32_t, and uint16_t
2916 // The uint64_t contains the first event number, average timestamps, and
2917 // run number & types. The uint16_t contains the event type(s). The
2918 // uint32_t contains the optional ROC specific meta data starting with
2919 // the specific timestamp for each event. All of these have some options
2920 // on exactly what info is contained in the bank. The first check here is
2921 // on the data type the bank contains. At most, one of the following pointers
2922 // should be non-zero.
2923 vector<uint64_t> *vec64 = bankPtr->getVector<uint64_t>();
2924 vector<uint32_t> *vec32 = bankPtr->getVector<uint32_t>();
2925 vector<uint16_t> *vec16 = bankPtr->getVector<uint16_t>();
2926
2927 // unit64_t = common data (1st part)
2928 if(vec64){
2929
2930 if(VERBOSE>9) evioout << " found uint64_t data" << endl;
2931
2932 // In addition to the first event number (1st word) there are three
2933 // additional pieces of information that may be present:
2934 // t = average timestamp
2935 // r = run number and type
2936 // d = run specific data
2937 //
2938 // The last one ("d") comes in the form of multiple uint32_t banks
2939 // so is not included in vec64. The other two have their presence
2940 // signaled by bit 0(=t) and bit 1(=r) in the trigbank tag. (We can
2941 // also deduce this from the bank length.)
2942
2943 if(vec64->size() == 0) continue; // need debug message here!
2944
2945 first_event_num = (*vec64)[0];
2946
2947 // Hi and lo 32bit words in 64bit numbers seem to be
2948 // switched for events read from ET, but not read from
2949 // file. Not sure if this is in the swapping routine
2950 if(source_type==kETSource) first_event_num = (first_event_num>>32) | (first_event_num<<32);
2951
2952 uint32_t Ntimestamps = vec64->size()-1;
2953 if(Ntimestamps==0) continue; // no more words of interest
2954 if(trigbank->tag & 0x2) Ntimestamps--; // subtract 1 for run number/type word if present
2955 for(uint32_t i=0; i<Ntimestamps; i++) avg_timestamps.push_back((*vec64)[i+1]);
2956
2957 // run number and run type
2958 if(trigbank->tag & 0x02){
2959 run_number = (*vec64)[vec64->size()-1] >> 32;
2960 run_type = (*vec64)[vec64->size()-1] & 0xFFFFFFFF;
2961 }
2962 }
2963
2964 // uint16_t = common data (2nd part)
2965 if(vec16){
2966
2967 if(VERBOSE>9) evioout << " found uint16_t data" << endl;
2968
2969 for(uint32_t i=0; i<Mevents; i++){
2970 if(i>=vec16->size()) break;
2971 event_types.push_back((*vec16)[i]);
2972 }
2973 }
2974
2975 // uint32_t = inidivdual ROC timestamps and misc. roc-specfic data
2976 if(vec32){
2977
2978 if(VERBOSE>9) evioout << " found uint32_t data" << endl;
2979
2980 // Get pointer to DCODAROCInfo object for this rocid/event, instantiating it if necessary
2981 uint32_t rocid = (uint32_t)bankPtr->tag;
2982 uint32_t Nwords_per_event = vec32->size()/Mevents;
2983 if(vec32->size() != Mevents*Nwords_per_event){
2984 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<2984<<" "
<< "Number of ROC data words in Trigger Bank inconsistent with header" << endl;
2985 exit(-1);
2986 }
2987
2988 uint32_t *iptr = &(*vec32)[0];
2989 for(uint32_t ievent=0; ievent<Mevents; ievent++){
2990
2991 DCODAROCInfo *codarocinfo = new DCODAROCInfo;
2992 codarocinfo->rocid = rocid;
2993
2994 uint64_t ts_low = *iptr++;
2995 uint64_t ts_high = *iptr++;
2996 codarocinfo->timestamp = (ts_high<<32) + ts_low;
2997 for(uint32_t i=2; i<Nwords_per_event; i++) codarocinfo->misc.push_back(*iptr++);
2998
2999 if(VERBOSE>7) evioout << " Adding DCODAROCInfo for rocid="<<rocid<< " with timestamp " << codarocinfo->timestamp << endl;
3000 rocinfos[ievent].push_back(codarocinfo);
3001 }
3002 }
3003 }
3004
3005 // Check that we have agreement on the number of events this data represents
3006 bool Nevent_mismatch = false;
3007 if(!avg_timestamps.empty()) Nevent_mismatch |= (avg_timestamps.size() != Mevents);
3008 if(!event_types.empty() ) Nevent_mismatch |= (event_types.size() != Mevents);
3009 if(!rocinfos.empty() ) Nevent_mismatch |= (rocinfos.size() != Mevents);
3010 if(Nevent_mismatch){
3011 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3011<<" "
<<"Mismatch in number of events in Trigger Bank!"<<endl;
3012 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3012<<" "
<<" Mevents="<<Mevents<<endl;
3013 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3013<<" "
<<" avg_timestamps.size()="<<avg_timestamps.size()<<endl;
3014 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3014<<" "
<<" event_types.size()="<<event_types.size()<<endl;
3015 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3015<<" "
<<" rocinfos.size()="<<rocinfos.size()<<endl;
3016 exit(-1);
3017 }
3018
3019 // Copy all objects into events
3020 for(uint32_t i=0; i<Mevents; i++){
3021 while(events.size()<=i){
3022 if(!ENABLE_DISENTANGLING && !events.empty()) break;
3023 events.push_back(new ObjList);
3024 }
3025 ObjList *objs = events.back();
3026
3027 DCODAEventInfo *codaeventinfo = new DCODAEventInfo;
3028 codaeventinfo->run_number = run_number;
3029 codaeventinfo->run_type = run_type;
3030 codaeventinfo->event_number = first_event_num + i;
3031 codaeventinfo->event_type = event_types.empty() ? 0:event_types[i];
3032 codaeventinfo->avg_timestamp = avg_timestamps.empty() ? 0:avg_timestamps[i];
3033 objs->misc_objs.push_back(codaeventinfo);
3034 objs->event_number = codaeventinfo->event_number;
3035
3036 vector<DCODAROCInfo*> &codarocinfos = rocinfos[i];
3037 for(uint32_t i=0; i<codarocinfos.size(); i++) objs->misc_objs.push_back(codarocinfos[i]);
3038 }
3039
3040 if(VERBOSE>6) evioout << " Found "<<events.size()<<" events in Built Trigger Bank"<< endl;
3041 if(VERBOSE>5) evioout << " Leaving ParseBuiltTriggerBank()" << endl;
3042}
3043
3044//----------------
3045// ParseModuleConfiguration
3046//----------------
3047void JEventSource_EVIO::ParseModuleConfiguration(int32_t rocid, const uint32_t* &iptr, const uint32_t *iend, list<ObjList*> &events)
3048{
3049 if(!PARSE_CONFIG){ iptr = iend; return; }
3050
3051 if(VERBOSE>5) evioout << " Entering ParseModuleConfiguration() (events.size()="<<events.size()<<")" << endl;
3052
3053 /// Parse a bank of module configuration data. These are configuration values
3054 /// programmed into the module at the beginning of the run that may be needed
3055 /// in the offline. For example, the number of samples to sum in a FADC pulse
3056 /// integral.
3057 ///
3058 /// The bank has one or more sections, each describing parameters applicable
3059 /// to a number of modules as indicated by a 24bit slot mask.
3060 ///
3061 /// This bank should appear only once per DAQ event which, if in multi-event
3062 /// block mode, may have multiple L1 events. The parameters here will apply
3063 /// to all L1 events in the block. This method will put the config objects
3064 /// in the first event of "events", creating it if needed. The config objects
3065 /// are duplicated for all other events in the block later, after all event
3066 /// parsing is finished and the total number of events is known.
3067 /// (See the end of ParseEvents() .)
3068
3069 while(iptr < iend){
3070 uint32_t slot_mask = (*iptr) & 0xFFFFFF;
3071 uint32_t Nvals = ((*iptr) >> 24) & 0xFF;
3072 iptr++;
3073
3074 Df250Config *f250config = NULL__null;
3075 Df125Config *f125config = NULL__null;
3076 DF1TDCConfig *f1tdcconfig = NULL__null;
3077 DCAEN1290TDCConfig *caen1290tdcconfig = NULL__null;
3078
3079 // Loop over all parameters in this section
3080 for(uint32_t i=0; i< Nvals; i++){
3081 if( iptr >= iend){
3082 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3082<<" "
<< "DAQ Configuration bank corrupt! slot_mask=0x" << hex << slot_mask << dec << " Nvals="<< Nvals << endl;
3083 exit(-1);
3084 }
3085
3086 daq_param_type ptype = (daq_param_type)((*iptr)>>16);
3087 uint16_t val = (*iptr) & 0xFFFF;
3088
3089 if(VERBOSE>6) evioout << " DAQ parameter of type: 0x" << hex << ptype << dec << " found with value: " << val << endl;
3090
3091 // Create config object of correct type if needed and copy
3092 // parameter value into it.
3093 switch(ptype>>8){
3094
3095 // f250
3096 case 0x05:
3097 if( !f250config ) f250config = new Df250Config(rocid, slot_mask);
3098 switch(ptype){
3099 case kPARAM250_NSA : f250config->NSA = val; break;
3100 case kPARAM250_NSB : f250config->NSB = val; break;
3101 case kPARAM250_NSA_NSB : f250config->NSA_NSB = val; break;
3102 case kPARAM250_NPED : f250config->NPED = val; break;
3103 default: _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3103<<" "
<< "UNKNOWN DAQ Config Parameter type: 0x" << hex << ptype << dec << endl;
3104 }
3105 break;
3106
3107 // f125
3108 case 0x0F:
3109 if( !f125config ) f125config = new Df125Config(rocid, slot_mask);
3110 switch(ptype){
3111 case kPARAM125_NSA : f125config->NSA = val; break;
3112 case kPARAM125_NSB : f125config->NSB = val; break;
3113 case kPARAM125_NSA_NSB : f125config->NSA_NSB = val; break;
3114 case kPARAM125_NPED : f125config->NPED = val; break;
3115 case kPARAM125_WINWIDTH : f125config->WINWIDTH = val; break;
3116 case kPARAM125_PL : f125config->PL = val; break;
3117 case kPARAM125_NW : f125config->NW = val; break;
3118 case kPARAM125_NPK : f125config->NPK = val; break;
3119 case kPARAM125_P1 : f125config->P1 = val; break;
3120 case kPARAM125_P2 : f125config->P2 = val; break;
3121 case kPARAM125_PG : f125config->PG = val; break;
3122 case kPARAM125_IE : f125config->IE = val; break;
3123 case kPARAM125_H : f125config->H = val; break;
3124 case kPARAM125_TH : f125config->TH = val; break;
3125 case kPARAM125_TL : f125config->TL = val; break;
3126 case kPARAM125_IBIT : f125config->IBIT = val; break;
3127 case kPARAM125_ABIT : f125config->ABIT = val; break;
3128 case kPARAM125_PBIT : f125config->PBIT = val; break;
3129 default: _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3129<<" "
<< "UNKNOWN DAQ Config Parameter type: 0x" << hex << ptype << dec << endl;
3130 }
3131 break;
3132
3133 // F1TDC
3134 case 0x06:
3135 if( !f1tdcconfig ) f1tdcconfig = new DF1TDCConfig(rocid, slot_mask);
3136 switch(ptype){
3137 case kPARAMF1_REFCNT : f1tdcconfig->REFCNT = val; break;
3138 case kPARAMF1_TRIGWIN : f1tdcconfig->TRIGWIN = val; break;
3139 case kPARAMF1_TRIGLAT : f1tdcconfig->TRIGLAT = val; break;
3140 case kPARAMF1_HSDIV : f1tdcconfig->HSDIV = val; break;
3141 case kPARAMF1_BINSIZE : f1tdcconfig->BINSIZE = val; break;
3142 case kPARAMF1_REFCLKDIV : f1tdcconfig->REFCLKDIV = val; break;
3143 default: _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3143<<" "
<< "UNKNOWN DAQ Config Parameter type: 0x" << hex << ptype << dec << endl;
3144 }
3145 break;
3146
3147 // caen1290
3148 case 0x10:
3149 if( !caen1290tdcconfig ) caen1290tdcconfig = new DCAEN1290TDCConfig(rocid, slot_mask);
3150 switch(ptype){
3151 case kPARAMCAEN1290_WINWIDTH : caen1290tdcconfig->WINWIDTH = val; break;
3152 case kPARAMCAEN1290_WINOFFSET : caen1290tdcconfig->WINOFFSET = val; break;
3153 default: _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3153<<" "
<< "UNKNOWN DAQ Config Parameter type: 0x" << hex << ptype << dec << endl;
3154 }
3155 break;
3156
3157 default:
3158 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3158<<" "
<< "Unknown module type: 0x" << hex << (ptype>>8) << endl;
3159 exit(-1);
3160 }
3161
3162#if 0
3163 // Create config object of correct type if needed. (Only one type
3164 // should be created per section!)
3165 switch(ptype>>8){
3166 case 0x05: if(!f250config ) f250config = new Df250Config(rocid, slot_mask); break;
3167 case 0x0F: if(!f125config ) f125config = new Df125Config(rocid, slot_mask); break;
3168 case 0x06: if(!f1tdcconfig ) f1tdcconfig = new DF1TDCConfig(rocid, slot_mask); break;
3169 case 0x10: if(!caen1290tdcconfig) caen1290tdcconfig = new DCAEN1290TDCConfig(rocid, slot_mask); break;
3170 default:
3171 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3171<<" "
<< "Unknown module type: 0x" << hex << (ptype>>8) << endl;
3172 exit(-1);
3173 }
3174
3175 // Copy parameter into config. object
3176 switch(ptype){
3177 case kPARAM250_NSA : f250config->NSA = val; break;
3178 case kPARAM250_NSB : f250config->NSB = val; break;
3179 case kPARAM250_NSA_NSB : f250config->NSA_NSB = val; break;
3180 case kPARAM250_NPED : f250config->NPED = val; break;
3181
3182 case kPARAM125_NSA : f125config->NSA = val; break;
3183 case kPARAM125_NSB : f125config->NSB = val; break;
3184 case kPARAM125_NSA_NSB : f125config->NSA_NSB = val; break;
3185 case kPARAM125_NPED : f125config->NPED = val; break;
3186 case kPARAM125_WINWIDTH : f125config->WINWIDTH = val; break;
3187 case kPARAM125_PL : f125config->PL = val; break;
3188 case kPARAM125_NW : f125config->NW = val; break;
3189 case kPARAM125_NPK : f125config->NPK = val; break;
3190 case kPARAM125_P1 : f125config->P1 = val; break;
3191 case kPARAM125_P2 : f125config->P2 = val; break;
3192 case kPARAM125_PG : f125config->PG = val; break;
3193 case kPARAM125_IE : f125config->IE = val; break;
3194 case kPARAM125_H : f125config->H = val; break;
3195 case kPARAM125_TH : f125config->TH = val; break;
3196 case kPARAM125_TL : f125config->TL = val; break;
3197 case kPARAM125_IBIT : f125config->IBIT = val; break;
3198 case kPARAM125_ABIT : f125config->ABIT = val; break;
3199 case kPARAM125_PBIT : f125config->PBIT = val; break;
3200
3201 case kPARAMF1_REFCNT : f1tdcconfig->REFCNT = val; break;
3202 case kPARAMF1_TRIGWIN : f1tdcconfig->TRIGWIN = val; break;
3203 case kPARAMF1_TRIGLAT : f1tdcconfig->TRIGLAT = val; break;
3204 case kPARAMF1_HSDIV : f1tdcconfig->HSDIV = val; break;
3205 case kPARAMF1_BINSIZE : f1tdcconfig->BINSIZE = val; break;
3206 case kPARAMF1_REFCLKDIV : f1tdcconfig->REFCLKDIV = val; break;
3207
3208 case kPARAMCAEN1290_WINWIDTH : caen1290tdcconfig->WINWIDTH = val; break;
3209 case kPARAMCAEN1290_WINOFFSET : caen1290tdcconfig->WINOFFSET = val; break;
3210
3211 default:
3212 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3212<<" "
<< "UNKNOWN DAQ Config Parameter type: 0x" << hex << ptype << dec << endl;
3213 }
3214#endif
3215
3216 iptr++;
3217 }
3218
3219 // If we get here it means we didn't exit in the switch(ptype>>16) statement above
3220 // so there is at least one DDAQConfig object we need to store. Get pointer to
3221 // first event's ObjList, creating it if needed.
3222 if(events.empty()) events.push_back(new ObjList());
3223 ObjList *objs = *(events.begin());
3224
3225 if(f250config ) objs->config_objs.push_back(f250config );
3226 if(f125config ) objs->config_objs.push_back(f125config );
3227 if(f1tdcconfig ) objs->config_objs.push_back(f1tdcconfig );
3228 if(caen1290tdcconfig) objs->config_objs.push_back(caen1290tdcconfig);
3229 }
3230
3231 if(VERBOSE>5) evioout << " Leaving ParseModuleConfiguration()" << endl;
3232}
3233
3234//----------------
3235// ParseEventTag
3236//----------------
3237void JEventSource_EVIO::ParseEventTag(const uint32_t* &iptr, const uint32_t *iend, list<ObjList*> &events)
3238{
3239 if(!PARSE_EVENTTAG){ iptr = iend; return; }
3240
3241 if(VERBOSE>5) evioout << " Entering ParseEventTag() (events.size()="<<events.size()<<")" << endl;
3242
3243 // Make sure there is one event in the event container
3244 // and get pointer to it.
3245 if(events.empty()) events.push_back(new ObjList());
3246 ObjList *objs = *(events.begin());
3247
3248
3249 DEventTag *etag = new DEventTag;
3250
3251 // event_status
3252 uint64_t lo = *iptr++;
3253 uint64_t hi = *iptr++;
3254 etag->event_status = (hi<<32) + lo;
3255
3256 // L3_status
3257 lo = *iptr++;
3258 hi = *iptr++;
3259 etag->L3_status = (hi<<32) + lo;
3260
3261 // L3_decision
3262 etag->L3_decision = (DL3Trigger::L3_decision_t)*iptr++;
3263
3264 // L3_algorithm
3265 etag->L3_algorithm = *iptr++;
3266
3267 objs->misc_objs.push_back(etag);
3268
3269
3270 if(VERBOSE>5) evioout << " Leaving ParseEventTag()" << endl;
3271}
3272
3273//----------------
3274// ParseJLabModuleData
3275//----------------
3276void JEventSource_EVIO::ParseJLabModuleData(int32_t rocid, const uint32_t* &iptr, const uint32_t *iend, list<ObjList*> &events)
3277{
3278 if(VERBOSE>5) evioout << " Entering ParseJLabModuleData()" << endl;
3279
3280 /// Parse a bank of data coming from one or more JLab modules.
3281 /// The data are assumed to follow the standard JLab format for
3282 /// block headers. If multiple modules are read out in a single
3283 /// chain block transfer, then the data will all be placed in
3284 /// a single EVIO bank and this will loop over the modules.
3285 while(iptr < iend){
3286
3287 if(VERBOSE>9) evioout << "Parsing word: " << hex << *iptr << dec << endl;
3288
3289 // This was observed in some CDC data. Not sure where it came from ...
3290 if(*iptr == 0xF800FAFA){
3291 if(VERBOSE>9) evioout << " 0xf800fafa is a known extra word. Skipping it ..." << endl;
3292 iptr++;
3293 continue;
3294 }
3295
3296 // Get module type from next word (bits 18-21)
3297 uint32_t mod_id = ((*iptr) >> 18) & 0x000F;
3298
3299 // The enum defined in DModuleType.h MUST be kept in alignment
3300 // with the DAQ group's definitions for modules types!
3301 MODULE_TYPE type = (MODULE_TYPE)mod_id;
3302 if(VERBOSE>5) evioout << " Encountered module type: " << type << " (=" << DModuleType::GetModule(type).GetName() << ")" << endl;
3303
3304 if(modtype_translate.find(type) != modtype_translate.end()){
3305 type = modtype_translate[type];
3306 if(VERBOSE>5) evioout << " switched module type to: " << type << " (=" << DModuleType::GetModule(type).GetName() << ")" << endl;
3307 }
3308
3309 // Parse buffer depending on module type
3310 // (Note that each of the ParseXXX routines called below will
3311 // update the "iptr" variable to point to the next word
3312 // after the block it parsed.)
3313 list<ObjList*> tmp_events;
3314 const uint32_t *istart=iptr; // just for UNKNOWN case below
3315 bool module_parsed = true;
3316 switch(type){
3317 case DModuleType::FADC250:
3318 Parsef250Bank(rocid, iptr, iend, tmp_events);
3319 break;
3320
3321 case DModuleType::FADC125:
3322 Parsef125Bank(rocid, iptr, iend, tmp_events);
3323 break;
3324
3325 case DModuleType::F1TDC32:
3326 ParseF1TDCBank(rocid, iptr, iend, tmp_events);
3327 break;
3328
3329 case DModuleType::F1TDC48:
3330 ParseF1TDCBank(rocid, iptr, iend, tmp_events);
3331 break;
3332
3333 case DModuleType::JLAB_TS:
3334 //ParseTSBank(rocid, iptr, iend, tmp_events); // This is not used
3335 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3335<<" "
<< "What the ? ! This data type isn't supposed to be here!!" << endl;
3336 break;
3337
3338 case DModuleType::TID:
3339 ParseTIBank(rocid, iptr, iend, tmp_events);
3340 break;
3341
3342 case DModuleType::UNKNOWN:
3343 default:
3344 jerr<<"Unknown module type ("<<mod_id<<") iptr=0x" << hex << iptr << dec << endl;
3345
3346 while(iptr<iend && ((*iptr) & 0xF8000000) != 0x88000000) iptr++; // Skip to JLab block trailer
3347 iptr++; // advance past JLab block trailer
3348 while(iptr<iend && *iptr == 0xF8000000) iptr++; // skip filler words after block trailer
3349 module_parsed = false;
3350 jerr<<"...skipping to 0x" << hex << iptr << dec << " (discarding " << (((uint64_t)iptr-(uint64_t)istart)/4) << " words)" << endl;
3351 break;
3352 }
3353
3354 if(VERBOSE>9) evioout << "Finished parsing (last word: " << hex << iptr[-1] << dec << ")" << endl;
3355
3356 if(module_parsed){
3357 if(VERBOSE>5) evioout << " Merging objects in ParseJLabModuleData" << endl;
3358 MergeObjLists(events, tmp_events);
3359 }
3360 }
3361
3362 if(VERBOSE>5) evioout << " Leaving ParseJLabModuleData()" << endl;
3363}
3364
3365//----------------
3366// Parsef250Bank
3367//----------------
3368void JEventSource_EVIO::Parsef250Bank(int32_t rocid, const uint32_t* &iptr, const uint32_t *iend, list<ObjList*> &events)
3369{
3370 /// Parse data from a single FADC250 module.
3371
3372 if(!PARSE_F250){ iptr = iend; return; }
3373
3374 // This will get updated to point to a newly allocated object when an
3375 // event header is encountered. The existing value (if non-NULL) is
3376 // added to the events queue first though so all events are kept.
3377 ObjList *objs = NULL__null;
3378
3379 // From the Block Header
3380 uint32_t slot=0;
3381 //uint32_t Nblock_events;
3382 //uint32_t iblock;
3383
3384 // From the Block Trailer
3385 //uint32_t slot_trailer;
3386 //uint32_t Nwords_in_block;
3387
3388 // From Event header
3389 //uint32_t slot_event_header;
3390 uint32_t itrigger = -1;
3391 uint32_t last_itrigger = -2;
3392
3393 // Loop over data words
3394 for(; iptr<iend; iptr++){
3395
3396 // Skip all non-data-type-defining words at this
3397 // level. When we do encounter one, the appropriate
3398 // case block below should handle parsing all of
3399 // the data continuation words and advance the iptr.
3400 if(((*iptr>>31) & 0x1) == 0)continue;
3401
3402 // Variables used inside of switch, but cannot be declared inside
3403 uint64_t t = 0L;
3404 uint32_t channel = 0;
3405 uint32_t sum = 0;
3406 uint32_t pulse_number = 0;
3407 uint32_t quality_factor = 0;
3408 uint32_t pulse_time = 0;
3409 uint32_t pedestal = 0;
3410 uint32_t pulse_peak = 0;
3411 uint32_t nsamples_integral = 0;
3412 uint32_t nsamples_pedestal = 0;
3413 bool overflow = false;
3414
3415 bool found_block_trailer = false;
3416 uint32_t data_type = (*iptr>>27) & 0x0F;
3417 switch(data_type){
3418 case 0: // Block Header
3419 slot = (*iptr>>22) & 0x1F;
3420 if(VERBOSE>7) evioout << " FADC250 Block Header: slot="<<slot<<" ("<<hex<<*iptr<<dec<<")"<<endl;
3421 //iblock= (*iptr>>8) & 0x03FF;
3422 //Nblock_events= (*iptr>>0) & 0xFF;
3423 break;
3424 case 1: // Block Trailer
3425 //slot_trailer = (*iptr>>22) & 0x1F;
3426 //Nwords_in_block = (*iptr>>0) & 0x3FFFFF;
3427 if(VERBOSE>7) evioout << " FADC250 Block Trailer"<<" ("<<hex<<*iptr<<dec<<")"<<endl;
3428 found_block_trailer = true;
3429 break;
3430 case 2: // Event Header
3431 //slot_event_header = (*iptr>>22) & 0x1F;
3432 itrigger = (*iptr>>0) & 0x3FFFFF;
3433 if(VERBOSE>7) evioout << " FADC250 Event Header: itrigger="<<itrigger<<" (objs=0x"<<hex<<objs<<dec<<", last_itrigger="<<last_itrigger<<", rocid="<<rocid<<", slot="<<slot<<")" <<" ("<<hex<<*iptr<<dec<<")" <<endl;
3434 if( (itrigger!=last_itrigger) || (objs==NULL__null) ){
3435 if(ENABLE_DISENTANGLING){
3436 if(objs){
3437 events.push_back(objs);
3438 objs = NULL__null;
3439 }
3440 }
3441 if(!objs) objs = new ObjList;
3442 last_itrigger = itrigger;
3443 }
3444 break;
3445 case 3: // Trigger Time
3446 t = ((*iptr)&0xFFFFFF)<<0;
3447 if(VERBOSE>7) evioout << " FADC250 Trigger Time: t="<<t<<" ("<<hex<<*iptr<<dec<<")"<<endl;
3448 iptr++;
3449 if(((*iptr>>31) & 0x1) == 0){
3450 t += ((*iptr)&0xFFFFFF)<<24; // from word on the street: second trigger time word is optional!!??
3451 if(VERBOSE>7) evioout << " Trigger time high word="<<(((*iptr)&0xFFFFFF))<<" ("<<hex<<*iptr<<dec<<")"<<endl;
3452 }else{
3453 iptr--;
3454 }
3455 if(objs) objs->hit_objs.push_back(new Df250TriggerTime(rocid, slot, itrigger, t));
3456 break;
3457 case 4: // Window Raw Data
3458 // iptr passed by reference and so will be updated automatically
3459 if(VERBOSE>7) evioout << " FADC250 Window Raw Data"<<" ("<<hex<<*iptr<<dec<<")"<<endl;
3460 MakeDf250WindowRawData(objs, rocid, slot, itrigger, iptr);
3461 break;
3462 case 5: // Window Sum
3463 channel = (*iptr>>23) & 0x0F;
3464 sum = (*iptr>>0) & 0x3FFFFF;
3465 overflow = (*iptr>>22) & 0x1;
3466 if(VERBOSE>7) evioout << " FADC250 Window Sum"<<" ("<<hex<<*iptr<<dec<<")"<<endl;
3467 if(objs) objs->hit_objs.push_back(new Df250WindowSum(rocid, slot, channel, itrigger, sum, overflow));
3468 break;
3469 case 6: // Pulse Raw Data
3470 // iptr passed by reference and so will be updated automatically
3471 if(VERBOSE>7) evioout << " FADC250 Pulse Raw Data"<<" ("<<hex<<*iptr<<dec<<")"<<endl;
3472 MakeDf250PulseRawData(objs, rocid, slot, itrigger, iptr);
3473 break;
3474 case 7: // Pulse Integral
3475 channel = (*iptr>>23) & 0x0F;
3476 pulse_number = (*iptr>>21) & 0x03;
3477 quality_factor = (*iptr>>19) & 0x03;
3478 sum = (*iptr>>0) & 0x7FFFF;
3479 nsamples_integral = 0; // must be overwritten later in GetObjects with value from Df125Config value
3480 nsamples_pedestal = 1; // The firmware returns an already divided pedestal
3481 pedestal = 0; // This will be replaced by the one from Df250PulsePedestal in GetObjects
3482 if(VERBOSE>7) evioout << " FADC250 Pulse Integral: chan="<<channel<<" pulse_number="<<pulse_number<<" sum="<<sum<<" ("<<hex<<*iptr<<dec<<")"<<endl;
3483 if( (objs!=NULL__null) && (pulse_number<F250PULSE_NUMBER_FILTER) ) {
3484 objs->hit_objs.push_back(new Df250PulseIntegral(rocid, slot, channel, itrigger, pulse_number,
3485 quality_factor, sum, pedestal, nsamples_integral, nsamples_pedestal));
3486 }
3487 break;
3488 case 8: // Pulse Time
3489 channel = (*iptr>>23) & 0x0F;
3490 pulse_number = (*iptr>>21) & 0x03;
3491 quality_factor = (*iptr>>19) & 0x03;
3492 pulse_time = (*iptr>>0) & 0x7FFFF;
3493 if(VERBOSE>7) evioout << " FADC250 Pulse Time: chan="<<channel<<" pulse_number="<<pulse_number<<" pulse_time="<<pulse_time<<" ("<<hex<<*iptr<<dec<<")"<<endl;
3494 if( (objs!=NULL__null) && (pulse_number<F250PULSE_NUMBER_FILTER) ) {
3495 objs->hit_objs.push_back(new Df250PulseTime(rocid, slot, channel, itrigger, pulse_number, quality_factor, pulse_time));
3496 }
3497 break;
3498 case 9: // Streaming Raw Data
3499 // This is marked "reserved for future implementation" in the current manual (v2).
3500 // As such, we don't try handling it here just yet.
3501 if(VERBOSE>7) evioout << " FADC250 Streaming Raw Data (unsupported)"<<" ("<<hex<<*iptr<<dec<<")"<<endl;
3502 break;
3503 case 10: // Pulse Pedestal
3504 channel = (*iptr>>23) & 0x0F;
3505 pulse_number = (*iptr>>21) & 0x03;
3506 pedestal = (*iptr>>12) & 0x1FF;
3507 pulse_peak = (*iptr>>0) & 0xFFF;
3508 if(VERBOSE>7) evioout << " FADC250 Pulse Pedestal chan="<<channel<<" pulse_number="<<pulse_number<<" pedestal="<<pedestal<<" pulse_peak="<<pulse_peak<<" ("<<hex<<*iptr<<dec<<")"<<endl;
3509 if( (objs!=NULL__null) && (pulse_number<F250PULSE_NUMBER_FILTER) ) {
3510 objs->hit_objs.push_back(new Df250PulsePedestal(rocid, slot, channel, itrigger, pulse_number, pedestal, pulse_peak));
3511 }
3512 break;
3513 case 13: // Event Trailer
3514 // This is marked "suppressed for normal readout – debug mode only" in the
3515 // current manual (v2). It does not contain any data so the most we could do here
3516 // is return early. I'm hesitant to do that though since it would mean
3517 // different behavior for debug mode data as regular data.
3518 case 14: // Data not valid (empty module)
3519 case 15: // Filler (non-data) word
3520 if(VERBOSE>7) evioout << " FADC250 Event Trailer, Data not Valid, or Filler word ("<<data_type<<")"<<" ("<<hex<<*iptr<<dec<<")"<<endl;
3521 break;
3522 }
3523
3524 // Once we find a block trailer, assume that is it for this module.
3525 if(found_block_trailer){
3526 iptr++; // iptr is still pointing to block trailer. Jump to next word.
3527 break;
3528 }
3529 }
3530
3531 // Chop off filler words
3532 for(; iptr<iend; iptr++){
3533 if(((*iptr)&0xf8000000) != 0xf8000000) break;
3534 }
3535
3536 // Add last event in block to list
3537 if(objs)events.push_back(objs);
3538
3539 // Here, we make object associations to link PulseIntegral, PulseTime, PulseRawData, etc
3540 // objects to each other so it is easier to get to these downstream without having to
3541 // make nested loops. This is the most efficient place to do it since the ObjList objects
3542 // in "event" contain only the objects from this EVIO block (i.e. at most one crate's
3543 // worth.)
3544 list<ObjList*>::iterator iter = events.begin();
3545 for(; iter!=events.end(); iter++){
3546
3547 // Sort list of objects into type-specific lists
3548 vector<DDAQAddress*> &hit_objs = (*iter)->hit_objs;
3549 vector<Df250TriggerTime*> vtrigt;
3550 vector<Df250WindowRawData*> vwrd;
3551 vector<Df250WindowSum*> vws;
3552 vector<Df250PulseRawData*> vprd;
3553 vector<Df250PulseIntegral*> vpi;
3554 vector<Df250PulseTime*> vpt;
3555 vector<Df250PulsePedestal*> vpp;
3556 for(unsigned int i=0; i<hit_objs.size(); i++){
3557 AddIfAppropriate(hit_objs[i], vtrigt);
3558 AddIfAppropriate(hit_objs[i], vwrd);
3559 AddIfAppropriate(hit_objs[i], vws);
3560 AddIfAppropriate(hit_objs[i], vprd);
3561 AddIfAppropriate(hit_objs[i], vpi);
3562 AddIfAppropriate(hit_objs[i], vpt);
3563 AddIfAppropriate(hit_objs[i], vpp);
3564 }
3565
3566 // Connect Df250PulseIntegral, Df250PulseTime, and
3567 // Df250PulsePedestal with Df250PulseRawData
3568 // (n.b. the associations between pi, pt, and pp are
3569 // done in GetObjects where emulated objects are
3570 // also available.)
3571 LinkAssociationsWithPulseNumber(vprd, vpi);
3572 LinkAssociationsWithPulseNumber(vprd, vpt);
3573 LinkAssociationsWithPulseNumber(vprd, vpp);
3574
3575 // Connect Df250WindowSum and Df250WindowRawData
3576 LinkAssociations(vwrd, vws);
3577
3578 // Connect Df250TriggerTime to everything
3579 LinkAssociationsModuleOnly(vtrigt, vwrd);
3580 LinkAssociationsModuleOnly(vtrigt, vws);
3581 LinkAssociationsModuleOnly(vtrigt, vprd);
3582 LinkAssociationsModuleOnly(vtrigt, vpi);
3583 LinkAssociationsModuleOnly(vtrigt, vpt);
3584 LinkAssociationsModuleOnly(vtrigt, vpp);
3585 }
3586}
3587
3588//----------------
3589// MakeDf250WindowRawData
3590//----------------
3591void JEventSource_EVIO::MakeDf250WindowRawData(ObjList *objs, uint32_t rocid, uint32_t slot, uint32_t itrigger, const uint32_t* &iptr)
3592{
3593 uint32_t channel = (*iptr>>23) & 0x0F;
3594 uint32_t window_width = (*iptr>>0) & 0x0FFF;
3595
3596 Df250WindowRawData *wrd = new Df250WindowRawData(rocid, slot, channel, itrigger);
3597
3598 for(uint32_t isample=0; isample<window_width; isample +=2){
3599
3600 // Advance to next word
3601 iptr++;
3602
3603 // Make sure this is a data continuation word, if not, stop here
3604 if(((*iptr>>31) & 0x1) != 0x0){
3605 iptr--; // calling method expects us to point to last word in block
3606 break;
3607 }
3608
3609 bool invalid_1 = (*iptr>>29) & 0x1;
3610 bool invalid_2 = (*iptr>>13) & 0x1;
3611 uint16_t sample_1 = 0;
3612 uint16_t sample_2 = 0;
3613 if(!invalid_1)sample_1 = (*iptr>>16) & 0x1FFF;
3614 if(!invalid_2)sample_2 = (*iptr>>0) & 0x1FFF;
3615
3616 // Sample 1
3617 wrd->samples.push_back(sample_1);
3618 wrd->invalid_samples |= invalid_1;
3619 wrd->overflow |= (sample_1>>12) & 0x1;
3620
3621 if((isample+2) == window_width && invalid_2)break; // skip last sample if flagged as invalid
3622
3623 // Sample 2
3624 wrd->samples.push_back(sample_2);
3625 wrd->invalid_samples |= invalid_2;
3626 wrd->overflow |= (sample_2>>12) & 0x1;
3627 }
3628
3629 // Due to how the calling function works, the value of "objs" passed to us may be NULL.
3630 // This will happen if a Window Raw Data block is encountered before an event header.
3631 // For these cases, we still want to try parsing the data so that the iptr is updated
3632 // but don't have an event to assign it to. If "objs" is non-NULL, add this object to
3633 // the list. Otherwise, delete it now.
3634 if(objs){
3635 objs->hit_objs.push_back(wrd);
3636 }else{
3637 delete wrd;
3638 }
3639}
3640
3641//----------------
3642// MakeDf250PulseRawData
3643//----------------
3644void JEventSource_EVIO::MakeDf250PulseRawData(ObjList *objs, uint32_t rocid, uint32_t slot, uint32_t itrigger, const uint32_t* &iptr)
3645{
3646 const uint32_t *istart = iptr;
3647 uint32_t channel = (*iptr>>23) & 0x0F;
3648 uint32_t pulse_number = (*iptr>>21) & 0x0003;
3649 uint32_t first_sample_number = (*iptr>>0) & 0x03FF;
3650
3651 if(VERBOSE>9) evioout << " DF250PulseRawData: iptr=0x" << hex << iptr << dec << " channel=" << channel << " pulse_number=" << pulse_number << " first_sample=" << first_sample_number << endl;
3652
3653 Df250PulseRawData *prd = new Df250PulseRawData(rocid, slot, channel, itrigger, pulse_number, first_sample_number);
3654
3655 // This loop needs to break when it hits a non-continuation word
3656 for(uint32_t isample=0; isample<1000; isample +=2){
3657
3658 // Advance to next word
3659 iptr++;
3660
3661 // Make sure this is a data continuation word, if not, stop here
3662 if(((*iptr>>31) & 0x1) != 0x0)break;
3663
3664 bool invalid_1 = (*iptr>>29) & 0x1;
3665 bool invalid_2 = (*iptr>>13) & 0x1;
3666 uint16_t sample_1 = 0;
3667 uint16_t sample_2 = 0;
3668 if(!invalid_1)sample_1 = (*iptr>>16) & 0x1FFF;
3669 if(!invalid_2)sample_2 = (*iptr>>0) & 0x1FFF;
3670
3671 // Sample 1
3672 prd->samples.push_back(sample_1);
3673 prd->invalid_samples |= invalid_1;
3674 prd->overflow |= (sample_1>>12) & 0x1;
3675
3676 bool last_word = (iptr[1]>>31) & 0x1;
3677 if(last_word && invalid_2)break; // skip last sample if flagged as invalid
3678
3679 // Sample 2
3680 prd->samples.push_back(sample_2);
3681 prd->invalid_samples |= invalid_2;
3682 prd->overflow |= (sample_2>>12) & 0x1;
3683 }
3684
3685 if(VERBOSE>9) evioout << " number of samples: " << prd->samples.size() << " words processed: " << iptr-istart << endl;
3686
3687 // When should get here because the loop above stopped when it found
3688 // a data defining word (bit 31=1). The method calling this one will
3689 // assume iptr is pointing to the last word of this block and it will
3690 // advance to the first word of the next block. We need to back up one
3691 // word so that it is pointing to the last word of this block.
3692 iptr--;
3693
3694 // Due to how the calling function works, the value of "objs" passed to us may be NULL.
3695 // This will happen if a Window Raw Data block is encountered before an event header.
3696 // For these cases, we still want to try parsing the data so that the iptr is updated
3697 // but don't have an event to assign it to. If "objs" is non-NULL, add this object to
3698 // the list. Otherwise, delete it now.
3699 if(objs){
3700 objs->hit_objs.push_back(prd);
3701 }else{
3702 delete prd;
3703 }
3704}
3705
3706//----------------
3707// Parsef125Bank
3708//----------------
3709void JEventSource_EVIO::Parsef125Bank(int32_t rocid, const uint32_t* &iptr, const uint32_t* iend, list<ObjList*> &events)
3710{
3711 /// Parse data from a single FADC125 module.
3712 /// This is currently written assuming that the Pulse Integral, Pulse Time, and Pulse Pedestal
3713 /// data formats follow what is in the file:
3714 /// https://halldweb1.jlab.org/wiki/index.php/File:FADC125_dataformat_250_modes.docx
3715
3716 if(!PARSE_F125){ iptr = iend; return; }
3717
3718 if(VERBOSE>6) evioout << " Entering Parsef125Bank for rocid=" << rocid << "..."<<endl;
3719
3720 // This will get updated to point to a newly allocated object when an
3721 // event header is encountered. The existing value (if non-NULL) is
3722 // added to the events queue first though so all events are kept.
3723 ObjList *objs = NULL__null;
3724
3725 // From the Block Header
3726 uint32_t slot=0;
3727 //uint32_t Nblock_events;
3728 //uint32_t iblock;
3729
3730 // From the Block Trailer
3731 //uint32_t slot_trailer;
3732 //uint32_t Nwords_in_block;
3733
3734 // From Event header
3735 //uint32_t slot_event_header;
3736 uint32_t itrigger = -1;
3737 uint32_t last_itrigger = -2;
3738 uint32_t last_pulse_time_channel=0;
3739 uint32_t last_slot = -1;
3740 uint32_t last_channel = -1;
3741
3742 // Loop over data words
3743 for(; iptr<iend; iptr++){
3744
3745 // Skip all non-data-type-defining words at this
3746 // level. When we do encounter one, the appropriate
3747 // case block below should handle parsing all of
3748 // the data continuation words and advance the iptr.
3749 if(((*iptr>>31) & 0x1) == 0)continue;
3750
3751 // Variables used inside of switch, but cannot be declared inside
3752 uint64_t t = 0L;
3753 uint32_t channel = 0;
3754 uint32_t sum = 0;
3755 uint32_t pulse_number = 0;
3756 uint32_t pulse_time = 0;
3757 uint32_t quality_factor = 0;
3758 uint32_t overflow_count = 0;
3759 uint32_t pedestal = 0;
3760 uint32_t pulse_peak = 0;
3761 uint32_t peak_time = 0;
3762 uint32_t nsamples_integral = 0;
3763 uint32_t nsamples_pedestal = 0;
3764 uint32_t word1=0;
3765 uint32_t word2=0;
3766
3767 bool found_block_trailer = false;
3768 uint32_t data_type = (*iptr>>27) & 0x0F;
3769 switch(data_type){
3770 case 0: // Block Header
3771 slot = (*iptr>>22) & 0x1F;
3772 if(VERBOSE>7) evioout << " FADC125 Block Header: slot="<<slot<<endl;
3773 //iblock= (*iptr>>8) & 0x03FF;
3774 //Nblock_events= (*iptr>>0) & 0xFF;
3775 break;
3776 case 1: // Block Trailer
3777 //slot_trailer = (*iptr>>22) & 0x1F;
3778 //Nwords_in_block = (*iptr>>0) & 0x3FFFFF;
3779 found_block_trailer = true;
3780 break;
3781 case 2: // Event Header
3782 //slot_event_header = (*iptr>>22) & 0x1F;
3783 itrigger = (*iptr>>0) & 0x3FFFFFF;
3784 if(VERBOSE>7) evioout << " FADC125 Event Header: itrigger="<<itrigger<<" (objs=0x"<<hex<<objs<<dec<<", last_itrigger="<<last_itrigger<<", rocid="<<rocid<<", slot="<<slot<<")" <<endl;
3785 if( (itrigger!=last_itrigger) || (objs==NULL__null) ){
3786 if(ENABLE_DISENTANGLING){
3787 if(objs){
3788 events.push_back(objs);
3789 objs = NULL__null;
3790 }
3791 }
3792 if(!objs) objs = new ObjList;
3793 last_itrigger = itrigger;
3794 }
3795 break;
3796 case 3: // Trigger Time
3797 t = ((*iptr)&0xFFFFFF)<<24; // n.b. Documentation is incorrect! This is opposite of f250 (see e-mail from Naomi/Cody on 4/28/2016)
3798 iptr++;
3799 if(((*iptr>>31) & 0x1) == 0){
3800 t += ((*iptr)&0xFFFFFF)<<0; // (see above)
3801 }else{
3802 iptr--;
3803 }
3804 if(VERBOSE>7) evioout << " FADC125 Trigger Time (t="<<t<<")"<<endl;
3805 if(objs) objs->hit_objs.push_back(new Df125TriggerTime(rocid, slot, itrigger, t));
3806 break;
3807 case 4: // Window Raw Data
3808 // iptr passed by reference and so will be updated automatically
3809 if(VERBOSE>7) evioout << " FADC125 Window Raw Data"<<endl;
3810 MakeDf125WindowRawData(objs, rocid, slot, itrigger, iptr);
3811 break;
3812
3813 case 5: // CDC pulse data (new) (GlueX-doc-2274-v8)
3814
3815 // Word 1:
3816 word1 = *iptr;
3817 channel = (*iptr>>20) & 0x7F;
3818 pulse_number = (*iptr>>15) & 0x1F;
3819 pulse_time = (*iptr>>4 ) & 0x7FF;
3820 quality_factor = (*iptr>>3 ) & 0x1; //time QF bit
3821 overflow_count = (*iptr>>0 ) & 0x7;
3822 if(VERBOSE>8) evioout << " FADC125 CDC Pulse Data word1: " << hex << (*iptr) << dec << endl;
3823 if(VERBOSE>7) evioout << " FADC125 CDC Pulse Data (chan="<<channel<<" pulse="<<pulse_number<<" time="<<pulse_time<<" QF="<<quality_factor<<" OC="<<overflow_count<<")"<<endl;
3824
3825 // Word 2:
3826 ++iptr;
3827 if(iptr>=iend){
3828 jerr << " Truncated f125 CDC hit (block ends before continuation word!)" << endl;
3829 continue;
3830 }
3831 if( ((*iptr>>31) & 0x1) != 0 ){
3832 jerr << " Truncated f125 CDC hit (missing continuation word!)" << endl;
3833 continue;
3834 }
3835 word2 = *iptr;
3836 pedestal = (*iptr>>23) & 0xFF;
3837 sum = (*iptr>>9 ) & 0x3FFF;
3838 pulse_peak = (*iptr>>0 ) & 0x1FF;
3839 if(VERBOSE>8) evioout << " FADC125 CDC Pulse Data word2: " << hex << (*iptr) << dec << endl;
3840 if(VERBOSE>7) evioout << " FADC125 CDC Pulse Data (pedestal="<<pedestal<<" sum="<<sum<<" peak="<<pulse_peak<<")"<<endl;
3841
3842 // Create hit objects
3843 nsamples_integral = 0; // must be overwritten later in GetObjects with value from Df125Config value
3844 nsamples_pedestal = 1; // The firmware pedestal divided by 2^PBIT where PBIT is a config. parameter
3845
3846 if( (objs!=NULL__null) && (pulse_number<F125PULSE_NUMBER_FILTER) ) {
3847 // n.b. This is were we might apply a check on whether we are
3848 // only producing emulated objects. If so, then we shouldn't
3849 // create the Df125CDCPulse. At this point in time though,
3850 // there are 3 config. parameters that control this because
3851 // the original firmware produced 3 separate data types as
3852 // opposed to the new firmware that puts the same infomation
3853 // into a single data type. The emulation framework is also
3854 // being revamped.
3855 objs->hit_objs.push_back( new Df125CDCPulse(rocid, slot, channel, itrigger
3856 , pulse_number // NPK
3857 , pulse_time // le_time
3858 , quality_factor // time_quality_bit
3859 , overflow_count // overflow_count
3860 , pedestal // pedestal
3861 , sum // integral
3862 , pulse_peak // first_max_amp
3863 , word1 // word1
3864 , word2 // word2
3865 , nsamples_pedestal // nsamples_pedestal
3866 , nsamples_integral // nsamples_integral
3867 , false) // emulated
3868 );
3869 }
3870
3871 // n.b. We don't record last_slot, last_channel, etc... here since those
3872 // are only used by data types corresponding to older firmware that did
3873 // not write out data type 5.
3874 break;
3875
3876 case 6: // FDC pulse data-integral (new) (GlueX-doc-2274-v8)
3877
3878 // Word 1:
3879 word1 = *iptr;
3880 channel = (*iptr>>20) & 0x7F;
3881 pulse_number = (*iptr>>15) & 0x1F;
3882 pulse_time = (*iptr>>4 ) & 0x7FF;
3883 quality_factor = (*iptr>>3 ) & 0x1; //time QF bit
3884 overflow_count = (*iptr>>0 ) & 0x7;
3885 if(VERBOSE>8) evioout << " FADC125 FDC Pulse Data(integral) word1: " << hex << (*iptr) << dec << endl;
3886 if(VERBOSE>7) evioout << " FADC125 FDC Pulse Data (chan="<<channel<<" pulse="<<pulse_number<<" time="<<pulse_time<<" QF="<<quality_factor<<" OC="<<overflow_count<<")"<<endl;
3887
3888 // Word 2:
3889 ++iptr;
3890 if(iptr>=iend){
3891 jerr << " Truncated f125 FDC hit (block ends before continuation word!)" << endl;
3892 continue;
3893 }
3894 if( ((*iptr>>31) & 0x1) != 0 ){
3895 jerr << " Truncated f125 FDC hit (missing continuation word!)" << endl;
3896 continue;
3897 }
3898 word2 = *iptr;
3899 pulse_peak = 0;
3900 sum = (*iptr>>19) & 0xFFF;
3901 peak_time = (*iptr>>11) & 0xFF;
3902 pedestal = (*iptr>>0 ) & 0x7FF;
3903 if(VERBOSE>8) evioout << " FADC125 FDC Pulse Data(integral) word2: " << hex << (*iptr) << dec << endl;
3904 if(VERBOSE>7) evioout << " FADC125 FDC Pulse Data (integral="<<sum<<" time="<<peak_time<<" pedestal="<<pedestal<<")"<<endl;
3905
3906 // Create hit objects
3907 nsamples_integral = 0; // must be overwritten later in GetObjects with value from Df125Config value
3908 nsamples_pedestal = 1; // The firmware pedestal divided by 2^PBIT where PBIT is a config. parameter
3909
3910 if( (objs!=NULL__null) && (pulse_number<F125PULSE_NUMBER_FILTER) ) {
3911 // n.b. This is were we might apply a check on whether we are
3912 // only producing emulated objects. If so, then we shouldn't
3913 // create the Df125FDCPulse. At this point in time though,
3914 // there are 3 config. parameters that control this because
3915 // the original firmware produced 3 separate data types as
3916 // opposed to the new firmware that puts the same infomation
3917 // into a single data type. The emulation framework is also
3918 // being revamped.
3919 objs->hit_objs.push_back( new Df125FDCPulse(rocid, slot, channel, itrigger
3920 , pulse_number // NPK
3921 , pulse_time // le_time
3922 , quality_factor // time_quality_bit
3923 , overflow_count // overflow_count
3924 , pedestal // pedestal
3925 , sum // integral
3926 , pulse_peak // peak_amp
3927 , peak_time // peak_time
3928 , word1 // word1
3929 , word2 // word2
3930 , nsamples_pedestal // nsamples_pedestal
3931 , nsamples_integral // nsamples_integral
3932 , false) // emulated
3933 );
3934 }
3935
3936 // n.b. We don't record last_slot, last_channel, etc... here since those
3937 // are only used by data types corresponding to older firmware that did
3938 // not write out data type 6.
3939 break;
3940
3941 case 7: // Pulse Integral
3942 if(VERBOSE>7) evioout << " FADC125 Pulse Integral"<<endl;
3943 channel = (*iptr>>20) & 0x7F;
3944 sum = (*iptr>>0) & 0xFFFFF;
3945 nsamples_integral = 0; // must be overwritten later in GetObjects with value from Df125Config value
3946 nsamples_pedestal = 1; // The firmware returns an already divided pedestal
3947 pedestal = 0; // This will be replaced by the one from Df250PulsePedestal in GetObjects
3948 if (last_slot == slot && last_channel == channel) pulse_number = 1;
3949 last_slot = slot;
3950 last_channel = channel;
3951 if( (objs!=NULL__null) && (pulse_number<F125PULSE_NUMBER_FILTER) ) {
3952 objs->hit_objs.push_back(new Df125PulseIntegral(rocid, slot, channel, itrigger, pulse_number,
3953 quality_factor, sum, pedestal, nsamples_integral, nsamples_pedestal));
3954 }
3955 break;
3956 case 8: // Pulse Time
3957 if(VERBOSE>7) evioout << " FADC125 Pulse Time"<<endl;
3958 channel = (*iptr>>20) & 0x7F;
3959 pulse_number = (*iptr>>18) & 0x03;
3960 pulse_time = (*iptr>>0) & 0xFFFF;
3961 if( (objs!=NULL__null) && (pulse_number<F125PULSE_NUMBER_FILTER) ) {
3962 objs->hit_objs.push_back(new Df125PulseTime(rocid, slot, channel, itrigger, pulse_number, quality_factor, pulse_time));
3963 }
3964 last_pulse_time_channel = channel;
3965 break;
3966
3967 case 9: // FDC pulse data-peak (new) (GlueX-doc-2274-v8)
3968
3969 // Word 1:
3970 word1 = *iptr;
3971 channel = (*iptr>>20) & 0x7F;
3972 pulse_number = (*iptr>>15) & 0x1F;
3973 pulse_time = (*iptr>>4 ) & 0x7FF;
3974 quality_factor = (*iptr>>3 ) & 0x1; //time QF bit
3975 overflow_count = (*iptr>>0 ) & 0x7;
3976 if(VERBOSE>8) evioout << " FADC125 FDC Pulse Data(peak) word1: " << hex << (*iptr) << dec << endl;
3977 if(VERBOSE>7) evioout << " FADC125 FDC Pulse Data (chan="<<channel<<" pulse="<<pulse_number<<" time="<<pulse_time<<" QF="<<quality_factor<<" OC="<<overflow_count<<")"<<endl;
3978
3979 // Word 2:
3980 ++iptr;
3981 if(iptr>=iend){
3982 jerr << " Truncated f125 FDC hit (block ends before continuation word!)" << endl;
3983 continue;
3984 }
3985 if( ((*iptr>>31) & 0x1) != 0 ){
3986 jerr << " Truncated f125 FDC hit (missing continuation word!)" << endl;
3987 continue;
3988 }
3989 word2 = *iptr;
3990 pulse_peak = (*iptr>>19) & 0xFFF;
3991 sum = 0;
3992 peak_time = (*iptr>>11) & 0xFF;
3993 pedestal = (*iptr>>0 ) & 0x7FF;
3994 if(VERBOSE>8) evioout << " FADC125 FDC Pulse Data(peak) word2: " << hex << (*iptr) << dec << endl;
3995 if(VERBOSE>7) evioout << " FADC125 FDC Pulse Data (integral="<<sum<<" time="<<peak_time<<" pedestal="<<pedestal<<")"<<endl;
3996
3997 // Create hit objects
3998 nsamples_integral = 0; // must be overwritten later in GetObjects with value from Df125Config value
3999 nsamples_pedestal = 1; // The firmware pedestal divided by 2^PBIT where PBIT is a config. parameter
4000
4001 if( (objs!=NULL__null) && (pulse_number<F125PULSE_NUMBER_FILTER) ) {
4002 // n.b. This is were we might apply a check on whether we are
4003 // only producing emulated objects. If so, then we shouldn't
4004 // create the Df125FDCPulse. At this point in time though,
4005 // there are 3 config. parameters that control this because
4006 // the original firmware produced 3 separate data types as
4007 // opposed to the new firmware that puts the same infomation
4008 // into a single data type. The emulation framework is also
4009 // being revamped.
4010 objs->hit_objs.push_back( new Df125FDCPulse(rocid, slot, channel, itrigger
4011 , pulse_number // NPK
4012 , pulse_time // le_time
4013 , quality_factor // time_quality_bit
4014 , overflow_count // overflow_count
4015 , pedestal // pedestal
4016 , sum // integral
4017 , pulse_peak // peak_amp
4018 , peak_time // peak_time
4019 , word1 // word1
4020 , word2 // word2
4021 , nsamples_pedestal // nsamples_pedestal
4022 , nsamples_integral // nsamples_integral
4023 , false) // emulated
4024 );
4025 }
4026
4027 // n.b. We don't record last_slot, last_channel, etc... here since those
4028 // are only used by data types corresponding to older firmware that did
4029 // not write out data type 6.
4030 break;
4031
4032 case 10: // Pulse Pedestal (consistent with Beni's hand-edited version of Cody's document)
4033 if(VERBOSE>7) evioout << " FADC125 Pulse Pedestal"<<endl;
4034 //channel = (*iptr>>20) & 0x7F;
4035 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")
4036 pulse_number = (*iptr>>21) & 0x03;
4037 pedestal = (*iptr>>12) & 0x1FF;
4038 pulse_peak = (*iptr>>0) & 0xFFF;
4039 nsamples_pedestal = 1; // The firmware returns an already divided pedestal
4040 if( (objs!=NULL__null) && (pulse_number<F125PULSE_NUMBER_FILTER) ) {
4041 objs->hit_objs.push_back(new Df125PulsePedestal(rocid, slot, channel, itrigger, pulse_number, pedestal, pulse_peak, nsamples_pedestal));
4042 }
4043 break;
4044
4045 case 13: // Event Trailer
4046 case 14: // Data not valid (empty module)
4047 case 15: // Filler (non-data) word
4048 if(VERBOSE>7) evioout << " FADC125 ignored data type: " << data_type <<endl;
4049 break;
4050 }
4051
4052 // Once we find a block trailer, assume that is it for this module.
4053 if(found_block_trailer){
4054 iptr++; // iptr is still pointing to block trailer. Jump to next word.
4055 break;
4056 }
4057 }
4058
4059 // Chop off filler words
4060 for(; iptr<iend; iptr++){
4061 if(((*iptr)&0xf8000000) != 0xf8000000) break;
4062 }
4063
4064 // Add last event in block to list
4065 if(objs)events.push_back(objs);
4066
4067 // Here, we make object associations to link PulseIntegral, PulseTime, PulseRawData, etc
4068 // objects to each other so it is easier to get to these downstream without having to
4069 // make nested loops. This is the most efficient place to do it since the ObjList objects
4070 // in "event" contain only the objects from this EVIO block (i.e. at most one crate's
4071 // worth.)
4072 list<ObjList*>::iterator iter = events.begin();
4073 for(; iter!=events.end(); iter++){
4074
4075 // Sort list of objects into type-specific lists
4076 vector<DDAQAddress*> &hit_objs = (*iter)->hit_objs;
4077 vector<Df125TriggerTime*> vtrigt;
4078 vector<Df125WindowRawData*> vwrd;
4079 vector<Df125PulseRawData*> vprd;
4080 vector<Df125PulseIntegral*> vpi;
4081 vector<Df125PulseTime*> vpt;
4082 vector<Df125PulsePedestal*> vpp;
4083 for(unsigned int i=0; i<hit_objs.size(); i++){
4084 AddIfAppropriate(hit_objs[i], vtrigt);
4085 AddIfAppropriate(hit_objs[i], vwrd);
4086 AddIfAppropriate(hit_objs[i], vprd);
4087 AddIfAppropriate(hit_objs[i], vpi);
4088 AddIfAppropriate(hit_objs[i], vpt);
4089 AddIfAppropriate(hit_objs[i], vpp);
4090 }
4091
4092 // Connect Df125PulseIntegral with Df125PulseTime
4093 LinkAssociationsWithPulseNumber(vprd, vpi);
4094 LinkAssociationsWithPulseNumber(vprd, vpt);
4095 LinkAssociationsWithPulseNumber(vprd, vpp);
4096 LinkAssociationsWithPulseNumber(vpi, vpt);
4097 LinkAssociationsWithPulseNumber(vpi, vpp);
4098 LinkAssociationsWithPulseNumber(vpt, vpp);
4099
4100 // Connect Df125TriggerTime to everything
4101 LinkAssociationsModuleOnly(vtrigt, vwrd);
4102 LinkAssociationsModuleOnly(vtrigt, vprd);
4103 LinkAssociationsModuleOnly(vtrigt, vpi);
4104 LinkAssociationsModuleOnly(vtrigt, vpt);
4105 LinkAssociationsModuleOnly(vtrigt, vpp);
4106 }
4107
4108 if(VERBOSE>6) evioout << " Leaving Parsef125Bank"<<endl;
4109}
4110
4111//----------------
4112// MakeDf125WindowRawData
4113//----------------
4114void JEventSource_EVIO::MakeDf125WindowRawData(ObjList *objs, uint32_t rocid, uint32_t slot, uint32_t itrigger, const uint32_t* &iptr)
4115{
4116 uint32_t channel = (*iptr>>20) & 0x7F;
4117 uint32_t window_width = (*iptr>>0) & 0x0FFF;
4118
4119 Df125WindowRawData *wrd = new Df125WindowRawData(rocid, slot, channel, itrigger);
4120
4121 for(uint32_t isample=0; isample<window_width; isample +=2){
4122
4123 // Advance to next word
4124 iptr++;
4125
4126 // Make sure this is a data continuation word, if not, stop here
4127 if(((*iptr>>31) & 0x1) != 0x0)break;
4128
4129 bool invalid_1 = (*iptr>>29) & 0x1;
4130 bool invalid_2 = (*iptr>>13) & 0x1;
4131 uint16_t sample_1 = 0;
4132 uint16_t sample_2 = 0;
4133 if(!invalid_1)sample_1 = (*iptr>>16) & 0x1FFF;
4134 if(!invalid_2)sample_2 = (*iptr>>0) & 0x1FFF;
4135
4136 // Sample 1
4137 wrd->samples.push_back(sample_1);
4138 wrd->invalid_samples |= invalid_1;
4139 wrd->overflow |= (sample_1>>12) & 0x1;
4140
4141 if((isample+2) == window_width && invalid_2)break; // skip last sample if flagged as invalid
4142
4143 // Sample 2
4144 wrd->samples.push_back(sample_2);
4145 wrd->invalid_samples |= invalid_2;
4146 wrd->overflow |= (sample_2>>12) & 0x1;
4147 }
4148
4149 if(VERBOSE>7) evioout << " FADC125 - " << wrd->samples.size() << " samples" << endl;
4150
4151 // Due to how the calling function works, the value of "objs" passed to us may be NULL.
4152 // This will happen if a Window Raw Data block is encountered before an event header.
4153 // For these cases, we still want to try parsing the data so that the iptr is updated
4154 // but don't have an event to assign it to. If "objs" is non-NULL, add this object to
4155 // the list. Otherwise, delete it now.
4156 if(objs){
4157 objs->hit_objs.push_back(wrd);
4158 }else{
4159 delete wrd;
4160 }
4161}
4162
4163//----------------
4164// MakeDf125PulseRawData
4165//----------------
4166void JEventSource_EVIO::MakeDf125PulseRawData(ObjList *objs, uint32_t rocid, uint32_t slot, uint32_t itrigger, const uint32_t* &iptr)
4167{
4168 uint32_t channel = (*iptr>>23) & 0x0F;
4169 uint32_t pulse_number = (*iptr>>21) & 0x000F;
4170 uint32_t first_sample_number = (*iptr>>0) & 0x03FF;
4171
4172 Df125PulseRawData *prd = new Df125PulseRawData(rocid, slot, channel, itrigger, pulse_number, first_sample_number);
4173
4174 // This loop needs to break when it hits a non-continuation word
4175 for(uint32_t isample=0; isample<1000; isample +=2){
4176
4177 // Advance to next word
4178 iptr++;
4179
4180 // Make sure this is a data continuation word, if not, stop here
4181 if(((*iptr>>31) & 0x1) != 0x0)break;
4182
4183 bool invalid_1 = (*iptr>>29) & 0x1;
4184 bool invalid_2 = (*iptr>>13) & 0x1;
4185 uint16_t sample_1 = 0;
4186 uint16_t sample_2 = 0;
4187 if(!invalid_1)sample_1 = (*iptr>>16) & 0x1FFF;
4188 if(!invalid_2)sample_2 = (*iptr>>0) & 0x1FFF;
4189
4190 // Sample 1
4191 prd->samples.push_back(sample_1);
4192 prd->invalid_samples |= invalid_1;
4193 prd->overflow |= (sample_1>>12) & 0x1;
4194
4195 bool last_word = (iptr[1]>>31) & 0x1;
4196 if(last_word && invalid_2)break; // skip last sample if flagged as invalid
4197
4198 // Sample 2
4199 prd->samples.push_back(sample_2);
4200 prd->invalid_samples |= invalid_2;
4201 prd->overflow |= (sample_2>>12) & 0x1;
4202 }
4203
4204
4205 // Due to how the calling function works, the value of "objs" passed to us may be NULL.
4206 // This will happen if a Window Raw Data block is encountered before an event header.
4207 // For these cases, we still want to try parsing the data so that the iptr is updated
4208 // but don't have an event to assign it to. If "objs" is non-NULL, add this object to
4209 // the list. Otherwise, delete it now.
4210 if(objs){
4211 objs->hit_objs.push_back(prd);
4212 }else{
4213 delete prd;
4214 }
4215}
4216
4217//----------------
4218// ParseF1TDCBank
4219//----------------
4220void JEventSource_EVIO::ParseF1TDCBank(int32_t rocid, const uint32_t* &iptr, const uint32_t* iend, list<ObjList*> &events)
4221{
4222 /// Parse data from a single F1TDCv2 (32 ch) or F1TDCv3 (48 ch) module.
4223 /// This code is based on the document F1TDC_V2_V3_4_29_14.pdf obtained from:
4224 /// https://coda.jlab.org/wiki/index.php/JLab_Module_Manuals
4225
4226 if(!PARSE_F1TDC){ iptr = iend; return; }
4227
4228 if(VERBOSE>6) evioout << " Entering ParseF1TDCBank (rocid=" << rocid << ")" << endl;
4229
4230 const uint32_t *istart = iptr;
4231
4232 // Some early data had a marker word at just before the actual F1 data
4233 if(*iptr == 0xf1daffff) iptr++;
4234
4235 // Block header word
4236 // Double check that block header is set
4237 if( ((*iptr) & 0xF8000000) != 0x80000000 ){
4238 throw JException("F1TDC Block header corrupt! (high 5 bits not set to 0x80000000!)");
4239 }
4240
4241 uint32_t slot_block_header = (*iptr)>>22 & 0x001F;
4242 uint32_t block_num = (*iptr)>> 8 & 0x03FF;
4243 uint32_t Nevents_block_header = (*iptr)>> 0 & 0x00FF;
4244 int modtype = (*iptr)>>18 & 0x000F; // should match a DModuleType::type_id_t
4245 if(VERBOSE>5) evioout << " F1 Block Header: slot=" << slot_block_header << " block_num=" << block_num << " Nevents=" << Nevents_block_header << endl;
4246
4247 // Advance to next word
4248 iptr++;
4249
4250 // Loop over events
4251 ObjList *objs = NULL__null;
4252 while(iptr<iend){
4253
4254 // Event header
4255 // Double check that event header is set
4256 if( ((*iptr) & 0xF8000000) != 0x90000000 ){
4257 if(VERBOSE>10){
4258 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<4258<<" "
<<"Corrupt F1TDC Event header! Data dump follows (\"*\" indicates bad header word):" <<endl;
4259 DumpBinary(istart, iend, 0, iptr);
4260 }
4261 throw JException("F1TDC Event header corrupt! (high 5 bits not set to 0x90000000!)");
4262 }
4263
4264 uint32_t slot_event_header = (*iptr)>>22 & 0x00000001F;
4265 uint32_t itrigger = (*iptr)>>0 & 0x0003FFFFF;
4266 if(VERBOSE>5) evioout << " F1 Event Header: slot=" << slot_block_header << " itrigger=" << itrigger << endl;
4267
4268 // Make sure slot number from event header matches block header
4269 if(slot_event_header != slot_block_header){
4270 char str[256];
4271 sprintf(str, "F1TDC slot from event header(%d) doesn't match block header(%d)", slot_event_header, slot_block_header);
4272 throw JException(str);
4273 }
4274
4275 // Advance to timestamp word
4276 iptr++;
4277 if(iptr>=iend) throw JException("F1TDC data corrupt! Block truncated before timestamp word!");
4278
4279 // The most recent documentation says that the first time stamp
4280 // word holds the low 24 bits and the second the high 16 bits. According to Dave A.,
4281 // the second word is optional.
4282 uint32_t trig_time = ((*iptr)&0xFFFFFF);
4283 if(VERBOSE>6) evioout << " F1 Trigger time: low 24 bits=" << trig_time << endl;
4284 iptr++;
4285 if(iptr>=iend) throw JException("F1TDC data corrupt! Block truncated before trailer word!");
4286 if(((*iptr>>31) & 0x1) == 0){
4287 trig_time += ((*iptr)&0xFFFF)<<24; // from word on the street: second trigger time word is optional!!??
4288 if(VERBOSE>6) evioout << " F1 Trigger time: high 16 bits=" << ((*iptr)&0xFFFF) << " total trig_time=" << trig_time << endl;
4289 }else{
4290 iptr--; // second time word not present, back up pointer
4291 }
4292
4293 // Create a new object list (i.e. new event)
4294 if(objs!=NULL__null && ENABLE_DISENTANGLING){
4295 events.push_back(objs);
4296 objs = NULL__null;
4297 }
4298 if(!objs) objs = new ObjList;
4299
4300 if(objs) objs->hit_objs.push_back(new DF1TDCTriggerTime(rocid, slot_block_header, itrigger, trig_time));
4301
4302 // Advance past last timestamp word to first data word (or rather, F1 chip header)
4303 iptr++;
4304
4305 // Loop over F1 data words
4306 uint32_t chip_f1header=0, chan_on_chip_f1header=0, itrigger_f1header=0, trig_time_f1header=0;
4307 while( iptr<iend && ((*iptr)>>31)==0x1 ){
4308
4309 bool done = false;
4310
4311 uint32_t chip, chan_on_chip, time;
4312 uint32_t channel;
4313 DF1TDCHit *hit=NULL__null;
4314 switch( (*iptr) & 0xF8000000 ){
4315 case 0xC0000000: // F1 Header
4316 chip_f1header = ((*iptr)>> 3) & 0x07;
4317 chan_on_chip_f1header = ((*iptr)>> 0) & 0x07; // this is always 7 in real data!
4318 itrigger_f1header = ((*iptr)>>16) & 0x3F;
4319 trig_time_f1header = ((*iptr)>> 7) & 0x1FF;
4320 if(VERBOSE>5) evioout << " Found F1 header: chip=" << chip_f1header << " chan=" << chan_on_chip_f1header << " itrig=" << itrigger_f1header << " trig_time=" << trig_time_f1header << endl;
4321 //if( itrigger_f1header != (itrigger & 0x3F)) throw JException("Trigger number in F1 header word does not match Event header word!");
4322 break;
4323 case 0xB8000000: // F1 Data
4324 chip = (*iptr>>19) & 0x07;
4325 chan_on_chip = (*iptr>>16) & 0x07;
4326 time = (*iptr>> 0) & 0xFFFF;
4327 if(VERBOSE>5) evioout << " Found F1 data : chip=" << chip << " chan=" << chan_on_chip << " time=" << time << " (header: chip=" << chip_f1header << ")" << endl;
4328 //if(chip!=chip_f1header) throw JException("F1 chip number in data does not match header!");
4329 channel = F1TDC_channel(chip, chan_on_chip, modtype);
4330 hit = new DF1TDCHit(rocid, slot_block_header, channel, itrigger, trig_time_f1header, time, *iptr, MODULE_TYPE(modtype));
4331 if(objs)objs->hit_objs.push_back(hit);
4332 break;
4333 case 0xF8000000: // Filler word
4334 if(VERBOSE>7) evioout << " Found F1 filler word" << endl;
4335 break;
4336 case 0x80000000: // JLab block header (handled in outer loop)
4337 case 0x88000000: // JLab block trailer (handled in outer loop)
4338 case 0x90000000: // JLab event header (handled in outer loop)
4339 case 0x98000000: // Trigger time (handled in outer loop)
4340 case 0xF0000000: // module has no valid data available for read out (how to handle this?)
4341 if(VERBOSE>5) evioout << " Found F1 break word: 0x" << hex << *iptr << dec << endl;
4342 done = true;
4343 break;
4344 default:
4345 cerr<<endl;
4346 cout.flush(); cerr.flush();
4347 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<4347<<" "
<<"Unknown data word in F1TDC block. Dumping for debugging:" << endl;
4348 for(const uint32_t *iiptr = istart; iiptr<iend; iiptr++){
4349 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<4349<<" "
<<"0x"<<hex<<*iiptr<<dec;
4350 if(iiptr == iptr)cerr<<" <----";
4351 switch( (*iiptr) & 0xF8000000 ){
4352 case 0x80000000: cerr << " F1 Block Header"; break;
4353 case 0x90000000: cerr << " F1 Event Header"; break;
4354 case 0x98000000: cerr << " F1 Trigger time"; break;
4355 case 0xC0000000: cerr << " F1 Header"; break;
4356 case 0xB8000000: cerr << " F1 Data"; break;
4357 case 0x88000000: cerr << " F1 Block Trailer"; break;
4358 case 0xF8000000: cerr << " Filler word"; break;
4359 case 0xF0000000: cerr << " <module has no valid data>"; break;
4360 default: break;
4361 }
4362 cerr<<endl;
4363 if(iiptr > (iptr+4)) break;
4364 }
4365
4366 throw JException("Unexpected word type in F1TDC block!");
4367 }
4368
4369 if(done)break;
4370
4371 // Advance to next data word
4372 iptr++;
4373
4374 } // end loop over data words in this event
4375
4376 // If the current word is a JLab block trailer, then we are done
4377 if( ((*iptr) & 0xF8000000) == 0x88000000) break;
4378
4379 } // end loop over events
4380
4381 // Add hits for last event to list of events.
4382 if(objs)events.push_back(objs);
4383
4384 if( ((*iptr) & 0xF8000000) != 0x88000000 ){
4385 throw JException("F1TDC Block Trailer corrupt! (high 5 bits not set to 0x88000000!)");
4386 }
4387
4388 // Advance past JLab block trailer
4389 iptr++;
4390
4391 // Skip filler words
4392 while(iptr<iend && (*iptr&0xF8000000)==0xF8000000)iptr++;
4393
4394 // Double check that we found all of the events we were supposed to
4395 if(!ENABLE_DISENTANGLING) Nevents_block_header=1;
4396 if(events.size() != Nevents_block_header){
4397 stringstream ss;
4398 ss << "F1TDC missing events in block! (found "<< events.size() <<" but should have found "<<Nevents_block_header<<")";
4399 DumpBinary(istart, iend, 128);
4400 throw JException(ss.str());
4401 }
4402
4403 if(VERBOSE>6) evioout << " Leaving ParseF1TDCBank (rocid=" << rocid << ")" << endl;
4404
4405}
4406
4407//----------------
4408// F1TDC_channel
4409//----------------
4410uint32_t JEventSource_EVIO::F1TDC_channel(uint32_t chip, uint32_t chan_on_chip, int modtype)
4411{
4412 /// Convert a F1TDC chip number and channel on the chip to the
4413 /// front panel channel number. This is based on "Input Channel Mapping"
4414 /// section at the very bottom of the document F1TDC_V2_V3_4_29_14.pdf
4415
4416 uint32_t channel_map[8] = {0, 0, 1, 1, 2, 2, 3, 3};
4417 switch(modtype){
4418 case DModuleType::F1TDC32:
4419 return (4 * chip) + channel_map[ chan_on_chip&0x7 ];
4420 case DModuleType::F1TDC48:
4421 return (chip <<3) | chan_on_chip;
4422 default:
4423 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<4423<<" "
<< "Calling F1TDC_channel for module type: " << DModuleType::GetName((DModuleType::type_id_t)modtype) << endl;
4424 throw JException("F1TDC_channel called for non-F1TDC module type");
4425 }
4426 return 1000000; // (should never get here)
4427}
4428
4429//----------------
4430// ParseTSBank
4431//----------------
4432void JEventSource_EVIO::ParseTSBank(int32_t rocid, const uint32_t* &iptr, const uint32_t* iend, list<ObjList*> &events)
4433{
4434 /// Parse data written to the TS roc data during sync events.
4435 /// This is written by the ts_scalers routine in the conf_utils.c
4436 /// file and called from ts_list.c
4437
4438 uint32_t Nwords = ((uint64_t)iend - (uint64_t)iptr)/sizeof(uint32_t);
4439 uint32_t Nwords_expected = (6+32+16+32+16);
4440 if(Nwords != Nwords_expected){
4441 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<4441<<" "
<< "TS bank size does not match expected!!" << endl;
4442 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<4442<<" "
<< "Found " << Nwords << " words. Expected " << Nwords_expected << endl;
4443
4444 }else{
4445 DTSscalers *s = new DTSscalers;
4446 s->nsync_event = *iptr++;
4447 s->int_count = *iptr++;
4448 s->live_time = *iptr++;
4449 s->busy_time = *iptr++;
4450 s->inst_livetime = *iptr++;
4451 s->time = *iptr++;
4452 for(uint32_t i=0; i<32; i++) s->gtp_scalers[i] = *iptr++;
4453 for(uint32_t i=0; i<16; i++) s->fp_scalers[i] = *iptr++;
4454 for(uint32_t i=0; i<32; i++) s->gtp_rate[i] = *iptr++;
4455 for(uint32_t i=0; i<16; i++) s->fp_rate[i] = *iptr++;
4456
4457 if(events.empty()) events.push_back(new ObjList);
4458 ObjList *objs = *(events.begin());
4459 objs->misc_objs.push_back(s);
4460 }
4461
4462 iptr = iend;
4463}
4464
4465//----------------
4466// ParseTIBank
4467//----------------
4468void JEventSource_EVIO::ParseTIBank(int32_t rocid, const uint32_t* &iptr, const uint32_t* iend, list<ObjList*> &events)
4469{
4470 while(iptr<iend && ((*iptr) & 0xF8000000) != 0x88000000) iptr++; // Skip to JLab block trailer
4471 iptr++; // advance past JLab block trailer
4472 while(iptr<iend && *iptr == 0xF8000000) iptr++; // skip filler words after block trailer
4473 //iptr = iend;
4474}
4475
4476//----------------
4477// ParseCAEN1190
4478//----------------
4479void JEventSource_EVIO::ParseCAEN1190(int32_t rocid, const uint32_t* &iptr, const uint32_t *iend, list<ObjList*> &events)
4480{
4481 /// Parse data from a CAEN 1190 or 1290 module
4482 /// (See ppg. 72-74 of V1290_REV15.pdf manual)
4483
4484 if(!PARSE_CAEN1290TDC){ iptr = iend; return; }
4485
4486 uint32_t slot = 0;
4487 uint32_t event_count = 0;
4488 uint32_t word_count = 0;
4489 uint32_t trigger_time_tag = 0;
4490 uint32_t tdc_num = 0;
4491 uint32_t event_id = 0;
4492 uint32_t bunch_id = 0;
4493
4494 // We need to accomodate multi-event blocks where
4495 // events are entangled (i.e. hits from event 1
4496 // are mixed inbetween those of event 2,3,4,
4497 // etc... With CAEN modules, we only know which
4498 // event a hit came from by looking at the event_id
4499 // in the TDC header. This value is only 12 bits
4500 // and could roll over within an event block. This
4501 // means we need to keep track of the order we
4502 // encounter them in so it is maintained in the
4503 // "events" container. The event_id order is kept
4504 // in the "event_id_order" vector.
4505 map<uint32_t, vector<DCAEN1290TDCHit*> > hits_by_event_id;
4506 vector<uint32_t> event_id_order;
4507
4508 while(iptr<iend){
4509
4510 // This word appears to be appended to the data.
4511 // Probably in the ROL. Ignore it if found.
4512 if(*iptr == 0xd00dd00d) {
4513 if(VERBOSE>7) evioout << " CAEN skipping 0xd00dd00d word" << endl;
4514 iptr++;
4515 continue;
4516 }
4517
4518 uint32_t type = (*iptr) >> 27;
4519 uint32_t edge = 0; // 1=trailing, 0=leading
4520 uint32_t channel = 0;
4521 uint32_t tdc = 0;
4522 uint32_t error_flags = 0;
4523 DCAEN1290TDCHit *caen1290tdchit = NULL__null;
4524 map<uint32_t, ObjList*>::iterator iter;
4525 switch(type){
4526 case 0b01000: // Global Header
4527 slot = (*iptr) & 0x1f;
4528 event_count = ((*iptr)>>5) & 0xffffff;
4529 if(VERBOSE>7) evioout << " CAEN TDC Global Header (slot=" << slot << " , event count=" << event_count << ")" << endl;
4530 break;
4531 case 0b10000: // Global Trailer
4532 slot = (*iptr) & 0x1f;
4533 word_count = ((*iptr)>>5) & 0x7ffff;
4534 if(VERBOSE>7) evioout << " CAEN TDC Global Trailer (slot=" << slot << " , word count=" << word_count << ")" << endl;
4535 slot = event_count = word_count = trigger_time_tag = tdc_num = event_id = bunch_id = 0;
4536 break;
4537 case 0b10001: // Global Trigger Time Tag
4538 trigger_time_tag = ((*iptr)>>5) & 0x7ffffff;
4539 if(VERBOSE>7) evioout << " CAEN TDC Global Trigger Time Tag (tag=" << trigger_time_tag << ")" << endl;
4540 break;
4541 case 0b00001: // TDC Header
4542 tdc_num = ((*iptr)>>24) & 0x03;
4543 event_id = ((*iptr)>>12) & 0x0fff;
4544 bunch_id = (*iptr) & 0x0fff;
4545 if( find(event_id_order.begin(), event_id_order.end(), event_id) == event_id_order.end()){
4546 event_id_order.push_back(event_id);
4547 }
4548 if(VERBOSE>7) evioout << " CAEN TDC TDC Header (tdc=" << tdc_num <<" , event id=" << event_id <<" , bunch id=" << bunch_id << ")" << endl;
4549 break;
4550 case 0b00000: // TDC Measurement
4551 edge = ((*iptr)>>26) & 0x01;
4552 channel = ((*iptr)>>21) & 0x1f;
4553 tdc = ((*iptr)>>0) & 0x1fffff;
4554 if(VERBOSE>7) evioout << " CAEN TDC TDC Measurement (" << (edge ? "trailing":"leading") << " , channel=" << channel << " , tdc=" << tdc << ")" << endl;
4555
4556 // Create DCAEN1290TDCHit object
4557 caen1290tdchit = new DCAEN1290TDCHit(rocid, slot, channel, 0, edge, tdc_num, event_id, bunch_id, tdc);
4558 hits_by_event_id[event_id].push_back(caen1290tdchit);
4559 break;
4560 case 0b00100: // TDC Error
4561 error_flags = (*iptr) & 0x7fff;
4562 if(VERBOSE>7) evioout << " CAEN TDC TDC Error (err flags=0x" << hex << error_flags << dec << ")" << endl;
4563 break;
4564 case 0b00011: // TDC Trailer
4565 tdc_num = ((*iptr)>>24) & 0x03;
4566 event_id = ((*iptr)>>12) & 0x0fff;
4567 word_count = ((*iptr)>>0) & 0x0fff;
4568 if(VERBOSE>7) evioout << " CAEN TDC TDC Trailer (tdc=" << tdc_num <<" , event id=" << event_id <<" , word count=" << word_count << ")" << endl;
4569 tdc_num = event_id = bunch_id = 0;
4570 break;
4571 case 0b11000: // Filler Word
4572 if(VERBOSE>7) evioout << " CAEN TDC Filler Word" << endl;
4573 break;
4574 default:
4575 evioout << "Unknown datatype: 0x" << hex << type << " full word: "<< *iptr << dec << endl;
4576 }
4577
4578 iptr++;
4579 }
4580
4581 // If disentagling is disabled, then lump all hits into single event
4582 if( (!ENABLE_DISENTANGLING) && (event_id_order.size()>1) ){
4583 if(VERBOSE>2) evioout << " Disentangling disabled. Merging all hits into single event" << endl;
4584 vector<DCAEN1290TDCHit*> &hits1 = hits_by_event_id[event_id_order[0]];
4585 for(uint32_t i=1; i<event_id_order.size(); i++){
4586 vector<DCAEN1290TDCHit*> &hits2 = hits_by_event_id[event_id_order[i]];
4587 hits1.insert(hits1.end(), hits2.begin(), hits2.end()); // copy hits into first event
4588 hits_by_event_id.erase(event_id_order[i]); // remove hits list for this event_id
4589 }
4590 }
4591
4592 // Add hits for each event to the events container, creating ObjList's as needed
4593 for(uint32_t i=0; i<event_id_order.size(); i++){
4594
4595 // Make sure there are enough event containers to hold this event
4596 while(events.size() <= i) events.push_back(new ObjList);
4597 list<ObjList*>::iterator it = events.begin();
4598 advance(it, i);
4599 ObjList *objs = *it;
4600
4601 vector<DCAEN1290TDCHit*> &hits = hits_by_event_id[event_id_order[i]];
4602 objs->hit_objs.insert(objs->hit_objs.end(), hits.begin(), hits.end());
4603
4604 if(VERBOSE>7) evioout << " Added " << hits.size() << " hits with event_id=" << event_id_order[i] << " to event " << i << endl;
4605 }
4606
4607}
4608
4609//----------------
4610// ParseBORevent
4611//----------------
4612void JEventSource_EVIO::ParseBORevent(evioDOMNodeP bankPtr)
4613{
4614 if(!PARSE_BOR) return;
4615
4616 // This really shouldn't be needed
4617 pthread_rwlock_wrlock(&BOR_lock);
4618
4619 // Delete any existing BOR config objects. BOR events should
4620 // be flagged as sequential (or barrier) events so all threads
4621 // that were using these should be done with them now.
4622 for(uint32_t i=0; i<BORobjs.size(); i++) delete BORobjs[i];
4623 BORobjs.clear();
4624
4625 evioDOMNodeListP bankList = bankPtr->getChildren();
4626 evioDOMNodeList::iterator iter = bankList->begin();
4627 if(VERBOSE>7) evioout << " Looping over " << bankList->size() << " banks in BOR event" << endl;
4628 for(int ibank=1; iter!=bankList->end(); iter++, ibank++){ // ibank only used for debugging messages
4629 evioDOMNodeP childBank = *iter;
4630
4631 if(childBank->tag==0x71){
4632 // uint32_t rocid = childBank->num;
4633 evioDOMNodeListP bankList = childBank->getChildren();
4634 evioDOMNodeList::iterator iter = bankList->begin();
4635 for(; iter!=bankList->end(); iter++){
4636 evioDOMNodeP dataBank = *iter;
4637 // uint32_t slot = dataBank->tag>>5;
4638 uint32_t modType = dataBank->tag&0x1f;
4639
4640 const vector<uint32_t> *vec = dataBank->getVector<uint32_t>();
4641
4642 const uint32_t *src = &(*vec)[0];
4643 uint32_t *dest = NULL__null;
4644 uint32_t sizeof_dest = 0;
4645
4646 Df250BORConfig *f250conf = NULL__null;
4647 Df125BORConfig *f125conf = NULL__null;
4648 DF1TDCBORConfig *F1TDCconf = NULL__null;
4649 DCAEN1290TDCBORConfig *caen1190conf = NULL__null;
4650
4651 switch(modType){
4652 case DModuleType::FADC250: // f250
4653 f250conf = new Df250BORConfig;
4654 dest = (uint32_t*)&f250conf->rocid;
4655 sizeof_dest = sizeof(f250config);
4656 break;
4657 case DModuleType::FADC125: // f125
4658 f125conf = new Df125BORConfig;
4659 dest = (uint32_t*)&f125conf->rocid;
4660 sizeof_dest = sizeof(f125config);
4661 break;
4662
4663 case DModuleType::F1TDC32: // F1TDCv2
4664 case DModuleType::F1TDC48: // F1TDCv3
4665 F1TDCconf = new DF1TDCBORConfig;
4666 dest = (uint32_t*)&F1TDCconf->rocid;
4667 sizeof_dest = sizeof(F1TDCconfig);
4668 break;
4669
4670 case DModuleType::CAEN1190: // CAEN 1190 TDC
4671 case DModuleType::CAEN1290: // CAEN 1290 TDC
4672 caen1190conf = new DCAEN1290TDCBORConfig;
4673 dest = (uint32_t*)&caen1190conf->rocid;
4674 sizeof_dest = sizeof(caen1190config);
4675 break;
4676 }
4677
4678 // Check that the bank size and data structure size match.
4679 // If they do, then copy the data and add the object to
4680 // the event. If not, then delete the object and print
4681 // a warning message.
4682 if( vec->size() == (sizeof_dest/sizeof(uint32_t)) ){
4683
4684 // Copy bank data, assuming format is the same
4685 for(uint32_t i=0; i<vec->size(); i++) *dest++ = *src++;
4686
4687 // Store object for use in this and subsequent events
4688 if(f250conf) BORobjs.push_back(f250conf);
4689 if(f125conf) BORobjs.push_back(f125conf);
4690 if(F1TDCconf) BORobjs.push_back(F1TDCconf);
4691 if(caen1190conf) BORobjs.push_back(caen1190conf);
4692
4693 }else if(sizeof_dest>0){
4694 if(f250conf) delete f250conf;
4695 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<4695<<" "
<< "BOR bank size does not match structure! " << vec->size() <<" != " << (sizeof_dest/sizeof(uint32_t)) << endl;
4696 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<4696<<" "
<< "sizeof(f250config)="<<sizeof(f250config)<<endl;
4697 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<4697<<" "
<< "sizeof(f125config)="<<sizeof(f125config)<<endl;
4698 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<4698<<" "
<< "sizeof(F1TDCconfig)="<<sizeof(F1TDCconfig)<<endl;
4699 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<4699<<" "
<< "sizeof(caen1190config)="<<sizeof(caen1190config)<<endl;
4700 }
4701 }
4702 }
4703 }
4704
4705 pthread_rwlock_unlock(&BOR_lock);
4706
4707}
4708
4709
4710//----------------
4711// ParseTSSyncevent
4712//----------------
4713void JEventSource_EVIO::ParseTSSync(evioDOMNodeP bankPtr, list<ObjList*> &events)
4714{
4715
4716 DL1Info *trig_info = new DL1Info;
4717
4718 // cout << " INSIDE ParseTSSync " << endl;
4719
4720 if((bankPtr->tag & 0xFFFF) == 0xEE02){
4721 const vector<uint32_t> *vec = bankPtr->getVector<uint32_t>();
4722
4723 trig_info->nsync = (*vec)[0];
4724 trig_info->trig_number = (*vec)[1];
4725 trig_info->live_time = (*vec)[2];
4726 trig_info->busy_time = (*vec)[3];
4727 trig_info->live_inst = (*vec)[4];
4728 trig_info->unix_time = (*vec)[5];
4729
4730
4731
4732 // GTP scalers
4733 for(uint32_t ii = 6; ii < 38; ii++){
4734 trig_info->gtp_sc.push_back((*vec)[ii]);
4735 }
4736
4737 // FP scalers
4738 for(uint32_t ii = 38; ii < 54; ii++){
4739 trig_info->fp_sc.push_back((*vec)[ii]);
4740 }
4741
4742 // GTP rate
4743 for(uint32_t ii = 54; ii < 86; ii++){
4744 trig_info->gtp_rate.push_back((*vec)[ii]);
4745 }
4746
4747 // FP rate
4748 for(uint32_t ii = 86; ii < 102; ii++){
4749 trig_info->fp_rate.push_back((*vec)[ii]);
4750 }
4751 }
4752
4753
4754 if(events.empty()){
4755 events.push_back(new ObjList());
4756 // cout << " TSSync: Empty event " << endl;
4757 }
4758
4759 ObjList *objs = *(events.begin());
4760
4761 objs->misc_objs.push_back(trig_info);
4762
4763
4764}
4765
4766
4767//----------------
4768// ParseEPICSevent
4769//----------------
4770void JEventSource_EVIO::ParseEPICSevent(evioDOMNodeP bankPtr, list<ObjList*> &events)
4771{
4772 if(!PARSE_EPICS) return;
4773
4774 time_t timestamp=0;
4775
4776 ObjList *objs = NULL__null;
4777
4778 evioDOMNodeListP bankList = bankPtr->getChildren();
4779 evioDOMNodeList::iterator iter = bankList->begin();
4780 if(VERBOSE>7) evioout << " Looping over " << bankList->size() << " banks in EPICS event" << endl;
4781 for(int ibank=1; iter!=bankList->end(); iter++, ibank++){ // ibank only used for debugging messages
4782 evioDOMNodeP childBank = *iter;
4783
4784 if(childBank->tag == 97){
4785 // timestamp bank
4786 const vector<uint32_t> *vec = childBank->getVector<uint32_t>();
4787 if(vec) {
4788 timestamp = (time_t)(*vec)[0];
4789 if(VERBOSE>7) evioout << " timestamp: " << ctime(&timestamp);
4790 }
4791 }else if(childBank->tag==98){
4792 const vector<uint8_t> *vec = childBank->getVector<uint8_t>();
4793 if(vec){
4794 string nameval = (const char*)&((*vec)[0]);
4795 DEPICSvalue *epicsval = new DEPICSvalue(timestamp, nameval);
4796 if(VERBOSE>7) evioout << " " << nameval << endl;
4797
4798 if(!objs){
4799 if(events.empty()) events.push_back(new ObjList);
4800 objs = *(events.begin());
4801 }
4802 objs->misc_objs.push_back(epicsval);
4803 }
4804 }
4805 }
4806}
4807
4808//----------------
4809// DumpBinary
4810//----------------
4811void JEventSource_EVIO::DumpBinary(const uint32_t *iptr, const uint32_t *iend, uint32_t MaxWords, const uint32_t *imark)
4812{
4813 /// This is used for debugging. It will print to the screen the words
4814 /// starting at the address given by iptr and ending just before iend
4815 /// or for MaxWords words, whichever comes first. If iend is NULL,
4816 /// then MaxWords will be printed. If MaxWords is zero then it is ignored
4817 /// and only iend is checked. If both iend==NULL and MaxWords==0, then
4818 /// only the word at iptr is printed.
4819
4820 cout << "Dumping binary: istart=" << hex << iptr << " iend=" << iend << " MaxWords=" << dec << MaxWords << endl;
4821
4822 if(iend==NULL__null && MaxWords==0) MaxWords=1;
4823 if(MaxWords==0) MaxWords = (uint32_t)0xffffffff;
4824
4825 uint32_t Nwords=0;
4826 while(iptr!=iend && Nwords<MaxWords){
4827
4828 // line1 is hex and line2 is decimal
4829 stringstream line1, line2;
4830
4831 // print words in columns 8 words wide. First part is
4832 // reserved for word number
4833 uint32_t Ncols = 8;
4834 line1 << setw(5) << Nwords;
4835 line2 << string(5, ' ');
4836
4837 // Loop over columns
4838 for(uint32_t i=0; i<Ncols; i++, iptr++, Nwords++){
4839
4840 if(iptr == iend) break;
4841 if(Nwords>=MaxWords) break;
4842
4843 stringstream iptr_hex;
4844 iptr_hex << hex << "0x" << *iptr;
4845
4846 string mark = (iptr==imark ? "*":" ");
4847
4848 line1 << setw(12) << iptr_hex.str() << mark;
4849 line2 << setw(12) << *iptr << mark;
4850 }
4851
4852 cout << line1.str() << endl;
4853 cout << line2.str() << endl;
4854 cout << endl;
4855 }
4856}
4857
4858#endif // HAVE_EVIO
4859
4860#if 0
4861//----------------
4862// GuessModuleType
4863//----------------
4864MODULE_TYPE JEventSource_EVIO::GuessModuleType(const uint32_t* istart, const uint32_t* iend, evioDOMNodeP bankPtr)
4865{
4866 /// Try parsing through the information in the given data buffer
4867 /// to determine which type of module produced the data.
4868
4869 if(IsFADC250(istart, iend)) return DModuleType::FADC250;
4870 if(IsF125ADC(istart, iend)) return DModuleType::F125ADC;
4871 if(IsF1TDC(istart, iend)) return DModuleType::F1TDC;
4872 if(IsTS(istart, iend)) return DModuleType::JLAB_TS;
4873 if(IsTI(istart, iend)) return DModuleType::JLAB_TID;
4874
4875
4876 // Couldn't figure it out...
4877 return DModuleType::UNKNOWN;
4878}
4879
4880//----------------
4881// IsFADC250
4882//----------------
4883bool JEventSource_EVIO::IsFADC250(const uint32_t *istart, const uint32_t *iend)
4884{
4885 //---- Check for f250
4886 // This will check if the first word appears to be a block header.
4887 // If so, it loops over all words looking for a block trailer.
4888 // If the slot number in the block trailer matches that in the
4889 // block header AND the number of words in the block matches that
4890 // specified in the block trailer, then it is assumed to be a f250.
4891 if(((*istart>>31) & 0x1) == 1){
4892 uint32_t data_type = (*istart>>27) & 0x0F;
4893 if(data_type == 0){ // Block Header
4894 uint32_t slot_header = (*istart>>22) & 0x1F;
4895 uint32_t Nwords = 1;
4896 for(const uint32_t *iptr=istart; iptr<iend; iptr++, Nwords++){
4897 if(((*iptr>>31) & 0x1) == 1){
4898 uint32_t data_type = (*iptr>>27) & 0x0F;
4899 if(data_type == 1){ // Block Trailer
4900 uint32_t slot_trailer = (*iptr>>22) & 0x1F;
4901 uint32_t Nwords_trailer = (*iptr>>0) & 0x3FFFFF;
4902
4903 if( slot_header == slot_trailer && Nwords == Nwords_trailer ){
4904 return true;
4905 }else{
4906 return false;
4907 }
4908 }
4909 }
4910 }
4911 }
4912 }
4913
4914 // either first word was not a block header or no block trailer was found
4915 return false;
4916}
4917
4918//----------------
4919// IsF1TDC
4920//----------------
4921bool JEventSource_EVIO::IsF1TDC(const uint32_t *istart, const uint32_t *iend)
4922{
4923 //---- Check for F1TDC
4924 // This will check for consistency in the slot numbers for all words
4925 // in the buffer. The slot number of data words are checked against
4926 // the slot number of the most recently encountered header word.
4927 uint32_t slot_header = 1000;
4928 uint32_t slot_trailer = 1000;
4929
4930 const uint32_t *iptr=istart;
4931
4932 // skip first word which appears to be ROL marker for F1TDC data
4933 if(*istart == 0xf1daffff)iptr++
4934
4935 // There is no distinction between header and trailer
4936 // words other than the order that they appear. We keep
4937 // track by flipping this value
4938 bool looking_for_header = true;
4939
4940 // Keep track of the number of valid blocks of F1TDC data we find
4941 // (i.e. ones where the header and trailer words were found
4942 int Nvalid = 0;
4943
4944 for(; iptr<iend; iptr++){
4945
4946 // ROL end of data marker (only in test setup data)
4947 if(*iptr == 0xda0000ff)break;
4948
4949 uint32_t slot = (*iptr>>27) & 0x1F;
4950
4951 // if slot is 0 or 30, we are supposed to ignore the data.
4952 if(slot == 30 || slot ==0)continue;
4953
4954 if(((*iptr>>23) & 0x1) == 0){
4955 // header/trailer word
4956 if(looking_for_header){
4957 slot_header = slot;
4958 looking_for_header = false;
4959 }else{
4960 slot_trailer = slot;
4961 if(slot_trailer != slot_header)return false;
4962 looking_for_header = true;
4963 Nvalid++;
4964 }
4965 }else{
4966 // data word
4967
4968 // if we encounter a data word when we are expecting
4969 // a header word, then the current word is not from
4970 // an F1TDC. However, if we did find at least one valid
4971 // block at the begining, of the buffer, claim the buffer
4972 // points to F1TDC data. We check for as many valid F1TDC
4973 // blocks as possible to help ensure that is what the data
4974 // is.
4975 if(looking_for_header)return Nvalid>0;
4976
4977 // If the slot number does not match, then this is
4978 // not valid F1TDC data
4979 if(slot != slot_header)return false;
4980 }
4981 }
4982
4983 return Nvalid>0;
4984}
4985
4986//----------------
4987// DumpModuleMap
4988//----------------
4989void JEventSource_EVIO::DumpModuleMap(void)
4990{
4991 // Open output file
4992 string fname = "module_map.txt";
4993 ofstream ofs(fname.c_str());
4994 if(!ofs.is_open()){
4995 jerr<<"Unable to open file \""<<fname<<"\" for writing!"<<endl;
4996 return;
4997 }
4998
4999 jout<<"Writing module map to file \""<<fname<<"\""<<endl;
5000
5001 // Write header
5002 time_t now = time(NULL__null);
5003 ofs<<"# Autogenerated module map"<<endl;
5004 ofs<<"# Created: "<<ctime(&now);
5005 ofs<<"#"<<endl;
5006
5007 // Write known module types in header
5008 vector<DModuleType> modules;
5009 DModuleType::GetModuleList(modules);
5010 ofs<<"# Known module types:"<<endl;
5011 ofs<<"# ----------------------"<<endl;
5012 for(unsigned int i=0; i<modules.size(); i++){
5013 string name = modules[i].GetName();
5014 string space(12-name.size(), ' ');
5015 ofs << "# " << name << space << " - " << modules[i].GetDescription() <<endl;
5016 }
5017 ofs<<"#"<<endl;
5018 ofs<<"#"<<endl;
5019
5020 // Write module map
5021 ofs<<"# Format is:"<<endl;
5022 ofs<<"# tag num type"<<endl;
5023 ofs<<"#"<<endl;
5024
5025 map<tagNum, MODULE_TYPE>::iterator iter = module_type.begin();
5026 for(; iter!=module_type.end(); iter++){
5027
5028 tagNum tag_num = iter->first;
5029 MODULE_TYPE type = iter->second;
5030 ofs<<tag_num.first<<" "<<(int)tag_num.second<<" "<<DModuleType::GetName(type)<<endl;
5031 }
5032 ofs<<endl;
5033
5034 // Close output file
5035 ofs.close();
5036}
5037#endif