Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2025-08-03 08:20:37

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   // for (int fee = 0; fee < MAX_FEECOUNT; fee++)
0029   //   {
0030   //     delete fee_data[fee];
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 //   for (int fee = 0; fee < MAX_FEECOUNT; fee++)
0053 //     {
0054 //       fee_data[fee] = new std::vector<unsigned short>();
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         // cout << __FILE__<< "  " << __LINE__ << " feeeba5e index at " << index
0082         //   << " word2 " << hex << buffer[index+2] << dec
0083         //   << " wordcount " << word_count
0084         //   << " link_count " << link_count
0085         //   << " link_enabled 0x" << hex << link_enabled << dec
0086         //   << endl;
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           // coutfl << "link_enabled " << hex << link_enabled << dec
0097           //     << " offset table " << offset_idx << " value " << bitcnt << endl;
0098           offset_idx++;
0099         }
0100         }
0101       
0102       int idx;
0103       int link;
0104         
0105       //        for (idx = index + 4; idx < index + 4 +  word_count * link_count ; idx++)
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           //coutfl << "pushing idx " << idx << " value " << hex << buffer[index] << dec << " into " << link << endl;
0112           fee_data[link].push_back(buffer[index]);
0113         }
0114           else if (buffer[index] == 0xfeed)
0115         {
0116           locked[link] = 1;
0117           //coutfl << "pushing idx " << idx << " value " << hex << buffer[index] << dec << " into " << link << " ** locking" << endl;
0118           fee_data[link].push_back(buffer[index]);
0119         }
0120         }
0121         
0122         // cout << __FILE__<< "  " << __LINE__ << " index " << index << " vector sizes " << fee_data[0].size()  << "  " << fee_data[1].size() << endl;
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   // here we are done unraveling the initil data structure.
0134   // We have now MAX_FEECOUNT * MAX_FEECHANNELS per-channel data structures in hand
0135 
0136   // first pass...
0137   
0138   for ( int fee = 0; fee < MAX_FEECOUNT; fee++)
0139     {
0140 
0141       unsigned int record_len  = 0;
0142       //unsigned int packet_type;
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         //  cerr << __FILE__<< "  " << __LINE__ << " FEE " << fee << " not starting with feed at " << index << " size " <<  fee_data[fee].size() << endl;
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         //packet_type = fee_data[fee].at(index+2);
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         //      coutfl << " bx " << bx_count << " delta to previous bx " << bx_count - old_bxcount << endl;
0173         if ( bx_count < old_bxcount )
0174           {
0175         rollover_offset += 0x100000;
0176         //      coutfl << " bx " << bx_count << " delta to previous bx " << bx_count - old_bxcount << " rollover " << hex << rollover_offset << endl;
0177           }
0178         old_bxcount = bx_count;
0179 
0180         if ( first_bx == 0xffffff )
0181           {
0182         first_bx = bx_count;
0183           }
0184         
0185         // if ( record_len != 0x88)
0186         //   {
0187         //  cerrfl << "wrong record length " << record_len << " fee " << fee << " channel " << channel << endl;
0188         //  //continue;
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         // cout << __FILE__<< "  " << __LINE__ << " FEE " << fee
0201         //      << " crc mismatch, index = " << index
0202         //      << " sampa address " << sampa_addr << " channel " << channel
0203         //      << " crc = " << hex << crc_value << " value " << fee_data[fee].at(index + record_len +1) << dec <<  endl;
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     // now, what is the max sample length per FEE?
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   //  if ( sample >= fee_samples[fee][ch].size() ) return 0;
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 )  // say if a FEE has been seen at all
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 )  // say if a FEE has been seen at all
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 )  // say if a FEE has been seen at all
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 )  // say if a FEE has been seen at all
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;  // how many colums to display
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           // print ithe smaple numbers
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   //n = (n >> 16) & 0x0000ffff | (n << 16) & 0xffff0000;
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       //      cout << "in crc " << hex << x << dec << endl;
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