File indexing completed on 2025-08-03 08:20:49
0001 #include "oncsSub_idtpcfeev2.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_idtpcfeev2::oncsSub_idtpcfeev2(subevtdata_ptr data)
0012 :oncsSubevent_w2 (data)
0013 {
0014
0015 _is_decoded = 0;
0016
0017 for ( int i = 0; i < MAX_FEECOUNT; i++)
0018 {
0019 _max_samples[i] = 0;
0020 _lowest_bx[i] = 0;
0021 _highest_bx[i] = 0;
0022 }
0023 }
0024
0025
0026 oncsSub_idtpcfeev2::~oncsSub_idtpcfeev2()
0027 {
0028
0029
0030
0031
0032
0033 }
0034
0035
0036 #define HEADER_LENGTH 9
0037
0038 int oncsSub_idtpcfeev2::tpc_decode ()
0039 {
0040
0041 if (_is_decoded ) return 0;
0042 _is_decoded = 1;
0043
0044 unsigned int payload_length = 2 * (getLength() - SEVTHEADERLENGTH - getPadding() );
0045
0046 unsigned int index = 0;
0047
0048
0049 unsigned short *buffer = ( unsigned short *) &SubeventHdr->data;
0050
0051
0052
0053
0054
0055
0056
0057 while (buffer[index] != 0xfeee && buffer[index+1] != 0xba5e)
0058 {
0059 index += 2;
0060 }
0061
0062 unsigned short word_count;
0063 unsigned short link_count;
0064 unsigned short link_enabled;
0065
0066
0067 int locked[16];
0068 for (int a = 0; a < 16; a++) locked[a] = 0;
0069
0070
0071 while ( index < payload_length)
0072 {
0073
0074 if (buffer[index] == 0xfeee && buffer[index+1] == 0xba5e)
0075 {
0076
0077 word_count = (buffer[index+2] >> 4) + 1;
0078 link_count = buffer[index+2] & 0xf;
0079 link_enabled = buffer[index+3];
0080
0081
0082
0083
0084
0085
0086
0087
0088 unsigned short offset_table[16] = {0};
0089
0090 int offset_idx = 0;
0091 for ( int bitcnt = 0 ; bitcnt < 16; bitcnt++)
0092 {
0093 if ( (link_enabled & (1 << bitcnt)) != 0)
0094 {
0095 offset_table[offset_idx] = bitcnt;
0096
0097
0098 offset_idx++;
0099 }
0100 }
0101
0102 int idx;
0103 int link;
0104
0105
0106 for (index += 4, idx=0; idx < word_count * link_count ; idx++, index++)
0107 {
0108 link = offset_table[idx % link_count];
0109 if (locked[link])
0110 {
0111
0112 fee_data[link].push_back(buffer[index]);
0113 }
0114 else if (buffer[index] == 0xfeed)
0115 {
0116 locked[link] = 1;
0117
0118 fee_data[link].push_back(buffer[index]);
0119 }
0120 }
0121
0122
0123
0124 }
0125 else
0126 {
0127 cout << __FILE__<< " " << __LINE__ << " corrupted FEE data missing 0xfeee 0xba5e marker. Stop further decoding "<< endl;
0128 break;
0129 }
0130
0131 }
0132
0133
0134
0135
0136
0137
0138 for ( int fee = 0; fee < MAX_FEECOUNT; fee++)
0139 {
0140
0141 unsigned int record_len = 0;
0142
0143 unsigned int channel;
0144 unsigned int sampa_addr;
0145 unsigned int bx_count;
0146
0147 unsigned int old_bxcount = 0;
0148 unsigned int first_bx = 0xffffff;
0149 unsigned int rollover_offset = 0;
0150
0151 for ( index = 0; index < fee_data[fee].size(); index += record_len + 2 )
0152 {
0153 if (index >= fee_data[fee].size() - HEADER_LENGTH) continue;
0154
0155 if ( fee_data[fee].at(index) != 0xfeed)
0156 {
0157
0158 while (index < fee_data[fee].size() - HEADER_LENGTH && fee_data[fee].at(index) != 0xfeed ) index++;
0159 }
0160
0161 if (index >= fee_data[fee].size() - HEADER_LENGTH) continue;
0162
0163 record_len = fee_data[fee].at(index+1);
0164 if ( index + record_len + 2 >= fee_data[fee].size()) break;
0165
0166
0167 channel = fee_data[fee].at(index+3) & 0x1f;
0168 sampa_addr = (fee_data[fee].at(index+3) >> 5) & 0xf;
0169 bx_count = (fee_data[fee].at(index+4) << 4) | (fee_data[fee].at(index+5) & 0xf);
0170
0171
0172
0173 if ( bx_count < old_bxcount )
0174 {
0175 rollover_offset += 0x100000;
0176
0177 }
0178 old_bxcount = bx_count;
0179
0180 if ( first_bx == 0xffffff )
0181 {
0182 first_bx = bx_count;
0183 }
0184
0185
0186
0187
0188
0189
0190
0191 unsigned short crc_value = crc16( fee, index, record_len+1);
0192 if ( index + record_len +1 >= fee_data[fee].size() )
0193 {
0194 cerrfl << "index out of range " << index + record_len + 1 << " " << fee_data[fee].size() << " record_len " << record_len << endl;
0195 }
0196 else
0197 {
0198 if ( crc_value != fee_data[fee].at(index + record_len +1) )
0199 {
0200
0201
0202
0203
0204 continue;
0205 }
0206 }
0207
0208 if ( channel >= 32 || sampa_addr > 7 )
0209 {
0210 cout << __FILE__<< " " << __LINE__ << " FEE " << fee
0211 << " illegal value, sampa address " << sampa_addr << " channel " << channel << endl;
0212 continue;
0213 }
0214
0215 unsigned int fee_channel = sampa_addr * 32 + channel;
0216
0217 for ( unsigned int s = HEADER_LENGTH; s < record_len +1; s++)
0218 {
0219 if ( index +s >= fee_data[fee].size() )
0220 {
0221 cerrfl << "index out of range " << index +s << " " << fee_data[fee].size() << " record_len " << record_len << endl;
0222 }
0223 else
0224 {
0225 tpc_sample x = { bx_count + s -HEADER_LENGTH + rollover_offset - first_bx,
0226 bx_count,
0227 fee_data[fee].at(index + s ) };
0228 fee_samples[fee][fee_channel].push_back(x);
0229 }
0230 }
0231
0232 }
0233 }
0234
0235
0236
0237
0238
0239 unsigned int maxvectorsize;
0240 for ( int fee = 0; fee < MAX_FEECOUNT; fee++)
0241 {
0242 maxvectorsize = 0;
0243 for ( int ch = 0; ch < MAX_FEECHANNELS; ch++)
0244 {
0245 if ( fee_samples[fee][ch].size() > maxvectorsize ) maxvectorsize = fee_samples[fee][ch].size();
0246 unsigned int s = fee_samples[fee][ch].size();
0247 if ( s > 0 )
0248 {
0249 if ( fee_samples[fee][ch].at(0).bx_time < _lowest_bx[fee] ) _lowest_bx[fee] = fee_samples[fee][ch].at(0).bx_time;
0250 if ( fee_samples[fee][ch].at(s-1).bx_time > _highest_bx[fee] ) _highest_bx[fee] = fee_samples[fee][ch].at(s-1).bx_time;
0251 }
0252 }
0253 _max_samples[fee] = maxvectorsize;
0254 }
0255
0256
0257 return 0;
0258 }
0259
0260
0261
0262 int oncsSub_idtpcfeev2::iValue(const int fee, const int sample)
0263 {
0264 tpc_decode();
0265
0266 return 0;
0267 }
0268
0269 int oncsSub_idtpcfeev2::iValue(const int fee, const int ch, const int sample)
0270 {
0271 tpc_decode();
0272 if ( fee > MAX_FEECOUNT ||
0273 ch < 0 || ch >= MAX_FEECHANNELS ||
0274 sample < 0 || (unsigned int) sample >= fee_samples[fee][ch].size() ) return 0;
0275
0276
0277 return fee_samples[fee][ch].at(sample).adc;
0278
0279 }
0280
0281 int oncsSub_idtpcfeev2::iValue(const int fee, const int ch, const int sample, const char *what)
0282 {
0283 tpc_decode();
0284
0285 if ( fee > MAX_FEECOUNT ||
0286 ch < 0 || ch >= MAX_FEECHANNELS ||
0287 sample < 0 || (unsigned int) sample >= fee_samples[fee][ch].size() ) return 0;
0288
0289
0290 if ( strcmp(what,"BXRAW") == 0 )
0291 {
0292 return fee_samples[fee][ch].at(sample).bx_time_raw;
0293 }
0294 else if ( strcmp(what,"BX") == 0 )
0295 {
0296 return fee_samples[fee][ch].at(sample).bx_time;
0297 }
0298 return 0;
0299 }
0300
0301 int oncsSub_idtpcfeev2::iValue(const int fee, const int ch, const char *what)
0302 {
0303
0304 tpc_decode();
0305
0306 if ( strcmp(what,"NR_SAMPLES") == 0 )
0307 {
0308 if ( fee > MAX_FEECOUNT || ch < 0 || ch >= MAX_FEECHANNELS ) return 0;
0309 return fee_samples[fee][ch].size();
0310
0311 }
0312
0313 return 0;
0314 }
0315
0316
0317 int oncsSub_idtpcfeev2::iValue(const int n, const char *what)
0318 {
0319
0320 tpc_decode();
0321
0322 if ( strcmp(what,"MAX_SAMPLES") == 0 )
0323 {
0324 if ( n < 0 || n >= MAX_FEECOUNT ) return 0;
0325
0326 return _max_samples[n];
0327 }
0328
0329 else if ( strcmp(what,"IS_PRESENT") == 0 )
0330 {
0331 if ( n < 0 || n >= MAX_FEECOUNT ) return 0;
0332
0333 if (_max_samples[n] > 0) return 1;
0334 return 0;
0335 }
0336
0337 else if ( strcmp(what,"LOWEST_BX") == 0 )
0338 {
0339 if ( n < 0 || n >= MAX_FEECOUNT ) return 0;
0340
0341 return _lowest_bx[n];
0342 }
0343
0344 else if ( strcmp(what,"HIGHEST_BX") == 0 )
0345 {
0346 if ( n < 0 || n >= MAX_FEECOUNT ) return 0;
0347
0348 return _highest_bx[n];
0349 }
0350
0351 else if ( strcmp(what,"MAX_FEECOUNT") == 0 )
0352 {
0353 return MAX_FEECOUNT;
0354 }
0355
0356
0357 else if ( strcmp(what,"BROKEN") == 0 )
0358 {
0359 return _broken;
0360 }
0361
0362
0363 return 0;
0364
0365 }
0366
0367 void oncsSub_idtpcfeev2::dump ( OSTREAM& os )
0368 {
0369 identify(os);
0370
0371 os << "Samples: ";
0372 for ( int i = 0 ; i < iValue(0,"MAX_FEECOUNT"); i++)
0373 {
0374 os << setw(9) << iValue(i,"MAX_SAMPLES") << " ";
0375 }
0376 os << std::endl;
0377
0378 os << "Lowest BX: ";
0379 for ( int i = 0 ; i < iValue(0,"MAX_FEECOUNT"); i++)
0380 {
0381 os << setw(9) << (unsigned int) iValue(i,"LOWEST_BX") << " ";
0382 }
0383 os << std::endl;
0384
0385 os << "Highest BX: ";
0386 for ( int i = 0 ; i < iValue(0,"MAX_FEECOUNT"); i++)
0387 {
0388 os << setw(9) << (unsigned int) iValue(i,"HIGHEST_BX") << " ";
0389 }
0390 os << std::endl;
0391
0392
0393 const int dwidth = 16;
0394
0395 for ( int fee = 0; fee < iValue(0,"MAX_FEECOUNT") ; fee++)
0396 {
0397 for ( int chblock = 0; chblock < MAX_FEECHANNELS ; chblock+=dwidth)
0398 {
0399 if ( iValue (fee,"IS_PRESENT") )
0400 {
0401 cout << " +++++++++++++++ FEE " << fee << " channels " << chblock << " through " << chblock + dwidth << " ++++++++" << endl;
0402
0403
0404 os << setw(3) << "nrs" << " | " ;
0405 for ( int ch = chblock; ch < chblock + dwidth; ch++)
0406 {
0407 os << setw(10) << iValue(fee,ch, "NR_SAMPLES") << " " ;
0408 }
0409
0410 os << endl;
0411
0412
0413 for ( int s = 0; s < iValue(fee, "MAX_SAMPLES"); s++)
0414 {
0415
0416 os << setw(3) << s << " | " ;
0417 for ( int ch = chblock; ch < chblock + dwidth; ch++)
0418 {
0419 os << setw(6) << hex << iValue(fee,ch,s, "BX") << " " << setw(4) << iValue(fee,ch,s) << dec << " ";
0420
0421 }
0422
0423 os << endl;
0424 }
0425 os << endl;
0426 }
0427 }
0428
0429 }
0430 }
0431
0432 unsigned short oncsSub_idtpcfeev2::reverseBits(const unsigned short x) const
0433 {
0434 unsigned short n = x;
0435 n = ((n >> 1) & 0x55555555) | ((n << 1) & 0xaaaaaaaa);
0436 n = ((n >> 2) & 0x33333333) | ((n << 2) & 0xcccccccc);
0437 n = ((n >> 4) & 0x0f0f0f0f) | ((n << 4) & 0xf0f0f0f0);
0438 n = ((n >> 8) & 0x00ff00ff) | ((n << 8) & 0xff00ff00);
0439
0440 return n;
0441 }
0442
0443
0444
0445 unsigned short oncsSub_idtpcfeev2::crc16(const unsigned int fee, const unsigned int index, const int l) const
0446 {
0447 int len = l;
0448 int i = index;
0449 unsigned short crc = 0xffff;
0450
0451 while (len--)
0452 {
0453 unsigned short x = fee_data[fee].at(i++);
0454
0455 crc ^= reverseBits( x);
0456 for (unsigned short k = 0; k < 16; k++)
0457 {
0458 crc = crc & 1 ? (crc >> 1) ^ 0xa001 : crc >> 1;
0459 }
0460 }
0461 crc = reverseBits(crc);
0462 return crc;
0463 }
0464