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