Back to home page

sPhenix code displayed by LXR

 
 

    


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

0001 #include "packet_iddigitizerv3.h"
0002 
0003 #include <string.h>
0004 
0005 using namespace std;
0006 
0007 
0008 #define coutfl std::cout << __FILE__<< "  " << __LINE__ << " "
0009 #define cerrfl std::cerr << __FILE__<< "  " << __LINE__ << " "
0010 
0011 
0012 Packet_iddigitizerv3::Packet_iddigitizerv3(PACKET_ptr data)
0013   :Packet_w4 (data)
0014 {
0015 
0016   _broken = 0;
0017   
0018   if ( getHitFormat() > 160 && getHitFormat() <= 190)
0019     {
0020       _nsamples = getHitFormat() - 160;
0021     }
0022   _nchannels = 0;
0023   _nr_modules = 0;
0024   
0025   _evtnr = 0;
0026   _module_address  = 0;
0027   _xmit_clock = 0;
0028   _AnyChannelisSuppressed = false;  // we use this later to see if the checksum can be calculated
0029   
0030   for ( int i = 0; i < NR_FEMS; i++)
0031     {
0032       _fem_slot[i] = 0;
0033       _fem_evtnr[i] = 0;
0034       _fem_clock[i] = 0;
0035       _fem_checksum_MSB[i] = 0;
0036       _fem_checksum_LSB[i] = 0;
0037       _fem_calculated_checksum_MSB[i] = 0;
0038       _fem_calculated_checksum_LSB[i] = 0;
0039 
0040     }
0041   
0042   _is_decoded = 0;
0043   
0044 }
0045 
0046 
0047 Packet_iddigitizerv3::~Packet_iddigitizerv3()
0048 {
0049 
0050 }
0051 
0052 int Packet_iddigitizerv3::decode ()
0053 {
0054 
0055   if (_is_decoded ) return 0;
0056   _is_decoded = 1;
0057   
0058   unsigned int *k;
0059 
0060 
0061   // check later  int dlength = ( getLength()-4) - getPadding();
0062 
0063   unsigned int *SubeventData = (unsigned int *) findPacketDataStart(packet); 
0064 
0065   int dlength = getDataLength();
0066   
0067   k = SubeventData;  // we make a shorter variale for less typing..
0068 
0069   
0070   for (int i = 0; i < 32; i++)
0071     {
0072       for (int j = 0; j < 4*64; j++)
0073     {
0074       adc[i][j] = 0;
0075     }
0076     }
0077 
0078   if ( dlength < 6 )
0079     {
0080       _broken = 1;
0081       return 0;  //safety belt
0082     }
0083   
0084   // we have here - 
0085   //  [0]  0x8000xxxx  with xxxx = evt nr
0086   //  [1]  0x9000xxxx  with xxxx = flag word
0087   //  [2]  0x9000xxxx  with xxxx = det id
0088   //  [3]  0x9000xxxx  with xxxx = module address
0089   //  [4]  0x9000xxxx  with xxxx = xmit clock nr
0090   
0091   if ( (k[0] >> 28) != 0x8)  return 1;
0092   if ( (k[1] >> 28) != 0x9)  return 1;
0093   if ( (k[2] >> 28) != 0x9)  return 1;
0094   if ( (k[3] >> 28) != 0x9)  return 1;
0095   if ( (k[4] >> 28) != 0x9)  return 1;
0096 
0097   _evtnr          = (k[0] & 0xffff);
0098   _clock_rollover = (k[1] & 0xffff);
0099   _evtrollover    = (k[2] & 0xffff);
0100   _module_address = (k[3] & 0xffff);
0101   _xmit_clock     = (k[4] & 0xffff);
0102 
0103   _evtnr = (_evtrollover << 16) + _evtnr;
0104   _xmit_clock = (_clock_rollover << 16) + _xmit_clock;
0105 
0106   int fem_nr = 0;
0107   
0108   for (int fem_index = 5; fem_index < dlength ; )  // we hop from FEM to FEM here
0109     {
0110 
0111       if ( k[fem_index] == 0xa000ffff)
0112     {
0113       // coutfl << " FEM_ start at  " << fem_index << "   " << hex << k[fem_index] << dec  << endl;
0114       
0115       unsigned int i = decode_FEM (  &k[fem_index], fem_nr, dlength - fem_index); // we make "i" so we can debug
0116       if ( i == 0)
0117         {
0118           //coutfl << " strange return " << i << endl;
0119           _broken = 2;
0120           break;  // no endless loops...
0121         }
0122       fem_nr++;
0123       if ( fem_nr >= NR_FEMS)
0124         {
0125           _broken = 3;
0126           return 1;
0127         }
0128       fem_index += i;
0129       //coutfl << " fem_index now  " << fem_index << "  " << hex <<  k[fem_index] << dec << endl;
0130     }
0131       else
0132     {
0133       _broken = 4;
0134       return 1;
0135     }
0136     }
0137 
0138   
0139   return 0;
0140 }
0141 
0142 
0143 unsigned int Packet_iddigitizerv3::decode_FEM ( unsigned int *k, const int fem_nr, const int len)
0144 {
0145   int NFEM = fem_nr;
0146   int CHNL = 0;
0147   int index_channel = NFEM*64;
0148   int index_sample = 0;
0149   int index_parity = 0;
0150 
0151   //  coutfl << " calling decode_FEM for fem " << fem_nr << endl << endl;
0152 
0153   
0154   // should have been checked but let's be sure
0155   if ( k[0] != 0xa000ffff) return 0;
0156   
0157   _fem_slot[fem_nr]  = k[1] & 0xffff;
0158   _fem_evtnr[fem_nr] = k[2] & 0xffff;
0159   _fem_clock[fem_nr] = k[3] & 0xffff;
0160 
0161   _nr_modules++;
0162   _nchannels += 64;  
0163 
0164   int index;
0165   int corrected_index_channel;
0166   // for ( index = 1; index < 4; index++)
0167   //   {
0168   //     _fem_calculated_checksum_MSB[NFEM] ^= ((k[index] >> 16 ) & 0xffff);
0169   //     _fem_calculated_checksum_LSB[NFEM] ^= (k[index] & 0xffff);
0170   //   }
0171 
0172 
0173 
0174   for ( index = 4; index < len;)
0175     {
0176       int word_classifier = k[index] >> 28;
0177       
0178       if ( (k[index] >> 28) == 0xe) // ah! another "0xe" channel
0179     {
0180       corrected_index_channel = index_channel^1;
0181       isZeroSuppressed[corrected_index_channel] = true;
0182       _AnyChannelisSuppressed = true;
0183       pre_post[0][corrected_index_channel] = (k[index] & 0x3fff);
0184       pre_post[1][corrected_index_channel] = ((k[index]>>14) & 0x3fff);
0185       // coutfl << " found a zp-word  " << hex << "0x" << k[index]  << dec << " at index " << index
0186       //     << " for channel " << index_channel << "  " << isZeroSuppressed[index_channel] << " **** zero-suppressed " <<  endl;
0187       index++;
0188       index_channel++;
0189     }
0190 
0191       else if ( word_classifier == 0x1) // FEM/Ch address
0192     {
0193       // _fem_calculated_checksum_MSB[NFEM] ^= ((k[index] >> 16 ) & 0xffff);
0194       // _fem_calculated_checksum_LSB[NFEM] ^= (k[index] & 0xffff);
0195 
0196       NFEM = (k[index] >> 6) & 0x7;
0197       CHNL   = k[index] & 0x3f;
0198       //      coutfl << "new NFEM and channel - " << NFEM << " " << CHNL << "   "  << hex << k[index] << dec << endl;
0199       if (NFEM != fem_nr || NFEM >= NR_FEMS)
0200         {
0201           //cerrfl << "NFEM and fem_nr differ - " << NFEM << " " << fem_nr << "  " << hex << k[index] << dec << endl;
0202           _broken = 5;
0203           return 0;
0204         }
0205       // we have a new channel. reset the sample and parity index, and set the channel index
0206       index_sample = 0;
0207       index_parity = 0;  
0208       index_channel = NFEM*64+CHNL;
0209       corrected_index_channel = index_channel^1;
0210       // we assume we are zero-suppressed and reset this if we find later that we are not
0211       //      isZeroSuppressed[index_channel] = true;
0212 
0213       if ( (k[index+1] >> 28) == 0x3) // we have a full waveform
0214         {
0215           index++;  //move on to that word
0216           for ( int c = 0; c < ( _nsamples/2 + 1) ; c++)  // like for 12 samples we expect 7 words
0217         {
0218           if ( (k[index] >> 28) == 0x3)  // normal word
0219             {
0220               // coutfl << " found a normal word   " << hex << "0x" << k[index]  << dec << " at index " << index
0221               //         << " for channel " << index_channel << " and " << index_sample  << endl;
0222               adc[index_sample++][corrected_index_channel] = k[index] & 0x3fff;
0223               adc[index_sample++][corrected_index_channel] = (k[index] >> 14) & 0x3fff;
0224               isZeroSuppressed[corrected_index_channel] = false; // we are ot zero-sppressed
0225               // coutfl << " setting not zp  for channel " << index_channel  << " " << isZeroSuppressed[index_channel] << endl;
0226 
0227             }
0228           else if ( (k[index] >> 28) == 0xe) // here is our regular pre-post word
0229             {
0230               pre_post[0][corrected_index_channel] = (k[index] & 0x3fff);
0231               pre_post[1][corrected_index_channel] = ((k[index]>>14) & 0x3fff);
0232               // coutfl << " found a regular zp-word  " << hex << "0x" << k[index]  << dec << " at index " << index
0233               //         << " for channel " << index_channel << endl;
0234             }
0235           else
0236             {
0237               // scream if that's not 0x3 nor 0xe
0238               coutfl << "wrong tag! " << hex << (k[index] >> 28) << dec << " at index " << index << endl;
0239             }
0240           index++;
0241         }
0242         }
0243       else
0244         {
0245           coutfl << "unknown case: word classifier " << hex << "0x" << word_classifier << " next word 0x" << (k[index+1] >> 28) << dec << endl;
0246           _broken = 2;
0247           return 0;
0248         }
0249 
0250       // just in case we get a zero-suppressed word, step the index_channel
0251       index_channel++;
0252     }
0253       
0254       else if ( word_classifier == 0xb)   // parity info
0255     {
0256       if ( index_parity == 0)
0257         {
0258           _fem_checksum_MSB[NFEM] = (k[index] & 0xffff);
0259           index_parity++;
0260           index++;
0261         }
0262       else
0263         {
0264           _fem_checksum_LSB[NFEM] = (k[index] & 0xffff);
0265           index++;
0266           break;
0267         }
0268       if ( index >= len) break;
0269     }
0270       else
0271     {
0272       coutfl << "unknown word classifier " << hex << "0x" << word_classifier << dec << endl;
0273       _broken = 2;
0274       return 0;
0275     }
0276     }
0277   return index;
0278 }
0279 
0280 
0281 int Packet_iddigitizerv3::iValue(const int sample, const int ch)
0282 {
0283   decode();
0284 
0285   if (_broken) return 0; 
0286   
0287   if ( sample >= _nsamples || sample < 0 
0288        || ch >= _nchannels || ch < 0 ) return 0;
0289  
0290   return adc[sample][ch];
0291   return 0;
0292 }
0293 
0294 long long Packet_iddigitizerv3::lValue(const int n, const char *what)
0295 {
0296 
0297   decode();
0298 
0299   if (_broken) return 0; 
0300   
0301   if ( strcmp(what,"CLOCK") == 0 )
0302   {
0303     return _xmit_clock;
0304   }
0305 
0306   if ( strcmp(what,"EVTNR") == 0 )
0307   {
0308     return _evtnr;
0309   }
0310 
0311   return 0;
0312 }
0313 
0314 
0315 int Packet_iddigitizerv3::iValue(const int n, const char *what)
0316 {
0317 
0318   decode();
0319 
0320   if (_broken) return 0; 
0321 
0322   // if ( strcmp(what,"CLOCK") == 0 )
0323   // {
0324   //   return _xmit_clock;
0325   // }
0326 
0327   if ( strcmp(what,"EVTNR") == 0 )
0328   {
0329     return _evtnr;
0330   }
0331 
0332   if ( strcmp(what,"SAMPLES") == 0 )
0333   {
0334     return _nsamples;
0335   }
0336 
0337   if ( strcmp(what,"NRMODULES") == 0 )
0338   {
0339     return _nr_modules;
0340   }
0341 
0342 
0343   if ( strcmp(what,"CHANNELS") == 0 )
0344   {
0345     return _nchannels;
0346   }
0347 
0348   if ( strcmp(what,"MODULEADDRESS") == 0 )
0349   {
0350     return _module_address;
0351   }
0352 
0353 
0354   if ( strcmp(what,"FEMSLOT") == 0 )
0355   {
0356     if ( n < 0 || n >= _nr_modules) return 0;
0357     return _fem_slot[n];
0358   }
0359 
0360   if ( strcmp(what,"FEMEVTNR") == 0 )
0361   {
0362     if ( n < 0 || n >= _nr_modules) return 0;
0363     return _fem_evtnr[n];
0364   }
0365 
0366   if ( strcmp(what,"FEMCLOCK") == 0 )
0367   {
0368     if ( n < 0 || n >= _nr_modules) return 0;
0369     return _fem_clock[n];
0370   }
0371 
0372   if ( strcmp(what,"CHECKSUMMSB") == 0 )
0373   {
0374     if ( n < 0 || n >= _nr_modules) return 0;
0375     return _fem_checksum_MSB[n];
0376   }
0377 
0378   if ( strcmp(what,"CHECKSUMLSB") == 0 )
0379   {
0380     if ( n < 0 || n >= _nr_modules) return 0;
0381     return _fem_checksum_LSB[n];
0382   }
0383 
0384   if ( strcmp(what,"CALCCHECKSUMMSB") == 0 )
0385   {
0386     if ( n < 0 || n >= _nr_modules) return 0;
0387     return _fem_calculated_checksum_MSB[n];
0388   }
0389 
0390   if ( strcmp(what,"CALCCHECKSUMLSB") == 0 )
0391   {
0392     if ( n < 0 || n >= _nr_modules) return 0;
0393     return _fem_calculated_checksum_LSB[n];
0394   }
0395 
0396   // to maintain compatibility with v2, we provide those interfaces
0397   // but we return -1 for "cannot be determined"
0398   if ( strcmp(what,"EVENCHECKSUMOK") == 0 )
0399   {
0400     return -1;
0401   }
0402 
0403   if ( strcmp(what,"ODDCHECKSUMOK") == 0 )
0404   {
0405     return -1;
0406   }
0407   
0408   if ( strcmp(what,"CHECKSUMOK") == 0 )
0409   {
0410     return -1;
0411   }
0412   
0413   if ( strcmp(what,"PRE") == 0 )
0414   {
0415     if ( n < 0 || n >= _nchannels ) return 0;
0416     return pre_post[0][n];
0417   }
0418 
0419   if ( strcmp(what,"POST") == 0 )
0420   {
0421     if ( n < 0 || n >= _nchannels ) return 0;
0422     return pre_post[1][n];
0423   }
0424 
0425   if ( strcmp(what,"SUPPRESSED") == 0 )
0426   {
0427     if ( n < 0 || n >= _nchannels ) return 0;
0428     if ( isZeroSuppressed[n] ) return 1;
0429     return 0;
0430   }
0431 
0432 
0433   return 0;
0434 
0435 }
0436 
0437 void  Packet_iddigitizerv3::dump ( OSTREAM& os )
0438 {
0439   identify(os);
0440 
0441   decode();
0442   
0443   if ( _broken)
0444     {
0445       os << " *** Corrupt packet "  << std::endl;
0446       return;
0447     }
0448   
0449   os << "Evt Nr:      " << lValue(0,"EVTNR") << std::endl;
0450   os << "Clock:       0x" << std::hex << lValue(0,"CLOCK") << std::dec << std::endl;
0451   os << "Nr Modules:  " << iValue(0,"NRMODULES") << std::endl;
0452   os << "Channels:    " << iValue(0,"CHANNELS") << std::endl;
0453   os << "Samples:     " << iValue(0,"SAMPLES") << std::endl;
0454   //os << "Det. ID:     " << hex << "0x" << iValue(0,"DETID") << dec <<  std::endl;
0455   os << "Mod. Addr:   " << hex << "0x" << iValue(0,"MODULEADDRESS") << dec << std::endl;
0456 
0457   os << "FEM Slot:    ";
0458   for ( int i = 0; i < iValue(0,"NRMODULES"); i++) os << setw(8) << iValue(i,"FEMSLOT");
0459   os <<  std::endl;
0460 
0461   os << "FEM Evt nr:  ";
0462   for ( int i = 0; i < iValue(0,"NRMODULES"); i++)  os << setw(8) << iValue(i,"FEMEVTNR");
0463   os << std::endl;
0464 
0465   os << "FEM Clock:          ";
0466   for ( int i = 0; i < iValue(0,"NRMODULES"); i++)  os << "0x" << std::hex << setw(4) << iValue(i,"FEMCLOCK") << "  " << std::dec;
0467   os << std::endl;
0468 
0469   char oldFill=os.fill('0');
0470   
0471   os << "FEM Checksum LSB:   ";
0472   for ( int i = 0; i < iValue(0,"NRMODULES"); i++)
0473     {
0474       os <<  "0x" << hex <<  setw(4) << iValue(i,"CHECKSUMLSB") << "  "  << dec;
0475     }
0476   os << std::endl;
0477 
0478   // os << "Calculated Checksum LSB:   ";
0479   // for ( int i = 0; i < iValue(0,"NRMODULES"); i++)
0480   //   {
0481   //     os <<  "0x" << hex <<  setw(4) << iValue(i,"CALCCHECKSUMLSB") << "  "  << dec;
0482   //   }
0483   // os << std::endl;
0484 
0485   os << "FEM Checksum MSB:   ";
0486   for ( int i = 0; i < iValue(0,"NRMODULES"); i++)
0487     {
0488       os <<  "0x" << hex << setw(4) << iValue(i,"CHECKSUMMSB")  << "  "<< dec;
0489     }
0490   os << std::endl;
0491 
0492   // os << "Calculated Checksum MSB:   ";
0493   // for ( int i = 0; i < iValue(0,"NRMODULES"); i++)
0494   //   {
0495   //     os <<  "0x" << hex <<  setw(4) << iValue(i,"CALCCHECKSUMMSB") << "  "  << dec;
0496   //   }
0497   // os << std::endl;
0498 
0499   os.fill(oldFill);
0500   os << endl;
0501 
0502   for ( int c = 0; c < _nchannels; c++)
0503     {
0504       if (  iValue(c,"SUPPRESSED") )
0505     {
0506       os << setw(4) << c << " |-";
0507     }
0508       else
0509     {
0510       os << setw(4) << c << " | ";
0511     }
0512 
0513       
0514       os << hex;
0515 
0516       os << setw(6) << iValue(c, "PRE");
0517       os << setw(6) << iValue(c, "POST") << " | " ;
0518 
0519       if ( ! iValue(c,"SUPPRESSED") )
0520     {
0521       for ( int s = 0; s < _nsamples; s++)
0522         {
0523           os << setw(6) << iValue(s,c);
0524         }
0525     }
0526       os << dec << endl;
0527     }
0528 
0529 }