algo_tpc_xmit.cc

Go to the documentation of this file.
00001 #ifndef ALGO_TPC_XMIT
00002 #define ALGO_TPC_XMIT
00003 
00004 #include "algo_tpc_xmit.hh"
00005 
00006 //#########################################
00007 algo_tpc_xmit::algo_tpc_xmit() 
00008   : algo_fem_decoder_base() 
00009 {
00010 //#########################################
00011 
00012   reset();
00013 
00014 }
00015 
00016 //#########################################
00017 void algo_tpc_xmit::reset() {
00018 //#########################################
00019 
00020   _event_data = 0;
00021 
00022   _ch_data.clear_data();
00023 
00024   algo_fem_decoder_base::reset();
00025 
00026 }
00027 
00028 //#########################################
00029 bool algo_tpc_xmit::process_ch_word(const PMT::word_t word, 
00030                     PMT::word_t &last_word) 
00031 {
00032 //#########################################
00033 
00034   bool status=true;
00035 
00036   if(_verbosity[MSG::DEBUG]){
00037     sprintf(_buf,"Processing ch-word: %x",word);
00038     Message::send(MSG::DEBUG,__FUNCTION__,_buf);
00039   }
00040 
00041   PMT::PMT_WORD word_class=get_word_class(word);
00042   PMT::PMT_WORD last_word_class=get_word_class(last_word);
00043   
00044   switch(word_class){
00045 
00046   case PMT::CHANNEL_HEADER:
00047     
00048     //
00049     // Check if the last word was event header or channel last word
00050     //
00051     if(last_word_class == PMT::FEM_HEADER ||
00052        last_word_class == PMT::CHANNEL_LAST_WORD ) {
00053 
00054       // New data starts here. 
00055       // Clear data content & assign channel number.
00056       _ch_data.clear_data();
00057 
00058       _ch_data.set_channel_number( (word & 0xfff) );
00059       
00060       if(_verbosity[MSG::DEBUG])
00061 
00062     Message::send(MSG::DEBUG,__FUNCTION__,
00063               Form("New channel header: %d",_ch_data.channel_number()));
00064       
00065     }else{
00066 
00067       Message::send(MSG::ERROR,__FUNCTION__,
00068             Form("Unexpected channel header (%x)! Last word = %x",word,last_word));
00069 
00070       status = false;
00071 
00072     }
00073 
00074     break;
00075 
00076   case PMT::CHANNEL_LAST_WORD:
00077 
00078     //
00079     // Check if the last word was channel word
00080     //
00081     if(last_word_class == PMT::CHANNEL_WORD) {
00082 
00083       // Check if the channel number in this ch-last-word agrees with that in the header
00084       PMT::ch_number_t ch( (word & 0xfff) );
00085 
00086       if(ch == _ch_data.channel_number()) {
00087 
00088     if(_verbosity[MSG::DEBUG])
00089 
00090       Message::send(MSG::DEBUG,__FUNCTION__,
00091             Form("Finished reading %zu samples for Ch %d",
00092                  _ch_data.size(),_ch_data.channel_number()));
00093     
00094     // Store
00095     _event_data->push_back(_ch_data);
00096     
00097     _ch_data.clear_data();
00098 
00099       }else{
00100 
00101     Message::send(MSG::ERROR,__FUNCTION__,
00102               Form("Ch. number disagreement! Header: %u ... Last: %u!",
00103                _ch_data.channel_number(),ch) );
00104     
00105     status = false;
00106 
00107       }
00108 
00109     }
00110     else{
00111 
00112       Message::send(MSG::ERROR,__FUNCTION__,
00113             Form("Unexpected channel ending (%x)! Last word = %x",word,last_word));
00114       
00115       status = false;
00116 
00117     }
00118 
00119     break;
00120 
00121   case PMT::CHANNEL_WORD:
00122 
00123     //
00124     // Check if the last word was channel header or channel adc word
00125     //
00126     if(last_word_class == PMT::CHANNEL_HEADER ||
00127        last_word_class == PMT::CHANNEL_WORD){
00128 
00129       status = decode_ch_word(word,last_word);
00130 
00131     }else{
00132 
00133       Message::send(MSG::ERROR,__FUNCTION__,
00134             Form("Unexpected channel word (%x)! Last word = %x",word,last_word));
00135 
00136       status = false;
00137 
00138     }
00139 
00140     break;
00141 
00142   case PMT::EVENT_LAST_WORD:
00143   case PMT::FEM_LAST_WORD:
00144   case PMT::UNDEFINED_WORD:
00145   case PMT::EVENT_HEADER:
00146   case PMT::FEM_HEADER:
00147   case PMT::FEM_FIRST_WORD:
00148 
00149     Message::send(MSG::ERROR,__FUNCTION__,
00150           Form("Unexpected word found while channel word processing: %x",word));
00151 
00152     status = false;
00153 
00154     break;
00155   }
00156 
00157   // If processing of this word is successful, add it to the checksum
00158   if(status) {
00159 
00160     _nwords++;
00161     _checksum += word;
00162     //std::cout<<_nwords<<" ... "<<_checksum<<std::endl;
00163   }else{
00164 
00165     Message::send(MSG::ERROR,__FUNCTION__,
00166           Form("Failed processing channel word %x (previous=%x)",word,last_word));
00167 
00168     clear_event();
00169   }
00170 
00171   if(word_class != PMT::UNDEFINED_WORD)
00172 
00173     last_word = word;
00174 
00175   return status;
00176 }
00177 
00178 //#########################################################
00179 bool algo_tpc_xmit::check_event_quality(){
00180 //#########################################################
00181 
00182   bool status = true;
00183 
00184   // Check if _checksum and _nwords agrees with that of event header.
00185   //if(_nwords != _header_info.nwords) {
00186   _nwords-=1;
00187   if(_nwords!=_header_info.nwords){
00188 
00189     Message::send(MSG::ERROR,__FUNCTION__,
00190           Form("Disagreement on nwords: counted=%u, expected=%u",_nwords,_header_info.nwords));
00191 
00192     status = false;
00193 
00194   }
00195 
00196   //if(_checksum != _header_info.checksum) {
00197   if((_checksum & 0xffffff) !=_header_info.checksum){
00198 
00199     Message::send(MSG::ERROR,__FUNCTION__,
00200           Form("Disagreement on checksum: summed=%x, expected=%x",_checksum,_header_info.checksum));
00201 
00202     status = false;
00203 
00204   }
00205 
00206   return status;
00207 
00208 }
00209 
00210 
00211 
00212 //#################################################
00213 bool algo_tpc_xmit::process_event_header(const PMT::word_t word, 
00214                      PMT::word_t &last_word) 
00215 {
00216 //#################################################
00217 
00218   bool status = true;
00219 
00220   if(!_event_data)
00221 
00222     _event_data = (tpc_wf_collection*)(_storage->get_data(DATA_STRUCT::TPC_WF_COLLECTION));
00223   
00224   if(get_word_class(last_word)==PMT::EVENT_LAST_WORD) {
00225     
00226     // Attempt to store data
00227     
00228     status = store_event();
00229   }else if(last_word != PMT::INVALID_WORD){
00230 
00231     Message::send(MSG::ERROR,__FUNCTION__,
00232           Form("Unexpected word (%x, previous=%x) while processing event header!",word,last_word));
00233 
00234     status = false;
00235 
00236   }
00237 
00238   last_word = word;
00239 
00240   return status;
00241 
00242 }
00243 
00244 //#########################################################
00245 bool algo_tpc_xmit::process_fem_last_word(const PMT::word_t word,
00246                           PMT::word_t &last_word)
00247 {
00248 //#########################################################
00249 
00250   // This should not exist in TPC-XMIT
00251   Message::send(MSG::ERROR,__FUNCTION__,
00252         Form("FEM-LAST-WORD (%x, previous=%x) ... NOT expected for TPC!",word,last_word));
00253 
00254   last_word = word;
00255 
00256   return false;
00257 }
00258 
00259 //#########################################################
00260 bool algo_tpc_xmit::process_event_last_word(const PMT::word_t word,
00261                         PMT::word_t &last_word)
00262 {  
00263 //#########################################################
00264 
00265   if(_verbosity[MSG::INFO]){
00266       
00267     Message::send(MSG::INFO,__FUNCTION__,
00268           Form("End of event word: %x...",word));
00269     
00270   }
00271 
00272   last_word = word;
00273 
00274   return true;
00275 }
00276 
00277 
00278 //#########################################################
00279 void algo_tpc_xmit::clear_event(){
00280 //#########################################################
00281 
00282   algo_fem_decoder_base::clear_event();
00283 
00284   _event_data->clear_data();
00285 
00286   _ch_data.clear();
00287 
00288 }
00289 
00290 //#########################################################
00291 bool algo_tpc_xmit::store_event(){
00292 //#########################################################
00293  
00294   bool status = check_event_quality();
00295 
00296   // Store if condition is satisfied
00297   if(status) {
00298 
00299     if(_verbosity[MSG::INFO]){
00300 
00301       Message::send(MSG::INFO,__FUNCTION__,
00302             Form("Storing event %u with %zu channel entries...",
00303              _event_data->event_id(), _event_data->size()));
00304 
00305     }
00306 
00307     _event_data->set_module_address    ( _header_info.module_address    );
00308     _event_data->set_module_id         ( _header_info.module_id         );
00309     _event_data->set_event_id          ( _header_info.event_id          );
00310     _event_data->set_event_frame_id    ( _header_info.event_frame_id    );
00311     _event_data->set_trigger_frame_id  ( _header_info.trigger_frame_id  );
00312     _event_data->set_trigger_timeslice ( _header_info.trigger_timeslice );
00313     _event_data->set_nwords            ( _header_info.nwords            );
00314     _event_data->set_checksum          ( _header_info.checksum          );
00315 
00316     status = _storage->next_event();
00317 
00318   }else{
00319     
00320     Message::send(MSG::ERROR,__FUNCTION__,
00321           Form("Skipping to store event %d...",_header_info.event_id));
00322 
00323     status = false;
00324     
00325   }
00326 
00327   clear_event();
00328 
00329   return status;
00330 }
00331 
00332 //#########################################################
00333 bool algo_tpc_xmit::decode_ch_word(const PMT::word_t word, 
00334                    PMT::word_t &last_word)
00335 {
00336 //#########################################################
00337 
00338   bool status = true;
00339   // Simply append if it is not compressed
00340   if( !(is_compressed(word)) ) _ch_data.push_back( (word & 0xfff) );
00341 
00342   else if(!(_ch_data.size())){
00343 
00344     // This is a problem: if huffman coded, then we must have a previous ADC sample
00345     // as a reference. Raise an error.
00346 
00347     Message::send(MSG::ERROR,__FUNCTION__,
00348           Form("Huffman coded word %x found while the previous was non-ADC word (%x)!",
00349                word,last_word));
00350     
00351     status = false;
00352 
00353   }
00354   else{
00355 
00356     // Compresed data is in last 15 bit of this word.
00357     PMT::word_t data = (word & 0x7fff);
00358 
00359     // The compression is based on an extremely simple Huffman encoding.
00360     // The Huffman tree used here assigns the following values:
00361     //
00362     // Value   Code
00363     //  +3     0000001
00364     //  +2     00001
00365     //  +1     001
00366     //  +0     1
00367     //  -1     01
00368     //  -2     0001
00369     //  -3     000001
00370 
00371     /*
00372     size_t zero_count     = 0;
00373     for(size_t index=0; index<15 && status; ++index){
00374 
00375       if( !((data >> index) & 0x1) ) zero_count++;
00376       else{
00377 
00378     switch(zero_count){
00379       
00380     case 0:
00381       _ch_data.push_back( (*(_ch_data.rbegin())) ); break;    
00382       
00383     case 1:
00384       _ch_data.push_back( (*(_ch_data.rbegin())) -1 ); break;
00385 
00386     case 2:
00387       _ch_data.push_back( (*(_ch_data.rbegin())) +1 ); break;
00388 
00389     case 3:
00390       _ch_data.push_back( (*(_ch_data.rbegin())) -2 ); break;
00391 
00392     case 4:
00393       _ch_data.push_back( (*(_ch_data.rbegin())) +2 ); break;
00394 
00395     case 5:
00396       _ch_data.push_back( (*(_ch_data.rbegin())) -3 ); break;
00397 
00398     case 6:
00399       _ch_data.push_back( (*(_ch_data.rbegin())) +3 ); break;
00400 
00401     default:
00402       Message::send(MSG::ERROR,__FUNCTION__,
00403             Form("Encountered unexpected number of zeros (=%zu) in the compressed word %x!",
00404                  zero_count,word));
00405       status = false;
00406     };
00407     
00408     zero_count=0;
00409       }
00410     }
00411     */
00412 
00413     size_t zero_count = 0;
00414     bool   non_zero_found = false;
00415     for(size_t index=0; index<15 && status; ++index){
00416 
00417       if( !((data >> index) & 0x1) )
00418 
00419     zero_count += ( non_zero_found ? 1 : 0 );
00420     
00421       else{
00422     
00423     if(!non_zero_found) non_zero_found=true;
00424 
00425     else status = add_huffman_adc(_ch_data,zero_count);
00426     
00427     if(status) zero_count=0;
00428       }
00429     }
00430 
00431     if(zero_count && status){
00432 
00433       status = add_huffman_adc(_ch_data,zero_count);
00434       
00435     }    
00436 
00437     if(!status)
00438       
00439       Message::send(MSG::ERROR,__FUNCTION__,
00440             Form("Encountered unexpected number of zeros (=%zu) in the compressed word %x!",
00441              zero_count,word));
00442     
00443   }
00444   
00445   return status;
00446 
00447 }
00448 
00449 #endif

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