Bug Summary

File:libraries/DAQ/JEventSource_EVIO.cc
Location:line 4662, column 67
Description:Dereference of null pointer

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