Bug Summary

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

Annotated Source Code

1// $Id$
2// $HeadURL$
3//
4// File: JEventSource_EVIO.cc
5// Created: Tue Aug 7 15:22:29 EDT 2012
6// Creator: davidl (on Darwin harriet.jlab.org 11.4.0 i386)
7//
8
9// See comments in JEventSource_EVIO.h for overview description
10
11#include <unistd.h>
12#include <stdint.h>
13
14#include <string>
15#include <cmath>
16#include <iomanip>
17using namespace std;
18
19
20// This flag allows us to switch back and forth from using HDEVIO and
21// the CODA-supplied EVIO
22#define USE_HDEVIO1 1
23
24//#define ENABLE_UPSAMPLING
25
26#ifdef HAVE_EVIO1
27
28#if USE_HDEVIO1 == 0
29#include <evioFileChannel.hxx>
30#endif
31
32extern "C" uint32_t *swap_int32_t(uint32_t *data, unsigned int length, uint32_t *dest);
33#endif // HAVE_EVIO
34
35#ifdef HAVE_ET
36//#include <evioETChannel.hxx>
37#include <et.h>
38#endif // HAVE_ET
39
40#include "JEventSourceGenerator_EVIO.h"
41//#include "JFactoryGenerator_DAQ.h"
42#include "JEventSource_EVIO.h"
43
44using namespace jana;
45
46#include <DANA/DStatusBits.h>
47#include <TTAB/DTranslationTable.h>
48#include <TTAB/DTranslationTable_factory.h>
49#include <DAQ/Df125EmulatorAlgorithm_factory.h>
50#include <DAQ/Df250EmulatorAlgorithm_factory.h>
51
52#define _DBG_DAQ(A)cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<":"<<
52<<" 0x"<<hex<<A<<" cntrl:0x"<<
(A&0xF0000000)<<dec<<" slot:"<<((A>>
22)&0x1F)<<endl
cerr<<__FILE__"libraries/DAQ/JEventSource_EVIO.cc"<<":"<<__LINE__52<<" 0x"<<hex<<A<<" cntrl:0x"<<(A&0xF0000000)<<dec<<" slot:"<<((A>>22)&0x1F)<<endl
53
54// Make us a plugin
55#include <JANA/JApplication.h>
56//extern "C"{
57// void InitPlugin(JApplication *app){
58// InitJANAPlugin(app);
59// app->AddEventSourceGenerator(new JEventSourceGenerator_EVIO());
60// app->AddFactoryGenerator(new JFactoryGenerator_DAQ());
61// }
62//} // "C"
63
64// if we don't find a run number in the file, then it's nice to let the user know
65static bool WARN_USER_RUN_FILENAME = false;
66
67set<uint32_t> ROCIDS_TO_PARSE;
68
69//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
70// If EVIO support is not available, define dummy methods
71#ifndef HAVE_EVIO1
72JEventSource_EVIO::JEventSource_EVIO(const char* source_name):JEventSource(source_name){
73 cerr << endl;
74 cerr << "You are trying to use code requiring EVIO when support" << endl;
75 cerr << "for EVIO was not built into this binary. Set your" << endl;
76 cerr << "EVIOROOT *and* your ETROOT environment variables to" << endl;
77 cerr << "point to your EVIO installation and recompile." << endl;
78 cerr << endl;
79 exit(-1);
80}
81 JEventSource_EVIO::~JEventSource_EVIO(){}
82jerror_t JEventSource_EVIO::GetEvent(jana::JEvent &event){return NOERROR;}
83 void JEventSource_EVIO::FreeEvent(jana::JEvent &event){}
84jerror_t JEventSource_EVIO::GetObjects(jana::JEvent &event, jana::JFactory_base *factory){return NOERROR;}
85jerror_t JEventSource_EVIO::ReadEVIOEvent(uint32_t* &buf){return NOERROR;}
86//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
87
88#else // HAVE_EVIO
89
90//----------------
91// Constructor
92//----------------
93JEventSource_EVIO::JEventSource_EVIO(const char* source_name):JEventSource(source_name)
94{
95 // Initialize connection objects and flags to NULL
96 et_connected = false;
97 //chan = NULL;
98 hdevio = NULL__null;
99 source_type = kNoSource;
100 quit_on_next_ET_timeout = false;
101
102 // Initialize dedicated JStreamLog used for debugging messages
103 evioout.SetTag("--- EVIO ---: ");
104 evioout.SetTimestampFlag();
105 evioout.SetThreadstampFlag();
106
107 // Define base set of status bits
108 if(japp) DStatusBits::SetStatusBitDescriptions(japp);
109
110 // Get configuration parameters
111 AUTODETECT_MODULE_TYPES = true;
112 DUMP_MODULE_MAP = false;
113 MAKE_DOM_TREE = true;
114 PARSE_EVIO_EVENTS = true;
115 PARSE_F250 = true;
116 PARSE_F125 = true;
117 PARSE_F1TDC = true;
118 PARSE_CAEN1290TDC = true;
119 PARSE_CONFIG = true;
120 PARSE_BOR = true;
121 PARSE_EPICS = true;
122 PARSE_EVENTTAG = true;
123 PARSE_TRIGGER = true;
124 BUFFER_SIZE = 20000000; // in bytes
125 ET_STATION_NEVENTS = 10;
126 ET_STATION_CREATE_BLOCKING = false;
127 ET_DEBUG_WORDS_TO_DUMP = 0;
128 LOOP_FOREVER = false;
129 VERBOSE = 0;
130 TIMEOUT = 2.0;
131 MODTYPE_MAP_FILENAME = "modtype.map";
132 ENABLE_DISENTANGLING = true;
133
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;
1
Taking false branch
1809 if(VERBOSE>3) evioout << " Entering EmulateDf250Firmware ..." <<endl;
2
Taking false branch
1810
1811 vector <const Df250EmulatorAlgorithm*> f250Emulator_const;
1812 Df250EmulatorAlgorithm *f250Emulator = NULL__null;
3
'f250Emulator' initialized to a null pointer value
1813 JEventLoop *loop = event.GetJEventLoop();
1814 Df250EmulatorAlgorithm_factory *f250EmFac = static_cast<Df250EmulatorAlgorithm_factory*>(loop->GetFactory("Df250EmulatorAlgorithm"));
1815 if (f250EmFac) {
4
Assuming 'f250EmFac' is null
5
Taking false branch
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;
6
Taking false branch
1822 // Loop over all window raw data objects
1823 for(unsigned int i=0; i<wrd_objs.size(); i++){
7
Loop condition is true. Entering loop body
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++){
8
Loop condition is false. Execution continues on line 1852
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++){
9
Loop condition is false. Execution continues on line 1872
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++){
10
Loop condition is false. Execution continues on line 1892
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;
11
Taking false branch
1896 f250Emulator->EmulateFirmware(f250WindowRawData, pt_objs, pp_objs, pi_objs);
12
Called C++ object pointer is null
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 // implement special exceptions for early pulse times in mode 8 data
1925 if (VERBOSE > 3 || !(pt_hw->time == 0 &&
1926 (pt_hw->time_emulated == 64 || pt_hw->time_emulated == 128 ||
1927 pt_hw->time_emulated == 192 || pt_hw->time_emulated == 256)) )
1928 {
1929 jout << " comparing f250 hw and emulation pulse times for ROC/slot/chan "
1930 << pt_hw->rocid << "/" << pt_hw->slot << "/" << pt_hw->channel << ": "
1931 << pt_hw->time << " vs " << pt_hw->time_emulated << endl;
1932 }
1933 }
1934 pt_objs.erase(pt_objs.begin() + i);
1935 delete pt_em;
1936 pt_em = 0;
1937 --i;
1938 break;
1939 }
1940 }
1941 if (pt_em != 0 && VERBOSE > 3) {
1942 jout << " new f250 emulation PulseTime generated for ROC/slot/chan "
1943 << pt_em->rocid << "/" << pt_em->slot << "/" << pt_em->channel << ": "
1944 << "pulse " << pt_em->pulse_number << ", time " << pt_em->time << endl;
1945 }
1946 }
1947
1948 uint32_t pp_hardware = 0;
1949 for (uint32_t i = pp_emulated; i < pp_objs.size(); i++) {
1950 Df250PulsePedestal *pp_em = dynamic_cast<Df250PulsePedestal*>(pp_objs[i]);
1951 const Df250WindowRawData *rd;
1952 pp_em->GetSingle(rd);
1953 if (rd != f250WindowRawData) {
1954 jerr << "Emulated object found that does not belong to WindowRawData object!" << endl;
1955 jerr << "This likely means there is a bug in JEventSource_EVIO.cc PulsePedestal emulation." << endl;
1956 jerr << "rocid=" << pp_em->rocid << " slot=" << pp_em->slot << " channel=" << pp_em->channel << endl;
1957 jerr << "Please report error to davidl@jlab.org" << endl;
1958 exit(-1);
1959 }
1960 for (uint32_t j=pp_hardware; j < pp_emulated; j++) {
1961 Df250PulsePedestal *pp_hw = dynamic_cast<Df250PulsePedestal*>(pp_objs[j]);
1962 pp_hw->GetSingle(rd);
1963 if (rd == f250WindowRawData && pp_hw->pulse_number == pp_em->pulse_number) {
1964 pp_hardware = j + 1;
1965 if (F250_EMULATION_MODE == kEmulationAlways) {
1966 *pp_hw = *pp_em;
1967 }
1968 else {
1969 pp_hw->pedestal_emulated = pp_em->pedestal_emulated;
1970 pp_hw->pulse_peak_emulated = pp_em->pulse_peak_emulated;
1971 }
1972 if ((VERBOSE > 0 && pp_hw->pulse_peak != pp_hw->pulse_peak_emulated) || VERBOSE > 3)
1973 jout << " comparing f250 hw and emulation pulse peaks for ROC/slot/chan "
1974 << pp_hw->rocid << "/" << pp_hw->slot << "/" << pp_hw->channel << ": "
1975 << pp_hw->pulse_peak << " vs " << pp_hw->pulse_peak_emulated << endl;
1976 pp_objs.erase(pp_objs.begin() + i);
1977 delete pp_em;
1978 pp_em = 0;
1979 --i;
1980 break;
1981 }
1982 }
1983 if (pp_em != 0 && VERBOSE > 3) {
1984 jout << " new f250 emulation PulsePedestal generated for ROC/slot/chan "
1985 << pp_em->rocid << "/" << pp_em->slot << "/" << pp_em->channel << ": "
1986 << "pulse " << pp_em->pulse_number << ", pedestal " << pp_em->pedestal
1987 << ", peak " << pp_em->pulse_peak << endl;
1988 }
1989 }
1990
1991 uint32_t pi_hardware = 0;
1992 for (uint32_t i = pi_emulated; i < pi_objs.size(); i++) {
1993 Df250PulseIntegral *pi_em = dynamic_cast<Df250PulseIntegral*>(pi_objs[i]);
1994 const Df250WindowRawData *rd;
1995 pi_em->GetSingle(rd);
1996 if (rd != f250WindowRawData) {
1997 jerr << "Emulated object found that does not belong to WindowRawData object!" << endl;
1998 jerr << "This likely means there is a bug in JEventSource_EVIO.cc PulseIntegral emulation." << endl;
1999 jerr << "rocid=" << pi_em->rocid << " slot=" << pi_em->slot << " channel=" << pi_em->channel << endl;
2000 jerr << "Please report error to davidl@jlab.org" << endl;
2001 exit(-1);
2002 }
2003 for (uint32_t j=pi_hardware; j < pi_emulated; j++) {
2004 Df250PulseIntegral *pi_hw = dynamic_cast<Df250PulseIntegral*>(pi_objs[j]);
2005 pi_hw->GetSingle(rd);
2006 if (rd == f250WindowRawData && pi_hw->pulse_number == pi_em->pulse_number) {
2007 pi_hardware = j + 1;
2008 if (F250_EMULATION_MODE == kEmulationAlways) {
2009 *pi_hw = *pi_em;
2010 }
2011 else {
2012 pi_hw->integral_emulated = pi_em->integral_emulated;
2013 pi_hw->pedestal_emulated = pi_em->pedestal_emulated;
2014 }
2015 if ((VERBOSE > 0 && pi_hw->integral != pi_hw->integral_emulated) || VERBOSE > 3)
2016 jout << " comparing f250 hw and emulation pulse integrals for ROC/slot/chan "
2017 << pi_hw->rocid << "/" << pi_hw->slot << "/" << pi_hw->channel << ": "
2018 << pi_hw->integral << " vs " << pi_hw->integral_emulated << endl;
2019 pi_objs.erase(pi_objs.begin() + i);
2020 delete pi_em;
2021 pi_em = 0;
2022 i--;
2023 break;
2024 }
2025 }
2026 if (pi_em != 0 && VERBOSE > 3) {
2027 jout << " new f250 emulation PulseIntegral generated for ROC/slot/chan "
2028 << pi_em->rocid << "/" << pi_em->slot << "/" << pi_em->channel << ": "
2029 << "pulse " << pi_em->pulse_number << ", integral " << pi_em->integral
2030 << ", pedestal " << pi_em->pedestal << endl;
2031 }
2032 }
2033 }
2034
2035 // PulseTime, PulsePedestal, PulseIntegral objects are associated to one another in GetObjects
2036 if(VERBOSE>3) evioout << " Leaving EmulateDf250Firmware" <<endl;
2037}
2038
2039//----------------
2040// EmulateDf125Firmware
2041//----------------
2042void JEventSource_EVIO::EmulateDf125Firmware( JEvent &event, vector<JObject*> &wrd_objs, vector<JObject*> &cp_objs, vector<JObject*> &fp_objs)
2043{
2044 /// This code implements an upsampling technique developed by Naomi Jarvis at
2045 /// CMU. This was not implemented in the firmware for the 2014-2015 commissioning
2046 /// run, but was implemented for later runs.
2047 ///
2048 /// Removed f250 style emulation of f125 firmware. Keep in mind if for some reason old
2049 /// mode 8 data is processed, it will return the new style words with 1/10
2050 /// sample resolution. It is doubtful anyone will be using these in the future so nbd. 3/18/2016 MS
2051
2052 if(wrd_objs.size() == 0) return; // Can't do anything without the raw data
2053 if(VERBOSE>3) evioout << " Entering EmulateDf125Firmware ..." <<endl;
2054
2055 vector <const Df125EmulatorAlgorithm*> f125Emulator_const;
2056 Df125EmulatorAlgorithm *f125Emulator = NULL__null;
2057 JEventLoop *loop = event.GetJEventLoop();
2058 Df125EmulatorAlgorithm_factory *f125EmFac = static_cast<Df125EmulatorAlgorithm_factory*>(loop->GetFactory("Df125EmulatorAlgorithm"));
2059 if (f125EmFac) {
2060 f125EmFac->Get(f125Emulator_const);
2061 // Drop const
2062 if (f125Emulator_const.size() != 0) f125Emulator = const_cast<Df125EmulatorAlgorithm*>(f125Emulator_const[0]);
2063 }
2064
2065 // Loop over all window raw data objects
2066 for(unsigned int i=0; i<wrd_objs.size(); i++){
2067 const Df125WindowRawData *f125WindowRawData = (Df125WindowRawData*)wrd_objs[i];
2068 Df125CDCPulse *f125CDCPulse = NULL__null;
2069 Df125FDCPulse *f125FDCPulse = NULL__null;
2070
2071 //search for existing CDCPulse
2072 for(uint32_t j=0; j<cp_objs.size(); j++){
2073 Df125CDCPulse *cp = (Df125CDCPulse*)cp_objs[j];
2074 if(cp->rocid == f125WindowRawData->rocid){
2075 if(cp->slot == f125WindowRawData->slot){
2076 if(cp->channel == f125WindowRawData->channel){
2077 f125CDCPulse = cp;
2078 f125CDCPulse->AddAssociatedObject(f125WindowRawData);
2079 break;
2080 }
2081 }
2082 }
2083 }
2084
2085 // search for existing FDCPulse
2086 for(uint32_t j=0; j<fp_objs.size(); j++){
2087 Df125FDCPulse *fp = (Df125FDCPulse*)fp_objs[j];
2088 if(fp->rocid == f125WindowRawData->rocid){
2089 if(fp->slot == f125WindowRawData->slot){
2090 if(fp->channel == f125WindowRawData->channel){
2091 f125FDCPulse = fp;
2092 f125FDCPulse->AddAssociatedObject(f125WindowRawData);
2093 break;
2094 }
2095 }
2096 }
2097 }
2098
2099 // If the the pulse objects do not exist, create new ones to go with our raw data
2100 // This should rarely happen since CDC_long and FDC_long have the raw data
2101 // along with the calculated quantities in a pulse word. Pure raw mode would be the only time
2102 // when this would not be the case. Since this is so infrequently used (if ever),
2103 // the ROCID check for CDC/FDC determination is hard coded...
2104 // ROCID CDC: 25-28
2105 // ROCID FDC Cathode: 52,53,55-62
2106
2107 if(f125CDCPulse == NULL__null && ( f125WindowRawData->rocid < 30 ) ){
2108 f125CDCPulse = new Df125CDCPulse;
2109 f125CDCPulse->rocid = f125WindowRawData->rocid;
2110 f125CDCPulse->slot = f125WindowRawData->slot;
2111 f125CDCPulse->channel = f125WindowRawData->channel;
2112 f125CDCPulse->emulated = true;
2113 f125CDCPulse->AddAssociatedObject(f125WindowRawData);
2114 cp_objs.push_back(f125CDCPulse);
2115 }
2116
2117 else if(f125FDCPulse == NULL__null && ( f125WindowRawData->rocid > 30 ) ){
2118 f125FDCPulse = new Df125FDCPulse;
2119 f125FDCPulse->rocid = f125WindowRawData->rocid;
2120 f125FDCPulse->slot = f125WindowRawData->slot;
2121 f125FDCPulse->channel = f125WindowRawData->channel;
2122 f125FDCPulse->emulated = true;
2123 f125FDCPulse->AddAssociatedObject(f125WindowRawData);
2124 cp_objs.push_back(f125FDCPulse);
2125 }
2126
2127 // Flag all objects as emulated and their values will be replaced with emulated quantities
2128 if (F125_EMULATION_MODE == kEmulationAlways){
2129 if(f125CDCPulse!=NULL__null) f125CDCPulse->emulated = 1;
2130 if(f125FDCPulse!=NULL__null) f125FDCPulse->emulated = 1;
2131 }
2132
2133 // Perform the emulation
2134 f125Emulator->EmulateFirmware(f125WindowRawData, f125CDCPulse, f125FDCPulse);
2135 }
2136
2137 if(VERBOSE>3) evioout << " Leaving EmulateDf125Firmware" <<endl;
2138}
2139
2140//----------------
2141// GetRunNumber
2142//----------------
2143int32_t JEventSource_EVIO::GetRunNumber(evioDOMTree *evt)
2144{
2145 // Note: This is currently not used. Preference is
2146 // now given to the run number found in FindRunNumber
2147 // which is called from GetEvent. This makes things
2148 // a little simpler and ensures the run number originally
2149 // presented to the processor/factory does not change.
2150 // 2/15/2016 DL
2151
2152 // This is called during event parsing to get the
2153 // run number for the event.
2154 // Look through event to try and extract the run number.
2155 // We do this by looking for all uint64_t nodes. Then
2156 // check for a parent with one of the magic values for
2157 // the tag indicating it has run number information.
2158 if(USER_RUN_NUMBER>0) return USER_RUN_NUMBER;
2159 if(!evt) return last_run_number;
2160
2161 evioDOMNodeListP bankList = evt->getNodeList(typeIs<uint64_t>());
2162 evioDOMNodeList::iterator iter = bankList->begin();
2163 const uint64_t *run_number_and_type = NULL__null;
2164 for(; iter!=bankList->end(); iter++){
2165 evioDOMNodeP bankPtr = *iter;
2166 evioDOMNodeP physics_event_built_trigger_bank = bankPtr->getParent();
2167 if(physics_event_built_trigger_bank == NULL__null) continue;
2168 uint32_t tag = physics_event_built_trigger_bank->tag;
2169 const vector<uint64_t> *vec;
2170 switch(tag){
2171 case 0xFF22:
2172 case 0xFF23:
2173 case 0xFF26:
2174 case 0xFF27:
2175 vec = bankPtr->getVector<uint64_t>();
2176 if(!vec) continue;
2177 if(vec->size()<1) continue;
2178 run_number_and_type = &((*vec)[vec->size()-1]);
2179 break;
2180 }
2181 if(run_number_and_type != NULL__null) break;
2182 }
2183
2184 if(run_number_and_type != NULL__null) last_run_number = (*run_number_and_type)>>32;
2185
2186 return last_run_number;
2187}
2188
2189//----------------
2190// FindRunNumber
2191//----------------
2192int32_t JEventSource_EVIO::FindRunNumber(uint32_t *iptr)
2193{
2194 /// This is called from GetEvent() to quickly look for the run number
2195 /// at the time the event is read in so it can be passed into
2196 /// JEvent. It is what will be used for accessing the CCDB.
2197 /// from this event. If a bank containing the run number is found,
2198 /// use it to provide the run number. Otherwise, return whatever run
2199 /// number we were able to extract from the file name.
2200
2201 if(VERBOSE>1) evioout << " .. Searching for run number ..." <<endl;
2202 if(USER_RUN_NUMBER>0){
2203 if(VERBOSE>1) evioout << " returning user-supplied run number: " << USER_RUN_NUMBER << endl;
2204 return last_run_number=USER_RUN_NUMBER;
2205 }
2206
2207 // Assume first word is number of words in bank
2208 uint32_t *iend = &iptr[*iptr - 1];
2209 if(*iptr > 2048) iend = &iptr[2048];
2210 bool has_timestamps = false;
2211 while(iptr<iend){
2212 iptr++;
2213
2214 // EPICS event
2215 if( (*iptr & 0xff000f) == 0x600001){
2216 if(VERBOSE>2) evioout << " Found EPICS header. Looking for HD:coda:daq:run_number ..." << endl;
2217 const char *cptr = (const char*)&iptr[1];
2218 const char *cend = (const char*)iend;
2219 const char *needle = "HD:coda:daq:run_number=";
2220 while(cptr<cend){
2221 if(VERBOSE>4) evioout << " \""<<cptr<<"\"" << endl;
2222 if(!strncmp(cptr, needle, strlen(needle))){
2223 if(VERBOSE>2) evioout << " Found it!" << endl;
2224 return last_run_number = atoi(&cptr[strlen(needle)]);
2225 }
2226 cptr+=4; // should only start on 4-byte boundary!
2227 }
2228 }
2229
2230 // BOR event
2231 if( (*iptr & 0xffffffff) == 0x00700E01){
2232 // OK, this looks like a BOR event which does not include the
2233 // run number. In this case, we have a couple of options:
2234 //
2235 // 1. If we are reading from a file then look further into
2236 // the file to see if we can find another event with the
2237 // run number in it.
2238 //
2239 // 2. Return the run number found from the filename.
2240 //
2241 if(source_type==kFileSource){
2242 int32_t run_number = EpicQuestForRunNumber();
2243 if(run_number != 0){
2244 if(VERBOSE>1) evioout << " Found run number " << run_number << " from Epic Quest." <<endl;
2245 return last_run_number = run_number;
2246 }
2247 }
2248 break; // return filename_run_number with warning message
2249 }
2250
2251 // PHYSICS event
2252 switch((*iptr)>>16){
2253 case 0xFF10:
2254 case 0xFF11:
2255 case 0xFF20:
2256 case 0xFF21:
2257 case 0xFF24:
2258 case 0xFF25:
2259 case 0xFF30:
2260 // These Trigger Bank Tag values have no run number info in them
2261 if(VERBOSE>2) evioout << " ... Trigger bank tag (0x" << hex << ((*iptr)>>16) << dec << ") does not contain run number" <<endl;
2262 if(!WARN_USER_RUN_FILENAME) {
2263 jout << "WARNING: setting run number " << filename_run_number << " based on file name" << endl;
2264 WARN_USER_RUN_FILENAME = true;
2265 }
2266 return last_run_number = filename_run_number;
2267 case 0xFF23:
2268 case 0xFF27:
2269 has_timestamps = true;
2270 case 0xFF22:
2271 case 0xFF26:
2272 if(VERBOSE>2) evioout << " ... Trigger bank tag (0x" << hex << ((*iptr)>>16) << dec << ") does contain run number" <<endl;
2273 // Nrocs = (*iptr) & 0x0F;
2274 break;
2275 default:
2276 continue;
2277 }
2278 iptr++;
2279 if( ((*iptr)&0x00FF0000) != 0x000A0000) { iptr--; continue; }
2280 uint32_t M = iptr[-3] & 0x000000FF; // Number of events from Physics Event header
2281 if(VERBOSE>2) evioout << " ... Trigger bank " << (has_timestamps ? "does":"doesn't") << " have timestamps. Nevents in block M=" << M <<endl;
2282 iptr++;
2283 uint64_t *iptr64 = (uint64_t*)iptr;
2284
2285 uint64_t event_num = *iptr64;
2286 if(source_type==kETSource) event_num = ((*iptr64)>>32) | ((*iptr64)<<32);
2287 if(VERBOSE>3) evioout << " .... Event num: " << event_num <<endl;
2288 iptr64++;
2289 if(has_timestamps) iptr64 = &iptr64[M]; // advance past timestamps
2290
2291 // I'm not sure I fully understand this, but if we read from
2292 // ET, then the run number is in the low 32 bits of *iptr64.
2293 // If we are reading from a file, it is in the high 32 bits.
2294 // No byte swapping is needed (it has already been done, though
2295 // perhaps incorrectly). We handle this here by checking if
2296 // this is an ET source or not.
2297 uint64_t run64 = (*iptr64)>>32;
2298 if(source_type==kETSource){
2299 run64 = (*iptr64)&0xffffffff;
2300 }
2301 int32_t run = (int32_t)run64;
2302 if(VERBOSE>1) evioout << " .. Found run number: " << run <<endl;
2303
2304 return last_run_number = run;
2305 }
2306
2307 // if we're not sure what else to do, try a more comprehensive search
2308 if(source_type==kFileSource){
2309 int32_t run_number = EpicQuestForRunNumber();
2310 if(run_number != 0){
2311 if(VERBOSE>1) evioout << " Found run number " << run_number << " from Epic Quest." <<endl;
2312 return last_run_number = run_number;
2313 }
2314 }
2315
2316 if(!WARN_USER_RUN_FILENAME) {
2317 jout << "WARNING: setting run number " << filename_run_number << " based on file name" << endl;
2318 WARN_USER_RUN_FILENAME = true;
2319 }
2320
2321 return last_run_number = filename_run_number;
2322}
2323
2324//----------------
2325// EpicQuestForRunNumber
2326//----------------
2327int32_t JEventSource_EVIO::EpicQuestForRunNumber(void)
2328{
2329 /// This is called when an event is encountered that does
2330 /// not have a run number in it. (e.g. a BOR event encountered
2331 /// in FindRunNumber() ). This is a last hope of finding the
2332 /// run number in the file by looking for other events that
2333 /// may contain it. Specifically, EPICS or PHYSICS events.
2334 /// This only works if it is a file source so that it can open
2335 /// the file and read in past the first event.
2336 ///
2337 /// Note that this is extremely inefficient so should not be
2338 /// called very often. As a precaution, this will look to see
2339 /// if last_run_number is not set to 0 first and will just
2340 /// return it if it is. Only if it is not will the epic quest
2341 /// commence.
2342
2343 if(source_type!=kFileSource) return 0;
2344 if(last_run_number != 0) return last_run_number;
2345
2346 uint32_t buff_len = 4000000;
2347 uint32_t *buff = new uint32_t[buff_len];
2348 HDEVIO *hdevio = new HDEVIO(source_name);
2349 while(hdevio->read(buff, buff_len)){
2350
2351 // Assume first word is number of words in bank
2352 uint32_t *iptr = buff;
2353 uint32_t *iend = &iptr[*iptr - 1];
2354 if(*iptr > 2048) iend = &iptr[2048];
2355 bool has_timestamps = false;
2356 while(iptr<iend){
2357 iptr++;
2358
2359 // EPICS event
2360 if( (*iptr & 0xff000f) == 0x600001){
2361 if(VERBOSE>2) evioout << " Found EPICS header. Looking for HD:coda:daq:run_number ..." << endl;
2362 const char *cptr = (const char*)&iptr[1];
2363 const char *cend = (const char*)iend;
2364 const char *needle = "HD:coda:daq:run_number=";
2365 while(cptr<cend){
2366 if(VERBOSE>4) evioout << " \""<<cptr<<"\"" << endl;
2367 if(!strncmp(cptr, needle, strlen(needle))){
2368 if(VERBOSE>2) evioout << " Found it!" << endl;
2369 int32_t run_number = atoi(&cptr[strlen(needle)]);
2370 if(hdevio) delete hdevio;
2371 if(buff) delete[] buff;
2372 return run_number;
2373 }
2374 cptr+=4; // should only start on 4-byte boundary!
2375 }
2376 }
2377
2378 // BOR event
2379 if( (*iptr & 0xffffffff) == 0x00700E01) continue;
2380
2381 // PHYSICS event
2382 bool not_in_this_buffer = false;
2383 switch((*iptr)>>16){
2384 case 0xFF10:
2385 case 0xFF11:
2386 case 0xFF20:
2387 case 0xFF21:
2388 case 0xFF24:
2389 case 0xFF25:
2390 case 0xFF30:
2391 not_in_this_buffer = true;
2392 break;
2393 case 0xFF23:
2394 case 0xFF27:
2395 has_timestamps = true;
2396 case 0xFF22:
2397 case 0xFF26:
2398 break;
2399 default:
2400 continue;
2401 }
2402
2403 if(not_in_this_buffer) break; // go to next EVIO buffer
2404
2405 iptr++;
2406 if( ((*iptr)&0x00FF0000) != 0x000A0000) { iptr--; continue; }
2407 uint32_t M = iptr[-3] & 0x000000FF; // Number of events from Physics Event header
2408 if(VERBOSE>2) evioout << " ...(epic quest) Trigger bank " << (has_timestamps ? "does":"doesn't") << " have timestamps. Nevents in block M=" << M <<endl;
2409 iptr++;
2410 uint64_t *iptr64 = (uint64_t*)iptr;
2411
2412 uint64_t event_num = *iptr64;
2413 if(source_type==kETSource) event_num = ((*iptr64)>>32) | ((*iptr64)<<32);
2414 if(VERBOSE>3) evioout << " ....(epic quest) Event num: " << event_num <<endl;
2415 iptr64++;
2416 if(has_timestamps) iptr64 = &iptr64[M]; // advance past timestamps
2417
2418 // I'm not sure I fully understand this, but if we read from
2419 // ET, then the run number is in the low 32 bits of *iptr64.
2420 // If we are reading from a file, it is in the high 32 bits.
2421 // No byte swapping is needed (it has already been done, though
2422 // perhaps incorrectly). We handle this here by checking if
2423 // this is an ET source or not.
2424 uint64_t run64 = (*iptr64)>>32;
2425 if(source_type==kETSource){
2426 run64 = (*iptr64)&0xffffffff;
2427 }
2428 int32_t run = (int32_t)run64;
2429 if(VERBOSE>1) evioout << " .. (epic quest) Found run number: " << run <<endl;
2430
2431 if(hdevio) delete hdevio;
2432 if(buff) delete[] buff;
2433 return run;
2434
2435 } // while(iptr<iend)
2436
2437 if(hdevio->Nevents > 500) break;
2438 } // while(hdevio->read(buff, buff_len))
2439
2440 if(hdevio) delete hdevio;
2441 if(buff) delete[] buff;
2442
2443 return 0;
2444}
2445
2446//----------------
2447// FindEventNumber
2448//----------------
2449uint64_t JEventSource_EVIO::FindEventNumber(uint32_t *iptr)
2450{
2451 /// This is called from GetEvent() to quickly look for the event number
2452 /// at the time the event is read in so it can be passed into JEvent.
2453 /// (See comments for FindRunNumber above.)
2454 if(VERBOSE>1) evioout << " .. Searching for event number ..." <<endl;
2455
2456 if(*iptr < 6){
2457 if(VERBOSE>1) evioout << " Word count(="<<*iptr<<")<6. Returning Nevents_read+1(=" << Nevents_read+1 << ") as event number" <<endl;
2458 return Nevents_read+1;
2459 }
2460
2461 // Check header of Trigger bank
2462 uint32_t mask = 0xFF202000;
2463 if( (iptr[3]&mask) != mask ){
2464 if(VERBOSE>1){
2465 evioout << " iptr[3]=" << hex << iptr[3] << " does not look like trigger bank tag (" << (iptr[3]&mask) << " != " << mask << ")" << dec <<endl;
2466 evioout << " Returning Nevents_read+1(=" << Nevents_read+1 << ") as event number" <<endl;
2467 }
2468 return Nevents_read+1;
2469 }
2470
2471 uint64_t loevent_num = iptr[5];
2472 uint64_t hievent_num = iptr[6];
2473 if(source_type==kETSource) {
2474 loevent_num = iptr[6];
2475 hievent_num = iptr[5];
2476 }
2477 uint64_t event_num = loevent_num + (hievent_num<<32);
2478 if(VERBOSE>1) evioout << " .. Found event number: " << event_num <<endl;
2479
2480 return event_num;
2481}
2482
2483//----------------
2484// FindEventType
2485//----------------
2486void JEventSource_EVIO::FindEventType(uint32_t *iptr, JEvent &event)
2487{
2488 /// This is called from GetEvent to quickly determine the type of
2489 /// event this is (Physics, EPICS, SYNC, BOR, ...)
2490 uint32_t head = iptr[1];
2491 if( (head & 0xff000f) == 0x600001){
2492 event.SetStatusBit(kSTATUS_EPICS_EVENT);
2493 }else if( (head & 0xffffffff) == 0x00700E01){
2494 event.SetStatusBit(kSTATUS_BOR_EVENT);
2495 }else if( (head & 0xffffff00) == 0xff501000){
2496 event.SetStatusBit(kSTATUS_PHYSICS_EVENT);
2497 }else if( (head & 0xffffff00) == 0xff701000){
2498 event.SetStatusBit(kSTATUS_PHYSICS_EVENT);
2499 }else if( (head & 0xfff000ff) == 0xffd00000){
2500 event.SetStatusBit(kSTATUS_CONTROL_EVENT);
2501 if( (head>>16) == 0xffd0 ) event.SetStatusBit(kSTATUS_SYNC_EVENT);
2502 }else{
2503 DumpBinary(iptr, &iptr[16]);
2504 }
2505}
2506
2507//----------------
2508// MergeObjLists
2509//----------------
2510void JEventSource_EVIO::MergeObjLists(list<ObjList*> &events1, list<ObjList*> &events2)
2511{
2512 if(VERBOSE>5) evioout << " Entering MergeObjLists(). "
2513 << " &events1=" << hex << &events1 << dec << "(" << events1.size() << " events) "
2514 << " &events2=" << hex << &events2 << dec << "(" << events2.size() << " events) " << endl;
2515
2516 /// Merge the events referenced in events2 into the events1 list.
2517 ///
2518 /// This will append the object lists for each type of data object
2519 /// stored in events2 onto the appropriate list in events1. It does this
2520 /// event-by-event. The idea being that each entry in the queue represents a
2521 /// partial list of the objects for the event. The two queues are most likely
2522 /// filled from different EVIO banks orginiating from different ROCs.
2523 ///
2524 /// Before the merging is done, it is checked that both lists either have the
2525 /// same number of events, or one list is empty. One list is allowed to be
2526 /// empty since it is possible it was "filled" from a bank that contains no
2527 /// data at all which may not neccessarily be an error. If both queues have
2528 /// at least one event, but they do not contain an equal number of events,
2529 /// then an exception is thrown.
2530 ///
2531 /// The contents of event2 will be erased before returning. Ownership of all
2532 /// ObjList objects pointed to by event2 upon entry should be considered
2533 /// owned by event1 upon return.
2534
2535 // Allow a list of 1 event with only config objects in test below
2536 bool justconfig = false;
2537 if(events1.size()==1){
2538 ObjList *objs1 = events1.front();
2539 justconfig = objs1->hit_objs.size()==0 && objs1->misc_objs.size()==0 && objs1->config_objs.size()!=0;
2540 }else if(events2.size()==1){
2541 ObjList *objs2 = events2.front();
2542 justconfig = objs2->hit_objs.size()==0 && objs2->misc_objs.size()==0 && objs2->config_objs.size()!=0;
2543 }
2544
2545 // Check number of events and throw exception if appropriate
2546 unsigned int Nevents1 = events1.size();
2547 unsigned int Nevents2 = events2.size();
2548 if(Nevents1>0 && Nevents2>0 && !justconfig){
2549 if(Nevents1 != Nevents2){
2550 evioout << "Mismatch of number of events passed to MergeObjLists. Throwing exception." << endl;
2551 evioout << "Nevents1="<<Nevents1<<" Nevents2="<<Nevents2<<endl;
2552 throw JException("Number of events in JEventSource_EVIO::MergeObjLists do not match!");
2553 }
2554 }
2555
2556 // Handle cases when one or both lists are empty
2557 if(Nevents1==0 && Nevents2==0)return;
2558 if(Nevents1==0){
2559 events1 = events2;
2560 events2.clear(); // clear queue
2561 return;
2562 }
2563 if(Nevents2==0)return;
2564
2565 // If we get here it means both events1 and events2 have events
2566 list<ObjList*>::iterator iter = events1.begin();
2567 for(; iter!=events1.end(); iter++){
2568 if(events2.empty()) break; // in case one has just config objects in a single event
2569 ObjList *objs1 = *iter;
2570 ObjList *objs2 = events2.front();
2571 events2.pop_front();
2572
2573 objs1->hit_objs.insert(objs1->hit_objs.end(), objs2->hit_objs.begin(), objs2->hit_objs.end());
2574 objs1->config_objs.insert(objs1->config_objs.end(), objs2->config_objs.begin(), objs2->config_objs.end());
2575 objs1->misc_objs.insert(objs1->misc_objs.end(), objs2->misc_objs.begin(), objs2->misc_objs.end());
2576
2577 // Delete the objs2 container
2578 delete objs2;
2579 }
2580
2581 // Clear out any references to objects in event2 (this should be redundant)
2582 events2.clear(); // clear queue
2583
2584 if(VERBOSE>5) evioout << " Leaving MergeObjLists(). &events1=" << hex << &events1 << " &events2=" << &events2 << dec << endl;
2585}
2586
2587//----------------
2588// ParseEVIOEvent
2589//----------------
2590void JEventSource_EVIO::ParseEVIOEvent(evioDOMTree *evt, list<ObjList*> &full_events)
2591{
2592 if(VERBOSE>5) evioout << " Entering ParseEVIOEvent() with evt=" << hex << evt << dec << endl;
2593
2594 if(!evt)throw RESOURCE_UNAVAILABLE;
2595
2596 // Since each bank contains parts of many events, have them fill in
2597 // the "tmp_events" list and then merge those into the "full_events".
2598 // It is done this way so each bank can grow tmp_events to the appropriate
2599 // size to hold the number of events it discovers in the bank. A check
2600 // can then be made that this is consistent with the number of event
2601 // fragments found in the other banks.
2602 //list<ObjList*> full_events;
2603 list<ObjList*> tmp_events;
2604
2605 // The Physics Event bank is the outermost bank of the event and
2606 // it is a bank of banks. One of those banks is the
2607 // "Built Trigger Bank" which is a bank of segments. The others
2608 // are the "Data Bank" banks which in turn contain the
2609 // "Data Block Bank" banks which hold the actual data. For the
2610 // mc2coda generated data files (and presumably the real data)
2611 // these Data Block Banks are banks of ints. More specifically,
2612 // uint32_t.
2613 //
2614 // The "Physics Event's Built Trigger Bank" is a bank of segments.
2615 // This contains 3 segments, one each of type uint64, uint16, and
2616 // unit32. The first two are "common data" which contains information
2617 // common to all rocs. The last (uint32) has information specific to each
2618 // event and for each ROC.
2619 //
2620 // For now, we skip parseing the Built Trigger Bank and just
2621 // look for Data Block Banks. We do this by getting a list of
2622 // all uint32_t banks in the enitries DOM Tree (at all levels
2623 // of the heirachy) and checking the parent banks for depth
2624 // and additional info.
2625
2626 // Loop over list of all EVIO banks at all levels of the tree and parse
2627 // them, creating data objects and adding them to the overall list.
2628 evioDOMNodeListP bankList = evt->getNodeList();
2629 evioDOMNodeList::iterator iter = bankList->begin();
2630 if(VERBOSE>7) evioout << " Looping over " << bankList->size() << " banks in EVIO event" << endl;
2631 for(int ibank=1; iter!=bankList->end(); iter++, ibank++){ // ibank only used for debugging messages
2632
2633 if(VERBOSE>7) evioout << " -------- bank " << ibank << "/" << bankList->size() << " --------" << endl;
2634
2635 // The data banks we want should have exactly two parents:
2636 // - Data Bank bank <-- parent
2637 // - Physics Event bank <-- grandparent
2638 //
2639 // other types of events may be inserted in the datastream though so we
2640 // check for those first.
2641
2642 // BOR event
2643 // BOR events will have an outermost
2644 // bank with tag=0x70 and num=1. If this is the outermost bank of
2645 // a BOR event, then parse it. If it is a inner BOR bank then ignore it.
2646 evioDOMNodeP outermostBankPtr = *iter;
2647 while(outermostBankPtr->getParent()) outermostBankPtr = outermostBankPtr->getParent();
2648 if(outermostBankPtr->tag==0x70 && outermostBankPtr->num==1){
2649 // This is a BOR bank
2650 if(VERBOSE>9) evioout << " bank is part of BOR event ... " << endl;
2651 if(outermostBankPtr == *iter){
2652 if(VERBOSE>9) evioout << " bank is outermost EVIO bank. Parsing BOR event ..." << endl;
2653 ParseBORevent(outermostBankPtr);
2654 }else{
2655 if(VERBOSE>9) evioout << " bank is not outermost EVIO bankin BOR event skipping ..." << endl;
2656 }
2657 continue; // no further processing of this bank is needed
2658 }
2659
2660 // EPICS event
2661 evioDOMNodeP bankPtr = *iter;
2662 evioDOMNodeP data_bank = bankPtr->getParent();
2663 if( data_bank==NULL__null ) {
2664
2665 if(VERBOSE>9) evioout << " bank has no parent. Checking if it's an EPICS event ... " << endl;
2666 if(bankPtr->tag==96 && bankPtr->num==1){
2667 // This looks like an EPICS event. Hand it over to EPICS parser
2668 ParseEPICSevent(bankPtr, full_events);
2669 }else{
2670 if(VERBOSE>9) evioout << " Not an EPICS event bank. skipping ... " << endl;
2671 }
2672
2673 continue;
2674 }
2675
2676 // Trigger Bank
2677 evioDOMNodeP physics_event_bank = data_bank->getParent();
2678
2679 // TS scalers for SYNC events. Currently us phys event tag
2680 // Don't use the parent tag in the future, to be checked
2681 if((physics_event_bank != NULL__null) && (bankPtr != NULL__null)){
2682 if( (physics_event_bank->tag == 0xff70) && (bankPtr->tag == 0xEE02)){
2683 const vector<uint32_t> *vec = bankPtr->getVector<uint32_t>();
2684 if(vec->size() < 102){
2685 evioout << " TS record for SYNC event is inconsistent. Don't parse " << endl;
2686 } else {
2687 ParseTSSync(bankPtr, full_events);
2688 // MergeObjLists(full_events, tmp_events);
2689 }
2690 }
2691 }
2692
2693
2694 if( physics_event_bank==NULL__null ){
2695 if(VERBOSE>6) evioout << " bank has no grandparent. Checking if this is a trigger bank ... " << endl;
2696
2697 // Check if this is a CODA Reserved Bank Tag. If it is, then
2698 // this probably is part of the built trigger bank and not
2699 // the ROC data we're looking to parse here.
2700 if((bankPtr->tag & 0xFF00) == 0xFF00){
2701 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;
2702 ParseBuiltTriggerBank(bankPtr, tmp_events);
2703 if(VERBOSE>5) evioout << " Merging objects in ParseEVIOEvent" << endl;
2704 MergeObjLists(full_events, tmp_events);
2705
2706 // Check if this is a DEventTag bank
2707 }else if(bankPtr->tag == 0x0056){
2708 const vector<uint32_t> *vec = bankPtr->getVector<uint32_t>();
2709 if(vec){
2710 const uint32_t *iptr = &(*vec)[0];
2711 const uint32_t *iend = &(*vec)[vec->size()];
2712 ParseEventTag(iptr, iend, tmp_events);
2713 if(VERBOSE>5) evioout << " Merging DEventTag objects in ParseEVIOEvent" << endl;
2714 MergeObjLists(full_events, tmp_events);
2715 }
2716 }
2717
2718 continue; // if this wasn't a trigger bank, then it has the wrong lineage to be a data bank
2719 }
2720 if( physics_event_bank->getParent() != NULL__null ){
2721 if(VERBOSE>9) evioout << " bank DOES have great-grandparent. skipping ... " << endl;
2722 continue; // physics event bank should have no parent!
2723 }
2724 if(VERBOSE>9){
2725 evioout << " Physics Event Bank: tag=" << hex << physics_event_bank->tag << " num=" << (int)physics_event_bank->num << dec << endl;
2726 evioout << " Data Bank: tag=" << hex << data_bank->tag << " num=" << (int)data_bank->num << dec << endl;
2727 }
2728
2729 if(VERBOSE>9) evioout << " bank lineage check OK. Continuing with parsing ... " << endl;
2730
2731 // Extract ROC id (crate number) from bank's parent
2732 uint32_t rocid = data_bank->tag & 0x0FFF;
2733
2734 // Get data from bank in the form of a vector of uint32_t
2735 const vector<uint32_t> *vec = bankPtr->getVector<uint32_t>();
2736 if(!vec){
2737 if(VERBOSE>6) evioout << " bank is not uint32_t. Skipping..." << endl;
2738 continue;
2739 }
2740 const uint32_t *iptr = &(*vec)[0];
2741 const uint32_t *iend = &(*vec)[vec->size()];
2742 if(VERBOSE>6) evioout << " uint32_t bank has " << vec->size() << " words" << endl;
2743
2744 // If there are rocid's specified that we wish to parse, make sure this one
2745 // is in the list. Otherwise, skip it.
2746 if(!ROCIDS_TO_PARSE.empty()){
2747 if(VERBOSE>4) evioout << " Skipping parsing of rocid="<<rocid<<" due to it being in ROCIDS_TO_PARSE set." << endl;
2748 if(ROCIDS_TO_PARSE.find(rocid) == ROCIDS_TO_PARSE.end()) continue;
2749 }
2750
2751 // Check if this is a CODA Reserved Bank Tag.
2752 if((data_bank->tag & 0xFF00) == 0xFF00){
2753 if(VERBOSE>6) evioout << " Data Bank tag="<<hex<<data_bank->tag<<dec<<" is in reserved CODA range. This is probably not ROC data"<< endl;
2754 continue;
2755 }
2756
2757 // Check if this is a TS Bank.
2758 if(bankPtr->tag == 0xEE02){
2759 if(VERBOSE>4) evioout << " TS bank tag="<<hex<<bankPtr->tag<<dec<< endl;
2760 ParseTSBank(rocid, iptr, iend, full_events);
2761 continue;
2762 }
2763
2764 // Check if this is a f250 Pedestal Bank.
2765 if(bankPtr->tag == 0xEE05){
2766 if(VERBOSE>6) evioout << " SYNC event - f250 pedestals not currently handled"<< endl;
2767 continue;
2768 }
2769
2770 // The number of events in block is stored in lower 8 bits
2771 // of header word (aka the "num") of Data Bank. This should
2772 // be at least 1.
2773 uint32_t NumEvents = data_bank->num & 0xFF;
2774 if( NumEvents<1 ){
2775 if(VERBOSE>9) evioout << " bank has less than 1 event (Data Bank num or \"M\" = 0) skipping ... " << endl;
2776 continue;
2777 }
2778
2779 // At this point iptr and iend indicate the data that came
2780 // from the ROC itself (all CODA headers have been stripped
2781 // away). Here, we need to decide what type of data this
2782 // bank contains. All JLab modules have a common block
2783 // header format and so are handled in a common way. Other
2784 // modules (e.g. CAEN) will have to appear in their own
2785 // EVIO bank and should be identified by their own det_id
2786 // value in the Data Block Bank.
2787 //
2788 // Current, preliminary thinking includes writing the type
2789 // of data into the 12-bit detector id contained in the
2790 // Data Block Bank of the DAQ group's "Event Building EVIO
2791 // Scheme". (This is the lower 12 bits of the "tag"). We
2792 // use this to decide if it is JLab module data or somehting
2793 // else.
2794 uint32_t det_id = bankPtr->tag & 0x0FFF;
2795 // Call appropriate parsing method
2796 bool bank_parsed = true; // will be set to false if default case is entered
2797 switch(det_id){
2798 case 0:
2799 case 1:
2800 case 3:
2801 case 6: // flash 250 module, MMD 2014/2/4
2802 case 16: // flash 125 module (CDC), DL 2014/6/19
2803 case 26: // F1 TDC module (BCAL), MMD 2014-07-31
2804 ParseJLabModuleData(rocid, iptr, iend, tmp_events);
2805 break;
2806
2807 case 20:
2808 ParseCAEN1190(rocid, iptr, iend, tmp_events);
2809 break;
2810
2811 case 0x55:
2812 ParseModuleConfiguration(rocid, iptr, iend, tmp_events);
2813 break;
2814
2815 case 5:
2816 // Beni's original CDC ROL used for the stand-alone CDC DAQ
2817 // had the following for the TS readout list (used in the TI):
2818 // *dma_dabufp++ = 0xcebaf111;
2819 // *dma_dabufp++ = tsGetIntCount();
2820 // *dma_dabufp++ = 0xdead;
2821 // *dma_dabufp++ = 0xcebaf222;
2822 // We skip this here, but put in the case so that we avoid errors
2823 break;
2824
2825
2826 default:
2827 jerr<<"Unknown module type ("<<det_id<<") encountered for tag="<<bankPtr->tag<<" num="<< (int)bankPtr->num << endl;
2828 bank_parsed = false;
2829 if(VERBOSE>5){
2830 cerr << endl;
2831 cout << "----- First few words to help with debugging -----" << endl;
2832 cout.flush(); cerr.flush();
2833 int i=0;
2834 for(const uint32_t *iiptr = iptr; iiptr<iend; iiptr++, i++){
2835 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<2835<<" "
<< "0x" << hex << *iiptr << dec << endl;
2836 if(i>=8) break;
2837 }
2838
2839 }
2840 }
2841
2842 // Merge this bank's partial events into the full events
2843 if(bank_parsed){
2844 if(VERBOSE>5) evioout << " Merging objects in ParseEVIOEvent" << endl;
2845 MergeObjLists(full_events, tmp_events);
2846 }
2847 }
2848
2849 // The following disabled in preference for keeping the
2850 // run number found by FindRunNumber called from
2851 // GetEvent() 2/15/2016
2852
2853 // // Set the run number for all events
2854 // uint32_t run_number = GetRunNumber(evt);
2855 // list<ObjList*>::iterator evt_iter = full_events.begin();
2856 // for(; evt_iter!=full_events.end(); evt_iter++){
2857 // ObjList *objs = *evt_iter;
2858 // objs->run_number = run_number;
2859 // }
2860
2861 if(VERBOSE>5) evioout << " Leaving ParseEVIOEvent()" << endl;
2862}
2863
2864//----------------
2865// ParseBuiltTriggerBank
2866//----------------
2867void JEventSource_EVIO::ParseBuiltTriggerBank(evioDOMNodeP trigbank, list<ObjList*> &events)
2868{
2869 if(!PARSE_TRIGGER) return;
2870
2871 if(VERBOSE>5) evioout << " Entering ParseBuiltTriggerBank()" << endl;
2872
2873 uint32_t Mevents = 1; // number of events in block (will be overwritten below)
2874 uint32_t Nrocs = (uint32_t)trigbank->num; // number of rocs providing data in this bank
2875 evioDOMNodeP physics_event_bank = trigbank->getParent();
2876 if(physics_event_bank) Mevents = (uint32_t)physics_event_bank->num;
2877
2878 if(VERBOSE>6) evioout << " Mevents=" << Mevents << " Nrocs=" << Nrocs << endl;
2879
2880 // Some values to fill in while parsing the banks that will be used later to create objects
2881 vector<uint64_t> avg_timestamps;
2882 uint32_t run_number = 0;
2883 uint32_t run_type = 0;
2884 uint64_t first_event_num = 1;
2885 vector<uint16_t> event_types;
2886 map<uint32_t, vector<DCODAROCInfo*> > rocinfos; // key=event (from 0 to Mevents-1)
2887 //vector<map<uint32_t, DCODAROCInfo*> > rocinfos; // key=rocid
2888
2889 // Loop over children of built trigger bank
2890 evioDOMNodeListP bankList = trigbank->getChildren();
2891 evioDOMNodeList::iterator iter = bankList->begin();
2892 for(int ibank=1; iter!=bankList->end(); iter++, ibank++){
2893
2894 if(VERBOSE>7) evioout << " Looking for data in child banks ..." << endl;
2895
2896 evioDOMNodeP bankPtr = *iter;
2897
2898 // The "Physics Event's Built Trigger Bank" is a bank of segments that
2899 // may contain banks of 3 data types: uint64_t, uint32_t, and uint16_t
2900 // The uint64_t contains the first event number, average timestamps, and
2901 // run number & types. The uint16_t contains the event type(s). The
2902 // uint32_t contains the optional ROC specific meta data starting with
2903 // the specific timestamp for each event. All of these have some options
2904 // on exactly what info is contained in the bank. The first check here is
2905 // on the data type the bank contains. At most, one of the following pointers
2906 // should be non-zero.
2907 vector<uint64_t> *vec64 = bankPtr->getVector<uint64_t>();
2908 vector<uint32_t> *vec32 = bankPtr->getVector<uint32_t>();
2909 vector<uint16_t> *vec16 = bankPtr->getVector<uint16_t>();
2910
2911 // unit64_t = common data (1st part)
2912 if(vec64){
2913
2914 if(VERBOSE>9) evioout << " found uint64_t data" << endl;
2915
2916 // In addition to the first event number (1st word) there are three
2917 // additional pieces of information that may be present:
2918 // t = average timestamp
2919 // r = run number and type
2920 // d = run specific data
2921 //
2922 // The last one ("d") comes in the form of multiple uint32_t banks
2923 // so is not included in vec64. The other two have their presence
2924 // signaled by bit 0(=t) and bit 1(=r) in the trigbank tag. (We can
2925 // also deduce this from the bank length.)
2926
2927 if(vec64->size() == 0) continue; // need debug message here!
2928
2929 first_event_num = (*vec64)[0];
2930
2931 // Hi and lo 32bit words in 64bit numbers seem to be
2932 // switched for events read from ET, but not read from
2933 // file. Not sure if this is in the swapping routine
2934 if(source_type==kETSource) first_event_num = (first_event_num>>32) | (first_event_num<<32);
2935
2936 uint32_t Ntimestamps = vec64->size()-1;
2937 if(Ntimestamps==0) continue; // no more words of interest
2938 if(trigbank->tag & 0x2) Ntimestamps--; // subtract 1 for run number/type word if present
2939 for(uint32_t i=0; i<Ntimestamps; i++) avg_timestamps.push_back((*vec64)[i+1]);
2940
2941 // run number and run type
2942 if(trigbank->tag & 0x02){
2943 run_number = (*vec64)[vec64->size()-1] >> 32;
2944 run_type = (*vec64)[vec64->size()-1] & 0xFFFFFFFF;
2945 }
2946 }
2947
2948 // uint16_t = common data (2nd part)
2949 if(vec16){
2950
2951 if(VERBOSE>9) evioout << " found uint16_t data" << endl;
2952
2953 for(uint32_t i=0; i<Mevents; i++){
2954 if(i>=vec16->size()) break;
2955 event_types.push_back((*vec16)[i]);
2956 }
2957 }
2958
2959 // uint32_t = inidivdual ROC timestamps and misc. roc-specfic data
2960 if(vec32){
2961
2962 if(VERBOSE>9) evioout << " found uint32_t data" << endl;
2963
2964 // Get pointer to DCODAROCInfo object for this rocid/event, instantiating it if necessary
2965 uint32_t rocid = (uint32_t)bankPtr->tag;
2966 uint32_t Nwords_per_event = vec32->size()/Mevents;
2967 if(vec32->size() != Mevents*Nwords_per_event){
2968 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<2968<<" "
<< "Number of ROC data words in Trigger Bank inconsistent with header" << endl;
2969 exit(-1);
2970 }
2971
2972 uint32_t *iptr = &(*vec32)[0];
2973 for(uint32_t ievent=0; ievent<Mevents; ievent++){
2974
2975 DCODAROCInfo *codarocinfo = new DCODAROCInfo;
2976 codarocinfo->rocid = rocid;
2977
2978 uint64_t ts_low = *iptr++;
2979 uint64_t ts_high = *iptr++;
2980 codarocinfo->timestamp = (ts_high<<32) + ts_low;
2981 for(uint32_t i=2; i<Nwords_per_event; i++) codarocinfo->misc.push_back(*iptr++);
2982
2983 if(VERBOSE>7) evioout << " Adding DCODAROCInfo for rocid="<<rocid<< " with timestamp " << codarocinfo->timestamp << endl;
2984 rocinfos[ievent].push_back(codarocinfo);
2985 }
2986 }
2987 }
2988
2989 // Check that we have agreement on the number of events this data represents
2990 bool Nevent_mismatch = false;
2991 if(!avg_timestamps.empty()) Nevent_mismatch |= (avg_timestamps.size() != Mevents);
2992 if(!event_types.empty() ) Nevent_mismatch |= (event_types.size() != Mevents);
2993 if(!rocinfos.empty() ) Nevent_mismatch |= (rocinfos.size() != Mevents);
2994 if(Nevent_mismatch){
2995 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<2995<<" "
<<"Mismatch in number of events in Trigger Bank!"<<endl;
2996 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<2996<<" "
<<" Mevents="<<Mevents<<endl;
2997 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<2997<<" "
<<" avg_timestamps.size()="<<avg_timestamps.size()<<endl;
2998 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<2998<<" "
<<" event_types.size()="<<event_types.size()<<endl;
2999 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<2999<<" "
<<" rocinfos.size()="<<rocinfos.size()<<endl;
3000 exit(-1);
3001 }
3002
3003 // Copy all objects into events
3004 for(uint32_t i=0; i<Mevents; i++){
3005 while(events.size()<=i){
3006 if(!ENABLE_DISENTANGLING && !events.empty()) break;
3007 events.push_back(new ObjList);
3008 }
3009 ObjList *objs = events.back();
3010
3011 DCODAEventInfo *codaeventinfo = new DCODAEventInfo;
3012 codaeventinfo->run_number = run_number;
3013 codaeventinfo->run_type = run_type;
3014 codaeventinfo->event_number = first_event_num + i;
3015 codaeventinfo->event_type = event_types.empty() ? 0:event_types[i];
3016 codaeventinfo->avg_timestamp = avg_timestamps.empty() ? 0:avg_timestamps[i];
3017 objs->misc_objs.push_back(codaeventinfo);
3018 objs->event_number = codaeventinfo->event_number;
3019
3020 vector<DCODAROCInfo*> &codarocinfos = rocinfos[i];
3021 for(uint32_t i=0; i<codarocinfos.size(); i++) objs->misc_objs.push_back(codarocinfos[i]);
3022 }
3023
3024 if(VERBOSE>6) evioout << " Found "<<events.size()<<" events in Built Trigger Bank"<< endl;
3025 if(VERBOSE>5) evioout << " Leaving ParseBuiltTriggerBank()" << endl;
3026}
3027
3028//----------------
3029// ParseModuleConfiguration
3030//----------------
3031void JEventSource_EVIO::ParseModuleConfiguration(int32_t rocid, const uint32_t* &iptr, const uint32_t *iend, list<ObjList*> &events)
3032{
3033 if(!PARSE_CONFIG){ iptr = iend; return; }
3034
3035 if(VERBOSE>5) evioout << " Entering ParseModuleConfiguration() (events.size()="<<events.size()<<")" << endl;
3036
3037 /// Parse a bank of module configuration data. These are configuration values
3038 /// programmed into the module at the beginning of the run that may be needed
3039 /// in the offline. For example, the number of samples to sum in a FADC pulse
3040 /// integral.
3041 ///
3042 /// The bank has one or more sections, each describing parameters applicable
3043 /// to a number of modules as indicated by a 24bit slot mask.
3044 ///
3045 /// This bank should appear only once per DAQ event which, if in multi-event
3046 /// block mode, may have multiple L1 events. The parameters here will apply
3047 /// to all L1 events in the block. This method will put the config objects
3048 /// in the first event of "events", creating it if needed. The config objects
3049 /// are duplicated for all other events in the block later, after all event
3050 /// parsing is finished and the total number of events is known.
3051 /// (See the end of ParseEvents() .)
3052
3053 while(iptr < iend){
3054 uint32_t slot_mask = (*iptr) & 0xFFFFFF;
3055 uint32_t Nvals = ((*iptr) >> 24) & 0xFF;
3056 iptr++;
3057
3058 Df250Config *f250config = NULL__null;
3059 Df125Config *f125config = NULL__null;
3060 DF1TDCConfig *f1tdcconfig = NULL__null;
3061 DCAEN1290TDCConfig *caen1290tdcconfig = NULL__null;
3062
3063 // Loop over all parameters in this section
3064 for(uint32_t i=0; i< Nvals; i++){
3065 if( iptr >= iend){
3066 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3066<<" "
<< "DAQ Configuration bank corrupt! slot_mask=0x" << hex << slot_mask << dec << " Nvals="<< Nvals << endl;
3067 exit(-1);
3068 }
3069
3070 daq_param_type ptype = (daq_param_type)((*iptr)>>16);
3071 uint16_t val = (*iptr) & 0xFFFF;
3072
3073 if(VERBOSE>6) evioout << " DAQ parameter of type: 0x" << hex << ptype << dec << " found with value: " << val << endl;
3074
3075 // Create config object of correct type if needed and copy
3076 // parameter value into it.
3077 switch(ptype>>8){
3078
3079 // f250
3080 case 0x05:
3081 if( !f250config ) f250config = new Df250Config(rocid, slot_mask);
3082 switch(ptype){
3083 case kPARAM250_NSA : f250config->NSA = val; break;
3084 case kPARAM250_NSB : f250config->NSB = val; break;
3085 case kPARAM250_NSA_NSB : f250config->NSA_NSB = val; break;
3086 case kPARAM250_NPED : f250config->NPED = val; break;
3087 default: _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3087<<" "
<< "UNKNOWN DAQ Config Parameter type: 0x" << hex << ptype << dec << endl;
3088 }
3089 break;
3090
3091 // f125
3092 case 0x0F:
3093 if( !f125config ) f125config = new Df125Config(rocid, slot_mask);
3094 switch(ptype){
3095 case kPARAM125_NSA : f125config->NSA = val; break;
3096 case kPARAM125_NSB : f125config->NSB = val; break;
3097 case kPARAM125_NSA_NSB : f125config->NSA_NSB = val; break;
3098 case kPARAM125_NPED : f125config->NPED = val; break;
3099 case kPARAM125_WINWIDTH : f125config->WINWIDTH = val; break;
3100 case kPARAM125_PL : f125config->PL = val; break;
3101 case kPARAM125_NW : f125config->NW = val; break;
3102 case kPARAM125_NPK : f125config->NPK = val; break;
3103 case kPARAM125_P1 : f125config->P1 = val; break;
3104 case kPARAM125_P2 : f125config->P2 = val; break;
3105 case kPARAM125_PG : f125config->PG = val; break;
3106 case kPARAM125_IE : f125config->IE = val; break;
3107 case kPARAM125_H : f125config->H = val; break;
3108 case kPARAM125_TH : f125config->TH = val; break;
3109 case kPARAM125_TL : f125config->TL = val; break;
3110 case kPARAM125_IBIT : f125config->IBIT = val; break;
3111 case kPARAM125_ABIT : f125config->ABIT = val; break;
3112 case kPARAM125_PBIT : f125config->PBIT = val; break;
3113 default: _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3113<<" "
<< "UNKNOWN DAQ Config Parameter type: 0x" << hex << ptype << dec << endl;
3114 }
3115 break;
3116
3117 // F1TDC
3118 case 0x06:
3119 if( !f1tdcconfig ) f1tdcconfig = new DF1TDCConfig(rocid, slot_mask);
3120 switch(ptype){
3121 case kPARAMF1_REFCNT : f1tdcconfig->REFCNT = val; break;
3122 case kPARAMF1_TRIGWIN : f1tdcconfig->TRIGWIN = val; break;
3123 case kPARAMF1_TRIGLAT : f1tdcconfig->TRIGLAT = val; break;
3124 case kPARAMF1_HSDIV : f1tdcconfig->HSDIV = val; break;
3125 case kPARAMF1_BINSIZE : f1tdcconfig->BINSIZE = val; break;
3126 case kPARAMF1_REFCLKDIV : f1tdcconfig->REFCLKDIV = val; break;
3127 default: _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3127<<" "
<< "UNKNOWN DAQ Config Parameter type: 0x" << hex << ptype << dec << endl;
3128 }
3129 break;
3130
3131 // caen1290
3132 case 0x10:
3133 if( !caen1290tdcconfig ) caen1290tdcconfig = new DCAEN1290TDCConfig(rocid, slot_mask);
3134 switch(ptype){
3135 case kPARAMCAEN1290_WINWIDTH : caen1290tdcconfig->WINWIDTH = val; break;
3136 case kPARAMCAEN1290_WINOFFSET : caen1290tdcconfig->WINOFFSET = val; break;
3137 default: _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3137<<" "
<< "UNKNOWN DAQ Config Parameter type: 0x" << hex << ptype << dec << endl;
3138 }
3139 break;
3140
3141 default:
3142 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3142<<" "
<< "Unknown module type: 0x" << hex << (ptype>>8) << endl;
3143 exit(-1);
3144 }
3145
3146#if 0
3147 // Create config object of correct type if needed. (Only one type
3148 // should be created per section!)
3149 switch(ptype>>8){
3150 case 0x05: if(!f250config ) f250config = new Df250Config(rocid, slot_mask); break;
3151 case 0x0F: if(!f125config ) f125config = new Df125Config(rocid, slot_mask); break;
3152 case 0x06: if(!f1tdcconfig ) f1tdcconfig = new DF1TDCConfig(rocid, slot_mask); break;
3153 case 0x10: if(!caen1290tdcconfig) caen1290tdcconfig = new DCAEN1290TDCConfig(rocid, slot_mask); break;
3154 default:
3155 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3155<<" "
<< "Unknown module type: 0x" << hex << (ptype>>8) << endl;
3156 exit(-1);
3157 }
3158
3159 // Copy parameter into config. object
3160 switch(ptype){
3161 case kPARAM250_NSA : f250config->NSA = val; break;
3162 case kPARAM250_NSB : f250config->NSB = val; break;
3163 case kPARAM250_NSA_NSB : f250config->NSA_NSB = val; break;
3164 case kPARAM250_NPED : f250config->NPED = val; break;
3165
3166 case kPARAM125_NSA : f125config->NSA = val; break;
3167 case kPARAM125_NSB : f125config->NSB = val; break;
3168 case kPARAM125_NSA_NSB : f125config->NSA_NSB = val; break;
3169 case kPARAM125_NPED : f125config->NPED = val; break;
3170 case kPARAM125_WINWIDTH : f125config->WINWIDTH = val; break;
3171 case kPARAM125_PL : f125config->PL = val; break;
3172 case kPARAM125_NW : f125config->NW = val; break;
3173 case kPARAM125_NPK : f125config->NPK = val; break;
3174 case kPARAM125_P1 : f125config->P1 = val; break;
3175 case kPARAM125_P2 : f125config->P2 = val; break;
3176 case kPARAM125_PG : f125config->PG = val; break;
3177 case kPARAM125_IE : f125config->IE = val; break;
3178 case kPARAM125_H : f125config->H = val; break;
3179 case kPARAM125_TH : f125config->TH = val; break;
3180 case kPARAM125_TL : f125config->TL = val; break;
3181 case kPARAM125_IBIT : f125config->IBIT = val; break;
3182 case kPARAM125_ABIT : f125config->ABIT = val; break;
3183 case kPARAM125_PBIT : f125config->PBIT = val; break;
3184
3185 case kPARAMF1_REFCNT : f1tdcconfig->REFCNT = val; break;
3186 case kPARAMF1_TRIGWIN : f1tdcconfig->TRIGWIN = val; break;
3187 case kPARAMF1_TRIGLAT : f1tdcconfig->TRIGLAT = val; break;
3188 case kPARAMF1_HSDIV : f1tdcconfig->HSDIV = val; break;
3189 case kPARAMF1_BINSIZE : f1tdcconfig->BINSIZE = val; break;
3190 case kPARAMF1_REFCLKDIV : f1tdcconfig->REFCLKDIV = val; break;
3191
3192 case kPARAMCAEN1290_WINWIDTH : caen1290tdcconfig->WINWIDTH = val; break;
3193 case kPARAMCAEN1290_WINOFFSET : caen1290tdcconfig->WINOFFSET = val; break;
3194
3195 default:
3196 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3196<<" "
<< "UNKNOWN DAQ Config Parameter type: 0x" << hex << ptype << dec << endl;
3197 }
3198#endif
3199
3200 iptr++;
3201 }
3202
3203 // If we get here it means we didn't exit in the switch(ptype>>16) statement above
3204 // so there is at least one DDAQConfig object we need to store. Get pointer to
3205 // first event's ObjList, creating it if needed.
3206 if(events.empty()) events.push_back(new ObjList());
3207 ObjList *objs = *(events.begin());
3208
3209 if(f250config ) objs->config_objs.push_back(f250config );
3210 if(f125config ) objs->config_objs.push_back(f125config );
3211 if(f1tdcconfig ) objs->config_objs.push_back(f1tdcconfig );
3212 if(caen1290tdcconfig) objs->config_objs.push_back(caen1290tdcconfig);
3213 }
3214
3215 if(VERBOSE>5) evioout << " Leaving ParseModuleConfiguration()" << endl;
3216}
3217
3218//----------------
3219// ParseEventTag
3220//----------------
3221void JEventSource_EVIO::ParseEventTag(const uint32_t* &iptr, const uint32_t *iend, list<ObjList*> &events)
3222{
3223 if(!PARSE_EVENTTAG){ iptr = iend; return; }
3224
3225 if(VERBOSE>5) evioout << " Entering ParseEventTag() (events.size()="<<events.size()<<")" << endl;
3226
3227 // Make sure there is one event in the event container
3228 // and get pointer to it.
3229 if(events.empty()) events.push_back(new ObjList());
3230 ObjList *objs = *(events.begin());
3231
3232
3233 DEventTag *etag = new DEventTag;
3234
3235 // event_status
3236 uint64_t lo = *iptr++;
3237 uint64_t hi = *iptr++;
3238 etag->event_status = (hi<<32) + lo;
3239
3240 // L3_status
3241 lo = *iptr++;
3242 hi = *iptr++;
3243 etag->L3_status = (hi<<32) + lo;
3244
3245 // L3_decision
3246 etag->L3_decision = (DL3Trigger::L3_decision_t)*iptr++;
3247
3248 // L3_algorithm
3249 etag->L3_algorithm = *iptr++;
3250
3251 objs->misc_objs.push_back(etag);
3252
3253
3254 if(VERBOSE>5) evioout << " Leaving ParseEventTag()" << endl;
3255}
3256
3257//----------------
3258// ParseJLabModuleData
3259//----------------
3260void JEventSource_EVIO::ParseJLabModuleData(int32_t rocid, const uint32_t* &iptr, const uint32_t *iend, list<ObjList*> &events)
3261{
3262 if(VERBOSE>5) evioout << " Entering ParseJLabModuleData()" << endl;
3263
3264 /// Parse a bank of data coming from one or more JLab modules.
3265 /// The data are assumed to follow the standard JLab format for
3266 /// block headers. If multiple modules are read out in a single
3267 /// chain block transfer, then the data will all be placed in
3268 /// a single EVIO bank and this will loop over the modules.
3269 while(iptr < iend){
3270
3271 if(VERBOSE>9) evioout << "Parsing word: " << hex << *iptr << dec << endl;
3272
3273 // This was observed in some CDC data. Not sure where it came from ...
3274 if(*iptr == 0xF800FAFA){
3275 if(VERBOSE>9) evioout << " 0xf800fafa is a known extra word. Skipping it ..." << endl;
3276 iptr++;
3277 continue;
3278 }
3279
3280 // Get module type from next word (bits 18-21)
3281 uint32_t mod_id = ((*iptr) >> 18) & 0x000F;
3282
3283 // The enum defined in DModuleType.h MUST be kept in alignment
3284 // with the DAQ group's definitions for modules types!
3285 MODULE_TYPE type = (MODULE_TYPE)mod_id;
3286 if(VERBOSE>5) evioout << " Encountered module type: " << type << " (=" << DModuleType::GetModule(type).GetName() << ")" << endl;
3287
3288 if(modtype_translate.find(type) != modtype_translate.end()){
3289 type = modtype_translate[type];
3290 if(VERBOSE>5) evioout << " switched module type to: " << type << " (=" << DModuleType::GetModule(type).GetName() << ")" << endl;
3291 }
3292
3293 // Parse buffer depending on module type
3294 // (Note that each of the ParseXXX routines called below will
3295 // update the "iptr" variable to point to the next word
3296 // after the block it parsed.)
3297 list<ObjList*> tmp_events;
3298 const uint32_t *istart=iptr; // just for UNKNOWN case below
3299 bool module_parsed = true;
3300 switch(type){
3301 case DModuleType::FADC250:
3302 Parsef250Bank(rocid, iptr, iend, tmp_events);
3303 break;
3304
3305 case DModuleType::FADC125:
3306 Parsef125Bank(rocid, iptr, iend, tmp_events);
3307 break;
3308
3309 case DModuleType::F1TDC32:
3310 ParseF1TDCBank(rocid, iptr, iend, tmp_events);
3311 break;
3312
3313 case DModuleType::F1TDC48:
3314 ParseF1TDCBank(rocid, iptr, iend, tmp_events);
3315 break;
3316
3317 case DModuleType::JLAB_TS:
3318 //ParseTSBank(rocid, iptr, iend, tmp_events); // This is not used
3319 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3319<<" "
<< "What the ? ! This data type isn't supposed to be here!!" << endl;
3320 break;
3321
3322 case DModuleType::TID:
3323 ParseTIBank(rocid, iptr, iend, tmp_events);
3324 break;
3325
3326 case DModuleType::UNKNOWN:
3327 default:
3328 jerr<<"Unknown module type ("<<mod_id<<") iptr=0x" << hex << iptr << dec << endl;
3329
3330 while(iptr<iend && ((*iptr) & 0xF8000000) != 0x88000000) iptr++; // Skip to JLab block trailer
3331 iptr++; // advance past JLab block trailer
3332 while(iptr<iend && *iptr == 0xF8000000) iptr++; // skip filler words after block trailer
3333 module_parsed = false;
3334 jerr<<"...skipping to 0x" << hex << iptr << dec << " (discarding " << (((uint64_t)iptr-(uint64_t)istart)/4) << " words)" << endl;
3335 break;
3336 }
3337
3338 if(VERBOSE>9) evioout << "Finished parsing (last word: " << hex << iptr[-1] << dec << ")" << endl;
3339
3340 if(module_parsed){
3341 if(VERBOSE>5) evioout << " Merging objects in ParseJLabModuleData" << endl;
3342 MergeObjLists(events, tmp_events);
3343 }
3344 }
3345
3346 if(VERBOSE>5) evioout << " Leaving ParseJLabModuleData()" << endl;
3347}
3348
3349//----------------
3350// Parsef250Bank
3351//----------------
3352void JEventSource_EVIO::Parsef250Bank(int32_t rocid, const uint32_t* &iptr, const uint32_t *iend, list<ObjList*> &events)
3353{
3354 /// Parse data from a single FADC250 module.
3355
3356 if(!PARSE_F250){ iptr = iend; return; }
3357
3358 // This will get updated to point to a newly allocated object when an
3359 // event header is encountered. The existing value (if non-NULL) is
3360 // added to the events queue first though so all events are kept.
3361 ObjList *objs = NULL__null;
3362
3363 // From the Block Header
3364 uint32_t slot=0;
3365 //uint32_t Nblock_events;
3366 //uint32_t iblock;
3367
3368 // From the Block Trailer
3369 //uint32_t slot_trailer;
3370 //uint32_t Nwords_in_block;
3371
3372 // From Event header
3373 //uint32_t slot_event_header;
3374 uint32_t itrigger = -1;
3375 uint32_t last_itrigger = -2;
3376
3377 // Loop over data words
3378 for(; iptr<iend; iptr++){
3379
3380 // Skip all non-data-type-defining words at this
3381 // level. When we do encounter one, the appropriate
3382 // case block below should handle parsing all of
3383 // the data continuation words and advance the iptr.
3384 if(((*iptr>>31) & 0x1) == 0)continue;
3385
3386 // Variables used inside of switch, but cannot be declared inside
3387 uint64_t t = 0L;
3388 uint32_t channel = 0;
3389 uint32_t sum = 0;
3390 uint32_t pulse_number = 0;
3391 uint32_t quality_factor = 0;
3392 uint32_t pulse_time = 0;
3393 uint32_t pedestal = 0;
3394 uint32_t pulse_peak = 0;
3395 uint32_t nsamples_integral = 0;
3396 uint32_t nsamples_pedestal = 0;
3397 bool overflow = false;
3398
3399 bool found_block_trailer = false;
3400 uint32_t data_type = (*iptr>>27) & 0x0F;
3401 switch(data_type){
3402 case 0: // Block Header
3403 slot = (*iptr>>22) & 0x1F;
3404 if(VERBOSE>7) evioout << " FADC250 Block Header: slot="<<slot<<" ("<<hex<<*iptr<<dec<<")"<<endl;
3405 //iblock= (*iptr>>8) & 0x03FF;
3406 //Nblock_events= (*iptr>>0) & 0xFF;
3407 break;
3408 case 1: // Block Trailer
3409 //slot_trailer = (*iptr>>22) & 0x1F;
3410 //Nwords_in_block = (*iptr>>0) & 0x3FFFFF;
3411 if(VERBOSE>7) evioout << " FADC250 Block Trailer"<<" ("<<hex<<*iptr<<dec<<")"<<endl;
3412 found_block_trailer = true;
3413 break;
3414 case 2: // Event Header
3415 //slot_event_header = (*iptr>>22) & 0x1F;
3416 itrigger = (*iptr>>0) & 0x3FFFFF;
3417 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;
3418 if( (itrigger!=last_itrigger) || (objs==NULL__null) ){
3419 if(ENABLE_DISENTANGLING){
3420 if(objs){
3421 events.push_back(objs);
3422 objs = NULL__null;
3423 }
3424 }
3425 if(!objs) objs = new ObjList;
3426 last_itrigger = itrigger;
3427 }
3428 break;
3429 case 3: // Trigger Time
3430 t = ((*iptr)&0xFFFFFF)<<0;
3431 if(VERBOSE>7) evioout << " FADC250 Trigger Time: t="<<t<<" ("<<hex<<*iptr<<dec<<")"<<endl;
3432 iptr++;
3433 if(((*iptr>>31) & 0x1) == 0){
3434 t += ((*iptr)&0xFFFFFF)<<24; // from word on the street: second trigger time word is optional!!??
3435 if(VERBOSE>7) evioout << " Trigger time high word="<<(((*iptr)&0xFFFFFF))<<" ("<<hex<<*iptr<<dec<<")"<<endl;
3436 }else{
3437 iptr--;
3438 }
3439 if(objs) objs->hit_objs.push_back(new Df250TriggerTime(rocid, slot, itrigger, t));
3440 break;
3441 case 4: // Window Raw Data
3442 // iptr passed by reference and so will be updated automatically
3443 if(VERBOSE>7) evioout << " FADC250 Window Raw Data"<<" ("<<hex<<*iptr<<dec<<")"<<endl;
3444 MakeDf250WindowRawData(objs, rocid, slot, itrigger, iptr);
3445 break;
3446 case 5: // Window Sum
3447 channel = (*iptr>>23) & 0x0F;
3448 sum = (*iptr>>0) & 0x3FFFFF;
3449 overflow = (*iptr>>22) & 0x1;
3450 if(VERBOSE>7) evioout << " FADC250 Window Sum"<<" ("<<hex<<*iptr<<dec<<")"<<endl;
3451 if(objs) objs->hit_objs.push_back(new Df250WindowSum(rocid, slot, channel, itrigger, sum, overflow));
3452 break;
3453 case 6: // Pulse Raw Data
3454 // iptr passed by reference and so will be updated automatically
3455 if(VERBOSE>7) evioout << " FADC250 Pulse Raw Data"<<" ("<<hex<<*iptr<<dec<<")"<<endl;
3456 MakeDf250PulseRawData(objs, rocid, slot, itrigger, iptr);
3457 break;
3458 case 7: // Pulse Integral
3459 channel = (*iptr>>23) & 0x0F;
3460 pulse_number = (*iptr>>21) & 0x03;
3461 quality_factor = (*iptr>>19) & 0x03;
3462 sum = (*iptr>>0) & 0x7FFFF;
3463 nsamples_integral = 0; // must be overwritten later in GetObjects with value from Df125Config value
3464 nsamples_pedestal = 1; // The firmware returns an already divided pedestal
3465 pedestal = 0; // This will be replaced by the one from Df250PulsePedestal in GetObjects
3466 if(VERBOSE>7) evioout << " FADC250 Pulse Integral: chan="<<channel<<" pulse_number="<<pulse_number<<" sum="<<sum<<" ("<<hex<<*iptr<<dec<<")"<<endl;
3467 if( (objs!=NULL__null) && (pulse_number<F250PULSE_NUMBER_FILTER) ) {
3468 objs->hit_objs.push_back(new Df250PulseIntegral(rocid, slot, channel, itrigger, pulse_number,
3469 quality_factor, sum, pedestal, nsamples_integral, nsamples_pedestal));
3470 }
3471 break;
3472 case 8: // Pulse Time
3473 channel = (*iptr>>23) & 0x0F;
3474 pulse_number = (*iptr>>21) & 0x03;
3475 quality_factor = (*iptr>>19) & 0x03;
3476 pulse_time = (*iptr>>0) & 0x7FFFF;
3477 if(VERBOSE>7) evioout << " FADC250 Pulse Time: chan="<<channel<<" pulse_number="<<pulse_number<<" pulse_time="<<pulse_time<<" ("<<hex<<*iptr<<dec<<")"<<endl;
3478 if( (objs!=NULL__null) && (pulse_number<F250PULSE_NUMBER_FILTER) ) {
3479 objs->hit_objs.push_back(new Df250PulseTime(rocid, slot, channel, itrigger, pulse_number, quality_factor, pulse_time));
3480 }
3481 break;
3482 case 9: // Streaming Raw Data
3483 // This is marked "reserved for future implementation" in the current manual (v2).
3484 // As such, we don't try handling it here just yet.
3485 if(VERBOSE>7) evioout << " FADC250 Streaming Raw Data (unsupported)"<<" ("<<hex<<*iptr<<dec<<")"<<endl;
3486 break;
3487 case 10: // Pulse Pedestal
3488 channel = (*iptr>>23) & 0x0F;
3489 pulse_number = (*iptr>>21) & 0x03;
3490 pedestal = (*iptr>>12) & 0x1FF;
3491 pulse_peak = (*iptr>>0) & 0xFFF;
3492 if(VERBOSE>7) evioout << " FADC250 Pulse Pedestal chan="<<channel<<" pulse_number="<<pulse_number<<" pedestal="<<pedestal<<" pulse_peak="<<pulse_peak<<" ("<<hex<<*iptr<<dec<<")"<<endl;
3493 if( (objs!=NULL__null) && (pulse_number<F250PULSE_NUMBER_FILTER) ) {
3494 objs->hit_objs.push_back(new Df250PulsePedestal(rocid, slot, channel, itrigger, pulse_number, pedestal, pulse_peak));
3495 }
3496 break;
3497 case 13: // Event Trailer
3498 // This is marked "suppressed for normal readout – debug mode only" in the
3499 // current manual (v2). It does not contain any data so the most we could do here
3500 // is return early. I'm hesitant to do that though since it would mean
3501 // different behavior for debug mode data as regular data.
3502 case 14: // Data not valid (empty module)
3503 case 15: // Filler (non-data) word
3504 if(VERBOSE>7) evioout << " FADC250 Event Trailer, Data not Valid, or Filler word ("<<data_type<<")"<<" ("<<hex<<*iptr<<dec<<")"<<endl;
3505 break;
3506 }
3507
3508 // Once we find a block trailer, assume that is it for this module.
3509 if(found_block_trailer){
3510 iptr++; // iptr is still pointing to block trailer. Jump to next word.
3511 break;
3512 }
3513 }
3514
3515 // Chop off filler words
3516 for(; iptr<iend; iptr++){
3517 if(((*iptr)&0xf8000000) != 0xf8000000) break;
3518 }
3519
3520 // Add last event in block to list
3521 if(objs)events.push_back(objs);
3522
3523 // Here, we make object associations to link PulseIntegral, PulseTime, PulseRawData, etc
3524 // objects to each other so it is easier to get to these downstream without having to
3525 // make nested loops. This is the most efficient place to do it since the ObjList objects
3526 // in "event" contain only the objects from this EVIO block (i.e. at most one crate's
3527 // worth.)
3528 list<ObjList*>::iterator iter = events.begin();
3529 for(; iter!=events.end(); iter++){
3530
3531 // Sort list of objects into type-specific lists
3532 vector<DDAQAddress*> &hit_objs = (*iter)->hit_objs;
3533 vector<Df250TriggerTime*> vtrigt;
3534 vector<Df250WindowRawData*> vwrd;
3535 vector<Df250WindowSum*> vws;
3536 vector<Df250PulseRawData*> vprd;
3537 vector<Df250PulseIntegral*> vpi;
3538 vector<Df250PulseTime*> vpt;
3539 vector<Df250PulsePedestal*> vpp;
3540 for(unsigned int i=0; i<hit_objs.size(); i++){
3541 AddIfAppropriate(hit_objs[i], vtrigt);
3542 AddIfAppropriate(hit_objs[i], vwrd);
3543 AddIfAppropriate(hit_objs[i], vws);
3544 AddIfAppropriate(hit_objs[i], vprd);
3545 AddIfAppropriate(hit_objs[i], vpi);
3546 AddIfAppropriate(hit_objs[i], vpt);
3547 AddIfAppropriate(hit_objs[i], vpp);
3548 }
3549
3550 // Connect Df250PulseIntegral, Df250PulseTime, and
3551 // Df250PulsePedestal with Df250PulseRawData
3552 // (n.b. the associations between pi, pt, and pp are
3553 // done in GetObjects where emulated objects are
3554 // also available.)
3555 LinkAssociationsWithPulseNumber(vprd, vpi);
3556 LinkAssociationsWithPulseNumber(vprd, vpt);
3557 LinkAssociationsWithPulseNumber(vprd, vpp);
3558
3559 // Connect Df250WindowSum and Df250WindowRawData
3560 LinkAssociations(vwrd, vws);
3561
3562 // Connect Df250TriggerTime to everything
3563 LinkAssociationsModuleOnly(vtrigt, vwrd);
3564 LinkAssociationsModuleOnly(vtrigt, vws);
3565 LinkAssociationsModuleOnly(vtrigt, vprd);
3566 LinkAssociationsModuleOnly(vtrigt, vpi);
3567 LinkAssociationsModuleOnly(vtrigt, vpt);
3568 LinkAssociationsModuleOnly(vtrigt, vpp);
3569 }
3570}
3571
3572//----------------
3573// MakeDf250WindowRawData
3574//----------------
3575void JEventSource_EVIO::MakeDf250WindowRawData(ObjList *objs, uint32_t rocid, uint32_t slot, uint32_t itrigger, const uint32_t* &iptr)
3576{
3577 uint32_t channel = (*iptr>>23) & 0x0F;
3578 uint32_t window_width = (*iptr>>0) & 0x0FFF;
3579
3580 Df250WindowRawData *wrd = new Df250WindowRawData(rocid, slot, channel, itrigger);
3581
3582 for(uint32_t isample=0; isample<window_width; isample +=2){
3583
3584 // Advance to next word
3585 iptr++;
3586
3587 // Make sure this is a data continuation word, if not, stop here
3588 if(((*iptr>>31) & 0x1) != 0x0){
3589 iptr--; // calling method expects us to point to last word in block
3590 break;
3591 }
3592
3593 bool invalid_1 = (*iptr>>29) & 0x1;
3594 bool invalid_2 = (*iptr>>13) & 0x1;
3595 uint16_t sample_1 = 0;
3596 uint16_t sample_2 = 0;
3597 if(!invalid_1)sample_1 = (*iptr>>16) & 0x1FFF;
3598 if(!invalid_2)sample_2 = (*iptr>>0) & 0x1FFF;
3599
3600 // Sample 1
3601 wrd->samples.push_back(sample_1);
3602 wrd->invalid_samples |= invalid_1;
3603 wrd->overflow |= (sample_1>>12) & 0x1;
3604
3605 if((isample+2) == window_width && invalid_2)break; // skip last sample if flagged as invalid
3606
3607 // Sample 2
3608 wrd->samples.push_back(sample_2);
3609 wrd->invalid_samples |= invalid_2;
3610 wrd->overflow |= (sample_2>>12) & 0x1;
3611 }
3612
3613 // Due to how the calling function works, the value of "objs" passed to us may be NULL.
3614 // This will happen if a Window Raw Data block is encountered before an event header.
3615 // For these cases, we still want to try parsing the data so that the iptr is updated
3616 // but don't have an event to assign it to. If "objs" is non-NULL, add this object to
3617 // the list. Otherwise, delete it now.
3618 if(objs){
3619 objs->hit_objs.push_back(wrd);
3620 }else{
3621 delete wrd;
3622 }
3623}
3624
3625//----------------
3626// MakeDf250PulseRawData
3627//----------------
3628void JEventSource_EVIO::MakeDf250PulseRawData(ObjList *objs, uint32_t rocid, uint32_t slot, uint32_t itrigger, const uint32_t* &iptr)
3629{
3630 const uint32_t *istart = iptr;
3631 uint32_t channel = (*iptr>>23) & 0x0F;
3632 uint32_t pulse_number = (*iptr>>21) & 0x0003;
3633 uint32_t first_sample_number = (*iptr>>0) & 0x03FF;
3634
3635 if(VERBOSE>9) evioout << " DF250PulseRawData: iptr=0x" << hex << iptr << dec << " channel=" << channel << " pulse_number=" << pulse_number << " first_sample=" << first_sample_number << endl;
3636
3637 Df250PulseRawData *prd = new Df250PulseRawData(rocid, slot, channel, itrigger, pulse_number, first_sample_number);
3638
3639 // This loop needs to break when it hits a non-continuation word
3640 for(uint32_t isample=0; isample<1000; isample +=2){
3641
3642 // Advance to next word
3643 iptr++;
3644
3645 // Make sure this is a data continuation word, if not, stop here
3646 if(((*iptr>>31) & 0x1) != 0x0)break;
3647
3648 bool invalid_1 = (*iptr>>29) & 0x1;
3649 bool invalid_2 = (*iptr>>13) & 0x1;
3650 uint16_t sample_1 = 0;
3651 uint16_t sample_2 = 0;
3652 if(!invalid_1)sample_1 = (*iptr>>16) & 0x1FFF;
3653 if(!invalid_2)sample_2 = (*iptr>>0) & 0x1FFF;
3654
3655 // Sample 1
3656 prd->samples.push_back(sample_1);
3657 prd->invalid_samples |= invalid_1;
3658 prd->overflow |= (sample_1>>12) & 0x1;
3659
3660 bool last_word = (iptr[1]>>31) & 0x1;
3661 if(last_word && invalid_2)break; // skip last sample if flagged as invalid
3662
3663 // Sample 2
3664 prd->samples.push_back(sample_2);
3665 prd->invalid_samples |= invalid_2;
3666 prd->overflow |= (sample_2>>12) & 0x1;
3667 }
3668
3669 if(VERBOSE>9) evioout << " number of samples: " << prd->samples.size() << " words processed: " << iptr-istart << endl;
3670
3671 // When should get here because the loop above stopped when it found
3672 // a data defining word (bit 31=1). The method calling this one will
3673 // assume iptr is pointing to the last word of this block and it will
3674 // advance to the first word of the next block. We need to back up one
3675 // word so that it is pointing to the last word of this block.
3676 iptr--;
3677
3678 // Due to how the calling function works, the value of "objs" passed to us may be NULL.
3679 // This will happen if a Window Raw Data block is encountered before an event header.
3680 // For these cases, we still want to try parsing the data so that the iptr is updated
3681 // but don't have an event to assign it to. If "objs" is non-NULL, add this object to
3682 // the list. Otherwise, delete it now.
3683 if(objs){
3684 objs->hit_objs.push_back(prd);
3685 }else{
3686 delete prd;
3687 }
3688}
3689
3690//----------------
3691// Parsef125Bank
3692//----------------
3693void JEventSource_EVIO::Parsef125Bank(int32_t rocid, const uint32_t* &iptr, const uint32_t* iend, list<ObjList*> &events)
3694{
3695 /// Parse data from a single FADC125 module.
3696 /// This is currently written assuming that the Pulse Integral, Pulse Time, and Pulse Pedestal
3697 /// data formats follow what is in the file:
3698 /// https://halldweb1.jlab.org/wiki/index.php/File:FADC125_dataformat_250_modes.docx
3699
3700 if(!PARSE_F125){ iptr = iend; return; }
3701
3702 if(VERBOSE>6) evioout << " Entering Parsef125Bank for rocid=" << rocid << "..."<<endl;
3703
3704 // This will get updated to point to a newly allocated object when an
3705 // event header is encountered. The existing value (if non-NULL) is
3706 // added to the events queue first though so all events are kept.
3707 ObjList *objs = NULL__null;
3708
3709 // From the Block Header
3710 uint32_t slot=0;
3711 //uint32_t Nblock_events;
3712 //uint32_t iblock;
3713
3714 // From the Block Trailer
3715 //uint32_t slot_trailer;
3716 //uint32_t Nwords_in_block;
3717
3718 // From Event header
3719 //uint32_t slot_event_header;
3720 uint32_t itrigger = -1;
3721 uint32_t last_itrigger = -2;
3722 uint32_t last_pulse_time_channel=0;
3723 uint32_t last_slot = -1;
3724 uint32_t last_channel = -1;
3725
3726 // Loop over data words
3727 for(; iptr<iend; iptr++){
3728
3729 // Skip all non-data-type-defining words at this
3730 // level. When we do encounter one, the appropriate
3731 // case block below should handle parsing all of
3732 // the data continuation words and advance the iptr.
3733 if(((*iptr>>31) & 0x1) == 0)continue;
3734
3735 // Variables used inside of switch, but cannot be declared inside
3736 uint64_t t = 0L;
3737 uint32_t channel = 0;
3738 uint32_t sum = 0;
3739 uint32_t pulse_number = 0;
3740 uint32_t pulse_time = 0;
3741 uint32_t quality_factor = 0;
3742 uint32_t overflow_count = 0;
3743 uint32_t pedestal = 0;
3744 uint32_t pulse_peak = 0;
3745 uint32_t peak_time = 0;
3746 uint32_t nsamples_integral = 0;
3747 uint32_t nsamples_pedestal = 0;
3748 uint32_t word1=0;
3749 uint32_t word2=0;
3750
3751 bool found_block_trailer = false;
3752 uint32_t data_type = (*iptr>>27) & 0x0F;
3753 switch(data_type){
3754 case 0: // Block Header
3755 slot = (*iptr>>22) & 0x1F;
3756 if(VERBOSE>7) evioout << " FADC125 Block Header: slot="<<slot<<endl;
3757 //iblock= (*iptr>>8) & 0x03FF;
3758 //Nblock_events= (*iptr>>0) & 0xFF;
3759 break;
3760 case 1: // Block Trailer
3761 //slot_trailer = (*iptr>>22) & 0x1F;
3762 //Nwords_in_block = (*iptr>>0) & 0x3FFFFF;
3763 found_block_trailer = true;
3764 break;
3765 case 2: // Event Header
3766 //slot_event_header = (*iptr>>22) & 0x1F;
3767 itrigger = (*iptr>>0) & 0x3FFFFFF;
3768 if(VERBOSE>7) evioout << " FADC125 Event Header: itrigger="<<itrigger<<" (objs=0x"<<hex<<objs<<dec<<", last_itrigger="<<last_itrigger<<", rocid="<<rocid<<", slot="<<slot<<")" <<endl;
3769 if( (itrigger!=last_itrigger) || (objs==NULL__null) ){
3770 if(ENABLE_DISENTANGLING){
3771 if(objs){
3772 events.push_back(objs);
3773 objs = NULL__null;
3774 }
3775 }
3776 if(!objs) objs = new ObjList;
3777 last_itrigger = itrigger;
3778 }
3779 break;
3780 case 3: // Trigger Time
3781 t = ((*iptr)&0xFFFFFF)<<0;
3782 iptr++;
3783 if(((*iptr>>31) & 0x1) == 0){
3784 t += ((*iptr)&0xFFFFFF)<<24; // from word on the street: second trigger time word is optional!!??
3785 }else{
3786 iptr--;
3787 }
3788 if(VERBOSE>7) evioout << " FADC125 Trigger Time (t="<<t<<")"<<endl;
3789 if(objs) objs->hit_objs.push_back(new Df125TriggerTime(rocid, slot, itrigger, t));
3790 break;
3791 case 4: // Window Raw Data
3792 // iptr passed by reference and so will be updated automatically
3793 if(VERBOSE>7) evioout << " FADC125 Window Raw Data"<<endl;
3794 MakeDf125WindowRawData(objs, rocid, slot, itrigger, iptr);
3795 break;
3796
3797 case 5: // CDC pulse data (new) (GlueX-doc-2274-v8)
3798
3799 // Word 1:
3800 word1 = *iptr;
3801 channel = (*iptr>>20) & 0x7F;
3802 pulse_number = (*iptr>>15) & 0x1F;
3803 pulse_time = (*iptr>>4 ) & 0x7FF;
3804 quality_factor = (*iptr>>3 ) & 0x1; //time QF bit
3805 overflow_count = (*iptr>>0 ) & 0x7;
3806 if(VERBOSE>8) evioout << " FADC125 CDC Pulse Data word1: " << hex << (*iptr) << dec << endl;
3807 if(VERBOSE>7) evioout << " FADC125 CDC Pulse Data (chan="<<channel<<" pulse="<<pulse_number<<" time="<<pulse_time<<" QF="<<quality_factor<<" OC="<<overflow_count<<")"<<endl;
3808
3809 // Word 2:
3810 ++iptr;
3811 if(iptr>=iend){
3812 jerr << " Truncated f125 CDC hit (block ends before continuation word!)" << endl;
3813 continue;
3814 }
3815 if( ((*iptr>>31) & 0x1) != 0 ){
3816 jerr << " Truncated f125 CDC hit (missing continuation word!)" << endl;
3817 continue;
3818 }
3819 word2 = *iptr;
3820 pedestal = (*iptr>>23) & 0xFF;
3821 sum = (*iptr>>9 ) & 0x3FFF;
3822 pulse_peak = (*iptr>>0 ) & 0x1FF;
3823 if(VERBOSE>8) evioout << " FADC125 CDC Pulse Data word2: " << hex << (*iptr) << dec << endl;
3824 if(VERBOSE>7) evioout << " FADC125 CDC Pulse Data (pedestal="<<pedestal<<" sum="<<sum<<" peak="<<pulse_peak<<")"<<endl;
3825
3826 // Create hit objects
3827 nsamples_integral = 0; // must be overwritten later in GetObjects with value from Df125Config value
3828 nsamples_pedestal = 1; // The firmware pedestal divided by 2^PBIT where PBIT is a config. parameter
3829
3830 if( (objs!=NULL__null) && (pulse_number<F125PULSE_NUMBER_FILTER) ) {
3831 // n.b. This is were we might apply a check on whether we are
3832 // only producing emulated objects. If so, then we shouldn't
3833 // create the Df125CDCPulse. At this point in time though,
3834 // there are 3 config. parameters that control this because
3835 // the original firmware produced 3 separate data types as
3836 // opposed to the new firmware that puts the same infomation
3837 // into a single data type. The emulation framework is also
3838 // being revamped.
3839 objs->hit_objs.push_back( new Df125CDCPulse(rocid, slot, channel, itrigger
3840 , pulse_number // NPK
3841 , pulse_time // le_time
3842 , quality_factor // time_quality_bit
3843 , overflow_count // overflow_count
3844 , pedestal // pedestal
3845 , sum // integral
3846 , pulse_peak // first_max_amp
3847 , word1 // word1
3848 , word2 // word2
3849 , nsamples_pedestal // nsamples_pedestal
3850 , nsamples_integral // nsamples_integral
3851 , false) // emulated
3852 );
3853 }
3854
3855 // n.b. We don't record last_slot, last_channel, etc... here since those
3856 // are only used by data types corresponding to older firmware that did
3857 // not write out data type 5.
3858 break;
3859
3860 case 6: // FDC pulse data-integral (new) (GlueX-doc-2274-v8)
3861
3862 // Word 1:
3863 word1 = *iptr;
3864 channel = (*iptr>>20) & 0x7F;
3865 pulse_number = (*iptr>>15) & 0x1F;
3866 pulse_time = (*iptr>>4 ) & 0x7FF;
3867 quality_factor = (*iptr>>3 ) & 0x1; //time QF bit
3868 overflow_count = (*iptr>>0 ) & 0x7;
3869 if(VERBOSE>8) evioout << " FADC125 FDC Pulse Data(integral) word1: " << hex << (*iptr) << dec << endl;
3870 if(VERBOSE>7) evioout << " FADC125 FDC Pulse Data (chan="<<channel<<" pulse="<<pulse_number<<" time="<<pulse_time<<" QF="<<quality_factor<<" OC="<<overflow_count<<")"<<endl;
3871
3872 // Word 2:
3873 ++iptr;
3874 if(iptr>=iend){
3875 jerr << " Truncated f125 FDC hit (block ends before continuation word!)" << endl;
3876 continue;
3877 }
3878 if( ((*iptr>>31) & 0x1) != 0 ){
3879 jerr << " Truncated f125 FDC hit (missing continuation word!)" << endl;
3880 continue;
3881 }
3882 word2 = *iptr;
3883 pulse_peak = 0;
3884 sum = (*iptr>>19) & 0xFFF;
3885 peak_time = (*iptr>>11) & 0xFF;
3886 pedestal = (*iptr>>0 ) & 0x7FF;
3887 if(VERBOSE>8) evioout << " FADC125 FDC Pulse Data(integral) word2: " << hex << (*iptr) << dec << endl;
3888 if(VERBOSE>7) evioout << " FADC125 FDC Pulse Data (integral="<<sum<<" time="<<peak_time<<" pedestal="<<pedestal<<")"<<endl;
3889
3890 // Create hit objects
3891 nsamples_integral = 0; // must be overwritten later in GetObjects with value from Df125Config value
3892 nsamples_pedestal = 1; // The firmware pedestal divided by 2^PBIT where PBIT is a config. parameter
3893
3894 if( (objs!=NULL__null) && (pulse_number<F125PULSE_NUMBER_FILTER) ) {
3895 // n.b. This is were we might apply a check on whether we are
3896 // only producing emulated objects. If so, then we shouldn't
3897 // create the Df125FDCPulse. At this point in time though,
3898 // there are 3 config. parameters that control this because
3899 // the original firmware produced 3 separate data types as
3900 // opposed to the new firmware that puts the same infomation
3901 // into a single data type. The emulation framework is also
3902 // being revamped.
3903 objs->hit_objs.push_back( new Df125FDCPulse(rocid, slot, channel, itrigger
3904 , pulse_number // NPK
3905 , pulse_time // le_time
3906 , quality_factor // time_quality_bit
3907 , overflow_count // overflow_count
3908 , pedestal // pedestal
3909 , sum // integral
3910 , pulse_peak // peak_amp
3911 , peak_time // peak_time
3912 , word1 // word1
3913 , word2 // word2
3914 , nsamples_pedestal // nsamples_pedestal
3915 , nsamples_integral // nsamples_integral
3916 , false) // emulated
3917 );
3918 }
3919
3920 // n.b. We don't record last_slot, last_channel, etc... here since those
3921 // are only used by data types corresponding to older firmware that did
3922 // not write out data type 6.
3923 break;
3924
3925 case 7: // Pulse Integral
3926 if(VERBOSE>7) evioout << " FADC125 Pulse Integral"<<endl;
3927 channel = (*iptr>>20) & 0x7F;
3928 sum = (*iptr>>0) & 0xFFFFF;
3929 nsamples_integral = 0; // must be overwritten later in GetObjects with value from Df125Config value
3930 nsamples_pedestal = 1; // The firmware returns an already divided pedestal
3931 pedestal = 0; // This will be replaced by the one from Df250PulsePedestal in GetObjects
3932 if (last_slot == slot && last_channel == channel) pulse_number = 1;
3933 last_slot = slot;
3934 last_channel = channel;
3935 if( (objs!=NULL__null) && (pulse_number<F125PULSE_NUMBER_FILTER) ) {
3936 objs->hit_objs.push_back(new Df125PulseIntegral(rocid, slot, channel, itrigger, pulse_number,
3937 quality_factor, sum, pedestal, nsamples_integral, nsamples_pedestal));
3938 }
3939 break;
3940 case 8: // Pulse Time
3941 if(VERBOSE>7) evioout << " FADC125 Pulse Time"<<endl;
3942 channel = (*iptr>>20) & 0x7F;
3943 pulse_number = (*iptr>>18) & 0x03;
3944 pulse_time = (*iptr>>0) & 0xFFFF;
3945 if( (objs!=NULL__null) && (pulse_number<F125PULSE_NUMBER_FILTER) ) {
3946 objs->hit_objs.push_back(new Df125PulseTime(rocid, slot, channel, itrigger, pulse_number, quality_factor, pulse_time));
3947 }
3948 last_pulse_time_channel = channel;
3949 break;
3950
3951 case 9: // FDC pulse data-peak (new) (GlueX-doc-2274-v8)
3952
3953 // Word 1:
3954 word1 = *iptr;
3955 channel = (*iptr>>20) & 0x7F;
3956 pulse_number = (*iptr>>15) & 0x1F;
3957 pulse_time = (*iptr>>4 ) & 0x7FF;
3958 quality_factor = (*iptr>>3 ) & 0x1; //time QF bit
3959 overflow_count = (*iptr>>0 ) & 0x7;
3960 if(VERBOSE>8) evioout << " FADC125 FDC Pulse Data(peak) word1: " << hex << (*iptr) << dec << endl;
3961 if(VERBOSE>7) evioout << " FADC125 FDC Pulse Data (chan="<<channel<<" pulse="<<pulse_number<<" time="<<pulse_time<<" QF="<<quality_factor<<" OC="<<overflow_count<<")"<<endl;
3962
3963 // Word 2:
3964 ++iptr;
3965 if(iptr>=iend){
3966 jerr << " Truncated f125 FDC hit (block ends before continuation word!)" << endl;
3967 continue;
3968 }
3969 if( ((*iptr>>31) & 0x1) != 0 ){
3970 jerr << " Truncated f125 FDC hit (missing continuation word!)" << endl;
3971 continue;
3972 }
3973 word2 = *iptr;
3974 pulse_peak = (*iptr>>19) & 0xFFF;
3975 sum = 0;
3976 peak_time = (*iptr>>11) & 0xFF;
3977 pedestal = (*iptr>>0 ) & 0x7FF;
3978 if(VERBOSE>8) evioout << " FADC125 FDC Pulse Data(peak) word2: " << hex << (*iptr) << dec << endl;
3979 if(VERBOSE>7) evioout << " FADC125 FDC Pulse Data (integral="<<sum<<" time="<<peak_time<<" pedestal="<<pedestal<<")"<<endl;
3980
3981 // Create hit objects
3982 nsamples_integral = 0; // must be overwritten later in GetObjects with value from Df125Config value
3983 nsamples_pedestal = 1; // The firmware pedestal divided by 2^PBIT where PBIT is a config. parameter
3984
3985 if( (objs!=NULL__null) && (pulse_number<F125PULSE_NUMBER_FILTER) ) {
3986 // n.b. This is were we might apply a check on whether we are
3987 // only producing emulated objects. If so, then we shouldn't
3988 // create the Df125FDCPulse. At this point in time though,
3989 // there are 3 config. parameters that control this because
3990 // the original firmware produced 3 separate data types as
3991 // opposed to the new firmware that puts the same infomation
3992 // into a single data type. The emulation framework is also
3993 // being revamped.
3994 objs->hit_objs.push_back( new Df125FDCPulse(rocid, slot, channel, itrigger
3995 , pulse_number // NPK
3996 , pulse_time // le_time
3997 , quality_factor // time_quality_bit
3998 , overflow_count // overflow_count
3999 , pedestal // pedestal
4000 , sum // integral
4001 , pulse_peak // peak_amp
4002 , peak_time // peak_time
4003 , word1 // word1
4004 , word2 // word2
4005 , nsamples_pedestal // nsamples_pedestal
4006 , nsamples_integral // nsamples_integral
4007 , false) // emulated
4008 );
4009 }
4010
4011 // n.b. We don't record last_slot, last_channel, etc... here since those
4012 // are only used by data types corresponding to older firmware that did
4013 // not write out data type 6.
4014 break;
4015
4016 case 10: // Pulse Pedestal (consistent with Beni's hand-edited version of Cody's document)
4017 if(VERBOSE>7) evioout << " FADC125 Pulse Pedestal"<<endl;
4018 //channel = (*iptr>>20) & 0x7F;
4019 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")
4020 pulse_number = (*iptr>>21) & 0x03;
4021 pedestal = (*iptr>>12) & 0x1FF;
4022 pulse_peak = (*iptr>>0) & 0xFFF;
4023 nsamples_pedestal = 1; // The firmware returns an already divided pedestal
4024 if( (objs!=NULL__null) && (pulse_number<F125PULSE_NUMBER_FILTER) ) {
4025 objs->hit_objs.push_back(new Df125PulsePedestal(rocid, slot, channel, itrigger, pulse_number, pedestal, pulse_peak, nsamples_pedestal));
4026 }
4027 break;
4028
4029 case 13: // Event Trailer
4030 case 14: // Data not valid (empty module)
4031 case 15: // Filler (non-data) word
4032 if(VERBOSE>7) evioout << " FADC125 ignored data type: " << data_type <<endl;
4033 break;
4034 }
4035
4036 // Once we find a block trailer, assume that is it for this module.
4037 if(found_block_trailer){
4038 iptr++; // iptr is still pointing to block trailer. Jump to next word.
4039 break;
4040 }
4041 }
4042
4043 // Chop off filler words
4044 for(; iptr<iend; iptr++){
4045 if(((*iptr)&0xf8000000) != 0xf8000000) break;
4046 }
4047
4048 // Add last event in block to list
4049 if(objs)events.push_back(objs);
4050
4051 // Here, we make object associations to link PulseIntegral, PulseTime, PulseRawData, etc
4052 // objects to each other so it is easier to get to these downstream without having to
4053 // make nested loops. This is the most efficient place to do it since the ObjList objects
4054 // in "event" contain only the objects from this EVIO block (i.e. at most one crate's
4055 // worth.)
4056 list<ObjList*>::iterator iter = events.begin();
4057 for(; iter!=events.end(); iter++){
4058
4059 // Sort list of objects into type-specific lists
4060 vector<DDAQAddress*> &hit_objs = (*iter)->hit_objs;
4061 vector<Df125TriggerTime*> vtrigt;
4062 vector<Df125WindowRawData*> vwrd;
4063 vector<Df125PulseRawData*> vprd;
4064 vector<Df125PulseIntegral*> vpi;
4065 vector<Df125PulseTime*> vpt;
4066 vector<Df125PulsePedestal*> vpp;
4067 for(unsigned int i=0; i<hit_objs.size(); i++){
4068 AddIfAppropriate(hit_objs[i], vtrigt);
4069 AddIfAppropriate(hit_objs[i], vwrd);
4070 AddIfAppropriate(hit_objs[i], vprd);
4071 AddIfAppropriate(hit_objs[i], vpi);
4072 AddIfAppropriate(hit_objs[i], vpt);
4073 AddIfAppropriate(hit_objs[i], vpp);
4074 }
4075
4076 // Connect Df125PulseIntegral with Df125PulseTime
4077 LinkAssociationsWithPulseNumber(vprd, vpi);
4078 LinkAssociationsWithPulseNumber(vprd, vpt);
4079 LinkAssociationsWithPulseNumber(vprd, vpp);
4080 LinkAssociationsWithPulseNumber(vpi, vpt);
4081 LinkAssociationsWithPulseNumber(vpi, vpp);
4082 LinkAssociationsWithPulseNumber(vpt, vpp);
4083
4084 // Connect Df125TriggerTime to everything
4085 LinkAssociationsModuleOnly(vtrigt, vwrd);
4086 LinkAssociationsModuleOnly(vtrigt, vprd);
4087 LinkAssociationsModuleOnly(vtrigt, vpi);
4088 LinkAssociationsModuleOnly(vtrigt, vpt);
4089 LinkAssociationsModuleOnly(vtrigt, vpp);
4090 }
4091
4092 if(VERBOSE>6) evioout << " Leaving Parsef125Bank"<<endl;
4093}
4094
4095//----------------
4096// MakeDf125WindowRawData
4097//----------------
4098void JEventSource_EVIO::MakeDf125WindowRawData(ObjList *objs, uint32_t rocid, uint32_t slot, uint32_t itrigger, const uint32_t* &iptr)
4099{
4100 uint32_t channel = (*iptr>>20) & 0x7F;
4101 uint32_t window_width = (*iptr>>0) & 0x0FFF;
4102
4103 Df125WindowRawData *wrd = new Df125WindowRawData(rocid, slot, channel, itrigger);
4104
4105 for(uint32_t isample=0; isample<window_width; isample +=2){
4106
4107 // Advance to next word
4108 iptr++;
4109
4110 // Make sure this is a data continuation word, if not, stop here
4111 if(((*iptr>>31) & 0x1) != 0x0)break;
4112
4113 bool invalid_1 = (*iptr>>29) & 0x1;
4114 bool invalid_2 = (*iptr>>13) & 0x1;
4115 uint16_t sample_1 = 0;
4116 uint16_t sample_2 = 0;
4117 if(!invalid_1)sample_1 = (*iptr>>16) & 0x1FFF;
4118 if(!invalid_2)sample_2 = (*iptr>>0) & 0x1FFF;
4119
4120 // Sample 1
4121 wrd->samples.push_back(sample_1);
4122 wrd->invalid_samples |= invalid_1;
4123 wrd->overflow |= (sample_1>>12) & 0x1;
4124
4125 if((isample+2) == window_width && invalid_2)break; // skip last sample if flagged as invalid
4126
4127 // Sample 2
4128 wrd->samples.push_back(sample_2);
4129 wrd->invalid_samples |= invalid_2;
4130 wrd->overflow |= (sample_2>>12) & 0x1;
4131 }
4132
4133 if(VERBOSE>7) evioout << " FADC125 - " << wrd->samples.size() << " samples" << endl;
4134
4135 // Due to how the calling function works, the value of "objs" passed to us may be NULL.
4136 // This will happen if a Window Raw Data block is encountered before an event header.
4137 // For these cases, we still want to try parsing the data so that the iptr is updated
4138 // but don't have an event to assign it to. If "objs" is non-NULL, add this object to
4139 // the list. Otherwise, delete it now.
4140 if(objs){
4141 objs->hit_objs.push_back(wrd);
4142 }else{
4143 delete wrd;
4144 }
4145}
4146
4147//----------------
4148// MakeDf125PulseRawData
4149//----------------
4150void JEventSource_EVIO::MakeDf125PulseRawData(ObjList *objs, uint32_t rocid, uint32_t slot, uint32_t itrigger, const uint32_t* &iptr)
4151{
4152 uint32_t channel = (*iptr>>23) & 0x0F;
4153 uint32_t pulse_number = (*iptr>>21) & 0x000F;
4154 uint32_t first_sample_number = (*iptr>>0) & 0x03FF;
4155
4156 Df125PulseRawData *prd = new Df125PulseRawData(rocid, slot, channel, itrigger, pulse_number, first_sample_number);
4157
4158 // This loop needs to break when it hits a non-continuation word
4159 for(uint32_t isample=0; isample<1000; isample +=2){
4160
4161 // Advance to next word
4162 iptr++;
4163
4164 // Make sure this is a data continuation word, if not, stop here
4165 if(((*iptr>>31) & 0x1) != 0x0)break;
4166
4167 bool invalid_1 = (*iptr>>29) & 0x1;
4168 bool invalid_2 = (*iptr>>13) & 0x1;
4169 uint16_t sample_1 = 0;
4170 uint16_t sample_2 = 0;
4171 if(!invalid_1)sample_1 = (*iptr>>16) & 0x1FFF;
4172 if(!invalid_2)sample_2 = (*iptr>>0) & 0x1FFF;
4173
4174 // Sample 1
4175 prd->samples.push_back(sample_1);
4176 prd->invalid_samples |= invalid_1;
4177 prd->overflow |= (sample_1>>12) & 0x1;
4178
4179 bool last_word = (iptr[1]>>31) & 0x1;
4180 if(last_word && invalid_2)break; // skip last sample if flagged as invalid
4181
4182 // Sample 2
4183 prd->samples.push_back(sample_2);
4184 prd->invalid_samples |= invalid_2;
4185 prd->overflow |= (sample_2>>12) & 0x1;
4186 }
4187
4188
4189 // Due to how the calling function works, the value of "objs" passed to us may be NULL.
4190 // This will happen if a Window Raw Data block is encountered before an event header.
4191 // For these cases, we still want to try parsing the data so that the iptr is updated
4192 // but don't have an event to assign it to. If "objs" is non-NULL, add this object to
4193 // the list. Otherwise, delete it now.
4194 if(objs){
4195 objs->hit_objs.push_back(prd);
4196 }else{
4197 delete prd;
4198 }
4199}
4200
4201//----------------
4202// ParseF1TDCBank
4203//----------------
4204void JEventSource_EVIO::ParseF1TDCBank(int32_t rocid, const uint32_t* &iptr, const uint32_t* iend, list<ObjList*> &events)
4205{
4206 /// Parse data from a single F1TDCv2 (32 ch) or F1TDCv3 (48 ch) module.
4207 /// This code is based on the document F1TDC_V2_V3_4_29_14.pdf obtained from:
4208 /// https://coda.jlab.org/wiki/index.php/JLab_Module_Manuals
4209
4210 if(!PARSE_F1TDC){ iptr = iend; return; }
4211
4212 if(VERBOSE>6) evioout << " Entering ParseF1TDCBank (rocid=" << rocid << ")" << endl;
4213
4214 const uint32_t *istart = iptr;
4215
4216 // Some early data had a marker word at just before the actual F1 data
4217 if(*iptr == 0xf1daffff) iptr++;
4218
4219 // Block header word
4220 // Double check that block header is set
4221 if( ((*iptr) & 0xF8000000) != 0x80000000 ){
4222 throw JException("F1TDC Block header corrupt! (high 5 bits not set to 0x80000000!)");
4223 }
4224
4225 uint32_t slot_block_header = (*iptr)>>22 & 0x001F;
4226 uint32_t block_num = (*iptr)>> 8 & 0x03FF;
4227 uint32_t Nevents_block_header = (*iptr)>> 0 & 0x00FF;
4228 int modtype = (*iptr)>>18 & 0x000F; // should match a DModuleType::type_id_t
4229 if(VERBOSE>5) evioout << " F1 Block Header: slot=" << slot_block_header << " block_num=" << block_num << " Nevents=" << Nevents_block_header << endl;
4230
4231 // Advance to next word
4232 iptr++;
4233
4234 // Loop over events
4235 ObjList *objs = NULL__null;
4236 while(iptr<iend){
4237
4238 // Event header
4239 // Double check that event header is set
4240 if( ((*iptr) & 0xF8000000) != 0x90000000 ){
4241 if(VERBOSE>10){
4242 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<4242<<" "
<<"Corrupt F1TDC Event header! Data dump follows (\"*\" indicates bad header word):" <<endl;
4243 DumpBinary(istart, iend, 0, iptr);
4244 }
4245 throw JException("F1TDC Event header corrupt! (high 5 bits not set to 0x90000000!)");
4246 }
4247
4248 uint32_t slot_event_header = (*iptr)>>22 & 0x00000001F;
4249 uint32_t itrigger = (*iptr)>>0 & 0x0003FFFFF;
4250 if(VERBOSE>5) evioout << " F1 Event Header: slot=" << slot_block_header << " itrigger=" << itrigger << endl;
4251
4252 // Make sure slot number from event header matches block header
4253 if(slot_event_header != slot_block_header){
4254 char str[256];
4255 sprintf(str, "F1TDC slot from event header(%d) doesn't match block header(%d)", slot_event_header, slot_block_header);
4256 throw JException(str);
4257 }
4258
4259 // Advance to timestamp word
4260 iptr++;
4261 if(iptr>=iend) throw JException("F1TDC data corrupt! Block truncated before timestamp word!");
4262
4263 // The most recent documentation says that the first time stamp
4264 // word holds the low 24 bits and the second the high 16 bits. According to Dave A.,
4265 // the second word is optional.
4266 uint32_t trig_time = ((*iptr)&0xFFFFFF);
4267 if(VERBOSE>6) evioout << " F1 Trigger time: low 24 bits=" << trig_time << endl;
4268 iptr++;
4269 if(iptr>=iend) throw JException("F1TDC data corrupt! Block truncated before trailer word!");
4270 if(((*iptr>>31) & 0x1) == 0){
4271 trig_time += ((*iptr)&0xFFFF)<<24; // from word on the street: second trigger time word is optional!!??
4272 if(VERBOSE>6) evioout << " F1 Trigger time: high 16 bits=" << ((*iptr)&0xFFFF) << " total trig_time=" << trig_time << endl;
4273 }else{
4274 iptr--; // second time word not present, back up pointer
4275 }
4276
4277 // Create a new object list (i.e. new event)
4278 if(objs!=NULL__null && ENABLE_DISENTANGLING){
4279 events.push_back(objs);
4280 objs = NULL__null;
4281 }
4282 if(!objs) objs = new ObjList;
4283
4284 if(objs) objs->hit_objs.push_back(new DF1TDCTriggerTime(rocid, slot_block_header, itrigger, trig_time));
4285
4286 // Advance past last timestamp word to first data word (or rather, F1 chip header)
4287 iptr++;
4288
4289 // Loop over F1 data words
4290 uint32_t chip_f1header=0, chan_on_chip_f1header=0, itrigger_f1header=0, trig_time_f1header=0;
4291 while( iptr<iend && ((*iptr)>>31)==0x1 ){
4292
4293 bool done = false;
4294
4295 uint32_t chip, chan_on_chip, time;
4296 uint32_t channel;
4297 DF1TDCHit *hit=NULL__null;
4298 switch( (*iptr) & 0xF8000000 ){
4299 case 0xC0000000: // F1 Header
4300 chip_f1header = ((*iptr)>> 3) & 0x07;
4301 chan_on_chip_f1header = ((*iptr)>> 0) & 0x07; // this is always 7 in real data!
4302 itrigger_f1header = ((*iptr)>>16) & 0x3F;
4303 trig_time_f1header = ((*iptr)>> 7) & 0x1FF;
4304 if(VERBOSE>5) evioout << " Found F1 header: chip=" << chip_f1header << " chan=" << chan_on_chip_f1header << " itrig=" << itrigger_f1header << " trig_time=" << trig_time_f1header << endl;
4305 //if( itrigger_f1header != (itrigger & 0x3F)) throw JException("Trigger number in F1 header word does not match Event header word!");
4306 break;
4307 case 0xB8000000: // F1 Data
4308 chip = (*iptr>>19) & 0x07;
4309 chan_on_chip = (*iptr>>16) & 0x07;
4310 time = (*iptr>> 0) & 0xFFFF;
4311 if(VERBOSE>5) evioout << " Found F1 data : chip=" << chip << " chan=" << chan_on_chip << " time=" << time << " (header: chip=" << chip_f1header << ")" << endl;
4312 //if(chip!=chip_f1header) throw JException("F1 chip number in data does not match header!");
4313 channel = F1TDC_channel(chip, chan_on_chip, modtype);
4314 hit = new DF1TDCHit(rocid, slot_block_header, channel, itrigger, trig_time_f1header, time, *iptr, MODULE_TYPE(modtype));
4315 if(objs)objs->hit_objs.push_back(hit);
4316 break;
4317 case 0xF8000000: // Filler word
4318 if(VERBOSE>7) evioout << " Found F1 filler word" << endl;
4319 break;
4320 case 0x80000000: // JLab block header (handled in outer loop)
4321 case 0x88000000: // JLab block trailer (handled in outer loop)
4322 case 0x90000000: // JLab event header (handled in outer loop)
4323 case 0x98000000: // Trigger time (handled in outer loop)
4324 case 0xF0000000: // module has no valid data available for read out (how to handle this?)
4325 if(VERBOSE>5) evioout << " Found F1 break word: 0x" << hex << *iptr << dec << endl;
4326 done = true;
4327 break;
4328 default:
4329 cerr<<endl;
4330 cout.flush(); cerr.flush();
4331 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<4331<<" "
<<"Unknown data word in F1TDC block. Dumping for debugging:" << endl;
4332 for(const uint32_t *iiptr = istart; iiptr<iend; iiptr++){
4333 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<4333<<" "
<<"0x"<<hex<<*iiptr<<dec;
4334 if(iiptr == iptr)cerr<<" <----";
4335 switch( (*iiptr) & 0xF8000000 ){
4336 case 0x80000000: cerr << " F1 Block Header"; break;
4337 case 0x90000000: cerr << " F1 Event Header"; break;
4338 case 0x98000000: cerr << " F1 Trigger time"; break;
4339 case 0xC0000000: cerr << " F1 Header"; break;
4340 case 0xB8000000: cerr << " F1 Data"; break;
4341 case 0x88000000: cerr << " F1 Block Trailer"; break;
4342 case 0xF8000000: cerr << " Filler word"; break;
4343 case 0xF0000000: cerr << " <module has no valid data>"; break;
4344 default: break;
4345 }
4346 cerr<<endl;
4347 if(iiptr > (iptr+4)) break;
4348 }
4349
4350 throw JException("Unexpected word type in F1TDC block!");
4351 }
4352
4353 if(done)break;
4354
4355 // Advance to next data word
4356 iptr++;
4357
4358 } // end loop over data words in this event
4359
4360 // If the current word is a JLab block trailer, then we are done
4361 if( ((*iptr) & 0xF8000000) == 0x88000000) break;
4362
4363 } // end loop over events
4364
4365 // Add hits for last event to list of events.
4366 if(objs)events.push_back(objs);
4367
4368 if( ((*iptr) & 0xF8000000) != 0x88000000 ){
4369 throw JException("F1TDC Block Trailer corrupt! (high 5 bits not set to 0x88000000!)");
4370 }
4371
4372 // Advance past JLab block trailer
4373 iptr++;
4374
4375 // Skip filler words
4376 while(iptr<iend && (*iptr&0xF8000000)==0xF8000000)iptr++;
4377
4378 // Double check that we found all of the events we were supposed to
4379 if(!ENABLE_DISENTANGLING) Nevents_block_header=1;
4380 if(events.size() != Nevents_block_header){
4381 stringstream ss;
4382 ss << "F1TDC missing events in block! (found "<< events.size() <<" but should have found "<<Nevents_block_header<<")";
4383 DumpBinary(istart, iend, 128);
4384 throw JException(ss.str());
4385 }
4386
4387 if(VERBOSE>6) evioout << " Leaving ParseF1TDCBank (rocid=" << rocid << ")" << endl;
4388
4389}
4390
4391//----------------
4392// F1TDC_channel
4393//----------------
4394uint32_t JEventSource_EVIO::F1TDC_channel(uint32_t chip, uint32_t chan_on_chip, int modtype)
4395{
4396 /// Convert a F1TDC chip number and channel on the chip to the
4397 /// front panel channel number. This is based on "Input Channel Mapping"
4398 /// section at the very bottom of the document F1TDC_V2_V3_4_29_14.pdf
4399
4400 uint32_t channel_map[8] = {0, 0, 1, 1, 2, 2, 3, 3};
4401 switch(modtype){
4402 case DModuleType::F1TDC32:
4403 return (4 * chip) + channel_map[ chan_on_chip&0x7 ];
4404 case DModuleType::F1TDC48:
4405 return (chip <<3) | chan_on_chip;
4406 default:
4407 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<4407<<" "
<< "Calling F1TDC_channel for module type: " << DModuleType::GetName((DModuleType::type_id_t)modtype) << endl;
4408 throw JException("F1TDC_channel called for non-F1TDC module type");
4409 }
4410 return 1000000; // (should never get here)
4411}
4412
4413//----------------
4414// ParseTSBank
4415//----------------
4416void JEventSource_EVIO::ParseTSBank(int32_t rocid, const uint32_t* &iptr, const uint32_t* iend, list<ObjList*> &events)
4417{
4418 /// Parse data written to the TS roc data during sync events.
4419 /// This is written by the ts_scalers routine in the conf_utils.c
4420 /// file and called from ts_list.c
4421
4422 uint32_t Nwords = ((uint64_t)iend - (uint64_t)iptr)/sizeof(uint32_t);
4423 uint32_t Nwords_expected = (6+32+16+32+16);
4424 if(Nwords != Nwords_expected){
4425 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<4425<<" "
<< "TS bank size does not match expected!!" << endl;
4426 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<4426<<" "
<< "Found " << Nwords << " words. Expected " << Nwords_expected << endl;
4427
4428 }else{
4429 DTSscalers *s = new DTSscalers;
4430 s->nsync_event = *iptr++;
4431 s->int_count = *iptr++;
4432 s->live_time = *iptr++;
4433 s->busy_time = *iptr++;
4434 s->inst_livetime = *iptr++;
4435 s->time = *iptr++;
4436 for(uint32_t i=0; i<32; i++) s->gtp_scalers[i] = *iptr++;
4437 for(uint32_t i=0; i<16; i++) s->fp_scalers[i] = *iptr++;
4438 for(uint32_t i=0; i<32; i++) s->gtp_rate[i] = *iptr++;
4439 for(uint32_t i=0; i<16; i++) s->fp_rate[i] = *iptr++;
4440
4441 if(events.empty()) events.push_back(new ObjList);
4442 ObjList *objs = *(events.begin());
4443 objs->misc_objs.push_back(s);
4444 }
4445
4446 iptr = iend;
4447}
4448
4449//----------------
4450// ParseTIBank
4451//----------------
4452void JEventSource_EVIO::ParseTIBank(int32_t rocid, const uint32_t* &iptr, const uint32_t* iend, list<ObjList*> &events)
4453{
4454 while(iptr<iend && ((*iptr) & 0xF8000000) != 0x88000000) iptr++; // Skip to JLab block trailer
4455 iptr++; // advance past JLab block trailer
4456 while(iptr<iend && *iptr == 0xF8000000) iptr++; // skip filler words after block trailer
4457 //iptr = iend;
4458}
4459
4460//----------------
4461// ParseCAEN1190
4462//----------------
4463void JEventSource_EVIO::ParseCAEN1190(int32_t rocid, const uint32_t* &iptr, const uint32_t *iend, list<ObjList*> &events)
4464{
4465 /// Parse data from a CAEN 1190 or 1290 module
4466 /// (See ppg. 72-74 of V1290_REV15.pdf manual)
4467
4468 if(!PARSE_CAEN1290TDC){ iptr = iend; return; }
4469
4470 uint32_t slot = 0;
4471 uint32_t event_count = 0;
4472 uint32_t word_count = 0;
4473 uint32_t trigger_time_tag = 0;
4474 uint32_t tdc_num = 0;
4475 uint32_t event_id = 0;
4476 uint32_t bunch_id = 0;
4477
4478 // We need to accomodate multi-event blocks where
4479 // events are entangled (i.e. hits from event 1
4480 // are mixed inbetween those of event 2,3,4,
4481 // etc... With CAEN modules, we only know which
4482 // event a hit came from by looking at the event_id
4483 // in the TDC header. This value is only 12 bits
4484 // and could roll over within an event block. This
4485 // means we need to keep track of the order we
4486 // encounter them in so it is maintained in the
4487 // "events" container. The event_id order is kept
4488 // in the "event_id_order" vector.
4489 map<uint32_t, vector<DCAEN1290TDCHit*> > hits_by_event_id;
4490 vector<uint32_t> event_id_order;
4491
4492 while(iptr<iend){
4493
4494 // This word appears to be appended to the data.
4495 // Probably in the ROL. Ignore it if found.
4496 if(*iptr == 0xd00dd00d) {
4497 if(VERBOSE>7) evioout << " CAEN skipping 0xd00dd00d word" << endl;
4498 iptr++;
4499 continue;
4500 }
4501
4502 uint32_t type = (*iptr) >> 27;
4503 uint32_t edge = 0; // 1=trailing, 0=leading
4504 uint32_t channel = 0;
4505 uint32_t tdc = 0;
4506 uint32_t error_flags = 0;
4507 DCAEN1290TDCHit *caen1290tdchit = NULL__null;
4508 map<uint32_t, ObjList*>::iterator iter;
4509 switch(type){
4510 case 0b01000: // Global Header
4511 slot = (*iptr) & 0x1f;
4512 event_count = ((*iptr)>>5) & 0xffffff;
4513 if(VERBOSE>7) evioout << " CAEN TDC Global Header (slot=" << slot << " , event count=" << event_count << ")" << endl;
4514 break;
4515 case 0b10000: // Global Trailer
4516 slot = (*iptr) & 0x1f;
4517 word_count = ((*iptr)>>5) & 0x7ffff;
4518 if(VERBOSE>7) evioout << " CAEN TDC Global Trailer (slot=" << slot << " , word count=" << word_count << ")" << endl;
4519 slot = event_count = word_count = trigger_time_tag = tdc_num = event_id = bunch_id = 0;
4520 break;
4521 case 0b10001: // Global Trigger Time Tag
4522 trigger_time_tag = ((*iptr)>>5) & 0x7ffffff;
4523 if(VERBOSE>7) evioout << " CAEN TDC Global Trigger Time Tag (tag=" << trigger_time_tag << ")" << endl;
4524 break;
4525 case 0b00001: // TDC Header
4526 tdc_num = ((*iptr)>>24) & 0x03;
4527 event_id = ((*iptr)>>12) & 0x0fff;
4528 bunch_id = (*iptr) & 0x0fff;
4529 if( find(event_id_order.begin(), event_id_order.end(), event_id) == event_id_order.end()){
4530 event_id_order.push_back(event_id);
4531 }
4532 if(VERBOSE>7) evioout << " CAEN TDC TDC Header (tdc=" << tdc_num <<" , event id=" << event_id <<" , bunch id=" << bunch_id << ")" << endl;
4533 break;
4534 case 0b00000: // TDC Measurement
4535 edge = ((*iptr)>>26) & 0x01;
4536 channel = ((*iptr)>>21) & 0x1f;
4537 tdc = ((*iptr)>>0) & 0x1fffff;
4538 if(VERBOSE>7) evioout << " CAEN TDC TDC Measurement (" << (edge ? "trailing":"leading") << " , channel=" << channel << " , tdc=" << tdc << ")" << endl;
4539
4540 // Create DCAEN1290TDCHit object
4541 caen1290tdchit = new DCAEN1290TDCHit(rocid, slot, channel, 0, edge, tdc_num, event_id, bunch_id, tdc);
4542 hits_by_event_id[event_id].push_back(caen1290tdchit);
4543 break;
4544 case 0b00100: // TDC Error
4545 error_flags = (*iptr) & 0x7fff;
4546 if(VERBOSE>7) evioout << " CAEN TDC TDC Error (err flags=0x" << hex << error_flags << dec << ")" << endl;
4547 break;
4548 case 0b00011: // TDC Trailer
4549 tdc_num = ((*iptr)>>24) & 0x03;
4550 event_id = ((*iptr)>>12) & 0x0fff;
4551 word_count = ((*iptr)>>0) & 0x0fff;
4552 if(VERBOSE>7) evioout << " CAEN TDC TDC Trailer (tdc=" << tdc_num <<" , event id=" << event_id <<" , word count=" << word_count << ")" << endl;
4553 tdc_num = event_id = bunch_id = 0;
4554 break;
4555 case 0b11000: // Filler Word
4556 if(VERBOSE>7) evioout << " CAEN TDC Filler Word" << endl;
4557 break;
4558 default:
4559 evioout << "Unknown datatype: 0x" << hex << type << " full word: "<< *iptr << dec << endl;
4560 }
4561
4562 iptr++;
4563 }
4564
4565 // If disentagling is disabled, then lump all hits into single event
4566 if( (!ENABLE_DISENTANGLING) && (event_id_order.size()>1) ){
4567 if(VERBOSE>2) evioout << " Disentangling disabled. Merging all hits into single event" << endl;
4568 vector<DCAEN1290TDCHit*> &hits1 = hits_by_event_id[event_id_order[0]];
4569 for(uint32_t i=1; i<event_id_order.size(); i++){
4570 vector<DCAEN1290TDCHit*> &hits2 = hits_by_event_id[event_id_order[i]];
4571 hits1.insert(hits1.end(), hits2.begin(), hits2.end()); // copy hits into first event
4572 hits_by_event_id.erase(event_id_order[i]); // remove hits list for this event_id
4573 }
4574 }
4575
4576 // Add hits for each event to the events container, creating ObjList's as needed
4577 for(uint32_t i=0; i<event_id_order.size(); i++){
4578
4579 // Make sure there are enough event containers to hold this event
4580 while(events.size() <= i) events.push_back(new ObjList);
4581 list<ObjList*>::iterator it = events.begin();
4582 advance(it, i);
4583 ObjList *objs = *it;
4584
4585 vector<DCAEN1290TDCHit*> &hits = hits_by_event_id[event_id_order[i]];
4586 objs->hit_objs.insert(objs->hit_objs.end(), hits.begin(), hits.end());
4587
4588 if(VERBOSE>7) evioout << " Added " << hits.size() << " hits with event_id=" << event_id_order[i] << " to event " << i << endl;
4589 }
4590
4591}
4592
4593//----------------
4594// ParseBORevent
4595//----------------
4596void JEventSource_EVIO::ParseBORevent(evioDOMNodeP bankPtr)
4597{
4598 if(!PARSE_BOR) return;
4599
4600 // This really shouldn't be needed
4601 pthread_rwlock_wrlock(&BOR_lock);
4602
4603 // Delete any existing BOR config objects. BOR events should
4604 // be flagged as sequential (or barrier) events so all threads
4605 // that were using these should be done with them now.
4606 for(uint32_t i=0; i<BORobjs.size(); i++) delete BORobjs[i];
4607 BORobjs.clear();
4608
4609 evioDOMNodeListP bankList = bankPtr->getChildren();
4610 evioDOMNodeList::iterator iter = bankList->begin();
4611 if(VERBOSE>7) evioout << " Looping over " << bankList->size() << " banks in BOR event" << endl;
4612 for(int ibank=1; iter!=bankList->end(); iter++, ibank++){ // ibank only used for debugging messages
4613 evioDOMNodeP childBank = *iter;
4614
4615 if(childBank->tag==0x71){
4616 // uint32_t rocid = childBank->num;
4617 evioDOMNodeListP bankList = childBank->getChildren();
4618 evioDOMNodeList::iterator iter = bankList->begin();
4619 for(; iter!=bankList->end(); iter++){
4620 evioDOMNodeP dataBank = *iter;
4621 // uint32_t slot = dataBank->tag>>5;
4622 uint32_t modType = dataBank->tag&0x1f;
4623
4624 const vector<uint32_t> *vec = dataBank->getVector<uint32_t>();
4625
4626 const uint32_t *src = &(*vec)[0];
4627 uint32_t *dest = NULL__null;
4628 uint32_t sizeof_dest = 0;
4629
4630 Df250BORConfig *f250conf = NULL__null;
4631 Df125BORConfig *f125conf = NULL__null;
4632 DF1TDCBORConfig *F1TDCconf = NULL__null;
4633 DCAEN1290TDCBORConfig *caen1190conf = NULL__null;
4634
4635 switch(modType){
4636 case DModuleType::FADC250: // f250
4637 f250conf = new Df250BORConfig;
4638 dest = (uint32_t*)&f250conf->rocid;
4639 sizeof_dest = sizeof(f250config);
4640 break;
4641 case DModuleType::FADC125: // f125
4642 f125conf = new Df125BORConfig;
4643 dest = (uint32_t*)&f125conf->rocid;
4644 sizeof_dest = sizeof(f125config);
4645 break;
4646
4647 case DModuleType::F1TDC32: // F1TDCv2
4648 case DModuleType::F1TDC48: // F1TDCv3
4649 F1TDCconf = new DF1TDCBORConfig;
4650 dest = (uint32_t*)&F1TDCconf->rocid;
4651 sizeof_dest = sizeof(F1TDCconfig);
4652 break;
4653
4654 case DModuleType::CAEN1190: // CAEN 1190 TDC
4655 case DModuleType::CAEN1290: // CAEN 1290 TDC
4656 caen1190conf = new DCAEN1290TDCBORConfig;
4657 dest = (uint32_t*)&caen1190conf->rocid;
4658 sizeof_dest = sizeof(caen1190config);
4659 break;
4660 }
4661
4662 // Check that the bank size and data structure size match.
4663 // If they do, then copy the data and add the object to
4664 // the event. If not, then delete the object and print
4665 // a warning message.
4666 if( vec->size() == (sizeof_dest/sizeof(uint32_t)) ){
4667
4668 // Copy bank data, assuming format is the same
4669 for(uint32_t i=0; i<vec->size(); i++) *dest++ = *src++;
4670
4671 // Store object for use in this and subsequent events
4672 if(f250conf) BORobjs.push_back(f250conf);
4673 if(f125conf) BORobjs.push_back(f125conf);
4674 if(F1TDCconf) BORobjs.push_back(F1TDCconf);
4675 if(caen1190conf) BORobjs.push_back(caen1190conf);
4676
4677 }else if(sizeof_dest>0){
4678 if(f250conf) delete f250conf;
4679 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<4679<<" "
<< "BOR bank size does not match structure! " << vec->size() <<" != " << (sizeof_dest/sizeof(uint32_t)) << endl;
4680 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<4680<<" "
<< "sizeof(f250config)="<<sizeof(f250config)<<endl;
4681 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<4681<<" "
<< "sizeof(f125config)="<<sizeof(f125config)<<endl;
4682 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<4682<<" "
<< "sizeof(F1TDCconfig)="<<sizeof(F1TDCconfig)<<endl;
4683 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<4683<<" "
<< "sizeof(caen1190config)="<<sizeof(caen1190config)<<endl;
4684 }
4685 }
4686 }
4687 }
4688
4689 pthread_rwlock_unlock(&BOR_lock);
4690
4691}
4692
4693
4694//----------------
4695// ParseTSSyncevent
4696//----------------
4697void JEventSource_EVIO::ParseTSSync(evioDOMNodeP bankPtr, list<ObjList*> &events)
4698{
4699
4700 DL1Info *trig_info = new DL1Info;
4701
4702 // cout << " INSIDE ParseTSSync " << endl;
4703
4704 if((bankPtr->tag & 0xFFFF) == 0xEE02){
4705 const vector<uint32_t> *vec = bankPtr->getVector<uint32_t>();
4706
4707 trig_info->nsync = (*vec)[0];
4708 trig_info->trig_number = (*vec)[1];
4709 trig_info->live_time = (*vec)[2];
4710 trig_info->busy_time = (*vec)[3];
4711 trig_info->live_inst = (*vec)[4];
4712 trig_info->unix_time = (*vec)[5];
4713
4714
4715
4716 // GTP scalers
4717 for(uint32_t ii = 6; ii < 38; ii++){
4718 trig_info->gtp_sc.push_back((*vec)[ii]);
4719 }
4720
4721 // FP scalers
4722 for(uint32_t ii = 38; ii < 54; ii++){
4723 trig_info->fp_sc.push_back((*vec)[ii]);
4724 }
4725
4726 // GTP rate
4727 for(uint32_t ii = 54; ii < 86; ii++){
4728 trig_info->gtp_rate.push_back((*vec)[ii]);
4729 }
4730
4731 // FP rate
4732 for(uint32_t ii = 86; ii < 102; ii++){
4733 trig_info->fp_rate.push_back((*vec)[ii]);
4734 }
4735 }
4736
4737
4738 if(events.empty()){
4739 events.push_back(new ObjList());
4740 // cout << " TSSync: Empty event " << endl;
4741 }
4742
4743 ObjList *objs = *(events.begin());
4744
4745 objs->misc_objs.push_back(trig_info);
4746
4747
4748}
4749
4750
4751//----------------
4752// ParseEPICSevent
4753//----------------
4754void JEventSource_EVIO::ParseEPICSevent(evioDOMNodeP bankPtr, list<ObjList*> &events)
4755{
4756 if(!PARSE_EPICS) return;
4757
4758 time_t timestamp=0;
4759
4760 ObjList *objs = NULL__null;
4761
4762 evioDOMNodeListP bankList = bankPtr->getChildren();
4763 evioDOMNodeList::iterator iter = bankList->begin();
4764 if(VERBOSE>7) evioout << " Looping over " << bankList->size() << " banks in EPICS event" << endl;
4765 for(int ibank=1; iter!=bankList->end(); iter++, ibank++){ // ibank only used for debugging messages
4766 evioDOMNodeP childBank = *iter;
4767
4768 if(childBank->tag == 97){
4769 // timestamp bank
4770 const vector<uint32_t> *vec = childBank->getVector<uint32_t>();
4771 if(vec) {
4772 timestamp = (time_t)(*vec)[0];
4773 if(VERBOSE>7) evioout << " timestamp: " << ctime(&timestamp);
4774 }
4775 }else if(childBank->tag==98){
4776 const vector<uint8_t> *vec = childBank->getVector<uint8_t>();
4777 if(vec){
4778 string nameval = (const char*)&((*vec)[0]);
4779 DEPICSvalue *epicsval = new DEPICSvalue(timestamp, nameval);
4780 if(VERBOSE>7) evioout << " " << nameval << endl;
4781
4782 if(!objs){
4783 if(events.empty()) events.push_back(new ObjList);
4784 objs = *(events.begin());
4785 }
4786 objs->misc_objs.push_back(epicsval);
4787 }
4788 }
4789 }
4790}
4791
4792//----------------
4793// DumpBinary
4794//----------------
4795void JEventSource_EVIO::DumpBinary(const uint32_t *iptr, const uint32_t *iend, uint32_t MaxWords, const uint32_t *imark)
4796{
4797 /// This is used for debugging. It will print to the screen the words
4798 /// starting at the address given by iptr and ending just before iend
4799 /// or for MaxWords words, whichever comes first. If iend is NULL,
4800 /// then MaxWords will be printed. If MaxWords is zero then it is ignored
4801 /// and only iend is checked. If both iend==NULL and MaxWords==0, then
4802 /// only the word at iptr is printed.
4803
4804 cout << "Dumping binary: istart=" << hex << iptr << " iend=" << iend << " MaxWords=" << dec << MaxWords << endl;
4805
4806 if(iend==NULL__null && MaxWords==0) MaxWords=1;
4807 if(MaxWords==0) MaxWords = (uint32_t)0xffffffff;
4808
4809 uint32_t Nwords=0;
4810 while(iptr!=iend && Nwords<MaxWords){
4811
4812 // line1 is hex and line2 is decimal
4813 stringstream line1, line2;
4814
4815 // print words in columns 8 words wide. First part is
4816 // reserved for word number
4817 uint32_t Ncols = 8;
4818 line1 << setw(5) << Nwords;
4819 line2 << string(5, ' ');
4820
4821 // Loop over columns
4822 for(uint32_t i=0; i<Ncols; i++, iptr++, Nwords++){
4823
4824 if(iptr == iend) break;
4825 if(Nwords>=MaxWords) break;
4826
4827 stringstream iptr_hex;
4828 iptr_hex << hex << "0x" << *iptr;
4829
4830 string mark = (iptr==imark ? "*":" ");
4831
4832 line1 << setw(12) << iptr_hex.str() << mark;
4833 line2 << setw(12) << *iptr << mark;
4834 }
4835
4836 cout << line1.str() << endl;
4837 cout << line2.str() << endl;
4838 cout << endl;
4839 }
4840}
4841
4842#endif // HAVE_EVIO
4843
4844#if 0
4845//----------------
4846// GuessModuleType
4847//----------------
4848MODULE_TYPE JEventSource_EVIO::GuessModuleType(const uint32_t* istart, const uint32_t* iend, evioDOMNodeP bankPtr)
4849{
4850 /// Try parsing through the information in the given data buffer
4851 /// to determine which type of module produced the data.
4852
4853 if(IsFADC250(istart, iend)) return DModuleType::FADC250;
4854 if(IsF125ADC(istart, iend)) return DModuleType::F125ADC;
4855 if(IsF1TDC(istart, iend)) return DModuleType::F1TDC;
4856 if(IsTS(istart, iend)) return DModuleType::JLAB_TS;
4857 if(IsTI(istart, iend)) return DModuleType::JLAB_TID;
4858
4859
4860 // Couldn't figure it out...
4861 return DModuleType::UNKNOWN;
4862}
4863
4864//----------------
4865// IsFADC250
4866//----------------
4867bool JEventSource_EVIO::IsFADC250(const uint32_t *istart, const uint32_t *iend)
4868{
4869 //---- Check for f250
4870 // This will check if the first word appears to be a block header.
4871 // If so, it loops over all words looking for a block trailer.
4872 // If the slot number in the block trailer matches that in the
4873 // block header AND the number of words in the block matches that
4874 // specified in the block trailer, then it is assumed to be a f250.
4875 if(((*istart>>31) & 0x1) == 1){
4876 uint32_t data_type = (*istart>>27) & 0x0F;
4877 if(data_type == 0){ // Block Header
4878 uint32_t slot_header = (*istart>>22) & 0x1F;
4879 uint32_t Nwords = 1;
4880 for(const uint32_t *iptr=istart; iptr<iend; iptr++, Nwords++){
4881 if(((*iptr>>31) & 0x1) == 1){
4882 uint32_t data_type = (*iptr>>27) & 0x0F;
4883 if(data_type == 1){ // Block Trailer
4884 uint32_t slot_trailer = (*iptr>>22) & 0x1F;
4885 uint32_t Nwords_trailer = (*iptr>>0) & 0x3FFFFF;
4886
4887 if( slot_header == slot_trailer && Nwords == Nwords_trailer ){
4888 return true;
4889 }else{
4890 return false;
4891 }
4892 }
4893 }
4894 }
4895 }
4896 }
4897
4898 // either first word was not a block header or no block trailer was found
4899 return false;
4900}
4901
4902//----------------
4903// IsF1TDC
4904//----------------
4905bool JEventSource_EVIO::IsF1TDC(const uint32_t *istart, const uint32_t *iend)
4906{
4907 //---- Check for F1TDC
4908 // This will check for consistency in the slot numbers for all words
4909 // in the buffer. The slot number of data words are checked against
4910 // the slot number of the most recently encountered header word.
4911 uint32_t slot_header = 1000;
4912 uint32_t slot_trailer = 1000;
4913
4914 const uint32_t *iptr=istart;
4915
4916 // skip first word which appears to be ROL marker for F1TDC data
4917 if(*istart == 0xf1daffff)iptr++
4918
4919 // There is no distinction between header and trailer
4920 // words other than the order that they appear. We keep
4921 // track by flipping this value
4922 bool looking_for_header = true;
4923
4924 // Keep track of the number of valid blocks of F1TDC data we find
4925 // (i.e. ones where the header and trailer words were found
4926 int Nvalid = 0;
4927
4928 for(; iptr<iend; iptr++){
4929
4930 // ROL end of data marker (only in test setup data)
4931 if(*iptr == 0xda0000ff)break;
4932
4933 uint32_t slot = (*iptr>>27) & 0x1F;
4934
4935 // if slot is 0 or 30, we are supposed to ignore the data.
4936 if(slot == 30 || slot ==0)continue;
4937
4938 if(((*iptr>>23) & 0x1) == 0){
4939 // header/trailer word
4940 if(looking_for_header){
4941 slot_header = slot;
4942 looking_for_header = false;
4943 }else{
4944 slot_trailer = slot;
4945 if(slot_trailer != slot_header)return false;
4946 looking_for_header = true;
4947 Nvalid++;
4948 }
4949 }else{
4950 // data word
4951
4952 // if we encounter a data word when we are expecting
4953 // a header word, then the current word is not from
4954 // an F1TDC. However, if we did find at least one valid
4955 // block at the begining, of the buffer, claim the buffer
4956 // points to F1TDC data. We check for as many valid F1TDC
4957 // blocks as possible to help ensure that is what the data
4958 // is.
4959 if(looking_for_header)return Nvalid>0;
4960
4961 // If the slot number does not match, then this is
4962 // not valid F1TDC data
4963 if(slot != slot_header)return false;
4964 }
4965 }
4966
4967 return Nvalid>0;
4968}
4969
4970//----------------
4971// DumpModuleMap
4972//----------------
4973void JEventSource_EVIO::DumpModuleMap(void)
4974{
4975 // Open output file
4976 string fname = "module_map.txt";
4977 ofstream ofs(fname.c_str());
4978 if(!ofs.is_open()){
4979 jerr<<"Unable to open file \""<<fname<<"\" for writing!"<<endl;
4980 return;
4981 }
4982
4983 jout<<"Writing module map to file \""<<fname<<"\""<<endl;
4984
4985 // Write header
4986 time_t now = time(NULL__null);
4987 ofs<<"# Autogenerated module map"<<endl;
4988 ofs<<"# Created: "<<ctime(&now);
4989 ofs<<"#"<<endl;
4990
4991 // Write known module types in header
4992 vector<DModuleType> modules;
4993 DModuleType::GetModuleList(modules);
4994 ofs<<"# Known module types:"<<endl;
4995 ofs<<"# ----------------------"<<endl;
4996 for(unsigned int i=0; i<modules.size(); i++){
4997 string name = modules[i].GetName();
4998 string space(12-name.size(), ' ');
4999 ofs << "# " << name << space << " - " << modules[i].GetDescription() <<endl;
5000 }
5001 ofs<<"#"<<endl;
5002 ofs<<"#"<<endl;
5003
5004 // Write module map
5005 ofs<<"# Format is:"<<endl;
5006 ofs<<"# tag num type"<<endl;
5007 ofs<<"#"<<endl;
5008
5009 map<tagNum, MODULE_TYPE>::iterator iter = module_type.begin();
5010 for(; iter!=module_type.end(); iter++){
5011
5012 tagNum tag_num = iter->first;
5013 MODULE_TYPE type = iter->second;
5014 ofs<<tag_num.first<<" "<<(int)tag_num.second<<" "<<DModuleType::GetName(type)<<endl;
5015 }
5016 ofs<<endl;
5017
5018 // Close output file
5019 ofs.close();
5020}
5021#endif