Back to home page

sPhenix code displayed by LXR

 
 

    


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

0001 #include "oncsSub_idfnalmwpcv2.h"
0002 
0003 // for ntohl and ntohs
0004 #include <arpa/inet.h>
0005 #include <cstring>
0006 
0007 
0008 using namespace std;
0009 
0010 oncsSub_idfnalmwpcv2::oncsSub_idfnalmwpcv2(subevtdata_ptr data)
0011   :oncsSubevent_w4 (data)
0012 {
0013   n_tdcs = 0;
0014   length= 0;
0015   _decoded = 0;
0016 
0017   // initialize all to 0
0018   memset (&spillinfo, 0 , sizeof(spillinfo) );
0019   memset (tsh, 0 , MAXNROFTDCS * sizeof(TDCspillheader) );
0020 
0021 }
0022   
0023 oncsSub_idfnalmwpcv2::~oncsSub_idfnalmwpcv2() {}
0024 
0025 
0026 int *oncsSub_idfnalmwpcv2::decode ( int *nwout)
0027 {
0028 
0029   if ( _decoded) return 0;
0030 
0031   _decoded = 1;
0032 
0033   int i;
0034 
0035   int *d = (int *) &SubeventHdr->data;  // here begins the payload
0036 
0037   tdcmask = d[0];
0038   
0039   // count the number of "on" bits = number of TDCs
0040   n_tdcs=0;
0041   for ( i = 0; i < MAXNROFTDCS; i++)
0042     {
0043       if ( (1<< i) & tdcmask ) n_tdcs++;
0044     }
0045 
0046 
0047   int length = ntohl ( d[1] );
0048   spillinfo.spillwords = length; // in 16bit units
0049   //  cout << __FILE__ << " " << __LINE__ << "Spillwords " << length << endl;
0050 
0051   //we now subtract 2 to remove the header length
0052   length -= 2;
0053 
0054   //  dlength is the remaining payload length without the 
0055   //  length word in 16bit units - we subtract 8 bytes for the mask and length
0056   int dlength = 2 * ( getLength()-getPadding() ) -8 ; 
0057 
0058   // length is the length of the entire spill stucture without the length 
0059   // in 16bit words; we do a consistency check
0060   if (length  > dlength ) return 0;
0061   
0062   unsigned short *s = ( unsigned short *) &d[1];
0063 
0064   //pre-swap the payload
0065   for ( i = 0; i < length; i++)
0066     {
0067       *s = ntohs(*s);
0068       s++;
0069     }
0070 
0071   // s = ( unsigned short *) &d[1];
0072   // for ( i = 100; i < 200; i++)
0073   //   {
0074   //     cout << setw(4) << i << "  " << hex << s[i] << dec << endl;
0075   //   }
0076   
0077 
0078   
0079   //and reset the "s" pointer
0080   // we make it so that "pos" point to the position in the payload
0081   // so we can think in terms of the counts in teh docs
0082   s = ( unsigned short *) &d[1];
0083   int pos = 2;  // we have digested 0 and 1
0084   
0085   short v;
0086 
0087   spillinfo.spillcounter = s[pos++];
0088   //cout << __FILE__ << " " << __LINE__ << "spillinfo.spillcounter " << spillinfo.spillcounter << endl;
0089   
0090   v =  s[pos++];
0091   spillinfo.year  = ( v>> 8 ) & 0xff;
0092   spillinfo.month =  v & 0xff;
0093 
0094   v =  s[pos++];
0095   spillinfo.day = ( v>> 8 ) & 0xff;
0096   spillinfo.hour = v & 0xff;
0097 
0098   v =  s[pos++];
0099   spillinfo.minute = ( v>> 8 ) & 0xff;
0100   spillinfo.second = v & 0xff;
0101 
0102   // Spill trigger count  32bits
0103   int x = s[pos++];    //MSB
0104   x <<=16;
0105   spillinfo.triggercount = x + s[pos++];  //LSB
0106   
0107   //  cout << __FILE__ << " " << __LINE__ << " spillinfo.triggercount " << spillinfo.triggercount << endl;
0108 
0109   spillinfo.TDC_Status_Bits = s[pos++];
0110   spillinfo.Spill_Link_Status_Bits = s[pos++];
0111 
0112   //cout << __FILE__ << " " << __LINE__ << " spillinfo.TDC_Status_Bits " << spillinfo.TDC_Status_Bits << endl;
0113   //cout << __FILE__ << " " << __LINE__ << " spillinfo.Spill_Link_Status_Bits " << spillinfo.Spill_Link_Status_Bits << endl;
0114 
0115 
0116   TDCEvent *te {nullptr};
0117 
0118 
0119   // we now push, up front, one event structure on the vector
0120   // for each trigger so we know that we have one for each event
0121   for ( i = 0; i< spillinfo.triggercount; i++)
0122     {
0123       te = new TDCEvent;
0124       memset ( te, 0, sizeof(TDCEvent) );
0125       TDCEventVector.push_back ( te);
0126     }
0127 
0128   // fill the WireChamberTdcSpillHeader (per TDC)  
0129   for ( i = 0; i< n_tdcs; i++)
0130     {
0131 
0132       //      cout << __FILE__ << " " <<  __LINE__ << " pos, value " << setw(4) << pos << " " << hex << s[pos] << dec << endl;
0133       tsh[i].spillwords =  s[pos++] << 16;  // we get a 32bit value
0134       tsh[i].spillwords +=  s[pos++] ;  
0135       //cout << __FILE__ << " " <<  __LINE__ << " i, spillwords, " << i << " " << tsh[i].spillwords << endl;
0136 
0137       tsh[i].TDC = s[pos++] -1;
0138       
0139       //cout << __FILE__ << " " <<  __LINE__ << " i, TDC " << i << " " << tsh[i].TDC << endl;
0140 
0141       tsh[i].spilltriggercount = pos++ << 16;
0142       tsh[i].spilltriggercount += pos++;
0143       //cout << __FILE__ << " " <<  __LINE__ << " spilltriggercount " <<  tsh[i].spilltriggercount << endl;
0144 
0145       tsh[i].spillstatus = s[pos++];
0146     }
0147 
0148   int old_trigger_number = -1;
0149 
0150 
0151   // here we keep the pos at the same value for a while
0152   while (pos < length)
0153     {
0154       //      cout << __FILE__ << " " <<  __LINE__ << " Event hdr: pos, value, length " << setw(4) << pos << " " << hex << s[pos] << dec << "  " << length << endl;
0155       int EventWordCount = s[pos];
0156       //      cout << __FILE__ << " " <<  __LINE__ << " EventWordCount " << EventWordCount << endl;
0157 
0158       short tdcindex =  s[pos+1] - 1; // the controller counts like fortran
0159       //cout << __FILE__ << " " <<  __LINE__ << " tdcindex " << tdcindex << endl;
0160       if ( tdcindex >= MAXNROFTDCS ) // sanity check
0161     {
0162       cout << __LINE__ << " " << __FILE__ 
0163            << " wrong TDC index " << tdcindex << " pos= " << pos-1 << endl;
0164     }
0165 
0166 
0167       //cout << __FILE__ << " " <<  __LINE__ << " pos, value " << setw(4) << pos << " " << hex << s[pos] << dec << endl;
0168       int SpillTriggerCount = s[pos+3]<<16;  // we get a 32bit value
0169       SpillTriggerCount += s[pos+4] -1;
0170 
0171       if (  SpillTriggerCount <0 || SpillTriggerCount >= spillinfo.triggercount )
0172     {
0173       cout << __LINE__ << " " << __FILE__ 
0174            << " wrong Trigger number " << SpillTriggerCount << " pos= " << pos << endl;
0175       return 0;
0176     }
0177 
0178       //cout << __FILE__ << " " <<  __LINE__ << " SpillTriggerCount " << SpillTriggerCount << endl;
0179       
0180       if ( SpillTriggerCount != old_trigger_number )  // ok, new event/trigger, so we get the next TDCEvent
0181     {
0182       old_trigger_number = SpillTriggerCount;
0183       te = TDCEventVector[SpillTriggerCount];
0184       te->trigger_nr = SpillTriggerCount;
0185       te->evt_timestamp = s[pos+5]; 
0186       te->local_ts_upper = s[pos+6]; 
0187       te->local_ts_lower = s[pos+7]; 
0188 
0189       // quick sanity check: bits 3...11 of 
0190       // the timstamp must be equal to the 
0191       // 9 lsb's of te->local_ts_lower
0192       
0193       // cout << " time stamps " << hex 
0194       //       << ( ( te->evt_timestamp>>3) &0x1ff ) << "  " 
0195       //       << ( te->local_ts_lower & 0x1ff) << dec << endl;
0196       
0197       
0198       // now we construct the long 35 bit 800MHz time stamp 
0199       // cout << "time stamps "  << hex 
0200       //       << te->evt_timestamp << " " 
0201       //       <<  te->local_ts_upper << " " 
0202       //       <<  te->local_ts_lower << dec << endl;
0203 
0204       te->absolute_time = te->local_ts_upper;
0205       te->absolute_time <<= 16;
0206       te->absolute_time += te->local_ts_lower;
0207       te->absolute_time <<= 3;
0208       te->absolute_time += ( te->evt_timestamp &0x3);
0209       // and we clear the TDCData structures
0210       memset ( te->td, 0, MAXNROFTDCS * sizeof( TDCData) );
0211           
0212       // we are done with filling in the new event "header" structure
0213       // now we fill in the TCDData structure. some of this 
0214       // is redundant to the header info, that's why we kept "pos" frozen
0215     }
0216           
0217       te->td[tdcindex].words = EventWordCount;
0218       te->td[tdcindex].TDC = tdcindex;
0219       te->td[tdcindex].EventStatus =s[pos+2]; 
0220       te->td[tdcindex].triggertype =s[pos+5]; 
0221 
0222       // this may look redundant with the code above, but is actually
0223       // per TDC info - the abve was per event. Should match, and we fill it in
0224       // so the user can perform a sanity check
0225       te->td[tdcindex].evt_timestamp  = s[pos+6]; 
0226       te->td[tdcindex].local_ts_upper = s[pos+7]; 
0227       te->td[tdcindex].local_ts_lower = s[pos+8]; 
0228 
0229       // now we construct the long 35 bit 800MHz time stamp 
0230       te->td[tdcindex].absolute_time = te->td[tdcindex].local_ts_upper;
0231       te->td[tdcindex].absolute_time <<= 16;
0232       te->td[tdcindex].absolute_time += te->td[tdcindex].local_ts_lower;
0233       te->td[tdcindex].absolute_time <<= 3;
0234       te->td[tdcindex].absolute_time += ( te->td[tdcindex].evt_timestamp &0x7);
0235 
0236       // at long last, the business end of this TDC - the TDC hit 
0237       int xpos = pos+9;  // that's where the hits start
0238       for ( i = 0; i < te->td[tdcindex].words -9; i++)  // so many hits, header is 9 long
0239     {
0240       te->td[tdcindex].hits++;  // this is the same as the TDCHitlist.size()
0241       
0242       TDC_hit *th = new TDC_hit;
0243       te->td[tdcindex].TDCHitlist.push_back ( th );
0244 
0245       short h = s[xpos+i];  // this is now the TDC word
0246       th->wire = ( h >> 10) & 0x3f;  // upper bits are "wire"
0247       th->timestamp = h & 0x3ff;     // lower 10 bits are "timestamp"
0248           
0249     }
0250       pos += EventWordCount;  // -1 because we stepped "pos" one position in already
0251     }
0252 
0253   
0254 
0255   return 0;
0256 }
0257 
0258 int oncsSub_idfnalmwpcv2::iValue(const int ich,const char *what)
0259 {
0260 
0261   decode (0);
0262   if ( strcmp(what,"NTDCS") == 0 )
0263   {
0264     return n_tdcs;
0265   }
0266 
0267   else if ( strcmp(what,"TRIGGERCOUNT") == 0 )
0268   {
0269     return spillinfo.triggercount;
0270   }
0271 
0272   else if ( strcmp(what,"SPILLCOUNTER") == 0 )
0273   {
0274     return spillinfo.spillcounter;
0275   }
0276 
0277   else if ( strcmp(what,"TDCSTATUSBITS") == 0 )
0278   {
0279     return   spillinfo.TDC_Status_Bits;
0280   }
0281 
0282   else if ( strcmp(what,"LINKSTATUSBITS") == 0 )
0283   {
0284     return spillinfo.Spill_Link_Status_Bits;
0285   }
0286 
0287   else if ( strcmp(what,"MONTH") == 0 )
0288   {
0289     return spillinfo.month;
0290   }
0291 
0292   else if ( strcmp(what,"DAY") == 0 )
0293   {
0294     return spillinfo.day;
0295   }
0296 
0297   else if ( strcmp(what,"YEAR") == 0 )
0298   {
0299     return spillinfo.year;
0300   }
0301 
0302   else if ( strcmp(what,"HOUR") == 0 )
0303   {
0304     return spillinfo.hour;
0305   }
0306 
0307   else if ( strcmp(what,"MINUTE") == 0 )
0308   {
0309     return spillinfo.minute;
0310   }
0311 
0312   else if ( strcmp(what,"SECOND") == 0 )
0313   {
0314     return spillinfo.second;
0315   }
0316 
0317   return 0;
0318 
0319 }
0320 
0321 
0322 int oncsSub_idfnalmwpcv2::iValue(const int trigger ,const int tdc, const int index)
0323 {
0324   decode (0);
0325   if ( trigger < 0 || (unsigned int ) trigger >= TDCEventVector.size()) return 0;
0326   if ( tdc < 0 || tdc >= n_tdcs) return 0;
0327   if ( index < 0 || index >= TDCEventVector[trigger]->td[tdc].hits) return 0;
0328 
0329   return TDCEventVector[trigger]->td[tdc].TDCHitlist[index]->wire;
0330 }
0331 
0332 int oncsSub_idfnalmwpcv2::iValue(const int trigger ,const int tdc, const char *what)
0333 {
0334   decode (0);
0335   if ( trigger < 0 || (unsigned int )trigger >= TDCEventVector.size()) return 0;
0336   if ( tdc < 0 || tdc >= n_tdcs) return 0;
0337 
0338 
0339   if ( strcmp(what,"HITS") == 0 )
0340   {
0341     if ( (unsigned int ) trigger >= TDCEventVector.size() )
0342       {
0343     cout << __LINE__ << " " << __FILE__ << " wrong trigger " <<  trigger << " max " << TDCEventVector.size() << endl;
0344     return 0;
0345       }
0346 
0347     return TDCEventVector[trigger]->td[tdc].hits;
0348   }
0349   else if ( strcmp(what,"TDC") == 0 )
0350   {
0351     return TDCEventVector[trigger]->td[tdc].TDC;
0352   }
0353 
0354   return 0;
0355 }
0356 
0357 int oncsSub_idfnalmwpcv2::iValue(const int trigger ,const int tdc, const int index, const char *what)
0358 {
0359   decode (0);
0360   if ( trigger < 0 || (unsigned int )trigger >= TDCEventVector.size()) return 0;
0361   if ( tdc < 0 || tdc >= n_tdcs) return 0;
0362   if ( index < 0 || index >= TDCEventVector[trigger]->td[tdc].hits) return 0;
0363 
0364 
0365   if ( strcmp(what,"WIRE") == 0 )
0366   {
0367     return iValue(trigger, tdc, index);
0368   }
0369 
0370   else if ( strcmp(what,"TIMESTAMP") == 0 )
0371   {
0372     return TDCEventVector[trigger]->td[tdc].TDCHitlist[index]->timestamp;
0373   }
0374 
0375   
0376   return 0;
0377 }
0378 
0379 void  oncsSub_idfnalmwpcv2::dump ( OSTREAM& os )
0380 {
0381 
0382   decode (0);
0383   identify(os);
0384 
0385   int j, k, l;
0386 
0387 
0388   os << " Date         " << iValue(0, "MONTH") 
0389      << "/"              << iValue(0,"DAY") 
0390      << "/20"            << iValue(0,"YEAR")  
0391      << " "              << iValue(0,"HOUR")
0392      << ":"              << iValue(0,"MINUTE") 
0393      << ":"              << iValue(0,"SECOND") << endl;
0394   
0395   os << " Spill Counter " << iValue(0,"SPILLCOUNTER") << endl;
0396   
0397   int tc = iValue(0,"TRIGGERCOUNT");
0398 
0399   os << " Trigger Count " << tc  << endl;
0400   os << " TDC Status Bits " <<  hex << iValue(0,"TDCSTATUSBITS") << dec << endl;
0401   os << " Link Status bits " << hex << iValue(0,"LINKSTATUSBITS") << dec << endl;
0402 
0403   for ( k = 0; k < tc; k++)
0404     {
0405 
0406       os << " new event " 
0407      << "      trg#     tdc     hit    wire  timestamp" << endl;
0408 
0409       for ( l = 0; l < iValue(0,"NTDCS"); l++)
0410     {
0411       int hits =iValue ( k, l, "HITS"); 
0412       if ( hits)
0413         {
0414           int tdc = iValue(k,l,"TDC");
0415 
0416           for ( j = 0; j < hits; j++)
0417         {
0418           os << "              " << setw(6) << k 
0419              << setw(8) <<  tdc  << setw(8) << j 
0420              <<  setw (8)  << iValue(k,l,j)
0421              << setw(8)  << iValue(k,l,j,"TIMESTAMP")  << endl;
0422         }
0423         }
0424     }
0425     }
0426   os << endl;
0427   
0428   
0429   
0430 }
0431