File indexing completed on 2025-08-03 08:20:48
0001 #include "oncsSub_idmvtxv1.h"
0002 #include <cstring>
0003 #include <bitset>
0004 #include <map>
0005 #include <vector>
0006
0007 #include <arpa/inet.h>
0008
0009 using namespace std;
0010
0011 oncsSub_idmvtxv1::oncsSub_idmvtxv1(subevtdata_ptr data)
0012 :oncsSubevent_w4 (data)
0013 {
0014 _is_decoded = 0;
0015 _highest_ruid = -1;
0016 for (int ruid=0; ruid<IDMVTXV1_MAXRUID+1; ruid++)
0017 {
0018 _bad_ruchns[ruid] = 0;
0019 _lanes_active[ruid] = -1;
0020 _lane_stops[ruid] = -1;
0021 _lane_timeouts[ruid] = -1;
0022 for ( int ruchn = 0; ruchn < IDMVTXV1_MAXRUCHN+1; ruchn++)
0023 {
0024 _chip_id[ruid][ruchn] = -1;
0025 _bad_bytes[ruid][ruchn] = 0;
0026 _excess_bytes[ruid][ruchn] = 0;
0027 _bunchcounter[ruid][ruchn] = -1;
0028 _header_found[ruid][ruchn] = false;
0029 _trailer_found[ruid][ruchn] = false;
0030 _readout_flags[ruid][ruchn] = -1;
0031 }
0032 }
0033 _unexpected_felix_counters = 0;
0034 _bad_ruids = 0;
0035 }
0036
0037 oncsSub_idmvtxv1::~oncsSub_idmvtxv1()
0038 {
0039
0040 }
0041
0042
0043 typedef struct
0044 {
0045 unsigned char d0[3][10];
0046 unsigned char counter;
0047 unsigned char ruid;
0048 } data32;
0049
0050 #define CHIPHEADER 1
0051 #define CHIPEMPTYFRAME 2
0052 #define DATASHORT 3
0053 #define DATALONG0 4
0054 #define DATALONG1 5
0055
0056 int oncsSub_idmvtxv1::decode_thebit(int the_row, int encoder_id, int address) const
0057 {
0058
0059
0060
0061
0062
0063 int is_an_odd_row = the_row & 1;
0064 int thebit;
0065 if ( is_an_odd_row)
0066 {
0067 thebit = (encoder_id*2) + ( ( address &1) ^ 1 );
0068 }
0069 else
0070 {
0071 thebit = (encoder_id*2) + ( address&1);
0072 }
0073 return thebit;
0074 }
0075
0076 void oncsSub_idmvtxv1::print_stuff(OSTREAM& out, unsigned int data, int width, int shift, bool blank) const
0077 {
0078 unsigned int mask = 0xffffffff;
0079 if (width<8) mask = ((1 << width*4)-1);
0080 if (blank)
0081 for (int i=0;i<width;i++) out << " ";
0082 else
0083 out << std::hex << SETW(width) << std::setfill('0') << ((data>>shift) & mask);
0084 }
0085
0086 int oncsSub_idmvtxv1::encode_hit(unsigned short row, unsigned short col) const
0087 {
0088 return (row << 16) + col;
0089 }
0090
0091 unsigned short oncsSub_idmvtxv1::decode_row(int hit) const
0092 {
0093 return hit >> 16;
0094 }
0095
0096 unsigned short oncsSub_idmvtxv1::decode_col(int hit) const
0097 {
0098 return hit & 0xffff;
0099 }
0100
0101 bool oncsSub_idmvtxv1::mask_contains_ruchn ( int mask, int ruchn )
0102 {
0103 if (ruchn<=0) return false;
0104 if (mask<0) return false;
0105 return (((mask >> (ruchn-1)) & 1) == 1);
0106 }
0107
0108 int *oncsSub_idmvtxv1::mvtx_decode ()
0109 {
0110 if ( _is_decoded) return 0;
0111 _is_decoded = 1;
0112
0113 unsigned int *payload = (unsigned int *) &SubeventHdr->data;
0114
0115 int dlength = getDataLength() - getPadding() - 1;
0116 unsigned char *the_end = ( unsigned char *) &payload[dlength];
0117
0118 unsigned char *pos = (unsigned char *) payload;
0119
0120 unsigned char b;
0121
0122 vector<unsigned char> ruchn_stream[IDMVTXV1_MAXRUID+1][IDMVTXV1_MAXRUCHN+1];
0123
0124 unsigned char felix_counter [IDMVTXV1_MAXRUID+1];
0125
0126 for( int i=0; i < IDMVTXV1_MAXRUID+1; i++)
0127 {
0128 felix_counter[i] = 0;
0129 }
0130
0131 while ( pos < the_end )
0132 {
0133
0134 data32 *d32 = ( data32*) pos;
0135
0136
0137 if (d32->ruid > IDMVTXV1_MAXRUID)
0138 {
0139 cout << __FILE__ << " " << __LINE__ << " --- invalid ruid " << hex << (int) d32->ruid << " at pos " << (long) pos << dec << endl;
0140 _bad_ruids++;
0141 break;
0142 }
0143 else if (d32->ruid > _highest_ruid)
0144 {
0145 _highest_ruid = d32->ruid;
0146 }
0147
0148
0149 int counter_increment = (d32->counter + 256 - felix_counter[d32->ruid])%256;
0150 if (counter_increment > 3)
0151 {
0152 if (d32->counter != 0)
0153 {
0154
0155 _unexpected_felix_counters++;
0156 }
0157 break;
0158 }
0159 felix_counter[d32->ruid] = d32->counter;
0160
0161
0162 for (int ichnk = 0; ichnk < counter_increment; ichnk++)
0163 {
0164 unsigned char ruchn = d32->d0[ichnk][9];
0165 if (ruchn == IDMVTXV1_RUHEADER)
0166 {
0167 memcpy(&_lanes_active[d32->ruid],&d32->d0[ichnk][2],4);
0168 }
0169 else if (ruchn == IDMVTXV1_RUTRAILER)
0170 {
0171 memcpy(&_lane_stops[d32->ruid],&d32->d0[ichnk][0],4);
0172 memcpy(&_lane_timeouts[d32->ruid],&d32->d0[ichnk][4],4);
0173 }
0174 else if (ruchn > IDMVTXV1_MAXRUCHN)
0175 {
0176 _bad_ruchns[d32->ruid]++;
0177 cout << __FILE__ << " " << __LINE__ << " --- invalid ruchn " << hex << ruchn << ", full RU word: ";
0178 for (int ibyte=9;ibyte>=0;ibyte--)
0179 {
0180 cout << setfill('0') << setw(2) << hex << (unsigned int) d32->d0[ichnk][ibyte] << " ";
0181 }
0182 cout << setfill(' ') << setw(0) << dec << endl;
0183 }
0184 else for ( int ibyte = 0; ibyte < 9; ibyte++)
0185 {
0186
0187 ruchn_stream[d32->ruid][ruchn].push_back(d32->d0[ichnk][ibyte]);
0188 }
0189 }
0190
0191 pos += sizeof(*d32);
0192 }
0193
0194
0195
0196
0197
0198
0199
0200
0201
0202 for ( int ruid = 1; ruid < IDMVTXV1_MAXRUID+1; ruid++)
0203 {
0204 for ( int ruchn = 1; ruchn < IDMVTXV1_MAXRUCHN+1; ruchn++)
0205 {
0206
0207 bool header_seen=false;
0208 int status = 0;
0209 int ibyte_endofdata = -1;
0210 int the_region = -1;
0211 unsigned int address = 0;
0212 unsigned int encoder_id = 0;
0213 for (unsigned int ibyte = 0; ibyte < ruchn_stream[ruid][ruchn].size(); ibyte++)
0214 {
0215 b = ruchn_stream[ruid][ruchn].at(ibyte);
0216
0217
0218
0219 if (status)
0220
0221 {
0222 switch (status)
0223 {
0224 case CHIPHEADER:
0225
0226 _bunchcounter[ruid][ruchn] = b;
0227
0228 status = 0;
0229 _header_found[ruid][ruchn] = true;
0230 break;
0231
0232 case CHIPEMPTYFRAME:
0233
0234 _bunchcounter[ruid][ruchn] = b;
0235
0236 ibyte_endofdata = ibyte;
0237 _header_found[ruid][ruchn] = true;
0238 _trailer_found[ruid][ruchn] = true;
0239 status = 0;
0240 break;
0241
0242 case DATASHORT:
0243 address += b;
0244
0245 if ( the_region >= 0 && encoder_id >=0 )
0246 {
0247 int the_row = (address >> 1);
0248 if ( the_row > 511)
0249 {
0250 cout << __FILE__ << " " << __LINE__ << " impossible row: " << the_row
0251 << " encoder " << encoder_id << " addr " << address << endl;
0252 }
0253 else
0254 {
0255 int thebit = decode_thebit(the_row, encoder_id, address);
0256
0257
0258 unsigned short col = the_region*32 + thebit;
0259 _hit_vectors[ruid][ruchn].push_back(encode_hit(the_row,col));
0260 }
0261 }
0262
0263
0264 status = 0;
0265 break;
0266
0267 case DATALONG0:
0268 address += b;
0269 status = DATALONG1;
0270 break;
0271
0272 case DATALONG1:
0273 if ( (b & 0x80) != 0)
0274 {
0275
0276 _bad_bytes[ruid][ruchn]++;
0277 }
0278
0279
0280
0281
0282 for (int ihit = 0; ihit<8; ihit++)
0283 {
0284 if (ihit==0 || ((b >> (ihit-1)) & 1))
0285 {
0286 int hit_address = address + ihit;
0287 if ( the_region >= 0 && encoder_id >=0 )
0288 {
0289 int the_row = (hit_address >> 1);
0290 if ( the_row > 511)
0291 {
0292 cout << __FILE__ << " " << __LINE__ << " impossible row: " << the_row
0293 << " encoder " << encoder_id << " addr " << hit_address << endl;
0294 }
0295 else
0296 {
0297 int thebit = decode_thebit(the_row, encoder_id, hit_address);
0298
0299
0300 unsigned short col = the_region*32 + thebit;
0301 _hit_vectors[ruid][ruchn].push_back(encode_hit(the_row,col));
0302 }
0303 }
0304 }
0305 }
0306 status = 0;
0307 break;
0308 }
0309 continue;
0310 }
0311
0312 if (ibyte_endofdata != -1) break;
0313
0314 if ( b == 0xff)
0315 {
0316
0317 status = 0;
0318 }
0319
0320 else if ( ( b >> 4) == 0xa)
0321 {
0322 _chip_id[ruid][ruchn] = ( b & 0xf);
0323 header_seen = true;
0324 status = CHIPHEADER;
0325 }
0326
0327 else if ( ( b >> 4) == 0xb)
0328 {
0329
0330
0331 ibyte_endofdata = ibyte;
0332 _trailer_found[ruid][ruchn] = true;
0333 if (!_header_found[ruid][ruchn])
0334 {
0335 _bad_bytes[ruid][ruchn]++;
0336 }
0337 else
0338 {
0339 _readout_flags[ruid][ruchn] = (b & 0xf);
0340 }
0341 break;
0342 }
0343
0344 else if ( ( b >> 4) == 0xE)
0345 {
0346 _chip_id[ruid][ruchn] = ( b & 0xf);
0347 header_seen = true;
0348 status = CHIPEMPTYFRAME;
0349 }
0350
0351 else if ( ( b >> 5) == 0x6)
0352 {
0353 unsigned int region_id = (b & 0x1f);
0354 if ( region_id <32)
0355 {
0356 the_region = region_id;
0357 }
0358 else
0359 {
0360 cout << __FILE__ << " " << __LINE__ << " wrong region header, id= " << hex << region_id << dec << endl;
0361 }
0362 }
0363
0364 else if ( ( b >> 6) == 0x1)
0365 {
0366 encoder_id = ( b>>2) & 0xf;
0367 address = (b & 0x3) << 8;
0368 status = DATASHORT;
0369 }
0370
0371 else if ( ( b >> 6) == 0x0)
0372 {
0373 encoder_id = ( b>>2) & 0xf;
0374 address = (b & 0x3) << 8;
0375 status = DATALONG0;
0376 }
0377
0378 else if ( b == 0xF1)
0379 {
0380
0381 }
0382
0383 else if ( b == 0xF0)
0384 {
0385
0386 }
0387
0388 else
0389 {
0390
0391 _bad_bytes[ruid][ruchn]++;
0392 }
0393 if (ibyte==0 && !header_seen) break;
0394
0395 }
0396
0397
0398 for (unsigned int ibyte = ibyte_endofdata+1; ibyte < ruchn_stream[ruid][ruchn].size(); ibyte++)
0399 {
0400 b = ruchn_stream[ruid][ruchn].at(ibyte);
0401 if (b!=0)
0402 {
0403
0404 _excess_bytes[ruid][ruchn]++;
0405 }
0406 }
0407 }
0408 }
0409
0410
0411 return 0;
0412 }
0413
0414 int oncsSub_idmvtxv1::iValue(const int ruid, const char *what)
0415 {
0416
0417 if ( strcmp(what,"MAXRUID") == 0 )
0418 {
0419 return IDMVTXV1_MAXRUID;
0420 }
0421 else if ( strcmp(what,"MAXRUCHN") == 0 )
0422 {
0423 return IDMVTXV1_MAXRUCHN;
0424 }
0425
0426
0427 mvtx_decode();
0428
0429 if ( strcmp(what,"UNEXPECTED_FELIX_COUNTERS") == 0 )
0430 {
0431 return _unexpected_felix_counters;
0432 }
0433
0434 else if ( strcmp(what,"BAD_RUIDS") == 0 )
0435 {
0436 return _bad_ruids;
0437 }
0438
0439 if (ruid > _highest_ruid) return -1;
0440 if (_lanes_active[ruid]==-1) return -1;
0441
0442 if ( strcmp(what,"BAD_RUCHNS") == 0 )
0443 {
0444 return _bad_ruchns[ruid];
0445 }
0446
0447 else if ( strcmp(what,"LANE_STOPS") == 0 )
0448 {
0449 return _lane_stops[ruid];
0450 }
0451
0452 else if ( strcmp(what,"LANE_TIMEOUTS") == 0 )
0453 {
0454 return _lane_timeouts[ruid];
0455 }
0456
0457 return 0;
0458 }
0459
0460 int oncsSub_idmvtxv1::iValue(const int ruid)
0461 {
0462 mvtx_decode();
0463
0464 if (ruid > _highest_ruid) return -1;
0465 return _lanes_active[ruid];
0466 }
0467
0468 int oncsSub_idmvtxv1::iValue(const int ruid, const int ruchn, const char *what)
0469 {
0470 mvtx_decode();
0471
0472 if (ruid > _highest_ruid) return -1;
0473 if (_lanes_active[ruid]==-1) return -1;
0474
0475 if ( strcmp(what,"CHIP_ID") == 0 )
0476 {
0477 return _chip_id[ruid][ruchn];
0478 }
0479
0480 else if ( strcmp(what,"BAD_BYTES") == 0 )
0481 {
0482 return _bad_bytes[ruid][ruchn];
0483 }
0484
0485 else if ( strcmp(what,"EXCESS_BYTES") == 0 )
0486 {
0487 return _excess_bytes[ruid][ruchn];
0488 }
0489
0490 else if ( strcmp(what,"BUNCHCOUNTER") == 0 )
0491 {
0492 return _bunchcounter[ruid][ruchn];
0493 }
0494
0495 else if ( strcmp(what,"HEADER_FOUND") == 0 )
0496 {
0497 return _header_found[ruid][ruchn]?1:0;
0498 }
0499
0500 else if ( strcmp(what,"TRAILER_FOUND") == 0 )
0501 {
0502 return _trailer_found[ruid][ruchn]?1:0;
0503 }
0504
0505 else if ( strcmp(what,"READOUT_FLAGS") == 0 )
0506 {
0507 return _readout_flags[ruid][ruchn];
0508 }
0509
0510 return 0;
0511 }
0512
0513 int oncsSub_idmvtxv1::iValue(const int ruid, const int ruchn)
0514 {
0515 mvtx_decode();
0516
0517 if (ruid > _highest_ruid) return -1;
0518 if (_lanes_active[ruid]==-1) return -1;
0519 if (!mask_contains_ruchn(_lanes_active[ruid],ruchn)) return -1;
0520 return _hit_vectors[ruid][ruchn].size();
0521 }
0522
0523 int oncsSub_idmvtxv1::iValue(const int ruid, const int ruchn, const int i)
0524 {
0525 mvtx_decode();
0526
0527 if (ruid > _highest_ruid) return -1;
0528 if (_lanes_active[ruid]==-1) return -1;
0529 if (!mask_contains_ruchn(_lanes_active[ruid],ruchn)) return -1;
0530 return _hit_vectors[ruid][ruchn].at(i);
0531 }
0532
0533 void oncsSub_idmvtxv1::dump ( OSTREAM& os )
0534 {
0535
0536 identify(os);
0537
0538 mvtx_decode();
0539 bool first;
0540 for (int ruid=0; ruid<IDMVTXV1_MAXRUID+1; ruid++)
0541 {
0542 if (iValue(ruid)!=-1)
0543 {
0544 os << "RU ID: " << ruid;
0545 os << ", bad_ruchns=" << iValue(ruid,"BAD_RUCHNS");
0546 os << hex << setfill('0');
0547 os << ", lanes_active 0x" << setw(7) << iValue(ruid);
0548 os << dec;
0549 first=true;
0550 os << " (";
0551 for ( int ruchn = 0; ruchn < IDMVTXV1_MAXRUCHN+1; ruchn++)
0552 {
0553 if (mask_contains_ruchn(iValue(ruid),ruchn))
0554 {
0555 if (!first)
0556 os << ", ";
0557 os << ruchn;
0558 first = false;
0559 }
0560 }
0561 os << hex << setfill('0');
0562 os << "), lane_stops=0x" << setw(7) << iValue(ruid,"LANE_STOPS");
0563 os << dec;
0564 first=true;
0565 os << " (";
0566 for ( int ruchn = 0; ruchn < IDMVTXV1_MAXRUCHN+1; ruchn++)
0567 {
0568 if (mask_contains_ruchn(iValue(ruid,"LANE_STOPS"),ruchn))
0569 {
0570 if (!first)
0571 os << ", ";
0572 os << ruchn;
0573 first = false;
0574 }
0575 }
0576 os << hex << setfill('0');
0577 os << "), lane_timeouts=0x" << setw(7) << iValue(ruid,"LANE_TIMEOUTS");
0578 os << dec;
0579 first=true;
0580 os << " (";
0581 for ( int ruchn = 0; ruchn < IDMVTXV1_MAXRUCHN+1; ruchn++)
0582 {
0583 if (mask_contains_ruchn(iValue(ruid,"LANE_TIMEOUTS"),ruchn))
0584 {
0585 if (!first)
0586 os << ", ";
0587 os << ruchn;
0588 first = false;
0589 }
0590 }
0591 os << ")";
0592 os << dec << setfill(' ') << endl;
0593 for ( int ruchn = 0; ruchn < IDMVTXV1_MAXRUCHN+1; ruchn++)
0594 {
0595 if (iValue(ruid,ruchn)!=-1)
0596 {
0597 os << "RU channel " << setw(2) << ruchn;
0598 os << " bad_bytes=" << iValue(ruid,ruchn,"BAD_BYTES") << " excess_bytes=" << iValue(ruid,ruchn,"EXCESS_BYTES") <<" header_found=" << iValue(ruid,ruchn,"HEADER_FOUND") << " trailer_found=" << iValue(ruid,ruchn,"TRAILER_FOUND");
0599 os << " bunchcounter=" << setw(3) << iValue(ruid,ruchn,"BUNCHCOUNTER") << " flags=" << iValue(ruid,ruchn,"READOUT_FLAGS");
0600 os << ", chip ID " << iValue(ruid,ruchn,"CHIP_ID") << ", " << iValue(ruid,ruchn) << " hits: ";
0601 for (int i=0;i<iValue(ruid,ruchn);i++)
0602 {
0603 int hit = iValue(ruid,ruchn,i);
0604 os << "(row " << decode_row(hit) << ", col " << decode_col(hit) << ") ";
0605 }
0606 os << endl;
0607 }
0608 }
0609 }
0610 }
0611 }
0612
0613
0614 void oncsSub_idmvtxv1::gdump(const int i, OSTREAM& out) const
0615 {
0616
0617 int *SubeventData = &SubeventHdr->data;
0618 unsigned int j;
0619 int l;
0620
0621 identify(out);
0622
0623 int current_offset;
0624 const int DWORDS_PER_WORD = 8;
0625
0626 switch (i)
0627 {
0628 case (EVT_HEXADECIMAL):
0629
0630 current_offset = 0;
0631 while (1)
0632 {
0633
0634 int dwords_remaining = getLength()-SEVTHEADERLENGTH - getPadding() - current_offset;
0635
0636 out << SETW(5) << current_offset << " | ";
0637
0638
0639
0640 print_stuff(out, SubeventData[current_offset+7], 4, 16, (dwords_remaining<=7));
0641 out << " ";
0642
0643
0644 print_stuff(out, SubeventData[current_offset+7], 4, 0, (dwords_remaining<=7));
0645 print_stuff(out, SubeventData[current_offset+6], 8, 0, (dwords_remaining<=6));
0646 print_stuff(out, SubeventData[current_offset+5], 8, 0, (dwords_remaining<=5));
0647 out << " ";
0648
0649
0650 print_stuff(out, SubeventData[current_offset+4], 8, 0, (dwords_remaining<=4));
0651 print_stuff(out, SubeventData[current_offset+3], 8, 0, (dwords_remaining<=3));
0652 print_stuff(out, SubeventData[current_offset+2], 4, 16, (dwords_remaining<=2));
0653 out << " ";
0654
0655
0656 print_stuff(out, SubeventData[current_offset+2], 4, 0, (dwords_remaining<=2));
0657 print_stuff(out, SubeventData[current_offset+1], 8, 0, (dwords_remaining<=1));
0658 print_stuff(out, SubeventData[current_offset+0], 8, 0, (dwords_remaining<=0));
0659 out << " " << std::dec << std::endl << std::setfill(' ');
0660
0661 if (dwords_remaining<8) break;
0662
0663 current_offset += DWORDS_PER_WORD;
0664 }
0665 break;
0666
0667 case (EVT_DECIMAL):
0668 j = 0;
0669 while (1)
0670 {
0671 out << std::dec << std::endl << SETW(5) << j << " | ";
0672
0673 for (l=0;l<6;l++)
0674 {
0675 out << SETW(10) << SubeventData[j++] << " ";
0676 if (j>=SubeventHdr->sub_length-SEVTHEADERLENGTH - SubeventHdr->sub_padding) break;
0677 }
0678 if (j>=SubeventHdr->sub_length-SEVTHEADERLENGTH - SubeventHdr->sub_padding) break;
0679 }
0680 break;
0681
0682 default:
0683 break;
0684 }
0685 out << std::endl;
0686
0687 }
0688