Back to home page

sPhenix code displayed by LXR

 
 

    


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

0001 #include "oncsSub_idtpcfeev3.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_idtpcfeev3::oncsSub_idtpcfeev3(subevtdata_ptr data)
0012   :oncsSubevent_w2 (data)
0013 {
0014 
0015  _is_decoded = 0;
0016  _last_requested_element = -1;  // impossible value to mark "unnused" 
0017  _last_requested_waveform = 0;
0018 }
0019 
0020 
0021 oncsSub_idtpcfeev3::~oncsSub_idtpcfeev3()
0022 {
0023 
0024   for (auto itr = waveforms.begin() ; itr  != waveforms.end() ; ++itr)
0025     {
0026       delete (*itr);
0027     }
0028   waveforms.clear();
0029   
0030   for (auto itr = waveform_vector.begin() ; itr  != waveform_vector.end() ; ++itr)
0031     {
0032       delete (*itr);
0033     }
0034   waveform_vector.clear();
0035   
0036   
0037   for (auto itr = gtm_data.begin() ; itr  != gtm_data.end() ; ++itr)
0038     {
0039       delete (*itr);
0040     }
0041   gtm_data.clear();
0042 
0043 }
0044 
0045 int oncsSub_idtpcfeev3::cacheIterator(const int n)
0046 {
0047   if ( n < 0) return 0; // not ok
0048   if ( _last_requested_element == n) return 1; // say "ok"
0049 
0050   unsigned i = n;
0051   if  ( i >= waveform_vector.size() )
0052     {
0053       _last_requested_element = -1;
0054       _last_requested_waveform = 0;
0055       return 0;
0056     }
0057 
0058   _last_requested_element = n;
0059   _last_requested_waveform = waveform_vector[n];  
0060 
0061   return 1;
0062 }
0063 
0064 int oncsSub_idtpcfeev3::decode_gtm_data(unsigned short dat[16])
0065 {
0066     unsigned char *gtm = (unsigned char *)dat;
0067     gtm_payload *payload = new gtm_payload;
0068 
0069     payload->pkt_type = gtm[0] | ((unsigned short)gtm[1] << 8);
0070     if (payload->pkt_type != GTM_LVL1_ACCEPT_MAGIC_KEY && payload->pkt_type != GTM_ENDAT_MAGIC_KEY)
0071       {
0072     delete payload;
0073     return -1;
0074       }
0075 
0076     payload->is_lvl1 = payload->pkt_type == GTM_LVL1_ACCEPT_MAGIC_KEY;
0077     payload->is_endat = payload->pkt_type == GTM_ENDAT_MAGIC_KEY;
0078 
0079     payload->bco = ((unsigned long long)gtm[2] << 0)
0080       | ((unsigned long long)gtm[3] << 8)
0081       | ((unsigned long long)gtm[4] << 16)
0082       | ((unsigned long long)gtm[5] << 24)
0083       | ((unsigned long long)gtm[6] << 32)
0084       | (((unsigned long long)gtm[7]) << 40);
0085     payload->lvl1_count = ((unsigned int)gtm[8] << 0)
0086       | ((unsigned int)gtm[9] << 8)
0087       | ((unsigned int)gtm[10] << 16)
0088       | ((unsigned int)gtm[11] << 24);
0089     payload->endat_count = ((unsigned int)gtm[12] << 0)
0090       | ((unsigned int)gtm[13] << 8)
0091       | ((unsigned int)gtm[14] << 16)
0092       | ((unsigned int)gtm[15] << 24);
0093     payload->last_bco = ((unsigned long long)gtm[16] << 0)
0094       | ((unsigned long long)gtm[17] << 8)
0095       | ((unsigned long long)gtm[18] << 16)
0096       | ((unsigned long long)gtm[19] << 24)
0097       | ((unsigned long long)gtm[20] << 32)
0098       | (((unsigned long long)gtm[21]) << 40);
0099     payload->modebits = gtm[22];
0100 
0101     this->gtm_data.push_back(payload);
0102 
0103     return 0;
0104 }
0105 
0106 int oncsSub_idtpcfeev3::tpc_decode ()
0107 {
0108 
0109   if (_is_decoded ) return 0;
0110   _is_decoded = 1;
0111 
0112   unsigned int payload_length = 2 * (getLength() - SEVTHEADERLENGTH - getPadding() );
0113   
0114   unsigned int index = 0;
0115   
0116 
0117   unsigned short *buffer = ( unsigned short *)  &SubeventHdr->data;
0118 
0119   // demultiplexer
0120   while (index < payload_length)
0121   {
0122     // Length for the 256-bit wide Round Robin Multiplexer for the data stream
0123     const unsigned int datalength = 0xf;
0124 
0125     if ((buffer[index] & 0xFF00) == FEE_MAGIC_KEY)
0126     {
0127 
0128       unsigned int fee_id = buffer[index] & 0xff;
0129       // coutfl << " index = " << index << " fee_id = " << fee_id << " len = " << datalength << endl;
0130       ++index;
0131       if (fee_id < MAX_FEECOUNT)
0132       {
0133         for (unsigned int i = 0; i < datalength; i++)
0134         {
0135           // watch out for any data corruption
0136           if (index >= payload_length) break;
0137 
0138           fee_data[fee_id].push_back(buffer[index++]);
0139         }
0140       }
0141     } else if ((buffer[index] & 0xFF00) == GTM_MAGIC_KEY) {
0142         unsigned short buf[16];
0143 
0144         // memcpy?
0145         for (unsigned int i = 0; i < 16; i++) {
0146             buf[i] = buffer[index++];
0147         }
0148 
0149         decode_gtm_data(buf);
0150     }
0151     else
0152     {
0153       // not FEE data, e.g. GTM data or other stream, to be decoded
0154       index += datalength + 1;
0155     }
0156 
0157   }
0158   //  coutfl << " done with tcp_decode index = " << index << endl;
0159 
0160   // std::vector<unsigned short>::const_iterator fee_data_itr;
0161 
0162   // for ( int ifee = 0 ; ifee < MAX_FEECOUNT ; ifee++)
0163   //   {
0164 
0165   //     coutfl << " starting with fee number " << ifee << " size of vector " << fee_data[ifee].size() << endl;
0166   //   }
0167   
0168   for ( int ifee = 0 ; ifee < MAX_FEECOUNT ; ifee++)
0169     {
0170       
0171       unsigned int pos;   // I'm too tired to play with iterators; pos is the position in a FEE vector
0172       
0173       //for ( fee_data_itr = fee_data[ifee].begin();  fee_data_itr != fee_data[ifee].end();  )
0174       for ( pos = 0; pos < fee_data[ifee].size() ;   ) 
0175     {
0176       // itr = fee_data_itr;
0177       int skip_amount = find_header (pos, fee_data[ifee]);
0178       if ( skip_amount < 0) break;
0179       //for ( int i = 0; i < skip_amount; i++) ++fee_data_itr;  // skip that many words
0180       pos +=  skip_amount;
0181 
0182       // as we advance pos, let's remember where the start is
0183       unsigned int startpos = pos;
0184 
0185       // first the check if our vector cuts off before the fixed-length header, then we are already done
0186       if ( startpos + HEADER_LENGTH >= fee_data[ifee].size() || startpos + fee_data[ifee][startpos] > fee_data[ifee].size())
0187         {
0188           pos = fee_data[ifee].size() + 1; // make sure we really terminate the loop
0189         }
0190       else
0191         {
0192           // capture the header so we can easier get the bit shift stuff
0193           unsigned short header[HEADER_LENGTH];
0194           for ( int i = 0; i < HEADER_LENGTH; i++ ) header[i] = (fee_data[ifee][pos++]) ;
0195 
0196           sampa_waveform *sw = new sampa_waveform;
0197       
0198           sw->fee           = ifee;
0199           sw->pkt_length    = header[0]; // this is indeed the number of 10-bit words + 5 in this packet
0200           sw->adc_length    = header[0]-5; // this is indeed the number of 10-bit words in this packet
0201           sw->sampa_address = (header[1] >> 5) & 0xf;
0202           sw->sampa_channel = header[1] & 0x1f;
0203           sw->channel       = header[1] & 0x1ff;
0204           sw->bx_timestamp  = ((header[3] & 0x1ff) << 11)
0205         | ((header[2] & 0x3ff) << 1)
0206         | (header[1] >> 9);   
0207 
0208           // now we add the actual waveform
0209          // unsigned short data_size = header[5] -1 ;
0210           short data_size_counter = header[0]-5;
0211 
0212           short actual_data_size = 0;
0213          //  coutfl << " Fee: " << ifee << " Sampa " << sw->sampa_address
0214          //      << " sampa channel: " << sw->sampa_channel
0215          //      << " channel: " << sw->channel
0216          //      << "  waveform length: " << data_size  << endl;
0217 
0218          // for (int i = 0 ; i < data_size ; i++)
0219           // First fill -100 for all time samples
0220           for (int i = 0 ; i < 1024 ; i++)
0221         {
0222           sw->waveform.push_back(65000);
0223 //      cout <<"Initializing waveform "<<i<<endl;
0224         }
0225 
0226           // Format is (N sample) (start time), (1st sample)... (Nth sample)
0227           //for (int i = 0 ; i < header[0]-5 ; i++)
0228           while(data_size_counter>0)
0229         {
0230           int nsamp = fee_data[ifee][pos++];
0231           int start_t = fee_data[ifee][pos++];
0232 
0233           data_size_counter-=2;
0234 
0235                   actual_data_size += nsamp;
0236                   actual_data_size += 2;
0237 
0238 // We decided to suppress errors (May 13, 2024)
0239 //        if(nsamp>data_size_counter){ cout<<"nsamp: "<<nsamp<<", size: "<<data_size_counter<<", format error"<<endl; break;}
0240 
0241           for (int j=0; j<nsamp;j++){
0242                       if(start_t+j<1024){ sw->waveform[start_t+j]= fee_data[ifee][pos++]; }
0243                       else { pos++; }
0244 //                   cout<<"data: "<< sw->waveform[start_t+j]<<endl;
0245               data_size_counter--;
0246 
0247           //
0248           // This line is inserted to accommodate the "wrong format issue", which is the
0249           // last sample from the data is missing. This issue should be fixed and eventually
0250           // the following two lines will be removed. Apr 30. by TS
0251           //
0252               if(data_size_counter==1) break;
0253             }
0254 //                  cout<<"data_size_counter: "<<data_size_counter<<" "<<endl;
0255               if(data_size_counter==1) break;
0256         }
0257 
0258 // We decided to suppress errors (May 13, 2024)
0259 //        if (data_size_counter<0) cout <<" error in datasize"<<endl;
0260 
0261 //              if(header[0]-5 != actual_data_size){ cout <<header[0]-5<<", "<<actual_data_size-1<<endl; cout<<"Error size"<<endl;}
0262           
0263           //
0264           // If the size defined by SAMPA is consitent with what the header says, we keep that data.
0265           //
0266               if(header[0]-5 == actual_data_size){
0267 // cout <<header[0]-5<<", "<<actual_data_size-1<<endl; cout<<"Error size"<<endl;
0268 
0269           // we calculate the checksum here because "pos" is at the right place
0270              unsigned short crc = crc16(ifee, startpos, header[0]-1);
0271           // coutfl << "fee " << setw(3) << sw->fee
0272           //         << " sampla channel " << setw(3) <<  sw->channel
0273           //         << " crc and value " << hex << setw(5) << crc << " " << setw(5) << fee_data[ifee][pos] << dec;
0274 //         if (  crc != fee_data[ifee][pos] ) cout << "  *********";
0275 
0276 //         if (  crc != fee_data[ifee][pos-1] ) cout << "crc: "<<crc<<", fee: "<<fee_data[ifee][pos-1]<<endl;
0277 
0278 //            if (  crc != fee_data[ifee][pos] ) cout << "crc: "<<crc<<", fee: "<<fee_data[ifee][pos]<<endl;
0279 
0280           
0281               sw->checksum = crc;
0282 
0283               sw->valid = ( crc == fee_data[ifee][pos]);
0284 
0285               waveforms.insert(sw);
0286            }
0287                else{ delete sw; }
0288         }
0289       
0290       //coutfl << "inserting at " << ifee*MAX_CHANNELS + sw->channel << " size is " << waveforms.size() << endl;
0291       //waveform_vector[ifee*MAX_CHANNELS + sw->channel].push_back(sw);
0292     }
0293     }
0294 
0295   auto it = waveforms.begin();
0296   for ( ; it != waveforms.end(); ++it)
0297     {
0298       waveform_vector.push_back( *it);
0299     }
0300   waveforms.clear();
0301   
0302   return 0;
0303 }
0304 
0305 long long oncsSub_idtpcfeev3::lValue(const int n, const char *what)
0306 {
0307   tpc_decode();
0308 
0309   const size_t i = n;
0310 
0311   if (strcmp(what, "N_TAGGER") == 0)  // the number of datasets
0312   {
0313     return gtm_data.size();
0314   }
0315 
0316   else if (strcmp(what, "TAGGER_TYPE") == 0 )
0317   {
0318     if (i < gtm_data.size())
0319     {
0320       return gtm_data[i]->pkt_type;
0321     }
0322   }
0323 
0324   else if (strcmp(what, "IS_ENDAT") == 0 )
0325   {
0326     if (i < gtm_data.size())
0327     {
0328       return gtm_data[i]->is_endat;
0329     }
0330   }
0331 
0332   else if (strcmp(what, "IS_LEVEL1_TRIGGER") == 0 )
0333   {
0334     if (i < gtm_data.size())
0335     {
0336       return gtm_data[i]->is_lvl1;
0337     }
0338   }
0339 
0340   else if (strcmp(what, "BCO") == 0 )
0341   {
0342     if (i < gtm_data.size())
0343     {
0344       return gtm_data[i]->bco;
0345     }
0346   }
0347 
0348   else if (strcmp(what, "LEVEL1_COUNT") == 0 )
0349   {
0350     if (i < gtm_data.size())
0351     {
0352       return gtm_data[i]->lvl1_count;
0353     }
0354   }
0355 
0356   else if (strcmp(what, "ENDAT_COUNT") == 0 )
0357   {
0358     if (i < gtm_data.size())
0359     {
0360       return gtm_data[i]->endat_count;
0361     }
0362   }
0363 
0364   else if (strcmp(what, "LAST_BCO") == 0 )
0365   {
0366     if (i < gtm_data.size())
0367     {
0368       return gtm_data[i]->last_bco;
0369     }
0370   }
0371 
0372   else if (strcmp(what, "MODEBITS") == 0 )
0373   {
0374     if (i < gtm_data.size())
0375     {
0376       return gtm_data[i]->modebits;
0377     }
0378   }
0379 
0380   return 0;
0381 }
0382 
0383 int oncsSub_idtpcfeev3::iValue(const int n, const int sample)
0384 {
0385   if ( n < 0) return 0;
0386   
0387   tpc_decode();
0388 
0389   if ( cacheIterator(n) )
0390     {
0391       unsigned int m = sample; 
0392       if ( m >= (_last_requested_waveform)->waveform.size() ) return 0;
0393       return (_last_requested_waveform)->waveform[m];
0394     }
0395   return 0;
0396 }
0397 
0398 
0399 
0400   
0401 
0402 int oncsSub_idtpcfeev3::iValue(const int n, const char *what)
0403 {
0404 
0405   tpc_decode();
0406 
0407   if ( strcmp(what,"NR_WF") == 0 )  // the number of datasets
0408   {
0409     return waveform_vector.size();
0410   }
0411 
0412   else if ( strcmp(what,"MAX_FEECOUNT") == 0 )
0413   {
0414     return MAX_FEECOUNT;
0415   }
0416 
0417   // see how many samples we have
0418   else if ( strcmp(what,"SAMPLES") == 0 )
0419     {
0420       if ( cacheIterator(n) )
0421     {
0422       return (int) (_last_requested_waveform)->waveform.size();
0423     }
0424       return 0;
0425     }
0426   
0427   else if ( strcmp(what,"FEE") == 0 )
0428     {
0429       if ( cacheIterator(n) )
0430     {
0431       return (int) (_last_requested_waveform)->fee;
0432     }
0433       return 0;
0434     }
0435   
0436   else if ( strcmp(what,"SAMPAADDRESS") == 0 )
0437     {
0438       if ( cacheIterator(n) )
0439     {
0440       return (int) (_last_requested_waveform)->sampa_address;
0441     }
0442       return 0;
0443     }
0444   
0445   else if ( strcmp(what,"SAMPACHANNEL") == 0 )
0446     {
0447       if ( cacheIterator(n) )
0448     {
0449       return (int) (_last_requested_waveform)->sampa_channel;
0450     }
0451       return 0;
0452     }
0453   
0454   else if ( strcmp(what,"CHANNEL") == 0 )
0455     {
0456       if ( cacheIterator(n) )
0457     {
0458       return (int) (_last_requested_waveform)->channel;
0459     }
0460       return 0;
0461     }
0462   
0463   else if ( strcmp(what,"BCO") == 0 )
0464     {
0465       if ( cacheIterator(n) )
0466     {
0467       return (int) (_last_requested_waveform)->bx_timestamp;
0468     }
0469       return 0;
0470     }
0471 
0472   else if ( strcmp(what,"CHECKSUM") == 0 )
0473     {
0474       if ( cacheIterator(n) )
0475     {
0476       return (int) (_last_requested_waveform)->checksum;
0477     }
0478       return 0;
0479     }
0480 
0481   else if ( strcmp(what,"CHECKSUMERROR") == 0 )
0482     {
0483       if ( cacheIterator(n) )
0484     {
0485       if ( (_last_requested_waveform)->valid ) return 0; 
0486       return 1;
0487     }
0488       return 0;
0489     }
0490 
0491   return 0;
0492   
0493 }
0494  
0495 //int oncsSub_idtpcfeev3::find_header ( std::vector<unsigned short>::const_iterator &itr,  const std::vector<unsigned short> &orig)
0496 int oncsSub_idtpcfeev3::find_header ( const unsigned int yy,  const std::vector<unsigned short> &orig)
0497 {
0498   bool found = false;
0499   unsigned int pos = yy;
0500   std::vector<unsigned short> header_candidate;
0501 
0502   // we slide over the data and find the header, if any.
0503   // we calculate and return the amount of words we need to skip to find the vector.
0504   // if we find it right away, the amount returned is 0;
0505   // -1 for an error condition or end, like we hit the end without finding another header.
0506   // the complication here is that we look ahead a few words to recognize it.  
0507   
0508   for ( unsigned int i = 0; i < HEADER_LENGTH ; i++)  // we start out with one "header candidate" = 7 entries
0509     {
0510       if ( pos >= orig.size())    // if we reached the end, no more header here
0511     {
0512       return -1;
0513     }
0514 
0515       header_candidate.push_back(orig[pos]);
0516       pos++;
0517     }
0518   
0519   int skip_amount = 0;
0520   while ( ! found)
0521     {
0522       //      coutfl << " current pos is  " << pos  << "  vector length " << orig.size()  << endl;
0523         
0524 //      if (header_candidate[4] == MAGIC_KEY_0 && header_candidate[6] == MAGIC_KEY_1 && (header_candidate[0] - header_candidate[5] == HEADER_LENGTH))
0525       if (header_candidate[4] == MAGIC_KEY_0)
0526     {
0527       // found it!
0528             found = true;
0529         //    coutfl << " found header skip value =  " << skip_amount << endl;
0530             break;
0531         }
0532       skip_amount++;
0533       if ( pos >= orig.size())    // if we reached the end, no more header here
0534     {
0535       return -1;
0536     }
0537 
0538       //   coutfl << " next value " << pos << "  " << hex << orig[pos]  << dec << endl;
0539       header_candidate.erase(header_candidate.begin());  // delete the vector 1st element
0540       header_candidate.push_back(orig[pos]);                  // push a new value, rinse and repeat
0541       pos++;
0542     }
0543 
0544   return skip_amount;
0545 }
0546  
0547 void  oncsSub_idtpcfeev3::dump ( OSTREAM& os )
0548 {
0549   tpc_decode();
0550   identify(os);
0551 
0552   if (lValue(0, "N_TAGGER") == 0)
0553     os << "  No lvl1 and Endat taggers" << endl;
0554   else
0555   {
0556     os << "  TAGGER_TYPE    BCO          LEVEL1 CNT  ENDAT CNT     LAST_BCO     MODEBITS" << endl;
0557 
0558     for (int i = 0; i < lValue(0, "N_TAGGER"); ++i)  // go through the datasets
0559     {
0560       os << "  0x" << setw(4) << hex << lValue(i, "TAGGER_TYPE") << dec
0561          << " (" << (lValue(i, "IS_ENDAT") ? "ENDAT" : "") << (lValue(i, "IS_LEVEL1_TRIGGER") ? "LVL1 " : "")
0562          << ") "
0563          << setw(12) << hex << lValue(i, "BCO") << dec << " "
0564          << setw(10) << lValue(i, "LEVEL1_COUNT") << " "
0565          << setw(10) << lValue(i, "ENDAT_COUNT") << " "
0566          << setw(12) << hex << lValue(i, "LAST_BCO") << dec
0567          << "     0x" << std::setfill('0') << setw(2) << hex << lValue(i, "MODEBITS") << std::setfill(' ')<< dec
0568          << endl;
0569     }
0570 
0571     os << endl;
0572   }
0573 
0574   os << " number of waveforms " << iValue(0, "NR_WF") << endl;
0575     
0576   for ( int i = 0; i < iValue(0, "NR_WF") ; i++) // go through the datasets
0577     {
0578       os << "  FEE   Channel   Sampachannel   Samples     BCO     CRC_ERR" << endl;
0579 
0580       os << setw(5) << iValue(i, "FEE")  << " "
0581      << setw(9) << iValue(i, "CHANNEL")  << " "
0582      << setw(9) << iValue(i, "SAMPACHANNEL")  << " "
0583      << setw(12) << iValue(i, "SAMPLES") << " "
0584      <<  "     0x" << setw(5) << hex << iValue(i, "BCO") << dec
0585     //   << " 0x" << setw(4) << hex << iValue(i, "CHECKSUM") << dec
0586      <<  setw(4) << iValue(i, "CHECKSUMERROR")
0587      << endl;
0588       
0589       for (int j = 0; j  < iValue(i, "SAMPLES") ; j += 10)
0590     {
0591       os << "                                                       ";
0592       for (int k = 0; k < 10 ; k++)
0593         {
0594           os << setw(4) << iValue(i,j+k)  << " ";
0595         }
0596       os << endl;
0597     }
0598       os << endl;
0599   
0600     }
0601 }
0602 
0603 
0604 
0605 unsigned short oncsSub_idtpcfeev3::reverseBits(const unsigned short x) const
0606 {
0607   unsigned short n = x;  
0608   n = ((n >> 1) & 0x55555555) | ((n << 1) & 0xaaaaaaaa);
0609   n = ((n >> 2) & 0x33333333) | ((n << 2) & 0xcccccccc);
0610   n = ((n >> 4) & 0x0f0f0f0f) | ((n << 4) & 0xf0f0f0f0);
0611   n = ((n >> 8) & 0x00ff00ff) | ((n << 8) & 0xff00ff00);
0612   //n = (n >> 16) & 0x0000ffff | (n << 16) & 0xffff0000;
0613   return n;
0614 }
0615 
0616 
0617 
0618 unsigned short oncsSub_idtpcfeev3::crc16(const unsigned int fee, const unsigned int index, const int  l) const 
0619 {
0620 
0621   unsigned short crc = 0xffff;
0622     
0623   for ( int i = 0; i < l; i++)
0624     {
0625       unsigned short x = fee_data[fee][index+i];
0626       //      cout << "in crc " << hex << x << dec << endl;
0627       crc ^= reverseBits( x);
0628       for (unsigned short k = 0; k < 16; k++)
0629     {
0630       crc = crc & 1 ? (crc >> 1) ^ 0xa001 : crc >> 1;
0631     }
0632       }
0633   crc = reverseBits(crc);
0634   return crc;
0635 }
0636