Back to home page

sPhenix code displayed by LXR

 
 

    


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

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