MQwF1TDC.cc

Go to the documentation of this file.
00001 /**********************************************************\
00002 * File: MQwF1TDC.C                                         *
00003 *                                                          *
00004 * Author: P. M. King, Rakitha Beminiwattha,                *
00005 *         J. H. Lee                                        *
00006 * Time-stamp: <2010-04-12 12:12>                           *
00007 \**********************************************************/
00008 
00009 #include "MQwF1TDC.h"
00010 #include "QwColor.h"
00011 #include "QwLog.h"
00012 
00013 #include <math.h>
00014 
00015 
00016 const UInt_t MQwF1TDC::kF1Mask_SlotNumber           = 0xf8000000;
00017 const UInt_t MQwF1TDC::kF1Mask_ResolutionLockFlag   = 0x04000000;
00018 const UInt_t MQwF1TDC::kF1Mask_OutputFIFOFlag       = 0x02000000;
00019 const UInt_t MQwF1TDC::kF1Mask_HitFIFOFlag          = 0x01000000;
00020 
00021 const UInt_t MQwF1TDC::kF1Mask_HeaderFlag           = 0x00800000;
00022 
00023 const UInt_t MQwF1TDC::kF1Mask_FakeDataFlag         = 0x00400000;
00024 const UInt_t MQwF1TDC::kF1Mask_ChannelNumber        = 0x003f0000;
00025 const UInt_t MQwF1TDC::kF1Mask_ChipAddress          = 0x00380000;
00026 const UInt_t MQwF1TDC::kF1Mask_ChannelAddress       = 0x00070000;
00027 
00028 const UInt_t MQwF1TDC::kF1Mask_Dataword             = 0x0000ffff;
00029 
00030 const UInt_t MQwF1TDC::kF1Mask_HeaderTrigFIFOFlag   = 0x00400000;
00031 const UInt_t MQwF1TDC::kF1Mask_HeaderEventNumber    = 0x003f0000;
00032 const UInt_t MQwF1TDC::kF1Mask_HeaderTriggerTime    = 0x0000ff80;
00033 const UInt_t MQwF1TDC::kF1Mask_HeaderXorSetupFlag   = 0x00000040;
00034 const UInt_t MQwF1TDC::kF1Mask_HeaderChannelNumber  = 0x0000003f;
00035 const UInt_t MQwF1TDC::kF1Mask_HeaderChipAddress    = 0x00000038;
00036 const UInt_t MQwF1TDC::kF1Mask_HeaderChannelAddress = 0x00000007;
00037 
00038 
00039 
00040 MQwF1TDC::MQwF1TDC()
00041 { 
00042   fF1ROCNumber          = 0;
00043   fF1SlotNumber         = 0;
00044 
00045   fF1HeaderFlag         = kFALSE;
00046 
00047   fF1HitFIFOFlag        = kFALSE;
00048   fF1OutputFIFOFlag     = kFALSE;
00049   fF1ResolutionLockFlag = kFALSE;
00050 
00051   fF1FakeDataFlag       = kFALSE;
00052   fF1ChannelNumber      = 0;
00053   fF1Dataword           = 0;
00054 
00055 
00056   fF1HeaderTrigFIFOFlag = kFALSE;
00057   fF1HeaderEventNumber  = 0;
00058   fF1HeaderTriggerTime  = 0;
00059   fF1HeaderXorSetupFlag = kFALSE;
00060 
00061   fF1MaxChannelsPerModule = 64; 
00062 
00063   // This initial fF1MaxChannelsPerModule 64
00064   // is used to "resize" a vector in RegisterSlotNumber() function
00065   // in each Subsystem, before one can access the real F1TDC 
00066   // configuration from CODA buffer. And it is a constant value (64)
00067   // and is totally independent upon the real F1TDC configuration. 
00068   // The real maximum channel number can be access via F1TDContainer
00069   // class of each subsystem.
00070 
00071   // However, Qweak uses only the Normal Resolution configuration. 
00072   // Thus, it is always 64 channels we uses. 
00073   // If someone wants to use the High Resolution Mode of F1TDC, 
00074   // it would be better to change this number to 32 by hand.
00075   // Friday, September  3 13:50:49 EDT 2010, jhlee
00076 
00077   fF1OverFlowEntryFlag  = kFALSE;
00078   fF1ValidDataSlotFlag  = kFALSE;
00079 }
00080 
00081 MQwF1TDC::~MQwF1TDC() { }
00082 
00083 
00084 void MQwF1TDC::DecodeTDCWord(UInt_t &word, const UInt_t roc_id)
00085 {
00086 
00087   fF1ROCNumber  = roc_id;
00088   fF1SlotNumber = (word & kF1Mask_SlotNumber)>>27;
00089 
00090   if( fF1SlotNumber>=1 && fF1SlotNumber<=21 ) fF1ValidDataSlotFlag = kTRUE;
00091   else                                        fF1ValidDataSlotFlag = kFALSE;
00092 
00093   
00094   fF1HeaderFlag         = ((word & kF1Mask_HeaderFlag)==0); 
00095   // TRUE if the mask bit IS NOT set
00096   
00097   // These three flags should be TRUE if their mask bit IS set
00098   fF1HitFIFOFlag        = ((word & kF1Mask_HitFIFOFlag       )!=0);
00099   fF1OutputFIFOFlag     = ((word & kF1Mask_OutputFIFOFlag    )!=0); 
00100   fF1ResolutionLockFlag = ((word & kF1Mask_ResolutionLockFlag)!=0);
00101   
00102   if (fF1HeaderFlag){
00103     //  This is a header word.
00104     fF1Dataword           = 0;
00105     fF1HeaderTrigFIFOFlag = ((word & kF1Mask_HeaderTrigFIFOFlag)!=0);
00106     fF1HeaderEventNumber  = ( word & kF1Mask_HeaderEventNumber )>>16;
00107     fF1HeaderTriggerTime  = ( word & kF1Mask_HeaderTriggerTime )>>7;
00108     fF1HeaderXorSetupFlag = ((word & kF1Mask_HeaderXorSetupFlag)!=0);
00109     fF1ChannelNumber      = ( word & kF1Mask_HeaderChannelNumber );
00110     fF1ChipAddress        = ( word & kF1Mask_HeaderChipAddress)>>3;
00111     fF1ChannelAddress     = ( word & kF1Mask_HeaderChannelAddress);
00112   } 
00113   else {
00114     // This is a data word.
00115     fF1FakeDataFlag   = ((word & kF1Mask_FakeDataFlag)!=0); // This flag should be TRUE if their mask bit IS set
00116     fF1ChannelNumber  = ( word & kF1Mask_ChannelNumber )>>16;
00117     fF1ChipAddress    = ( word & kF1Mask_ChipAddress )>>19;
00118     fF1ChannelAddress = ( word & kF1Mask_ChannelAddress )>>16;
00119     fF1Dataword       = ( word & kF1Mask_Dataword );
00120 
00121     if(fF1Dataword == 65535) fF1OverFlowEntryFlag = kTRUE;
00122     else                     fF1OverFlowEntryFlag = kFALSE;
00123     // skip to record overflow dataword entry (65535, 0xFFFF)
00124     fF1HeaderEventNumber   = 0;
00125     fF1HeaderTriggerTime   = 0;
00126     // std::cout << "fake flag " << fF1FakeDataFlag
00127     //        << " channel: " << fF1ChannelNumber 
00128     //        << " raw time: " << fF1Dataword 
00129     //        << std::endl;
00130   }
00131   return;
00132 }
00133 
00134 std::ostream& operator<< (std::ostream& os, const MQwF1TDC &f1tdc)
00135 {
00136   if(f1tdc.fF1HeaderFlag) {
00137     os << "<<<< Header:"; 
00138   }
00139   else {
00140     os << ">>>>  DATA :";
00141   }
00142 
00143   os << " Ch" << std::setw(3) << f1tdc.fF1ChannelNumber;
00144   os << "[" << f1tdc.fF1ChipAddress;
00145   os << "," << f1tdc.fF1ChannelAddress;
00146   os << "]";
00147 
00148   if(f1tdc.fF1HeaderFlag) {
00149     os << " Xor " << f1tdc.fF1HeaderXorSetupFlag
00150        << " tOF " << f1tdc.fF1HeaderTrigFIFOFlag;
00151   }
00152   else {
00153      os << " - DATA " 
00154        << f1tdc.fF1FakeDataFlag
00155        << " - ";
00156    }
00157   
00158   os << "(hitOF,outOF,resLK)("
00159      << f1tdc.fF1HitFIFOFlag
00160      << f1tdc.fF1OutputFIFOFlag
00161      << f1tdc.fF1ResolutionLockFlag
00162      << ")";
00163   os << " ROC" << std::setw(2) << f1tdc.fF1ROCNumber;
00164 
00165   Int_t slot = 0;
00166   slot = f1tdc.fF1SlotNumber;
00167 
00168   os << " Slot" << std::setw(2) << slot;
00169     
00170   if(f1tdc.fF1HeaderFlag) {
00171     os << " EvtN" << std::setw(2) << f1tdc.fF1HeaderEventNumber;
00172     os << " TriT" << std::setw(4) << f1tdc.fF1HeaderTriggerTime;
00173   }
00174   else {
00175     os << " RawT " << std::setw(10) << f1tdc.fF1Dataword;
00176   }
00177   
00178   if(slot == 0) {
00179     os << ": a filler word";
00180   }
00181   if( (not f1tdc.fF1HeaderFlag) and (f1tdc.fF1FakeDataFlag) ){
00182     os << ": --> fake data";
00183   }
00184   
00185     //  os << std::endl;
00186   return os;
00187 }
00188 
00189 
00190 
00191 void MQwF1TDC::Print(Bool_t flag)
00192 {
00193   if (! this) return; // do nothing if this is a null object
00194 
00195   if(flag) {
00196     std::cout << *this << std::endl;
00197   }
00198   return;
00199 }
00200 
00201 
00202 void MQwF1TDC::PrintTDCHeader(Bool_t flag)
00203 {
00204   if (! this) return; // do nothing if this is a null object
00205 
00206   if(flag) {
00207     std::cout << *this << std::endl;
00208   }
00209   return;
00210 }
00211 
00212 
00213 void MQwF1TDC::PrintTDCData(Bool_t flag)
00214 {
00215   if (! this) return; // do nothing if this is a null object
00216   
00217   if(flag) {
00218     std::cout << *this << std::endl;
00219   }
00220   return;
00221 }
00222 
00223 
00224 // Double_t MQwF1TDC::SubtractReference(Double_t rawtime, Double_t reftime)
00225 // {
00226 //   //  Note that this produces the opposite sign of the corrected time
00227 //   //  as compared to the UInt_t version from revision 423 shown above.
00228 //   //
00229 //   //  For Region 3, according to the UInt_t version from revision 423,
00230 //   //  the internal parameters should be:
00231 //   //      fMinDiff   = -30000
00232 //   //      fMaxDiff   =  30000
00233 //   //      fOffset    =  64495
00234 //   //      fTimeShift =   8929
00235 //   //
00236 //   Double_t real_time = rawtime - reftime;  
00237 
00238 //   if( real_time < fMinDiff ) {
00239 //     real_time += fOffset;
00240 //   }
00241 //   else if( real_time > fMaxDiff) {
00242 //     real_time -= fOffset;
00243 //   }
00244 //   real_time = real_time + fTimeShift;
00245 //   return real_time;
00246 // }
00247 
00248 
00249 
00250 // Double_t MQwF1TDC::ActualTimeDifference(Double_t raw_time, Double_t ref_time)
00251 // {
00252  
00253 //   Double_t trigger_window = 12896.0;
00254 //   Double_t time_offset    = 65341.0;
00255 
00256 //   Double_t time_condition = 0.0;
00257 //   Double_t local_time_difference = 0.0;
00258 //   Double_t actual_time_difference = 0.0;
00259 
00260 //   local_time_difference = raw_time - ref_time; 
00261   
00262 //   if(local_time_difference == 0.0) {
00263 //     // raw_time is the same as ref_time
00264 //     actual_time_difference = local_time_difference;
00265 //   }
00266 //   else {
00267 //     time_condition = fabs(local_time_difference); 
00268 //     // maximum value is trigger_window -1, 
00269 //     // thus 12896-1 =  12895 - 0 = 12985
00270 //     if(time_condition < trigger_window) {
00271 //       // there is no ROLLEVENT within trigger window
00272 //       actual_time_difference = local_time_difference;
00273 //     }
00274 //     else {
00275 //       // there is an ROLLOVER event within trigger window
00276 //       if (local_time_difference > 0.0) {
00277 //  // ref_time is in after ROLLOVER event
00278 //  actual_time_difference =  local_time_difference - time_offset;
00279 //       }
00280 //       else {
00281 //  // we already excluded local_time_diffrence == 0 case.
00282 //  // ref_time is in before ROLLOVER event
00283 //  actual_time_difference = local_time_difference + time_offset;
00284 //       }
00285       
00286 //     }
00287 //   }
00288 //   return actual_time_difference;
00289 // }
00290 
00291 
00292 
00293 void MQwF1TDC::PrintResolutionLockStatus(const UInt_t roc_id)
00294 {
00295   if (not fF1ResolutionLockFlag) {
00296     QwWarning << "F1TDC board RESOULTION LOCK FAIL at Ch " 
00297         << GetTDCChannelNumber() << " ROC " << roc_id
00298         << " Slot " << GetTDCSlotNumber() << QwLog::endl;
00299   }
00300   return;
00301 }
00302 
00303 
00304 
00305 void MQwF1TDC::PrintHitFIFOStatus(const UInt_t roc_id)
00306 {
00307   if (fF1HitFIFOFlag) {
00308     QwWarning << "F1TDC board HIT FIFO FULL at Ch "
00309               << GetTDCChannelNumber() << " ROC " << roc_id
00310               << " Slot " << GetTDCSlotNumber() << QwLog::endl;
00311   }
00312   return;
00313 }
00314 
00315 
00316 
00317 void MQwF1TDC::PrintOutputFIFOStatus(const UInt_t roc_id)
00318 {
00319   if (fF1OutputFIFOFlag) {
00320     QwWarning << "F1TDC board OUTPUT FIFO FULL at Ch "
00321               << GetTDCChannelNumber() << " ROC " << roc_id
00322               << " Slot " << GetTDCSlotNumber() << QwLog::endl;
00323   }
00324   return;
00325 }
00326 
00327 
00328 Bool_t MQwF1TDC::IsValidDataword() const
00329 {
00330   // fF1ValidDataSlotFlag = TRUE,
00331   // fF1ResolutionFlag    = TRUE,  
00332   // fF1HeaderFlag        = FALSE, 
00333   // fF1OverFlowEntry     = FALSE, 
00334   // fF1FakeDataWord      = FALSE, then it is a valid data word.
00335   if( fF1ValidDataSlotFlag && fF1ResolutionLockFlag && !fF1HeaderFlag && !fF1OverFlowEntryFlag && !fF1FakeDataFlag)
00336     //  if( fF1ValidDataSlotFlag && fF1ResolutionLockFlag && !fF1HeaderFlag)
00337     return kTRUE;
00338   else                                             
00339     return kFALSE; 
00340 }
00341 
00342 
00343 // Bool_t MQwF1TDC::CheckDataIntegrity(const UInt_t roc_id, UInt_t *buffer, UInt_t num_words)
00344 // {
00345 //   UInt_t reference_trig_time = 0;
00346 //   UInt_t reference_event_num = 0;
00347 
00348 //   const Int_t valid_trigger_time_offset = 1;
00349   
00350 //   Bool_t event_ok_flag       = kFALSE;
00351 //   Bool_t trig_time_ok_flag   = kFALSE;
00352 //   Bool_t data_integrity_flag = kFALSE;
00353 
00354 //   Bool_t temp_print_flag = false;
00355 
00356 //   for (UInt_t i=0; i<num_words ; i++) {
00357 
00358 //     DecodeTDCWord(buffer[i], roc_id); 
00359 
00360  
00361 //     // We use the multiblock data transfer for F1TDC, thus
00362 //     // we must get the event number and the trigger time from the first buffer
00363 //     // (buffer[0]), and these valuse can be used to check "data" integrity
00364 //     // over all F1TDCs
00365 //     if ( i==0 ) {//;
00366 //       if ( IsHeaderword() ) {//;;
00367 //  reference_event_num = GetTDCEventNumber();
00368 //  reference_trig_time = GetTDCTriggerTime();
00369 //  PrintTDCHeader(temp_print_flag);
00370 //       }//;;
00371 //       else {//;;
00372 //  QwWarning << QwColor(Qw::kRed)
00373 //      << "The first word of F1TDC must be header word. "
00374 //      << "Something wrong into this CODA stream.\n";
00375 //  QwWarning << QwLog::endl;
00376 //  return false;
00377 //       }//;;
00378 //     }//;
00379 //     else {//;
00380 //       if ( IsHeaderword() ) {//;;
00381 //  // Check date integrity, if it is fail, we skip this whole buffer to do further process 
00382 //  event_ok_flag     = ( reference_event_num == GetTDCHeaderEventNumber() );
00383 //  trig_time_ok_flag = abs( reference_trig_time - GetTDCHeaderTriggerTime() ) <= valid_trigger_time_offset;
00384 //  PrintTDCHeader(temp_print_flag);
00385 
00386 //  // If SEU exists, Xor Setup Register bit is changing from 1 to 0, I think.
00387 //  // Thus, it sets the trigger time 0 and the event number 0.
00388 //  // For example, 
00389 //  // Ch  8 Xor 0 tOF 0(hitOF,outOF,resLK)(001) ROC  9 Slot 10 EvtN 0 TriT   0
00390 //  // And it is the source of the trigger time and the event number differences
00391 //  // within the same ROC. In the CheckDataIntegrity routine, I decided
00392 //  // to skip such a event. 
00393 //  // Sunday, August  8 03:42:48 EDT 2010, jhlee
00394   
00395 //  if (IsHeaderXorSetup()) {//;;;
00396 //    // Trigger Time difference of up to 1 count among the chips is acceptable
00397 //    // For the Trigger Time, this assumes that an external SYNC_RESET signal has
00398 //    // been successfully applied at the start of the run
00399 //    if (not trig_time_ok_flag) {
00400 //      if(temp_print_flag){
00401 //        QwWarning  << QwColor(Qw::kBlue)
00402 //       << "There is the no SYNC_RESET on the F1TDC board at"
00403 //       << " Ch "   << fF1ChannelNumber
00404 //       << " ROC "  << fF1ROCNumber 
00405 //       << " Slot " << fF1SlotNumber <<"\n";
00406 //        QwWarning  << QwColor(Qw::kBlue)
00407 //       << "This event is excluded from the ROOT data stream.\n";
00408 //        QwWarning << QwColor(Qw::kRed) 
00409 //      << "Please, send an email to (a) Qweak DAQ expert(s) if you have time.\n";
00410 //        QwWarning  << QwLog::endl;
00411 //      }
00412 //    }
00413 //    // Any difference in the Event Number among the chips indicates a serious error
00414 //    // that requires a reset of the board.
00415     
00416 //    if (not event_ok_flag) {
00417 //      if(temp_print_flag){
00418 //        QwWarning << QwColor(Qw::kRed)
00419 //      << "There is the Event Number Mismatch issue on the F1TDC board at"
00420 //      << " ROC "  << fF1ROCNumber
00421 //      << " Slot " << fF1SlotNumber << "\n";
00422 //        QwWarning << QwColor(Qw::kRed) 
00423 //      << "This event is excluded from the ROOT data stream.\n";
00424 //        QwWarning << QwColor(Qw::kRed) 
00425 //      << "Please, send an email to (a) Qweak DAQ expert(s) if you have time.\n";
00426 //        QwWarning << QwLog::endl;
00427 //      }
00428 //    }
00429     
00430 //    data_integrity_flag = (event_ok_flag) && (trig_time_ok_flag) && IsNotHeaderTrigFIFO() ;
00431 
00432 //    if (not data_integrity_flag)  return data_integrity_flag; //false
00433 //    // we stop check data, because all other next buffers 
00434 //    // is useless and we don't need to check them in order to save some time.
00435 //  } //;;;
00436 //  else {//;;;
00437 
00438 //    if (temp_print_flag) {
00439 
00440 //      // I don't include the SEU in the CheckDataIntegrity.
00441 //      // At this moment, I have no idea how I handle during data processes.
00442 //      // Sunday, August  8 04:02:17 EDT 2010, jhlee
00443       
00444 //      QwWarning << QwColor(Qw::kRed)
00445 //          << "There is the Single Event Upset (SEU) on the F1TDC board at"
00446 //          << " ROC "  << fF1ROCNumber
00447 //          << " Slot " << fF1SlotNumber << "\n";
00448 //      QwWarning << QwColor(Qw::kRed) 
00449 //          << "Please, send an email to (a) Qweak DAQ expert(s) if you have time.\n";
00450 //      QwWarning << QwLog::endl;
00451 //    }
00452 //  }//;;;
00453 //       }//;;
00454 //       else { //;; // dataword
00455 //  if(!fF1OverFlowEntryFlag) PrintTDCData(temp_print_flag);
00456 //       }//;;
00457 //     }//;
00458 //   }//for (UInt_t i=0; i<num_words ; i++) {
00459   
00460   
00461 //   return (data_integrity_flag); 
00462   
00463 // }
00464 

Generated on 19 Feb 2017 for QwAnalysis by  doxygen 1.6.1