JAPAn
Just Another Parity Analyzer
Loading...
Searching...
No Matches
Coda3EventDecoder.cc
Go to the documentation of this file.
1/*!
2 * \file Coda3EventDecoder.cc
3 * \brief CODA version 3 event decoder implementation
4 */
5
6#include "Coda3EventDecoder.h"
7#include "THaCodaFile.h"
8#include "QwOptions.h"
9
10#include <vector>
11#include <ctime>
12#include <cstring>
13
14#include "TError.h"
15
16// Creates PHYS Event EVIO Header. See header for parameters and return value.
17std::vector<UInt_t> Coda3EventDecoder::EncodePHYSEventHeader(std::vector<ROCID_t> &ROCList)
18{
19 int localtime = (int) time(0);
20 int ROCCount = ROCList.size();
21 int wordcount = (8 + ROCCount*3);
22 std::vector<UInt_t> header;
23 header.push_back(0xFF501001);
24 header.push_back(wordcount); // word count for Trigger Bank
25 header.push_back(0xFF212000 | ROCCount); // # of ROCs
26
27 header.push_back(0x010a0004);
28 // evtnum is held by a 64 bit ... for now we set the upper 32 bits to 0
29 header.push_back(++fEvtNumber );
30 header.push_back(0x0);
31
32 // evttime is held by a 64 bit (bits 0-48 is the time) ... for now we set the upper 32 bits to 0
33 header.push_back(localtime);
34 header.push_back(0x0);
35
36 header.push_back(0x1850001);
37 header.push_back(0xc0da); // TS# Trigger
38 for(auto it = ROCList.begin(); it != ROCList.end(); it++){
39 int base = 0x010002;
40 int roc = (*it << 24);
41 header.push_back(roc | base);
42 header.push_back(0x4D6F636B); // ASCII for 'MOCK'
43 header.push_back(0x4D6F636B); // ASCII for 'MOCK'
44 }
45
46 return header;
47}
48
49
50// Creates PRESTART Event EVIO Header. See header for parameters.
51void Coda3EventDecoder::EncodePrestartEventHeader(int* buffer, int runnumber, int runtype, int localtime)
52{
53 buffer[0] = 4; // Prestart event length
54 buffer[1] = ((0xffd1 << 16) | (0x01 << 8));
55 buffer[2] = localtime;
56 buffer[3] = runnumber;
57 buffer[4] = runtype;
58 ProcessPrestart(localtime, runnumber, runtype);
59}
60
61// Creates GO Event EVIO Header. See header for parameters.
62void Coda3EventDecoder::EncodeGoEventHeader(int* buffer, int eventcount, int localtime)
63{
64 buffer[0] = 4; // Go event length
65 buffer[1] = ((0xffd2 << 16) | (0x01 << 8) );
66 buffer[2] = localtime;
67 buffer[3] = 0; // unused
68 buffer[4] = eventcount;
69 ProcessGo(localtime, eventcount);
70}
71
72// Creates PAUSE Event EVIO Header. See header for parameters.
73void Coda3EventDecoder::EncodePauseEventHeader(int* buffer, int eventcount, int localtime)
74{
75 buffer[0] = 4; // Pause event length
76 buffer[1] = ((0xffd3 << 16) | (0x01 << 8) );
77 buffer[2] = localtime;
78 buffer[3] = 0; // unused
79 buffer[4] = eventcount;
80 ProcessPause(localtime, eventcount);
81}
82
83// Creates END Event EVIO Header. See header for parameters.
84void Coda3EventDecoder::EncodeEndEventHeader(int* buffer, int eventcount, int localtime)
85{
86 buffer[0] = 4; // End event length
87 buffer[1] = ((0xffd4 << 16) | (0x01 << 8) );
88 buffer[2] = localtime;
89 buffer[3] = 0; // unused
90 buffer[4] = eventcount;
91 ProcessEnd(localtime, eventcount);
92}
93
94// Determine if a buffer contains a PHYS event, control event, or other event.
96{
97 fPhysicsEventFlag = kFALSE;
98 fControlEventFlag = kFALSE;
99 Int_t ret = HED_OK;
100
101 // Main engine for decoding, called by public LoadEvent() methods
102 // this assert checks to see if buffer points to NULL
103 assert(buffer);
104
105 // General Event information
106 fEvtLength = buffer[0]+1; // in longwords (4 bytes)
107 fEvtType = 0;
108 fEvtTag = 0;
109 fBankDataType = 0;
110
111 // Prep TBOBJ variables
112 tbank.Clear();
113 tsEvType = 0;
114 evt_time = 0;
115 trigger_bits = 0;
116 block_size = 0;
117
118 // Start Filling Data
119 fEvtTag = (buffer[1] & 0xffff0000) >> 16;
120 fBankDataType = (buffer[1] & 0xff00) >> 8;
121 block_size = (buffer[1] & 0xff);
122
123 if(block_size > 1) {
124 QwWarning << "MultiBlock is not properly supported! block_size = "
126 }
127
128 // Determine the event type by the evt tag
130 fWordsSoFar = (2);
131 if(fEvtTag < 0xff00) {
132 // User Event
133 printUserEvent(buffer);
134 }
135 else if(fControlEventFlag) {
137 }
138 else if(fPhysicsEventFlag) {
139 ret = trigBankDecode( buffer );
140 if(ret != HED_OK) { trigBankErrorHandler( ret ); }
141 else {
142 fEvtNumber = tbank.evtNum;
143 fWordsSoFar = 2 + tbank.len;
144 }
145 }
146 else {
147 // Not a control event, user event, nor physics event. Not sure what it is
148 // Arbitrarily set the event type to "fEvtTag".
149 // The first two words have been examined.
150 QwWarning << "Undetermined Event Type" << QwLog::endl;
151 for(size_t index = 0; fEvtLength; index++){
152 QwVerbose << "\t" << buffer[index];
153 if(index % 4 == 0){ QwVerbose << QwLog::endl; }
154 }
156 }
157
159 QwDebug << Form("buffer[0-1] 0x%x 0x%x ; ", buffer[0], buffer[1]);
160 if (gQwLog.GetLogLevel() >= QwLog::kDebug) {
161 PrintDecoderInfo(gQwLog(QwLog::kDebug,__PRETTY_FUNCTION__));
162 }
163
164 return CODA_OK;
165}
166
167// Determine the Event Type (PHYS, CONTROL, OTHER). See header for details.
169{
170 UInt_t evtyp{};
171 if( tag >= 0xff00 ) { // CODA Reserved bank type
172 switch( tag ) {
173 case 0xffd1:
174 evtyp = kPRESTART_EVENT;
175 fControlEventFlag = kTRUE;
176 break;
177 case 0xffd2:
178 evtyp = kGO_EVENT;
179 fControlEventFlag = kTRUE;
180 break;
181 case 0xffd4:
182 evtyp = kEND_EVENT;
183 fControlEventFlag = kTRUE;
184 break;
185 case 0xff50:
186 case 0xff58: // Physics event with sync bit
187 case 0xFF78:
188 case 0xff70:
189 evtyp = 1; // for CODA 3.* physics events are type 1.
190 fPhysicsEventFlag=kTRUE;
191 break;
192 default: // Undefined CODA 3 event type
193 QwWarning << "CodaDecoder:: WARNING: Undefined CODA 3 event type, tag = "
194 << "0x" << std::hex << tag << std::dec << QwLog::endl;
195 evtyp = 0;
196 //FIXME evtyp = 0 could also be a user event type ...
197 // maybe throw an exception here?
198 }
199 } else { // User event type
200 evtyp = tag; // EPICS, ROC CONFIG, ET-insertions, etc.
201 }
202 return evtyp;
203}
204
205
206// Print user events (non-PHYS and non-control). See header for details.
207void Coda3EventDecoder::printUserEvent(const UInt_t *buffer)
208{
209 // checks of ET-inserted data
210 Int_t print_it=0;
211
212 switch( fEvtType ) {
213
214 case EPICS_EVTYPE:
215 // QwMessage << "EPICS data "<<QwLog::endl;
216 // print_it=1;
217 break;
218 // Do we need this event?
219 case PRESCALE_EVTYPE:
220 QwMessage << "Prescale data "<<QwLog::endl;
221 print_it=1;
222 break;
223 // Do we need this event?
224 case DAQCONFIG_FILE1:
225 QwMessage << "DAQ config file 1 "<<QwLog::endl;
226 print_it=1;
227 break;
228 // Do we need this event?
229 case DAQCONFIG_FILE2:
230 QwMessage << "DAQ config file 2 "<<QwLog::endl;
231 print_it=1;
232 break;
233 // Do we need this event?
234 case SCALER_EVTYPE:
235 QwMessage << "LHRS scaler event "<<QwLog::endl;
236 print_it=1;
237 break;
238 // Do we need this event?
239 case SBSSCALER_EVTYPE:
240 QwMessage << "SBS scaler event "<<QwLog::endl;
241 print_it=1;
242 break;
243 // Do we need this event?
244 case HV_DATA_EVTYPE:
245 QwMessage << "High voltage data event "<<QwLog::endl;
246 print_it=1;
247 break;
248 default:
249 // something else ?
250 QwWarning << "\n--- Special event type: " << fEvtTag << " ---\n" << QwLog::endl;
251 }
252 if(print_it) {
253 char *cbuf = (char *)buffer; // These are character data
254 size_t elen = sizeof(int)*(buffer[0]+1);
255 QwMessage << "Dump of event buffer . Len = "<<elen<<QwLog::endl;
256 // This dump will look exactly like the text file that was inserted.
257 for (size_t ii=0; ii<elen; ii++) QwMessage << cbuf[ii];
258 }
259}
260
261// Print internal decoder information. See header for details.
263{
264
265 out << Form("Event Number: %d; Length: %d; Tag: 0x%x; Bank data type: 0x%x ",
267 << Form("Evt type: 0x%x; Evt number %d; fWordsSoFar %d",
269 << QwLog::endl;
270}
271
272// Decode the TI Trigger Bank for PHYS events. See header for parameters and returns.
274{
275 const char* const HERE = "Coda3EventDecoder::trigBankDecode";
276 if(block_size == 0) {
277 QwError << HERE << ": CODA 3 Format Error: Physics event #" << fEvtNumber
278 << " with block size 0" << QwLog::endl;
279 return HED_ERR;
280 }
281 // Set up exception handling for the PHYS Bank
282 try {
283 tbank.Fill(&buffer[fWordsSoFar], block_size, TSROCNumber);
284 }
285 catch( const coda_format_error& e ) {
286 Error(HERE, "CODA 3 format error: %s", e.what() );
287 return HED_ERR;
288 }
289 // Copy pertinent data to member variables for faster retrieval
290 LoadTrigBankInfo(0); // Load data for first event in block
291 return HED_OK;
292}
293
294
295// Extract TI header information. See header for parameters and returns.
296uint32_t Coda3EventDecoder::TBOBJ::Fill( const uint32_t* evbuffer,
297 uint32_t blkSize, uint32_t tsroc )
298{
299 if( blkSize == 0 )
300 throw std::invalid_argument("CODA block size must be > 0");
301 start = evbuffer;
302 blksize = blkSize;
303 len = evbuffer[0] + 1;
304 tag = (evbuffer[1] & 0xffff0000) >> 16;
305 nrocs = evbuffer[1] & 0xff;
306
307 const uint32_t* p = evbuffer + 2;
308 // Segment 1:
309 // uint64_t event_number
310 // uint64_t run_info if withRunInfo
311 // uint64_t time_stamp[blkSize] if withTimeStamp
312 {
313 uint32_t slen = *p & 0xffff;
314 if( slen != 2*(1 + (withRunInfo() ? 1 : 0) + (withTimeStamp() ? blkSize : 0)))
315 throw coda_format_error("Invalid length for Trigger Bank seg 1");
316 const uint32_t *q = (p+1);
317 memcpy(&evtNum, q++, sizeof(evtNum)); // uint64_t
318 if (withTimeStamp()) {
319 evTS = reinterpret_cast<const uint64_t*>(++q); // uint64_t[blkSize]
320 q += 2*(blksize-1);
321 } else {
322 evTS = nullptr;
323 }
324 if (withRunInfo()) {
325 memcpy(&runInfo, q+=2, sizeof(runInfo)); // uint64_t
326 } else {
327 runInfo = 0;
328 }
329 p += slen + 1;
330 }
331 if( p-evbuffer >= len )
332 throw coda_format_error("Past end of bank after Trigger Bank seg 1");
333
334 // Segment 2:
335 // uint16_t event_type[blkSize]
336 // padded to next 32-bit boundary
337 {
338 uint32_t slen = *p & 0xffff;
339 if( slen != (blkSize-1)/2 + 1 )
340 throw coda_format_error("Invalid length for Trigger Bank seg 2");
341 evType = (const uint16_t*) (p + 1);
342 p += slen + 1;
343 }
344
345 // nroc ROC segments containing timestamps and optional
346 // data like trigger latch bits:
347 // struct {
348 // uint64_t roc_time_stamp; // Lower 48 bits only seem to be the time.
349 // uint32_t roc_trigger_bits; // Optional. Typically only in TSROC.
350 // } roc_segment[blkSize];
351 TSROC = nullptr;
352 tsrocLen = 0;
353 for( uint32_t i = 0; i < nrocs; ++i ) {
354 if( p-evbuffer >= len )
355 throw coda_format_error("Past end of bank while scanning trigger bank segments");
356 uint32_t slen = *p & 0xffff;
357 uint32_t rocnum = (*p & 0xff000000) >> 24;
358 // TODO:
359 // tsroc is the crate # of the TS
360 // This is filled with Podd's THaCrateMap class which we are not using
361 // tsroc is currently always 0
362 if( rocnum == tsroc ) {
363 TSROC = p + 1;
364 tsrocLen = slen;
365 break;
366 }
367 p += slen + 1;
368 }
369
370 return len;
371}
372
373// Load trigger bank information of an event. See header for parameters and returns.
375{
376 // CODA3: Load tsEvType, evt_time, and trigger_bits for i-th event
377 // in event block buffer. index_buffer must be < block size.
378
379 assert(i < tbank.blksize);
380 if( i >= tbank.blksize )
381 return -1;
382 tsEvType = tbank.evType[i]; // event type (configuration-dependent)
383 if( tbank.evTS ) {
384 // Use memcpy to safely read potentially unaligned 64-bit timestamp
385 uint64_t timestamp;
386 memcpy(&timestamp, &tbank.evTS[i], sizeof(timestamp));
387 evt_time = timestamp; // event time (4ns clock, I think)
388 }
389 else if( tbank.TSROC ) {
390 UInt_t struct_size = tbank.withTriggerBits() ? 3 : 2;
391 // Use memcpy to safely read potentially unaligned 64-bit value
392 uint64_t timestamp;
393 memcpy(&timestamp, tbank.TSROC + struct_size * i, sizeof(timestamp));
394 evt_time = timestamp;
395 // Only the lower 48 bits seem to contain the time
396 evt_time &= 0x0000FFFFFFFFFFFF;
397 }
398 if( tbank.withTriggerBits() ){
399 // Trigger bits. Only the lower 6 bits seem to contain the actual bits
400 uint32_t trigger_word;
401 memcpy(&trigger_word, &tbank.TSROC[2 + 3 * i], sizeof(trigger_word));
402 trigger_bits = trigger_word & 0x3F;
403 }
404 return 0;
405}
406
407
408// Display warning given a trigBank error flag. See header for details.
410{
411 switch(flag){
412 case HED_OK:
413 QwWarning << "TrigBankDecode() returned HED_OK... why are we here?" << QwLog::endl;
414 break;
415 case HED_WARN:
416 QwError << "TrigBankDecode() returned HED_WARN" << QwLog::endl;
417 break;
418 case HED_ERR:
419 QwError << "TrigBankDecode() returned HED_ERR" << QwLog::endl;
420 break;
421 case HED_FATAL:
422 QwError << "TrigBankDecoder() returned HED_FATAL" << QwLog::endl;
423 break;
424 default:
425 QwError << "TrigBankDecoder() returned an Unknown Error" << QwLog::endl;
426 break;
427 }
428 // Act as if we are at the end of the event and set everything to false (0)
429 QwWarning << "Skipping to the end of the event and setting everything to false (0)!" << QwLog::endl;
430 fPhysicsEventFlag = kFALSE;
431 fControlEventFlag = kFALSE;
432
433 fEvtType = 0;
434 fEvtTag = 0;
435 fBankDataType = 0;
436 tbank.Clear();
437 tsEvType = 0;
438 evt_time = 0;
439 trigger_bits = 0;
440 block_size = 0;
441
443}
444
445
446
An options class which parses command line, config file and environment.
#define QwVerbose
Predefined log drain for verbose messages.
Definition QwLog.h:54
QwLog gQwLog
Definition QwLog.cc:20
#define QwError
Predefined log drain for errors.
Definition QwLog.h:39
#define QwWarning
Predefined log drain for warnings.
Definition QwLog.h:44
#define QwMessage
Predefined log drain for regular messages.
Definition QwLog.h:49
#define QwDebug
Predefined log drain for debugging output.
Definition QwLog.h:59
CODA version 3 event decoder implementation.
void EncodePauseEventHeader(int *buffer, int eventcount, int localtime) override
static const UInt_t SCALER_EVTYPE
std::vector< UInt_t > EncodePHYSEventHeader(std::vector< ROCID_t > &ROCList) override
Int_t trigBankDecode(UInt_t *buffer)
void trigBankErrorHandler(Int_t flag)
void printUserEvent(const UInt_t *buffer)
static const UInt_t SBSSCALER_EVTYPE
void EncodeGoEventHeader(int *buffer, int eventcount, int localtime) override
static const UInt_t HV_DATA_EVTYPE
static const UInt_t DAQCONFIG_FILE2
Int_t LoadTrigBankInfo(UInt_t index_buffer)
void PrintDecoderInfo(QwLog &out) override
static const UInt_t DAQCONFIG_FILE1
void EncodeEndEventHeader(int *buffer, int eventcount, int localtime) override
UInt_t InterpretBankTag(UInt_t tag)
void EncodePrestartEventHeader(int *buffer, int runnumber, int runtype, int localtime) override
static const UInt_t PRESCALE_EVTYPE
Int_t DecodeEventIDBank(UInt_t *buffer) override
uint32_t Fill(const uint32_t *evbuffer, uint32_t blkSize, uint32_t tsroc)
void ProcessPause(UInt_t local_time, UInt_t evt_count)
void ProcessGo(UInt_t local_time, UInt_t evt_count)
void ProcessPrestart(UInt_t local_time, UInt_t local_runnumber, UInt_t local_runtype)
void ProcessEnd(UInt_t local_time, UInt_t evt_count)
void ProcessControlEvent(UInt_t evtype, UInt_t *buffer)
Logging and output management system with configurable verbosity levels.
Definition QwLog.h:73
@ kDebug
Definition QwLog.h:94
static std::ostream & endl(std::ostream &)
End of the line.
Definition QwLog.cc:297
Bool_t fPhysicsEventFlag
UInt_t fEvtNumber
CODA event number; only defined for physics events.
Bool_t fControlEventFlag