Bug Summary

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