Back to home page

sPhenix code displayed by LXR

 
 

    


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

0001 #include "oncsSub_idtpcfeev5.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_idtpcfeev5::oncsSub_idtpcfeev5(subevtdata_ptr data)
0012   :oncsSubevent_w2 (data)
0013 {}
0014 
0015 
0016 oncsSub_idtpcfeev5::~oncsSub_idtpcfeev5()
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   for (auto itr = current_vector.begin() ; itr  != current_vector.end() ; ++itr)
0032     {
0033       delete (*itr);
0034     }
0035   current_vector.clear();
0036   
0037   
0038   for (auto itr = gtm_data.begin() ; itr  != gtm_data.end() ; ++itr)
0039     {
0040       delete (*itr);
0041     }
0042   gtm_data.clear();
0043 
0044 }
0045 
0046 int oncsSub_idtpcfeev5::cacheIterator(const int n)
0047 {
0048   if ( n < 0) return 0; // not ok
0049   if ( _last_requested_element == n) return 1; // say "ok"
0050 
0051   unsigned i = n;
0052   if  ( i >= waveform_vector.size() )
0053     {
0054       _last_requested_element = -1;
0055       _last_requested_waveform = 0;
0056       return 0;
0057     }
0058 
0059   _last_requested_element = n;
0060   _last_requested_waveform = waveform_vector[n];  
0061 
0062   return 1;
0063 }
0064 
0065 int oncsSub_idtpcfeev5::DCcacheIterator(const int n)
0066 {
0067   if ( n < 0) return 0; // not ok
0068   if ( _last_requested_dcelement == n) return 1; // say "ok"
0069 
0070   unsigned i = n;
0071   if  ( i >= current_vector.size() )
0072     {
0073       _last_requested_dcelement = -1;
0074       _last_requested_currentform = 0;
0075       return 0;
0076     }
0077 
0078   _last_requested_dcelement = n;
0079   _last_requested_currentform = current_vector[n];  
0080 
0081   return 1;
0082 }
0083 
0084 int oncsSub_idtpcfeev5::decode_gtm_data(unsigned short dat[16])
0085 {
0086     unsigned char *gtm = (unsigned char *)dat;
0087     gtm_payload *payload = new gtm_payload;
0088 
0089     payload->pkt_type = gtm[0] | ((unsigned short)gtm[1] << 8);
0090 //    if (payload->pkt_type != GTM_LVL1_ACCEPT_MAGIC_KEY && payload->pkt_type != GTM_ENDAT_MAGIC_KEY)
0091     if (payload->pkt_type != GTM_LVL1_ACCEPT_MAGIC_KEY && payload->pkt_type != GTM_ENDAT_MAGIC_KEY && payload->pkt_type != GTM_MODEBIT_MAGIC_KEY)
0092       {
0093     delete payload;
0094     return -1;
0095       }
0096 
0097     payload->is_lvl1 = payload->pkt_type == GTM_LVL1_ACCEPT_MAGIC_KEY;
0098     payload->is_endat = payload->pkt_type == GTM_ENDAT_MAGIC_KEY;
0099     payload->is_modebit = payload->pkt_type == GTM_MODEBIT_MAGIC_KEY;
0100 
0101     payload->bco = ((unsigned long long)gtm[2] << 0)
0102       | ((unsigned long long)gtm[3] << 8)
0103       | ((unsigned long long)gtm[4] << 16)
0104       | ((unsigned long long)gtm[5] << 24)
0105       | ((unsigned long long)gtm[6] << 32)
0106       | (((unsigned long long)gtm[7]) << 40);
0107     payload->lvl1_count = ((unsigned int)gtm[8] << 0)
0108       | ((unsigned int)gtm[9] << 8)
0109       | ((unsigned int)gtm[10] << 16)
0110       | ((unsigned int)gtm[11] << 24);
0111     payload->endat_count = ((unsigned int)gtm[12] << 0)
0112       | ((unsigned int)gtm[13] << 8)
0113       | ((unsigned int)gtm[14] << 16)
0114       | ((unsigned int)gtm[15] << 24);
0115     payload->last_bco = ((unsigned long long)gtm[16] << 0)
0116       | ((unsigned long long)gtm[17] << 8)
0117       | ((unsigned long long)gtm[18] << 16)
0118       | ((unsigned long long)gtm[19] << 24)
0119       | ((unsigned long long)gtm[20] << 32)
0120       | (((unsigned long long)gtm[21]) << 40);
0121     payload->modebits = gtm[22];
0122     payload->userbits = gtm[23];
0123 
0124     this->gtm_data.push_back(payload);
0125 
0126     return 0;
0127 }
0128 
0129 int oncsSub_idtpcfeev5::tpc_gtm_decode()
0130 {
0131 
0132   if (_is_gtm_decoded ) return 0;
0133   _is_gtm_decoded = 1;
0134   NR_VALIDFEE=0;
0135 
0136   unsigned int payload_length = 2 * (getLength() - SEVTHEADERLENGTH - getPadding() );
0137 
0138   unsigned int index = 0;
0139 
0140   unsigned short *buffer = ( unsigned short *)  &SubeventHdr->data;
0141   std::bitset<26> fee_seen;
0142 
0143 
0144   // demultiplexer
0145   while (index < payload_length)
0146   {
0147     // this part is decoded in tpc_decode()
0148     // Length for the 256-bit wide Round Robin Multiplexer for the data stream
0149     const unsigned int datalength = 0xf;
0150 
0151     if ((buffer[index] & 0xFF00) == FEE_MAGIC_KEY)
0152     {
0153 
0154       unsigned int fee_id = buffer[index] & 0xff;
0155       if (!fee_seen[fee_id]) {
0156         fee_seen[fee_id] = true;
0157         NR_VALIDFEE++;
0158       }
0159       // coutfl << " index = " << index << " fee_id = " << fee_id << " len = " << datalength << endl;
0160       ++index;
0161       if (fee_id < MAX_FEECOUNT)
0162       {
0163         index += datalength;
0164       }
0165       if (index >= payload_length) break;
0166     }
0167     else if ((buffer[index] & 0xFF00) == GTM_MAGIC_KEY)
0168     {
0169       unsigned short buf[16];
0170 
0171       // memcpy?
0172       for (unsigned int i = 0; i < 16; i++)
0173       {
0174         buf[i] = buffer[index++];
0175       }
0176 
0177       decode_gtm_data(buf);
0178     }
0179     else
0180     {
0181       // not FEE data, e.g. GTM data or other stream, to be decoded
0182       index += datalength + 1;
0183     }
0184 
0185   }
0186   return 0;
0187 }
0188 
0189 int oncsSub_idtpcfeev5::tpc_decode ()
0190 {
0191 
0192   if (_is_decoded ) return 0;
0193   _is_decoded = 1;
0194 
0195   unsigned int payload_length = 2 * (getLength() - SEVTHEADERLENGTH - getPadding() );
0196   
0197   unsigned int index = 0;
0198   
0199 
0200   unsigned short *buffer = ( unsigned short *)  &SubeventHdr->data;
0201 
0202   // demultiplexer
0203   while (index < payload_length)
0204   {
0205     // Length for the 256-bit wide Round Robin Multiplexer for the data stream
0206     const unsigned int datalength = 0xf;
0207 
0208     if ((buffer[index] & 0xFF00) == FEE_MAGIC_KEY)
0209     {
0210 
0211       unsigned int fee_id = buffer[index] & 0xff;
0212       // coutfl << " index = " << index << " fee_id = " << fee_id << " len = " << datalength << endl;
0213       ++index;
0214       if (fee_id < MAX_FEECOUNT)
0215       {
0216         for (unsigned int i = 0; i < datalength; i++)
0217         {
0218           // watch out for any data corruption
0219           if (index >= payload_length) break;
0220 
0221           fee_data[fee_id].push_back(buffer[index++]);
0222         }
0223       }
0224     }
0225     else if ((buffer[index] & 0xFF00) == GTM_MAGIC_KEY)
0226     {
0227       index += 16; // decoded in tpc_gtm_decode()
0228     }
0229     else
0230     {
0231       // not FEE data, e.g. GTM data or other stream, to be decoded
0232       index += datalength + 1;
0233     }
0234 
0235   }
0236   //  coutfl << " done with tcp_decode index = " << index << endl;
0237 
0238   // std::vector<unsigned short>::const_iterator fee_data_itr;
0239 
0240   // for ( int ifee = 0 ; ifee < MAX_FEECOUNT ; ifee++)
0241   //   {
0242 
0243   //     coutfl << " starting with fee number " << ifee << " size of vector " << fee_data[ifee].size() << endl;
0244   //   }
0245   
0246   for ( int ifee = 0 ; ifee < MAX_FEECOUNT ; ifee++)
0247     {
0248       
0249       unsigned int pos;   // I'm too tired to play with iterators; pos is the position in a FEE vector
0250       
0251       //for ( fee_data_itr = fee_data[ifee].begin();  fee_data_itr != fee_data[ifee].end();  )
0252       for ( pos = 0; pos < fee_data[ifee].size() ;   ) 
0253     {
0254       // itr = fee_data_itr;
0255       int skip_amount = find_header (pos, fee_data[ifee]);
0256       if ( skip_amount < 0) break;
0257       //for ( int i = 0; i < skip_amount; i++) ++fee_data_itr;  // skip that many words
0258       pos +=  skip_amount;
0259 
0260       // as we advance pos, let's remember where the start is
0261       unsigned int startpos = pos;
0262 
0263       // first the check if our vector cuts off before the fixed-length header, then we are already done
0264       if ( startpos + HEADER_LENGTH >= fee_data[ifee].size() || startpos + fee_data[ifee][startpos] >= fee_data[ifee].size())
0265         {
0266           pos = fee_data[ifee].size() + 1; // make sure we really terminate the loop
0267         }
0268       else
0269         {
0270           // capture the header so we can easier get the bit shift stuff
0271           unsigned short header[HEADER_LENGTH]={0,0,0,0,0,0,0};
0272           for ( int i = 0; i < HEADER_LENGTH; i++ ) header[i] = (fee_data[ifee][pos++]) ;
0273 
0274           if(header[3]==MAGIC_KEY_2){
0275                   current_packet(header,ifee,startpos,pos);
0276               }
0277               else{
0278                   normal_packet(header,ifee,startpos,pos);
0279               }
0280         }
0281     }
0282     }
0283 
0284   waveform_vector.resize(waveforms.size());
0285   std::copy(waveforms.begin(),waveforms.end(),waveform_vector.begin());
0286   waveforms.clear();
0287 
0288   current_vector.resize(currentforms.size());
0289   std::copy(currentforms.begin(),currentforms.end(),current_vector.begin());
0290   currentforms.clear();
0291   
0292   return 0;
0293 }
0294 
0295 
0296 int oncsSub_idtpcfeev5::normal_packet(unsigned short header[],int ifee,unsigned int startpos,unsigned int pos)
0297 {
0298   sampa_waveform *sw = new sampa_waveform;
0299 
0300   sw->fee           = ifee;
0301   sw->pkt_length    = header[0]+1; // this is indeed the number of 10-bit words + 5 in this packet
0302   sw->adc_length    = header[0]-HEADER_LENGTH; // this is indeed the number of 10-bit words in this packet
0303   sw->data_parity   = header[4] >> 9;
0304   sw->sampa_address = (header[4] >> 5) & 0xf;
0305   sw->sampa_channel = header[4] & 0x1f;
0306   sw->channel       = header[4] & 0x1ff;
0307   sw->type          = (header[3] >>7) & 0x7;
0308   sw->user_word     = header[3] & 0x7f;
0309   sw->bx_timestamp  = ((header[6] & 0x3ff) << 10) | (header[5] & 0x3ff);
0310 
0311   // now we add the actual waveform
0312   // unsigned short data_size = header[5] -1 ;
0313   short data_size_counter = header[0]-HEADER_LENGTH;
0314 
0315   short actual_data_size = 0;
0316          //  coutfl << " Fee: " << ifee << " Sampa " << sw->sampa_address
0317          //      << " sampa channel: " << sw->sampa_channel
0318          //      << " channel: " << sw->channel
0319          //      << "  waveform length: " << data_size  << endl;
0320 
0321   // for (int i = 0 ; i < data_size ; i++)
0322   // First fill 65000 for all time samples
0323  
0324   sw->waveform.resize(1024);
0325   fill(sw->waveform.begin(), sw->waveform.end(), 65000);
0326  
0327   // Format is (N sample) (start time), (1st sample)... (Nth sample)
0328   //for (int i = 0 ; i < header[0]-5 ; i++)
0329 
0330   while(data_size_counter>0)
0331     {
0332       int nsamp = fee_data[ifee][pos++];
0333       int start_t = fee_data[ifee][pos++];
0334 
0335       data_size_counter-=2;
0336 
0337       actual_data_size += nsamp;
0338       actual_data_size += 2;
0339 
0340       for (int j=0; j<nsamp;j++){
0341           if (pos>= fee_data[ifee].size())
0342           {
0343             // std::cout<<__PRETTY_FUNCTION__<<" : warning - sampa data wavelet loss at the end of fee_data for fee "<<ifee<<std::endl;
0344             break;
0345           }
0346           if(start_t+j<1024){ sw->waveform[start_t+j]= fee_data[ifee][pos++]; }
0347           else { pos++; }
0348 //     cout<<"data: "<< sw->waveform[start_t+j]<<endl;
0349           data_size_counter--;
0350       }
0351       if (pos>= fee_data[ifee].size())
0352         {
0353           continue;
0354         }
0355     }
0356 
0357 // If the size defined by SAMPA is consitent with what the header says, we keep that data.
0358 //
0359   if(header[0]-HEADER_LENGTH == actual_data_size){
0360 // cout <<header[0]-5<<", "<<actual_data_size-1<<endl; cout<<"Error size"<<endl;
0361 
0362           // we calculate the checksum here because "pos" is at the right place
0363     unsigned short crc = crc16(ifee, startpos, header[0]);
0364     unsigned short parity = check_data_parity(ifee, startpos+HEADER_LENGTH, header[0]-HEADER_LENGTH);
0365           
0366     sw->checksum = crc;
0367 
0368     sw->valid = ( crc == fee_data[ifee][pos]);
0369     sw->parity_valid = ((!parity) == sw->data_parity); 
0370 
0371     waveforms.insert(sw);
0372   }
0373   else{ delete sw; }
0374 
0375   return 0;
0376 }
0377 
0378 
0379 int oncsSub_idtpcfeev5::current_packet(unsigned short header[],int ifee,unsigned int startpos, unsigned int pos)
0380 {
0381   digital_current *dc = new digital_current;
0382 
0383   dc->fee           = ifee;
0384   dc->pkt_length    = header[0]+1;
0385   dc->sampa_address = (header[4] >> 5) & 0xf;
0386   dc->sampa_max_channel = header[4] & 0x1f;
0387   dc->channel       = header[4] & 0x1ff;
0388   dc->type          = header[3];
0389 //  dc->bx_timestamp  = ((header[5] & 0xffff) << 4) | (header[6] & 0xf);
0390   dc->bx_timestamp  = ((header[6] & 0x3ff) << 10) | (header[5] & 0x3ff);
0391 //cout <<dc->fee<<" "<<hex<<dc->bx_timestamp<<dec<<endl;
0392 
0393   // now we add the actual waveform
0394   // unsigned short data_size = header[5] -1 ;
0395   short actual_data_size = 0;
0396   int ich=0;
0397 
0398   for(ich = 0; ich<8; ich++){
0399       dc->current[ich] = ((unsigned int)fee_data[ifee][pos])<<16 | ((unsigned int)fee_data[ifee][pos+1]);
0400       pos++; pos++;
0401       dc->nsamples[ich] = ((unsigned int)fee_data[ifee][pos])<<16 | ((unsigned int)fee_data[ifee][pos+1]);
0402       pos++; pos++;
0403 
0404       actual_data_size += 4;
0405     }
0406 
0407 
0408 //  cout<< "DC size "<< header[0]-HEADER_LENGTH-1 <<" "<<actual_data_size<<endl;
0409 //  if(header[0]-HEADER_LENGTH-1 == actual_data_size){
0410 
0411   if(header[0]-HEADER_LENGTH == actual_data_size){
0412 // cout <<header[0]-5<<", "<<actual_data_size-1<<endl; cout<<"Error size"<<endl;
0413 
0414           // we calculate the checksum here because "pos" is at the right place
0415 //    unsigned short crc = crc16(ifee, startpos, header[0]-1);
0416     unsigned short crc = crc16(ifee, startpos, header[0]);
0417           
0418     dc->checksum = crc;
0419 
0420 //    cout<< crc<<" "<< fee_data[ifee][pos]<<endl;
0421     dc->valid = ( crc == fee_data[ifee][pos]);
0422 
0423     currentforms.insert(dc);
0424   }
0425   else{ delete dc; }
0426 
0427   return 0;
0428 }
0429 
0430 
0431 long long oncsSub_idtpcfeev5::lValue(const int n, const char *what)
0432 {
0433   tpc_gtm_decode(); // this only decodes the gtm
0434 
0435   const size_t i = n;
0436 
0437   if (strcmp(what, "N_TAGGER") == 0)  // the number of datasets
0438   {
0439     return gtm_data.size();
0440   }
0441   
0442   else if ( strcmp(what,"NR_VALIDFEE") == 0 )
0443   {
0444     return NR_VALIDFEE;
0445   }
0446   
0447 
0448   else if (strcmp(what, "TAGGER_TYPE") == 0 )
0449   {
0450     if (i < gtm_data.size())
0451     {
0452       return gtm_data[i]->pkt_type;
0453     }
0454   }
0455 
0456   else if (strcmp(what, "IS_ENDAT") == 0 )
0457   {
0458     if (i < gtm_data.size())
0459     {
0460       return gtm_data[i]->is_endat;
0461     }
0462   }
0463 
0464   else if (strcmp(what, "IS_LEVEL1_TRIGGER") == 0 )
0465   {
0466     if (i < gtm_data.size())
0467     {
0468       return gtm_data[i]->is_lvl1;
0469     }
0470   }
0471 
0472   else if (strcmp(what, "IS_MODEBIT") == 0 )
0473   {
0474     if (i < gtm_data.size())
0475     {
0476       return gtm_data[i]->is_modebit;
0477     }
0478   }
0479 
0480   else if (strcmp(what, "BCO") == 0 )
0481   {
0482     if (i < gtm_data.size())
0483     {
0484       return gtm_data[i]->bco;
0485     }
0486   }
0487 
0488   else if (strcmp(what, "LEVEL1_COUNT") == 0 )
0489   {
0490     if (i < gtm_data.size())
0491     {
0492       return gtm_data[i]->lvl1_count;
0493     }
0494   }
0495 
0496   else if (strcmp(what, "ENDAT_COUNT") == 0 )
0497   {
0498     if (i < gtm_data.size())
0499     {
0500       return gtm_data[i]->endat_count;
0501     }
0502   }
0503 
0504   else if (strcmp(what, "LAST_BCO") == 0 )
0505   {
0506     if (i < gtm_data.size())
0507     {
0508       return gtm_data[i]->last_bco;
0509     }
0510   }
0511 
0512   else if (strcmp(what, "MODEBITS") == 0 )
0513   {
0514     if (i < gtm_data.size())
0515     {
0516       return gtm_data[i]->modebits;
0517     }
0518   }
0519 
0520   else if (strcmp(what, "FEMUSERBITS") == 0 )
0521   {
0522     if (i < gtm_data.size())
0523     {
0524       return gtm_data[i]->userbits;
0525     }
0526   }
0527 
0528   return 0;
0529 }
0530 
0531 int oncsSub_idtpcfeev5::iValue(const int n, const int sample)
0532 {
0533   if ( n < 0) return 0;
0534   
0535   tpc_decode();
0536 
0537   unsigned int m = sample; 
0538 
0539   if(m>=1030 && m<=1037){
0540     if ( DCcacheIterator(n) )
0541       {
0542         return (_last_requested_currentform)->current[m-1030];
0543       }
0544     }
0545   else if(m>=1040 && m<=1047){
0546     if ( DCcacheIterator(n) )
0547       {
0548         return (_last_requested_currentform)->nsamples[m-1040];
0549       }
0550     }
0551 
0552   
0553   if ( cacheIterator(n) )
0554     {
0555       if ( m >= (_last_requested_waveform)->waveform.size() ) return 0;
0556       return (_last_requested_waveform)->waveform[m];
0557     }
0558   return 0;
0559 }
0560 
0561 int oncsSub_idtpcfeev5::iValue(const int n, const int sample, const char *what)
0562 {
0563   if ( n < 0) return 0;
0564   
0565   tpc_decode();
0566 
0567   unsigned int m = sample; 
0568 
0569   if ( strcmp(what,"DC_VAL") == 0 )
0570     {
0571     if ( DCcacheIterator(n) )
0572       {
0573         return (_last_requested_currentform)->current[m];
0574       }
0575     }
0576   else if ( strcmp(what,"DC_NSAMPLES") == 0 )
0577     {
0578     if ( DCcacheIterator(n) )
0579       {
0580         return (_last_requested_currentform)->nsamples[m];
0581       }
0582     }
0583   else return -1;
0584   
0585   return 0;
0586 }
0587 
0588 
0589 int oncsSub_idtpcfeev5::iValue(const int n, const char *what)
0590 {
0591 
0592   tpc_decode();
0593 
0594   if ( strcmp(what,"NR_WF") == 0 )  // the number of datasets
0595   {
0596     return waveform_vector.size();
0597   }
0598 
0599   else if ( strcmp(what,"MAX_FEECOUNT") == 0 )
0600   {
0601     return MAX_FEECOUNT;
0602   }
0603 
0604   // see how many samples we have
0605   else if ( strcmp(what,"SAMPLES") == 0 )
0606     {
0607       if ( cacheIterator(n) )
0608     {
0609       return (int) (_last_requested_waveform)->waveform.size();
0610     }
0611       return 0;
0612     }
0613   
0614   else if ( strcmp(what,"FEE") == 0 )
0615     {
0616       if ( cacheIterator(n) )
0617     {
0618       return (int) (_last_requested_waveform)->fee;
0619     }
0620       return 0;
0621     }
0622   
0623   else if ( strcmp(what,"SAMPAADDRESS") == 0 )
0624     {
0625       if ( cacheIterator(n) )
0626     {
0627       return (int) (_last_requested_waveform)->sampa_address;
0628     }
0629       return 0;
0630     }
0631   
0632   else if ( strcmp(what,"SAMPACHANNEL") == 0 )
0633     {
0634       if ( cacheIterator(n) )
0635     {
0636       return (int) (_last_requested_waveform)->sampa_channel;
0637     }
0638       return 0;
0639     }
0640   
0641   else if ( strcmp(what,"CHANNEL") == 0 )
0642     {
0643       if ( cacheIterator(n) )
0644     {
0645       return (int) (_last_requested_waveform)->channel;
0646     }
0647       return 0;
0648     }
0649   
0650   else if ( strcmp(what,"BCO") == 0 )
0651     {
0652       if ( cacheIterator(n) )
0653     {
0654       return (int) (_last_requested_waveform)->bx_timestamp;
0655     }
0656       return 0;
0657     }
0658 
0659   else if ( strcmp(what,"CHECKSUM") == 0 )
0660     {
0661       if ( cacheIterator(n) )
0662     {
0663       return (int) (_last_requested_waveform)->checksum;
0664     }
0665       return 0;
0666     }
0667 
0668   else if ( strcmp(what,"CHECKSUMERROR") == 0 )
0669     {
0670       if ( cacheIterator(n) )
0671     {
0672       if ( (_last_requested_waveform)->valid ) return 0; 
0673       return 1;
0674     }
0675       return 0;
0676     }
0677 
0678   else if ( strcmp(what,"DATAPARITY") == 0 )
0679     {
0680       if ( cacheIterator(n) )
0681     {
0682       return (int) (_last_requested_waveform)->data_parity;
0683     }
0684       return 0;
0685     }
0686 
0687   else if ( strcmp(what,"DATAPARITYERROR") == 0 )
0688     {
0689       if ( cacheIterator(n) )
0690     {
0691       if ( (_last_requested_waveform)->parity_valid ) return 0; 
0692       return 1;
0693     }
0694       return 0;
0695     }
0696 
0697   else if ( strcmp(what,"TYPE") == 0 )
0698     {
0699       if ( cacheIterator(n) )
0700     {
0701       return (int) (_last_requested_waveform)->type;
0702     }
0703       return 0;
0704     }
0705 
0706   else if ( strcmp(what,"USERWORD") == 0 )
0707     {
0708       if ( cacheIterator(n) )
0709     {
0710       return (int) (_last_requested_waveform)->user_word;
0711     }
0712       return 0;
0713     }
0714 
0715   // From Here, digital current
0716 
0717   else if ( strcmp(what,"NR_DC") == 0 )  // the number of datasets
0718   {
0719     return current_vector.size();
0720   }
0721 
0722   else if ( strcmp(what,"FEE_DC") == 0 )
0723     {
0724       if ( DCcacheIterator(n) )
0725     {
0726       return (int) (_last_requested_currentform)->fee;
0727     }
0728       return 0;
0729     }
0730   
0731   else if ( strcmp(what,"SAMPAADDRESS_DC") == 0 )
0732     {
0733       if ( DCcacheIterator(n) )
0734     {
0735       return (int) (_last_requested_currentform)->sampa_address;
0736     }
0737       return 0;
0738     }
0739   
0740   else if ( strcmp(what,"SAMPAMAXCHANNEL_DC") == 0 )
0741     {
0742       if ( DCcacheIterator(n) )
0743     {
0744       return (int) (_last_requested_currentform)->sampa_max_channel;
0745     }
0746       return 0;
0747     }
0748   
0749   else if ( strcmp(what,"CHANNEL_DC") == 0 )
0750     {
0751       if ( DCcacheIterator(n) )
0752     {
0753       return (int) (_last_requested_currentform)->channel;
0754     }
0755       return 0;
0756     }
0757   
0758   else if ( strcmp(what,"BCO_DC") == 0 )
0759     {
0760       if ( DCcacheIterator(n) )
0761     {
0762       return (int) (_last_requested_currentform)->bx_timestamp;
0763     }
0764       return 0;
0765     }
0766 
0767   else if ( strcmp(what,"CHECKSUM_DC") == 0 )
0768     {
0769       if ( DCcacheIterator(n) )
0770     {
0771       return (int) (_last_requested_currentform)->checksum;
0772     }
0773       return 0;
0774     }
0775 
0776   else if ( strcmp(what,"CHECKSUMERROR_DC") == 0 )
0777     {
0778       if ( DCcacheIterator(n) )
0779     {
0780       if ( (_last_requested_currentform)->valid ) return 0; 
0781       return 1;
0782     }
0783       return 0;
0784     }
0785 
0786   else if ( strcmp(what,"TYPE_DC") == 0 )
0787     {
0788       if ( DCcacheIterator(n) )
0789     {
0790       return (int) (_last_requested_currentform)->type;
0791     }
0792       return 0;
0793     }
0794 
0795   return 0;
0796   
0797 }
0798  
0799 //int oncsSub_idtpcfeev5::find_header ( std::vector<unsigned short>::const_iterator &itr,  const std::vector<unsigned short> &orig)
0800 int oncsSub_idtpcfeev5::find_header ( const unsigned int yy,  const std::vector<unsigned short> &orig)
0801 {
0802   bool found = false;
0803   unsigned int pos = yy;
0804   std::vector<unsigned short> header_candidate(HEADER_LENGTH);
0805 
0806   // we slide over the data and find the header, if any.
0807   // we calculate and return the amount of words we need to skip to find the vector.
0808   // if we find it right away, the amount returned is 0;
0809   // -1 for an error condition or end, like we hit the end without finding another header.
0810   // the complication here is that we look ahead a few words to recognize it.  
0811   
0812   for ( unsigned int i = 0; i < HEADER_LENGTH ; i++)  // we start out with one "header candidate" = 7 entries
0813     {
0814       if ( pos >= orig.size())    // if we reached the end, no more header here
0815     {
0816       return -1;
0817     }
0818 
0819       header_candidate[i] = orig[pos];
0820       pos++;
0821     }
0822   
0823   int skip_amount = 0;
0824   while ( ! found)
0825     {
0826       //      coutfl << " current pos is  " << pos  << "  vector length " << orig.size()  << endl;
0827         
0828 //      if (header_candidate[4] == MAGIC_KEY_0)
0829       if (header_candidate[1] == MAGIC_KEY_0 && header_candidate[2] == MAGIC_KEY_1)
0830     {
0831       // found it!
0832     // It doesn't help
0833         //    found = true;
0834         //    coutfl << " found header skip value =  " << skip_amount << endl;
0835             break;
0836         }
0837       skip_amount++;
0838       if ( pos >= orig.size())    // if we reached the end, no more header here
0839       {
0840     return -1;
0841       }
0842 
0843       //   coutfl << " next value " << pos << "  " << hex << orig[pos]  << dec << endl;
0844       header_candidate.erase(header_candidate.begin());  // delete the vector 1st element
0845       header_candidate.push_back(orig[pos]);                  // push a new value, rinse and repeat
0846       pos++;
0847     }
0848 
0849   return skip_amount;
0850 }
0851  
0852 void  oncsSub_idtpcfeev5::dump ( OSTREAM& os )
0853 {
0854   tpc_decode();
0855   identify(os);
0856 
0857   if (lValue(0, "N_TAGGER") == 0)
0858     os << "  No lvl1 and Endat taggers" << endl;
0859   else
0860   {
0861     os << "  TAGGER_TYPE       BCO       LEVEL1 CNT  ENDAT CNT     LAST_BCO  MODE/USERBIT" << endl;
0862 
0863     for (int i = 0; i < lValue(0, "N_TAGGER"); ++i)  // go through the datasets
0864     {
0865       os << "  0x" << setw(4) << hex << lValue(i, "TAGGER_TYPE") << dec
0866 //         << " (" << (lValue(i, "IS_ENDAT") ? "ENDAT" : "") << (lValue(i, "IS_LEVEL1_TRIGGER") ? "LVL1 " : "")
0867          << " (" << (lValue(i, "IS_ENDAT") ? "ENDAT" : "") << (lValue(i, "IS_LEVEL1_TRIGGER") ? "LVL1 " : "") << (lValue(i, "IS_MODEBIT") ? "MDBIT" : "")
0868          << ") "
0869          << setw(12) << hex << lValue(i, "BCO") << dec << " "
0870          << setw(10) << lValue(i, "LEVEL1_COUNT") << " "
0871          << setw(10) << lValue(i, "ENDAT_COUNT") << " "
0872          << setw(12) << hex << lValue(i, "LAST_BCO") << dec
0873          << "   0x" << std::setfill('0') << setw(2) << hex << lValue(i, "MODEBITS") << std::setfill(' ')<< dec
0874          << " / 0x" << std::setfill('0') << setw(2) << hex << lValue(i, "FEMUSERBITS") << std::setfill(' ')<< dec
0875          << endl;
0876     }
0877 
0878     os << endl;
0879   }
0880 
0881   os << " number of waveforms " << iValue(0, "NR_WF") << endl;
0882     
0883   for ( int i = 0; i < iValue(0, "NR_WF") ; i++) // go through the datasets
0884     {
0885       os << "  FEE   Channel   Sampachannel   Samples     BCO    CRC_ERR   PARITY_ERR  DATA_TYPE  USERWORD" << endl;
0886 
0887       os << setw(5) << iValue(i, "FEE")  << " "
0888      << setw(9) << iValue(i, "CHANNEL")  << " "
0889      << setw(9) << iValue(i, "SAMPACHANNEL")  << " "
0890      << setw(12) << iValue(i, "SAMPLES") << " "
0891      <<  "     0x" << setw(5) << hex << iValue(i, "BCO") << dec
0892     //   << " 0x" << setw(4) << hex << iValue(i, "CHECKSUM") << dec
0893      <<  setw(4) << iValue(i, "CHECKSUMERROR")
0894      <<  setw(10) << iValue(i, "DATAPARITYERROR")
0895      <<  setw(12) << iValue(i, "TYPE")
0896      <<  setw(12) << iValue(i, "USERWORD")
0897      << endl;
0898       
0899       for (int j = 0; j  < iValue(i, "SAMPLES") ; j += 10)
0900     {
0901       os << "                                                       ";
0902       for (int k = 0; k < 10 ; k++)
0903         {
0904           os << setw(4) << iValue(i,j+k)  << " ";
0905         }
0906       os << endl;
0907     }
0908       os << endl;
0909   
0910     }
0911 
0912   os << " number of digital current " << iValue(0, "NR_DC") << endl;
0913     
0914   for ( int i = 0; i < iValue(0, "NR_DC") ; i++) // go through the datasets
0915     {
0916       os << "  BCO   CRC_ERR   DATA_TYPE" << endl;
0917 
0918       os <<  " 0x" << setw(5) << hex << iValue(i, "BCO_DC") << dec
0919     //   << " 0x" << setw(4) << hex << iValue(i, "CHECKSUM") << dec
0920      <<  setw(4) << iValue(i, "CHECKSUMERROR_DC")
0921      <<  setw(12) << hex<<iValue(i, "TYPE_DC")<<dec
0922      << endl;
0923       
0924 //      os << " (DC0) (Nsamples0) (DC1) (Nsamples1).... "<<endl;
0925 
0926       os << "  FEE   Channel   SampaChan     DC       Nsample" << endl;
0927       for (int j = 0; j  < 8 ; j ++)
0928     {
0929           os << setw(5) << iValue(i, "FEE_DC")  << " "
0930          << setw(7) << iValue(i, "CHANNEL_DC")-7+j  << " "
0931          << setw(9) << iValue(i, "SAMPAMAXCHANNEL_DC")-7+j  << " "
0932 //       << setw(12) << iValue(i,j+1030)  << " "
0933 //       << setw(9) << iValue(i,j+1040)  << " ";
0934          << setw(12) << iValue(i,j,"DC_VAL")  << " "
0935          << setw(9) << iValue(i,j,"DC_NSAMPLES")  << " ";
0936     os << endl;
0937         }
0938 
0939       os << endl;
0940   
0941     }
0942 }
0943 
0944 
0945 
0946 unsigned short oncsSub_idtpcfeev5::reverseBits(const unsigned short x) const
0947 {
0948   unsigned short n = x;  
0949   n = ((n >> 1) & 0x55555555) | ((n << 1) & 0xaaaaaaaa);
0950   n = ((n >> 2) & 0x33333333) | ((n << 2) & 0xcccccccc);
0951   n = ((n >> 4) & 0x0f0f0f0f) | ((n << 4) & 0xf0f0f0f0);
0952   n = ((n >> 8) & 0x00ff00ff) | ((n << 8) & 0xff00ff00);
0953   //n = (n >> 16) & 0x0000ffff | (n << 16) & 0xffff0000;
0954   return n;
0955 }
0956 
0957 
0958 
0959 unsigned short oncsSub_idtpcfeev5::crc16(const unsigned int fee, const unsigned int index, const int  l) const 
0960 {
0961 
0962   unsigned short crc = 0xffff;
0963     
0964   for ( int i = 0; i < l; i++)
0965     {
0966       unsigned short x = fee_data[fee][index+i];
0967       //      cout << "in crc " << hex << x << dec << endl;
0968       crc ^= reverseBits( x);
0969       for (unsigned short k = 0; k < 16; k++)
0970     {
0971       crc = crc & 1 ? (crc >> 1) ^ 0xa001 : crc >> 1;
0972     }
0973       }
0974   crc = reverseBits(crc);
0975   return crc;
0976 }
0977 
0978 uint16_t oncsSub_idtpcfeev5::check_data_parity(const unsigned int fee, const unsigned int index, const int  l) const 
0979 {
0980     uint16_t data_parity = 1;
0981     for (uint16_t i = 0; i < l; i++) {
0982         for (int j = 0; j < 10; j++) {
0983             data_parity ^= ((fee_data[fee][index+i] & (1 << j)) >> j);
0984         }
0985     }
0986 
0987     return data_parity;
0988 }