algo_tpc_huffman.cc

Go to the documentation of this file.
00001 #ifndef ALGO_TPC_HUFFMAN_CC
00002 #define ALGO_TPC_HUFFMAN_CC
00003 
00004 #include "algo_tpc_huffman.hh"
00005 
00006 algo_tpc_huffman::algo_tpc_huffman() : algo_tpc_xmit()
00007 {
00008   _name = "algo_tpc_huffman";
00009   reset();
00010 }  
00011 
00012 void algo_tpc_huffman::reset() {
00013 
00014   algo_tpc_xmit::reset();
00015 
00016 }
00017 
00018 void algo_tpc_huffman::clear_event() {
00019 
00020   _search_header = false;
00021 
00022   algo_tpc_xmit::clear_event();
00023 
00024 }
00025 
00026 bool algo_tpc_huffman::process_word(const PMT::word_t word) {
00027 
00028   // If in back_trace mode, add this word in record
00029   if(_bt_mode){
00030     
00031     // Check if buffer is filled
00032     if(!_bt_nwords_filled)
00033       _bt_nwords_filled = (_bt_nwords == _bt_words.size());
00034 
00035     // If filled, remove the oldest element
00036     if(_bt_nwords_filled)
00037       _bt_words.pop_front();
00038 
00039     // Add new word
00040     _bt_words.push_back(word);
00041 
00042   }
00043 
00044   if(word==0x0)
00045 
00046     return true;
00047 
00048   bool status = true;
00049   PMT::word_t word_class = get_word_class(word);
00050   PMT::word_t last_word_class = get_word_class(_last_word);
00051 
00052   if( _search_for_next_event ) {
00053     
00054     if( !(word_class == PMT::EVENT_HEADER && 
00055       last_word_class == PMT::EVENT_LAST_WORD ) ) {
00056       
00057       _last_word = word;
00058       return status;
00059     }
00060 
00061   }
00062 
00063 
00064 
00065   //
00066   // In case of huffman coded data stream, uniquely marked
00067   // words are only:
00068   // (*) event header
00069   // (*) event last word 
00070   // (*) channel header
00071   // (*) channel last word
00072   //
00073   switch(word_class){
00074 
00075   case PMT::EVENT_HEADER:
00076 
00077     if( (last_word_class == PMT::EVENT_LAST_WORD && !(_header_info.nwords)) || !(_event_data)) {
00078       
00079       _search_for_next_event = false;
00080       
00081       status = process_event_header(word,_last_word);
00082     }
00083     else{
00084 
00085       PMT::word_t first_word  = (word & 0xffff);
00086       PMT::word_t second_word = (word >> 16);
00087       
00088       status = process_ch_word(first_word,_last_word);
00089 
00090       if(status) status = process_ch_word(second_word,_last_word);
00091 
00092     }
00093 
00094     break;
00095 
00096   case PMT::FEM_HEADER:
00097 
00098     if(_nwords && _nwords == _header_info.nwords){
00099 
00100       _nwords++;
00101       status = store_event();
00102 
00103     }
00104 
00105     if(status){ 
00106 
00107       if(!(_header_info.nwords))
00108 
00109     status = process_fem_header(word,_last_word);
00110       
00111       else{
00112 
00113     PMT::word_t first_word  = (word & 0xffff);
00114     PMT::word_t second_word = (word >> 16);
00115     
00116     status = process_ch_word(first_word,_last_word);
00117     
00118     if(status) status = process_ch_word(second_word,_last_word);
00119     
00120       }
00121     }
00122 
00123     break;
00124     
00125   case PMT::EVENT_LAST_WORD:
00126 
00127     //if(last_word_class == PMT::CHANNEL_LAST_WORD){
00128 
00129     status = process_event_last_word(word,_last_word);
00130     break;
00131     //}
00132 
00133   default:
00134 
00135     PMT::word_t first_word  = (word & 0xffff);
00136     PMT::word_t second_word = (word >> 16);
00137     
00138     status = process_ch_word(first_word,_last_word);
00139     
00140     if(status) status = process_ch_word(second_word,_last_word);
00141 
00142   }
00143 
00144   if(!status){
00145 
00146     if(_bt_mode)
00147       backtrace();
00148 
00149     clear_event();
00150 
00151     if(_debug_mode){
00152 
00153       Message::send(MSG::WARNING,__FUNCTION__,"DEBUG MODE => Continue to next event...");
00154       
00155       _search_for_next_event = true;
00156 
00157     }
00158 
00159   }
00160 
00161   return status;
00162 }
00163 
00164 bool algo_tpc_huffman::process_event_header(const PMT::word_t word,
00165                         PMT::word_t &last_word) 
00166 {
00167   bool status = true;
00168 
00169   if(!_event_data)
00170 
00171     _event_data = (tpc_wf_collection*)(_storage->get_data(DATA_STRUCT::TPC_WF_COLLECTION));
00172 
00173   else if(get_word_class(last_word)!=PMT::EVENT_LAST_WORD){
00174 
00175     Message::send(MSG::ERROR,__FUNCTION__,
00176           Form("Unexpected event header (%x) with the previous word %x!",word,last_word));
00177 
00178     status = false;
00179 
00180   }
00181 
00182   last_word = word;
00183 
00184   return status;
00185 }
00186 
00187 bool algo_tpc_huffman::process_fem_header(const PMT::word_t word,
00188                       PMT::word_t &last_word) 
00189 {
00190   bool status = true;
00191   //
00192   // This function must be called for true FEM headers.
00193   // Hence we implement a strict check to make sure this is FEM header
00194   //
00195   PMT::word_t last_word_class = get_word_class(last_word);
00196 
00197   if(last_word_class != PMT::EVENT_HEADER &&
00198      last_word_class != PMT::FEM_HEADER &&
00199      last_word_class != PMT::CHANNEL_LAST_WORD) {
00200 
00201     Message::send(MSG::ERROR,__FUNCTION__,
00202           Form("Unexpected FEM header (%x) with the previous word %x!",word,last_word));
00203 
00204     status = false;
00205   }else if(get_word_class(word>>16)!=PMT::FEM_HEADER) {
00206 
00207     // Event header should come as a 32-bit word which is a pair of two 16-bit header words.
00208     // The first 16-bit is already checked by this point. Check the second part.
00209 
00210     Message::send(MSG::ERROR,__FUNCTION__,Form("Found an odd event header word: %x",word));
00211       
00212     status = false;    
00213   }else{
00214 
00215     _event_header_words[_event_header_count] = word;
00216 
00217     _event_header_count++;
00218 
00219     if(_event_header_count == FEM_HEADER_COUNT)
00220 
00221       status = decode_fem_header(_event_header_words);
00222   
00223   }
00224 
00225   last_word = word;
00226 
00227   return status;
00228 }
00229 
00230 bool algo_tpc_huffman::process_event_last_word(const PMT::word_t word,
00231                            PMT::word_t &last_word) 
00232 {
00233   bool status = true;
00234   
00235   //
00236   // Make an explicit check.
00237   // Previous word should be the channel last word
00238   // By this point data should be saved and _header_info should be cleared.
00239   //
00240   PMT::word_t last_word_class = get_word_class(last_word);
00241 
00242   if(last_word_class != PMT::CHANNEL_LAST_WORD) {
00243 
00244     Message::send(MSG::ERROR,__FUNCTION__,
00245           Form("Unexpected event last word (%x) with the previous word %x!",word,last_word));
00246 
00247     status = false;
00248 
00249   }else if(_header_info.event_id!=PMT::INVALID_WORD){
00250 
00251     Message::send(MSG::ERROR,__FUNCTION__,
00252           Form("End of event (%x) ... but buffer holds data for event %d!",word,_header_info.event_id));
00253 
00254     status = false;
00255 
00256   }
00257 
00258   last_word = word;
00259 
00260   return status;
00261 }
00262 
00263 bool algo_tpc_huffman::process_fem_last_word(const PMT::word_t word,
00264                          PMT::word_t &last_word) 
00265 {
00266   //
00267   // This function should not be used as of now
00268   //
00269   Message::send(MSG::ERROR,__FUNCTION__,
00270         "This function should not be called...");
00271 
00272   last_word = word;
00273   return false;
00274 }
00275 
00276 bool algo_tpc_huffman::process_ch_word(const PMT::word_t word,
00277                        PMT::word_t &last_word) 
00278 {
00279 
00280   //
00281   // This function expects either of three kinds:
00282   // ch header ... marked
00283   // ch data (adc) ... unmarked
00284   // ch last word ... marked
00285   //
00286   bool status = true;
00287   PMT::word_t word_class      = get_word_class(word);
00288   PMT::word_t last_word_class = get_word_class(last_word);
00289 
00290   // Check for zero-padding that is allowed after channel last word
00291   if(word == 0x0){
00292 
00293     if(get_word_class(last_word)!=PMT::CHANNEL_LAST_WORD){
00294 
00295       Message::send(MSG::ERROR,__FUNCTION__,
00296             Form("Unexpected Zero-padding found after %x",last_word));
00297       status = false;
00298     }else if(_verbosity[MSG::INFO])
00299      
00300       Message::send(MSG::INFO,__FUNCTION__,
00301             Form("Zero-padding found after %x",last_word));
00302     
00303     return status;
00304   }
00305 
00306   switch(word_class){
00307     
00308   case PMT::CHANNEL_HEADER:
00309    
00310     //
00311     // Check if the last word was event header or channel last word
00312     //
00313     if(last_word_class == PMT::FEM_HEADER ||
00314        last_word_class == PMT::CHANNEL_LAST_WORD ) {
00315       
00316       // New data starts here. 
00317       // Clear data content & assign channel number.
00318       _ch_data.clear_data();
00319 
00320       _ch_data.set_channel_number( (word & 0xfff) );
00321       
00322       if(_verbosity[MSG::DEBUG])
00323 
00324     Message::send(MSG::DEBUG,__FUNCTION__,
00325               Form("New channel header: %d",_ch_data.channel_number()));
00326       
00327     }else{
00328 
00329       Message::send(MSG::ERROR,__FUNCTION__,
00330             Form("Unexpected channel header (%x)! Last word = %x",word,last_word));
00331 
00332       status = false;
00333 
00334     }
00335 
00336     break;
00337 
00338   case PMT::CHANNEL_LAST_WORD:{
00339 
00340     // Check channel number is same as the header
00341     PMT::ch_number_t ch( (word & 0xfff) );
00342     if(ch == _ch_data.channel_number()) {
00343 
00344       if(_verbosity[MSG::DEBUG])
00345     
00346     Message::send(MSG::DEBUG,__FUNCTION__,
00347               Form("Finished reading %zu samples for Ch %d",
00348                _ch_data.size(),_ch_data.channel_number()));
00349       
00350       // Store
00351       _event_data->push_back(_ch_data);
00352       
00353       _ch_data.clear_data();
00354       
00355     }else{
00356 
00357     Message::send(MSG::ERROR,__FUNCTION__,
00358               Form("Ch. number disagreement! Header: %u ... Last: %u!",
00359                _ch_data.channel_number(),ch) );
00360     
00361     status = false;
00362     }
00363 
00364     // Attempt to store data if nwords matches with the expected number
00365     if(status && _nwords == _header_info.nwords){
00366       _nwords++;
00367       _checksum += word;
00368       status = store_event();
00369     }
00370 
00371     break;
00372   }
00373   case PMT::FEM_LAST_WORD:
00374     
00375     if(last_word_class == PMT::CHANNEL_LAST_WORD)
00376 
00377       status = process_fem_last_word(word,last_word);
00378 
00379     else status = decode_ch_word(word,last_word);
00380 
00381     break;
00382 
00383   default:
00384 
00385     status = decode_ch_word(word,last_word);
00386   }
00387 
00388   if(status && _header_info.nwords){
00389     
00390     _nwords++;
00391     _checksum += word;
00392 
00393   }    
00394 
00395   last_word = word;
00396 
00397   return status;
00398 }
00399 
00400 #endif

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