Back to home page

sPhenix code displayed by LXR

 
 

    


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

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