Bug Summary

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

Annotated Source Code

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