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