File indexing completed on 2025-08-03 08:20:49
0001 #include "oncsSub_idtpcfeev3.h"
0002
0003 #include <string.h>
0004 #include <stdint.h>
0005
0006 #define coutfl cout << __FILE__<< " " << __LINE__ << " "
0007 #define cerrfl cerr << __FILE__<< " " << __LINE__ << " "
0008
0009 using namespace std;
0010
0011 oncsSub_idtpcfeev3::oncsSub_idtpcfeev3(subevtdata_ptr data)
0012 :oncsSubevent_w2 (data)
0013 {
0014
0015 _is_decoded = 0;
0016 _last_requested_element = -1;
0017 _last_requested_waveform = 0;
0018 }
0019
0020
0021 oncsSub_idtpcfeev3::~oncsSub_idtpcfeev3()
0022 {
0023
0024 for (auto itr = waveforms.begin() ; itr != waveforms.end() ; ++itr)
0025 {
0026 delete (*itr);
0027 }
0028 waveforms.clear();
0029
0030 for (auto itr = waveform_vector.begin() ; itr != waveform_vector.end() ; ++itr)
0031 {
0032 delete (*itr);
0033 }
0034 waveform_vector.clear();
0035
0036
0037 for (auto itr = gtm_data.begin() ; itr != gtm_data.end() ; ++itr)
0038 {
0039 delete (*itr);
0040 }
0041 gtm_data.clear();
0042
0043 }
0044
0045 int oncsSub_idtpcfeev3::cacheIterator(const int n)
0046 {
0047 if ( n < 0) return 0;
0048 if ( _last_requested_element == n) return 1;
0049
0050 unsigned i = n;
0051 if ( i >= waveform_vector.size() )
0052 {
0053 _last_requested_element = -1;
0054 _last_requested_waveform = 0;
0055 return 0;
0056 }
0057
0058 _last_requested_element = n;
0059 _last_requested_waveform = waveform_vector[n];
0060
0061 return 1;
0062 }
0063
0064 int oncsSub_idtpcfeev3::decode_gtm_data(unsigned short dat[16])
0065 {
0066 unsigned char *gtm = (unsigned char *)dat;
0067 gtm_payload *payload = new gtm_payload;
0068
0069 payload->pkt_type = gtm[0] | ((unsigned short)gtm[1] << 8);
0070 if (payload->pkt_type != GTM_LVL1_ACCEPT_MAGIC_KEY && payload->pkt_type != GTM_ENDAT_MAGIC_KEY)
0071 {
0072 delete payload;
0073 return -1;
0074 }
0075
0076 payload->is_lvl1 = payload->pkt_type == GTM_LVL1_ACCEPT_MAGIC_KEY;
0077 payload->is_endat = payload->pkt_type == GTM_ENDAT_MAGIC_KEY;
0078
0079 payload->bco = ((unsigned long long)gtm[2] << 0)
0080 | ((unsigned long long)gtm[3] << 8)
0081 | ((unsigned long long)gtm[4] << 16)
0082 | ((unsigned long long)gtm[5] << 24)
0083 | ((unsigned long long)gtm[6] << 32)
0084 | (((unsigned long long)gtm[7]) << 40);
0085 payload->lvl1_count = ((unsigned int)gtm[8] << 0)
0086 | ((unsigned int)gtm[9] << 8)
0087 | ((unsigned int)gtm[10] << 16)
0088 | ((unsigned int)gtm[11] << 24);
0089 payload->endat_count = ((unsigned int)gtm[12] << 0)
0090 | ((unsigned int)gtm[13] << 8)
0091 | ((unsigned int)gtm[14] << 16)
0092 | ((unsigned int)gtm[15] << 24);
0093 payload->last_bco = ((unsigned long long)gtm[16] << 0)
0094 | ((unsigned long long)gtm[17] << 8)
0095 | ((unsigned long long)gtm[18] << 16)
0096 | ((unsigned long long)gtm[19] << 24)
0097 | ((unsigned long long)gtm[20] << 32)
0098 | (((unsigned long long)gtm[21]) << 40);
0099 payload->modebits = gtm[22];
0100
0101 this->gtm_data.push_back(payload);
0102
0103 return 0;
0104 }
0105
0106 int oncsSub_idtpcfeev3::tpc_decode ()
0107 {
0108
0109 if (_is_decoded ) return 0;
0110 _is_decoded = 1;
0111
0112 unsigned int payload_length = 2 * (getLength() - SEVTHEADERLENGTH - getPadding() );
0113
0114 unsigned int index = 0;
0115
0116
0117 unsigned short *buffer = ( unsigned short *) &SubeventHdr->data;
0118
0119
0120 while (index < payload_length)
0121 {
0122
0123 const unsigned int datalength = 0xf;
0124
0125 if ((buffer[index] & 0xFF00) == FEE_MAGIC_KEY)
0126 {
0127
0128 unsigned int fee_id = buffer[index] & 0xff;
0129
0130 ++index;
0131 if (fee_id < MAX_FEECOUNT)
0132 {
0133 for (unsigned int i = 0; i < datalength; i++)
0134 {
0135
0136 if (index >= payload_length) break;
0137
0138 fee_data[fee_id].push_back(buffer[index++]);
0139 }
0140 }
0141 } else if ((buffer[index] & 0xFF00) == GTM_MAGIC_KEY) {
0142 unsigned short buf[16];
0143
0144
0145 for (unsigned int i = 0; i < 16; i++) {
0146 buf[i] = buffer[index++];
0147 }
0148
0149 decode_gtm_data(buf);
0150 }
0151 else
0152 {
0153
0154 index += datalength + 1;
0155 }
0156
0157 }
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168 for ( int ifee = 0 ; ifee < MAX_FEECOUNT ; ifee++)
0169 {
0170
0171 unsigned int pos;
0172
0173
0174 for ( pos = 0; pos < fee_data[ifee].size() ; )
0175 {
0176
0177 int skip_amount = find_header (pos, fee_data[ifee]);
0178 if ( skip_amount < 0) break;
0179
0180 pos += skip_amount;
0181
0182
0183 unsigned int startpos = pos;
0184
0185
0186 if ( startpos + HEADER_LENGTH >= fee_data[ifee].size() || startpos + fee_data[ifee][startpos] > fee_data[ifee].size())
0187 {
0188 pos = fee_data[ifee].size() + 1;
0189 }
0190 else
0191 {
0192
0193 unsigned short header[HEADER_LENGTH];
0194 for ( int i = 0; i < HEADER_LENGTH; i++ ) header[i] = (fee_data[ifee][pos++]) ;
0195
0196 sampa_waveform *sw = new sampa_waveform;
0197
0198 sw->fee = ifee;
0199 sw->pkt_length = header[0];
0200 sw->adc_length = header[0]-5;
0201 sw->sampa_address = (header[1] >> 5) & 0xf;
0202 sw->sampa_channel = header[1] & 0x1f;
0203 sw->channel = header[1] & 0x1ff;
0204 sw->bx_timestamp = ((header[3] & 0x1ff) << 11)
0205 | ((header[2] & 0x3ff) << 1)
0206 | (header[1] >> 9);
0207
0208
0209
0210 short data_size_counter = header[0]-5;
0211
0212 short actual_data_size = 0;
0213
0214
0215
0216
0217
0218
0219
0220 for (int i = 0 ; i < 1024 ; i++)
0221 {
0222 sw->waveform.push_back(65000);
0223
0224 }
0225
0226
0227
0228 while(data_size_counter>0)
0229 {
0230 int nsamp = fee_data[ifee][pos++];
0231 int start_t = fee_data[ifee][pos++];
0232
0233 data_size_counter-=2;
0234
0235 actual_data_size += nsamp;
0236 actual_data_size += 2;
0237
0238
0239
0240
0241 for (int j=0; j<nsamp;j++){
0242 if(start_t+j<1024){ sw->waveform[start_t+j]= fee_data[ifee][pos++]; }
0243 else { pos++; }
0244
0245 data_size_counter--;
0246
0247
0248
0249
0250
0251
0252 if(data_size_counter==1) break;
0253 }
0254
0255 if(data_size_counter==1) break;
0256 }
0257
0258
0259
0260
0261
0262
0263
0264
0265
0266 if(header[0]-5 == actual_data_size){
0267
0268
0269
0270 unsigned short crc = crc16(ifee, startpos, header[0]-1);
0271
0272
0273
0274
0275
0276
0277
0278
0279
0280
0281 sw->checksum = crc;
0282
0283 sw->valid = ( crc == fee_data[ifee][pos]);
0284
0285 waveforms.insert(sw);
0286 }
0287 else{ delete sw; }
0288 }
0289
0290
0291
0292 }
0293 }
0294
0295 auto it = waveforms.begin();
0296 for ( ; it != waveforms.end(); ++it)
0297 {
0298 waveform_vector.push_back( *it);
0299 }
0300 waveforms.clear();
0301
0302 return 0;
0303 }
0304
0305 long long oncsSub_idtpcfeev3::lValue(const int n, const char *what)
0306 {
0307 tpc_decode();
0308
0309 const size_t i = n;
0310
0311 if (strcmp(what, "N_TAGGER") == 0)
0312 {
0313 return gtm_data.size();
0314 }
0315
0316 else if (strcmp(what, "TAGGER_TYPE") == 0 )
0317 {
0318 if (i < gtm_data.size())
0319 {
0320 return gtm_data[i]->pkt_type;
0321 }
0322 }
0323
0324 else if (strcmp(what, "IS_ENDAT") == 0 )
0325 {
0326 if (i < gtm_data.size())
0327 {
0328 return gtm_data[i]->is_endat;
0329 }
0330 }
0331
0332 else if (strcmp(what, "IS_LEVEL1_TRIGGER") == 0 )
0333 {
0334 if (i < gtm_data.size())
0335 {
0336 return gtm_data[i]->is_lvl1;
0337 }
0338 }
0339
0340 else if (strcmp(what, "BCO") == 0 )
0341 {
0342 if (i < gtm_data.size())
0343 {
0344 return gtm_data[i]->bco;
0345 }
0346 }
0347
0348 else if (strcmp(what, "LEVEL1_COUNT") == 0 )
0349 {
0350 if (i < gtm_data.size())
0351 {
0352 return gtm_data[i]->lvl1_count;
0353 }
0354 }
0355
0356 else if (strcmp(what, "ENDAT_COUNT") == 0 )
0357 {
0358 if (i < gtm_data.size())
0359 {
0360 return gtm_data[i]->endat_count;
0361 }
0362 }
0363
0364 else if (strcmp(what, "LAST_BCO") == 0 )
0365 {
0366 if (i < gtm_data.size())
0367 {
0368 return gtm_data[i]->last_bco;
0369 }
0370 }
0371
0372 else if (strcmp(what, "MODEBITS") == 0 )
0373 {
0374 if (i < gtm_data.size())
0375 {
0376 return gtm_data[i]->modebits;
0377 }
0378 }
0379
0380 return 0;
0381 }
0382
0383 int oncsSub_idtpcfeev3::iValue(const int n, const int sample)
0384 {
0385 if ( n < 0) return 0;
0386
0387 tpc_decode();
0388
0389 if ( cacheIterator(n) )
0390 {
0391 unsigned int m = sample;
0392 if ( m >= (_last_requested_waveform)->waveform.size() ) return 0;
0393 return (_last_requested_waveform)->waveform[m];
0394 }
0395 return 0;
0396 }
0397
0398
0399
0400
0401
0402 int oncsSub_idtpcfeev3::iValue(const int n, const char *what)
0403 {
0404
0405 tpc_decode();
0406
0407 if ( strcmp(what,"NR_WF") == 0 )
0408 {
0409 return waveform_vector.size();
0410 }
0411
0412 else if ( strcmp(what,"MAX_FEECOUNT") == 0 )
0413 {
0414 return MAX_FEECOUNT;
0415 }
0416
0417
0418 else if ( strcmp(what,"SAMPLES") == 0 )
0419 {
0420 if ( cacheIterator(n) )
0421 {
0422 return (int) (_last_requested_waveform)->waveform.size();
0423 }
0424 return 0;
0425 }
0426
0427 else if ( strcmp(what,"FEE") == 0 )
0428 {
0429 if ( cacheIterator(n) )
0430 {
0431 return (int) (_last_requested_waveform)->fee;
0432 }
0433 return 0;
0434 }
0435
0436 else if ( strcmp(what,"SAMPAADDRESS") == 0 )
0437 {
0438 if ( cacheIterator(n) )
0439 {
0440 return (int) (_last_requested_waveform)->sampa_address;
0441 }
0442 return 0;
0443 }
0444
0445 else if ( strcmp(what,"SAMPACHANNEL") == 0 )
0446 {
0447 if ( cacheIterator(n) )
0448 {
0449 return (int) (_last_requested_waveform)->sampa_channel;
0450 }
0451 return 0;
0452 }
0453
0454 else if ( strcmp(what,"CHANNEL") == 0 )
0455 {
0456 if ( cacheIterator(n) )
0457 {
0458 return (int) (_last_requested_waveform)->channel;
0459 }
0460 return 0;
0461 }
0462
0463 else if ( strcmp(what,"BCO") == 0 )
0464 {
0465 if ( cacheIterator(n) )
0466 {
0467 return (int) (_last_requested_waveform)->bx_timestamp;
0468 }
0469 return 0;
0470 }
0471
0472 else if ( strcmp(what,"CHECKSUM") == 0 )
0473 {
0474 if ( cacheIterator(n) )
0475 {
0476 return (int) (_last_requested_waveform)->checksum;
0477 }
0478 return 0;
0479 }
0480
0481 else if ( strcmp(what,"CHECKSUMERROR") == 0 )
0482 {
0483 if ( cacheIterator(n) )
0484 {
0485 if ( (_last_requested_waveform)->valid ) return 0;
0486 return 1;
0487 }
0488 return 0;
0489 }
0490
0491 return 0;
0492
0493 }
0494
0495
0496 int oncsSub_idtpcfeev3::find_header ( const unsigned int yy, const std::vector<unsigned short> &orig)
0497 {
0498 bool found = false;
0499 unsigned int pos = yy;
0500 std::vector<unsigned short> header_candidate;
0501
0502
0503
0504
0505
0506
0507
0508 for ( unsigned int i = 0; i < HEADER_LENGTH ; i++)
0509 {
0510 if ( pos >= orig.size())
0511 {
0512 return -1;
0513 }
0514
0515 header_candidate.push_back(orig[pos]);
0516 pos++;
0517 }
0518
0519 int skip_amount = 0;
0520 while ( ! found)
0521 {
0522
0523
0524
0525 if (header_candidate[4] == MAGIC_KEY_0)
0526 {
0527
0528 found = true;
0529
0530 break;
0531 }
0532 skip_amount++;
0533 if ( pos >= orig.size())
0534 {
0535 return -1;
0536 }
0537
0538
0539 header_candidate.erase(header_candidate.begin());
0540 header_candidate.push_back(orig[pos]);
0541 pos++;
0542 }
0543
0544 return skip_amount;
0545 }
0546
0547 void oncsSub_idtpcfeev3::dump ( OSTREAM& os )
0548 {
0549 tpc_decode();
0550 identify(os);
0551
0552 if (lValue(0, "N_TAGGER") == 0)
0553 os << " No lvl1 and Endat taggers" << endl;
0554 else
0555 {
0556 os << " TAGGER_TYPE BCO LEVEL1 CNT ENDAT CNT LAST_BCO MODEBITS" << endl;
0557
0558 for (int i = 0; i < lValue(0, "N_TAGGER"); ++i)
0559 {
0560 os << " 0x" << setw(4) << hex << lValue(i, "TAGGER_TYPE") << dec
0561 << " (" << (lValue(i, "IS_ENDAT") ? "ENDAT" : "") << (lValue(i, "IS_LEVEL1_TRIGGER") ? "LVL1 " : "")
0562 << ") "
0563 << setw(12) << hex << lValue(i, "BCO") << dec << " "
0564 << setw(10) << lValue(i, "LEVEL1_COUNT") << " "
0565 << setw(10) << lValue(i, "ENDAT_COUNT") << " "
0566 << setw(12) << hex << lValue(i, "LAST_BCO") << dec
0567 << " 0x" << std::setfill('0') << setw(2) << hex << lValue(i, "MODEBITS") << std::setfill(' ')<< dec
0568 << endl;
0569 }
0570
0571 os << endl;
0572 }
0573
0574 os << " number of waveforms " << iValue(0, "NR_WF") << endl;
0575
0576 for ( int i = 0; i < iValue(0, "NR_WF") ; i++)
0577 {
0578 os << " FEE Channel Sampachannel Samples BCO CRC_ERR" << endl;
0579
0580 os << setw(5) << iValue(i, "FEE") << " "
0581 << setw(9) << iValue(i, "CHANNEL") << " "
0582 << setw(9) << iValue(i, "SAMPACHANNEL") << " "
0583 << setw(12) << iValue(i, "SAMPLES") << " "
0584 << " 0x" << setw(5) << hex << iValue(i, "BCO") << dec
0585
0586 << setw(4) << iValue(i, "CHECKSUMERROR")
0587 << endl;
0588
0589 for (int j = 0; j < iValue(i, "SAMPLES") ; j += 10)
0590 {
0591 os << " ";
0592 for (int k = 0; k < 10 ; k++)
0593 {
0594 os << setw(4) << iValue(i,j+k) << " ";
0595 }
0596 os << endl;
0597 }
0598 os << endl;
0599
0600 }
0601 }
0602
0603
0604
0605 unsigned short oncsSub_idtpcfeev3::reverseBits(const unsigned short x) const
0606 {
0607 unsigned short n = x;
0608 n = ((n >> 1) & 0x55555555) | ((n << 1) & 0xaaaaaaaa);
0609 n = ((n >> 2) & 0x33333333) | ((n << 2) & 0xcccccccc);
0610 n = ((n >> 4) & 0x0f0f0f0f) | ((n << 4) & 0xf0f0f0f0);
0611 n = ((n >> 8) & 0x00ff00ff) | ((n << 8) & 0xff00ff00);
0612
0613 return n;
0614 }
0615
0616
0617
0618 unsigned short oncsSub_idtpcfeev3::crc16(const unsigned int fee, const unsigned int index, const int l) const
0619 {
0620
0621 unsigned short crc = 0xffff;
0622
0623 for ( int i = 0; i < l; i++)
0624 {
0625 unsigned short x = fee_data[fee][index+i];
0626
0627 crc ^= reverseBits( x);
0628 for (unsigned short k = 0; k < 16; k++)
0629 {
0630 crc = crc & 1 ? (crc >> 1) ^ 0xa001 : crc >> 1;
0631 }
0632 }
0633 crc = reverseBits(crc);
0634 return crc;
0635 }
0636