algo_fem_decoder_base.cc

Go to the documentation of this file.
00001 #ifndef ALGO_FEM_DECODER_BASE
00002 #define ALGO_FEM_DECODER_BASE
00003 
00004 #include "algo_fem_decoder_base.hh"
00005 
00006 //#################################################
00007 algo_fem_decoder_base::algo_fem_decoder_base() 
00008   : algo_base() 
00009 //#################################################
00010 {
00011   _name = "algo_fem_decoder_base";
00012   reset();
00013 }
00014 
00015 
00016 //#################################################
00017 void algo_fem_decoder_base::reset() {
00018 //#################################################
00019 
00020   algo_base::reset();
00021   
00022   _last_word             = PMT::INVALID_WORD;
00023 
00024   _event_header_count    = 0;
00025 
00026   _search_for_next_event = false;
00027 
00028   for(size_t i=0; i< FEM_HEADER_COUNT; i++)
00029 
00030     _event_header_words[i] = 0;
00031 
00032 }
00033 
00034 
00035 //#################################################
00036 bool algo_fem_decoder_base::process_word(PMT::word_t word)
00037 //#################################################
00038 {
00039   //std::cout<<Form("%x",word)<<std::endl;
00040   // 
00041   // A simple function to call other members depending on the status.
00042   // Let other members to deal with expected/unexpected case
00043   //
00044 
00045   // If in back_trace mode, add this word in record
00046   if(_bt_mode){
00047     
00048     // Check if buffer is filled
00049     if(!_bt_nwords_filled)
00050       _bt_nwords_filled = (_bt_nwords == _bt_words.size());
00051 
00052     // If filled, remove the oldest element
00053     if(_bt_nwords_filled)
00054       _bt_words.pop_front();
00055 
00056     // Add new word
00057     _bt_words.push_back(word);
00058 
00059   }
00060 
00061   bool status=true;
00062   PMT::word_t word_class=get_word_class(word);
00063   PMT::word_t last_word_class=get_word_class(_last_word);
00064   //
00065   // Skip this word if a boolean is set to skip to the next event header
00066   //
00067   if( _search_for_next_event &&  
00068       word_class == PMT::FEM_HEADER &&
00069       last_word_class != PMT::FEM_HEADER ) 
00070     
00071     _search_for_next_event = false;
00072 
00073 
00074   if( _search_for_next_event ) {
00075 
00076     if(_verbosity[MSG::INFO])
00077 
00078       Message::send(MSG::INFO,__FUNCTION__,
00079             Form("Skipping a word (%x, previous=%x) to the next event..",word,_last_word));
00080 
00081     _last_word = PMT::INVALID_WORD;
00082 
00083     return true;
00084   }
00085 
00086   switch(word_class){
00087     
00088   case PMT::EVENT_HEADER:
00089 
00090     // (1) Call process_event_header()
00091     status = process_event_header(word,_last_word);
00092     break;
00093 
00094   case PMT::FEM_HEADER:
00095 
00096     // (1) Check if the last word was EVENT_HEADER, FEM_HEADER, or EVENT_LAST_WORD
00097     //     - If EVENT_HEADER, continue to (2)
00098     //     - If FEM_HEADER,   continue to (2)
00099     //     - If EVENT_LAST_WORD, attempt to store & continue to (2)
00100     // (2) Call process_fem_header()
00101     status = process_fem_header(word,_last_word);
00102     break;
00103 
00104   case PMT::FEM_FIRST_WORD:
00105   case PMT::CHANNEL_HEADER:
00106   case PMT::CHANNEL_WORD:
00107   case PMT::CHANNEL_LAST_WORD:
00108   case PMT::FEM_LAST_WORD:
00109     {
00110       // (1) Call process_ch_word()
00111       //     - Children class should implement what should be checked in correlation to the last word.
00112       
00113       // Split two 16 bit words
00114       PMT::word_t first_word  = (word & 0xffff);
00115       PMT::word_t second_word = (word >> 16);
00116 
00117       if(status) status = process_ch_word(first_word,_last_word);
00118       
00119       // Check if the left 16-bit word is also the relevant type or not
00120       if(status){
00121 
00122     switch(get_word_class(second_word)){
00123     case PMT::FEM_FIRST_WORD:
00124     case PMT::CHANNEL_HEADER:
00125     case PMT::CHANNEL_WORD:
00126     case PMT::CHANNEL_LAST_WORD:
00127       status = process_ch_word(second_word,_last_word);
00128       break;
00129     case PMT::FEM_LAST_WORD:
00130       status = process_fem_last_word(second_word,_last_word);
00131       break;
00132     default:
00133       status = false;
00134       Message::send(MSG::ERROR,__FUNCTION__,
00135             Form("Unexpected word (%x) while processing channel data (previous=%x)",second_word,first_word));
00136     }
00137 
00138       }
00139       break;
00140     }
00141   case PMT::EVENT_LAST_WORD:
00142     // (1) Call process_event_last_word()
00143     status = process_event_last_word(word,_last_word);
00144     break;
00145 
00146   case PMT::UNDEFINED_WORD: 
00147 
00148 
00149     if(word != 0x0 || (last_word_class != PMT::EVENT_LAST_WORD && last_word_class != PMT::FEM_LAST_WORD) ) {
00150 
00151       Message::send(MSG::ERROR,__FUNCTION__,
00152             Form("Undefined word: %x (previous = %x)",word,_last_word));
00153       
00154       status = false;
00155     }else if(_verbosity[MSG::INFO]){
00156     
00157       // This happens sometimes according to Chi 10/01/13
00158       Message::send(MSG::INFO,__FUNCTION__,
00159             Form("Padding of undefined word (tolerated): %x (previous=%x)",word,_last_word));
00160     }
00161     break;
00162   }
00163 
00164   if(!status){
00165 
00166     backtrace();
00167 
00168     if(_debug_mode) {
00169 
00170       if(_header_info.event_id>0)
00171 
00172     Message::send(MSG::WARNING,__FUNCTION__,Form("Failed decoding event %d ...",_header_info.event_id));
00173 
00174       Message::send(MSG::WARNING,__FUNCTION__,"DEBUG MODE => Continue to the next event...\n");
00175 
00176       _search_for_next_event = true;
00177       clear_event();
00178     }
00179   }
00180 
00181   return status;
00182 }
00183 
00184 //#################################################
00185 bool algo_fem_decoder_base::process_fem_header(const PMT::word_t word, PMT::word_t &last_word) {
00186 //#################################################
00187   
00188   bool status=true;
00189   //
00190   // Check if this is an event header word or not
00191   //
00192   PMT::PMT_WORD word_class=get_word_class(word);
00193   if(_verbosity[MSG::DEBUG]){
00194     sprintf(_buf,"Processing Header: %x",word);
00195     Message::send(MSG::DEBUG,__FUNCTION__,_buf);
00196   }
00197 
00198 
00199   if( word_class != PMT::FEM_HEADER) {
00200     
00201     Message::send(MSG::ERROR,__FUNCTION__,
00202           Form("Encountered unexpected word while an event header search: %x (word type=%d)",
00203                word,word_class) );
00204     status = false;    
00205 
00206   }else if(get_word_class(word>>16)!=PMT::FEM_HEADER) {
00207 
00208     // Event header should come as a 32-bit word which is a pair of two 16-bit header words.
00209     // The first 16-bit is already checked by this point. Check the second part.
00210 
00211     Message::send(MSG::ERROR,__FUNCTION__,Form("Found an odd event header word: %x",word));
00212       
00213     status = false;
00214     
00215   }
00216 
00217   if(status) {
00218 
00219     //
00220     // Check the last word type
00221     //
00222     switch(get_word_class(last_word)){
00223     case PMT::EVENT_HEADER:      
00224     case PMT::FEM_HEADER:
00225     case PMT::FEM_LAST_WORD:
00226       // Expected. Nothing to do
00227       break;
00228     case PMT::FEM_FIRST_WORD:
00229     case PMT::CHANNEL_HEADER:
00230     case PMT::CHANNEL_WORD:
00231     case PMT::UNDEFINED_WORD:
00232     case PMT::EVENT_LAST_WORD:
00233       // ERROR
00234       Message::send(MSG::ERROR,__FUNCTION__,
00235             Form("Unexpected word while FEM_HEADER processing: %x (previous word=%x)",word,last_word));
00236       status = false;
00237       break;
00238     case PMT::CHANNEL_LAST_WORD:
00239       // Store data
00240       status = store_event();
00241       if(_debug_mode) {
00242     // We have to handle this case separately from a uniifed handling @ process_word
00243     // Because "this" header word is still good. Make a warning to a user.
00244 
00245     Message::send(MSG::WARNING,__FUNCTION__,"DEBUG MODE => Continue to the next event...\n");
00246 
00247     clear_event();
00248 
00249     status = true; 
00250       }
00251       break;
00252     }
00253 
00254     if(status){
00255     
00256       // Process the subject word as an event header
00257       if (_event_header_count<FEM_HEADER_COUNT) {
00258     
00259     // Store header words
00260     _event_header_words[_event_header_count]=word;
00261     _event_header_count++;
00262     
00263     // If stored number of header words reached to the expected number, decode.
00264     if(_event_header_count==FEM_HEADER_COUNT) {
00265       
00266       // Decode header words
00267       status = decode_fem_header(_event_header_words);
00268       
00269     }
00270       }else{
00271     
00272     // Raise error if a header word count > set constant (should not happen)
00273     Message::send(MSG::ERROR,__FUNCTION__,
00274               Form("Logic error: event header word counter not working! (%zu/%zu)",
00275                _event_header_count,FEM_HEADER_COUNT));
00276     status=false;
00277       }
00278     }
00279   }
00280   
00281   if(!status){
00282     
00283     Message::send(MSG::ERROR,__FUNCTION__,
00284           Form("Failed processing the word %x (last word %x) as an event header!",word,last_word));
00285 
00286   }
00287   
00288   last_word = word;
00289   return status;  
00290   
00291 }
00292 
00293 
00294 //#################################################
00295 bool algo_fem_decoder_base::decode_fem_header(const PMT::word_t *event_header){
00296 //#################################################
00297 
00298   bool status=true;
00299   //
00300   // Get event information
00301   //
00302 
00303   // (1) check if the very first 16-bit word is as expected
00304   if(!( event_header[0] & 0xffff))
00305     Message::send(MSG::ERROR,"Unexpected first word in event headers!");
00306 
00307   if(!status) return status;
00308 
00309   // Initialize data holder
00310   _header_info.clear_event();
00311 
00312   // (2) get module address ... lowest 5 of 12 bits
00313   _header_info.module_address = ( (event_header[0]>>16 & 0xfff)    & 0x1f);
00314 
00315   // (3) get module ID number ... upper 7 bit of 12 bits
00316   _header_info.module_id      = ( (event_header[0]>>16 & 0xfff)>>5 & 0x7f);
00317 
00318   // (4) get number of 16-bit words to be read in this event.
00319   // Lower 12 bits of two 16-bit words.
00320   // The very last "last word for channel info" is not included in this.
00321   // For later checking purpose, increment by 1.
00322   _header_info.nwords         = ( (((event_header[1]>>16) & 0xfff) + ((event_header[1] & 0xfff)<<12)));
00323 
00324   // (5) get event ID
00325   // Lower 12 bits of two 16-bit words.
00326   _header_info.event_id       = ( (((event_header[2]>>16) & 0xfff) + ((event_header[2] & 0xfff)<<12)));
00327 
00328   // (6) get frame ID
00329   // Lower 12 bits of two 16-bit words.
00330   _header_info.event_frame_id = ( (((event_header[3]>>16) & 0xfff) + ((event_header[3] & 0xfff)<<12)));
00331 
00332   // (7) get checksum
00333   _header_info.checksum       = ( (((event_header[4]>>16) & 0xfff) + ((event_header[4] & 0xfff)<<12)));
00334 
00335 
00336 #ifdef INCLUDE_EXTRA_HEADER
00337   _header_info.trigger_frame_id  = ( ((event_header[5] & 0xfff)>>4 & 0xf) +
00338                      (((_header_info.event_frame_id)>>4)<<4)); 
00339 
00340   // Correct for a roll over
00341   _header_info.trigger_frame_id  = round_diff(_header_info.event_frame_id, _header_info.trigger_frame_id, 0x7);
00342 
00343   _header_info.trigger_timeslice = ((((event_header[5]>>16) & 0xf)<<8) + (event_header[5] & 0xff));
00344 
00345 #endif
00346 
00347   // Report if verbosity is set.
00348   if(_verbosity[MSG::INFO])
00349     {
00350       Message::send(MSG::INFO,Form("Module %d (ID=%d)", _header_info.module_address, _header_info.module_id));
00351       Message::send(MSG::INFO,Form("Event ID %d",_header_info.event_id));
00352       Message::send(MSG::INFO,Form("Frame ID %d",_header_info.event_frame_id));
00353       Message::send(MSG::INFO,Form("Number of Words = %d",_header_info.nwords));
00354       Message::send(MSG::INFO,Form("Checksum = %x", _header_info.checksum));
00355       Message::send(MSG::INFO,Form("Trigger Frame %d",_header_info.trigger_frame_id));
00356       Message::send(MSG::INFO,Form("Trigger Sample %d",_header_info.trigger_timeslice));
00357     }
00358 
00359   _checksum=0;
00360 
00361   _nwords=0;
00362               
00363   return status;
00364 }
00365 
00366 
00367 //#################################################
00368 PMT::word_t algo_fem_decoder_base::round_diff(PMT::word_t ref_id, 
00369                           PMT::word_t subject_id, 
00370                           PMT::word_t diff) const
00371 //#################################################
00372 {
00373   // Used to recover pmt/trigger frame id from roll over effect.
00374   // One can test this by simply calling this function.
00375   // For instance, to test the behavior for a roll-over of 0x7 ...
00376   //
00377   // > root
00378   // root[0] gSystem->Load("libDecoder")
00379   // root[1] algo_slow_readout_decoder k
00380   // root [6] k.get_pmt_frame(583,584,0x7)
00381   // (const unsigned int)584
00382   // root [7] k.get_pmt_frame(584,583,0x7)
00383   // (const unsigned int)583
00384   //
00385   // I think this implementation works. ... Aug. 12 2013
00386   if( (subject_id > ref_id) && ((subject_id-ref_id) >= diff) )
00387     return subject_id - (diff+1);
00388   else if( (ref_id > subject_id) && ((ref_id-subject_id) >= diff) )    
00389     return subject_id + (diff+1);
00390   else
00391     return subject_id;
00392 
00393 }
00394 
00395 //#################################################
00396 bool algo_fem_decoder_base::add_huffman_adc(std::vector<UShort_t> &wf, size_t zero_count) 
00397 {
00398 //#################################################
00399 
00400   bool status = true;
00401 
00402   switch(zero_count){
00403     
00404   case 0:
00405     wf.push_back( (*(wf.rbegin())) ); break;      
00406     
00407   case 1:
00408     wf.push_back( (*(wf.rbegin())) -1 ); break;
00409     
00410   case 2:
00411     wf.push_back( (*(wf.rbegin())) +1 ); break;
00412     
00413   case 3:
00414     wf.push_back( (*(wf.rbegin())) -2 ); break;
00415     
00416   case 4:
00417     wf.push_back( (*(wf.rbegin())) +2 ); break;
00418     
00419   case 5:
00420     wf.push_back( (*(wf.rbegin())) -3 ); break;
00421     
00422   case 6:
00423     wf.push_back( (*(wf.rbegin())) +3 ); break;
00424     
00425   default:
00426 
00427     std::cout<<zero_count<<std::endl;
00428     
00429     status = false;
00430   }
00431   
00432   return status;
00433 
00434 }
00435 
00436 
00437 #endif

Generated on Mon Apr 7 15:35:12 2014 for MyProject by  doxygen 1.4.7