algo_pmt_xmit.cc

Go to the documentation of this file.
00001 #ifndef ALGO_PMT_XMIT
00002 #define ALGO_PMT_XMIT
00003 
00004 #include "algo_pmt_xmit.hh"
00005 
00006 //#########################################
00007 algo_pmt_xmit::algo_pmt_xmit() 
00008   : algo_fem_decoder_base() 
00009 {
00010 //#########################################
00011 
00012   reset();
00013 
00014 }
00015 
00016 //#########################################
00017 void algo_pmt_xmit::reset() {
00018 //#########################################
00019 
00020   _event_data = 0;
00021 
00022   clear_event();
00023 
00024   algo_fem_decoder_base::reset();
00025 
00026 }
00027 
00028 
00029 //#########################################
00030 void algo_pmt_xmit::clear_event() {
00031 //#########################################
00032 
00033   algo_fem_decoder_base::clear_event();
00034 
00035   if(_event_data)
00036 
00037     _event_data->clear_data();
00038   
00039   _ch_data.clear_data();
00040   
00041   _channel_header_count = 0;
00042 
00043   _last_channel_number=PMT::INVALID_CH;
00044   _last_disc_id=PMT::DISC_MAX;
00045 
00046 }
00047 
00048 //#########################################
00049 bool algo_pmt_xmit::process_ch_word(const PMT::word_t word, 
00050                     PMT::word_t &last_word) 
00051 {
00052 //#########################################
00053 
00054   bool status=true;
00055 
00056   if(_verbosity[MSG::DEBUG]){
00057     sprintf(_buf,"Processing ch-word: %x",word);
00058     Message::send(MSG::DEBUG,__FUNCTION__,_buf);
00059   }
00060 
00061   status = decode_ch_word(word,last_word);
00062 
00063   if(status){
00064     _nwords++;
00065     _checksum+=word;
00066   }
00067 
00068   last_word = word;
00069 
00070   return status;
00071 }
00072 
00073 //#########################################################
00074 bool algo_pmt_xmit::check_event_quality(){
00075 //#########################################################
00076 
00077   bool status = true;
00078 
00079   // Check if _checksum and _nwords agrees with that of event header.
00080   _nwords-=1;
00081   if(_nwords!=_header_info.nwords){
00082 
00083     Message::send(MSG::ERROR,__FUNCTION__,
00084           Form("Disagreement on nwords: counted=%u, expected=%u",_nwords,_header_info.nwords));
00085 
00086     status = false;
00087 
00088   }
00089 
00090   // checksum is only 24 bit!
00091   _checksum = (_checksum & 0xffffff);
00092   if(_checksum!=_header_info.checksum){
00093 
00094     Message::send(MSG::ERROR,__FUNCTION__,
00095           Form("Disagreement on checksum: summed=%x, expected=%x",_checksum,_header_info.checksum));
00096 
00097     status = false;
00098 
00099   }
00100 
00101   return status;
00102 
00103 }
00104 
00105 
00106 
00107 //#################################################
00108 bool algo_pmt_xmit::process_event_header(const PMT::word_t word, 
00109                      PMT::word_t &last_word) 
00110 {
00111 //#################################################
00112 
00113   bool status = true;
00114 
00115   if(!_event_data)
00116 
00117     _event_data = (pmt_wf_collection*)(_storage->get_data(DATA_STRUCT::PMT_WF_COLLECTION));
00118   
00119   else if(get_word_class(last_word) != PMT::EVENT_LAST_WORD){
00120 
00121     Message::send(MSG::ERROR,__FUNCTION__,
00122           Form("Unexpected word (%x, previous=%x) while processing event header!",word,last_word));
00123 
00124     status = false;
00125 
00126   }
00127 
00128   last_word = word;
00129 
00130   return status;
00131 
00132 }
00133 
00134 //#########################################################
00135 bool algo_pmt_xmit::process_fem_last_word(const PMT::word_t word,
00136                           PMT::word_t &last_word)
00137 {
00138 //#########################################################
00139 
00140   bool status = true;
00141 
00142   if(_verbosity[MSG::INFO])
00143       
00144     Message::send(MSG::INFO,__FUNCTION__,Form("End of FEM word: %x...",word));
00145   
00146   PMT::word_t last_word_class = get_word_class(last_word);
00147   if(last_word_class != PMT::CHANNEL_LAST_WORD &&
00148      last_word_class != PMT::FEM_FIRST_WORD) {
00149 
00150     Message::send(MSG::ERROR,__FUNCTION__,
00151           Form("Unexpected word: %x (previous = %x)",word,last_word));
00152 
00153     status = false;
00154 
00155   }
00156 
00157   _nwords++;
00158   //_checksum+=word;
00159 
00160   if(status) status=store_event();
00161 
00162   last_word = word;
00163 
00164   return status;
00165 }
00166 
00167 //#########################################################
00168 bool algo_pmt_xmit::process_event_last_word(const PMT::word_t word,
00169                         PMT::word_t &last_word)
00170 {  
00171 //#########################################################
00172 
00173   bool status = true;
00174 
00175   if(_verbosity[MSG::INFO])
00176     
00177     Message::send(MSG::INFO,__FUNCTION__,Form("End of event word: %x...",word));
00178 
00179   if(get_word_class(last_word)!=PMT::FEM_LAST_WORD){
00180 
00181     Message::send(MSG::ERROR,__FUNCTION__,
00182           Form("Unexpected word: %x (previous = %x)",word,last_word));
00183 
00184     status = false;
00185 
00186   }
00187 
00188   last_word = word;
00189 
00190   return status;
00191 }
00192 
00193 //#########################################################
00194 bool algo_pmt_xmit::store_event(){
00195 //#########################################################
00196 
00197   bool status = check_event_quality();
00198 
00199   // Store if condition is satisfied
00200   if(status) {
00201 
00202     if(_verbosity[MSG::INFO]){
00203 
00204       Message::send(MSG::INFO,__FUNCTION__,
00205             Form("Storing event %u with %zu channel entries...",
00206              _event_data->event_id(), _event_data->size()));
00207 
00208     }
00209 
00210     _event_data->set_module_address    ( _header_info.module_address    );
00211     _event_data->set_module_id         ( _header_info.module_id         );
00212     _event_data->set_event_id          ( _header_info.event_id          );
00213     _event_data->set_event_frame_id    ( _header_info.event_frame_id    );
00214     _event_data->set_trigger_frame_id  ( _header_info.trigger_frame_id  );
00215     _event_data->set_trigger_timeslice ( _header_info.trigger_timeslice );
00216     _event_data->set_nwords            ( _header_info.nwords            );
00217     _event_data->set_checksum          ( _header_info.checksum          );
00218 
00219     status = _storage->next_event();
00220 
00221   }
00222   else
00223     
00224     Message::send(MSG::ERROR,__FUNCTION__,
00225           Form("Skipping to store event %d...",_header_info.event_id));
00226 
00227   clear_event();
00228 
00229   return status;
00230 }
00231 
00232 //#########################################################
00233 bool algo_pmt_xmit::decode_ch_word(const PMT::word_t word, 
00234                    PMT::word_t &last_word)
00235 {
00236 //#########################################################
00237 
00238   PMT::PMT_WORD word_class      = get_word_class(word);
00239   PMT::PMT_WORD last_word_class = get_word_class(last_word);
00240   bool status=true;
00241 
00242   if(_verbosity[MSG::DEBUG]){
00243     sprintf(_buf,"Decoding word: %x ... last word class: %d",word,last_word_class);
00244     Message::send(MSG::DEBUG,__FUNCTION__,_buf);
00245   }  
00246   
00247   switch(word_class){
00248 
00249   case PMT::EVENT_HEADER:
00250   case PMT::FEM_HEADER:
00251   case PMT::UNDEFINED_WORD:
00252   case PMT::FEM_LAST_WORD:
00253   case PMT::EVENT_LAST_WORD:
00254     Message::send(MSG::ERROR,__FUNCTION__,
00255           Form("Unexpected word: %x (previous=%x)",word,last_word));
00256     status = false;
00257     break;
00258   case PMT::FEM_FIRST_WORD:
00259     //
00260     // First channel word in this event ... nothing special to do
00261     if(last_word_class!=PMT::FEM_HEADER){
00262       Message::send(MSG::ERROR,__FUNCTION__,
00263             Form("Found FEM first word (%x) in an unexpected place (previous=%x)!",word,last_word));
00264       status=false;
00265     }
00266     break;
00267 
00268   case PMT::CHANNEL_HEADER:
00269     //
00270     // Channel header ... read in channel info from this word
00271     if(last_word_class!=PMT::FEM_FIRST_WORD && 
00272        last_word_class!=PMT::CHANNEL_LAST_WORD) {
00273       Message::send(MSG::ERROR,__FUNCTION__,
00274             Form("Found channel header (%x) in an unexpected place (previous=%x)!",word,last_word));
00275       status=false;
00276     }else{
00277       // Initialize channel info, then fill with channel number & disc. id.
00278       _channel_header_count=0;
00279       _ch_data.clear_data();
00280       _channel_header_count=1;
00281       // Channel Number
00282       _ch_data.set_channel_number( word & 0x3f ); 
00283       // Discriminator ID
00284       _ch_data.set_disc_id((PMT::DISCRIMINATOR)((word & 0xfff)>>9));  
00285     }
00286     break;
00287 
00288   case PMT::CHANNEL_WORD:
00289   case PMT::CHANNEL_LAST_WORD:
00290     //
00291     // This is channel ADC count or possibly remaining channel header info
00292     // The first two sample are treated as channel header info
00293     if(last_word_class!=PMT::CHANNEL_HEADER && 
00294        last_word_class!=PMT::CHANNEL_WORD &&
00295        last_word_class!=PMT::CHANNEL_LAST_WORD ) {
00296       // Sanity check: the last word should be either channel header or data word.
00297       Message::send(MSG::ERROR,__FUNCTION__,
00298             Form("Found channel word (%x) in an unexpected place (previous=%x)!",word,last_word));
00299 
00300       status=false;
00301     }else{
00302       // Treat a case of missing very first channel header word: happens when there is no time in between two readout data.
00303       if(last_word_class==PMT::CHANNEL_LAST_WORD){
00304     // In this case, we should be missing the CHANNEL_HEADER because this pulse is from the same channel & discriminator id.
00305     // Do an operation that is done for the case of CHANNEL_HEADER, but use a stored value of channel number & disc. id.
00306     _channel_header_count=1;
00307     _ch_data.set_channel_number(_last_channel_number);
00308     _ch_data.set_disc_id(_last_disc_id);
00309     if(_verbosity[MSG::NORMAL])
00310       Message::send(MSG::NORMAL,__FUNCTION__,
00311             Form("Found consecutively readout data arrays @ event %d (missing channel very first header)!",
00312                  _event_data->event_id())
00313             );
00314       }
00315 
00316       //
00317       // Ordinary operation for channel header / adc words
00318       //
00319       if(_channel_header_count==CHANNEL_HEADER_COUNT ) {
00320 
00321     // Finished reading in header words. This should be a mere ADC count.
00322     // Raise error if the last word class is not channel word
00323     if(last_word_class!=PMT::CHANNEL_WORD){
00324 
00325       Message::send(MSG::ERROR,__FUNCTION__,
00326             Form("Found channel word (%x) in an unexpected place (previous=%x)!",word,last_word));
00327 
00328       status = false;
00329     }     
00330     else if(word_class!=PMT::CHANNEL_LAST_WORD)
00331 
00332       _ch_data.push_back(word & 0xfff); 
00333     
00334       }else if(last_word_class==PMT::CHANNEL_HEADER   ) {
00335     // First of 2 channel header words. Record the values.
00336 
00337     // This gives upper 8 bits of 20-bit timeslice number
00338     _ch_data.set_timeslice( (word & 0x1f)<<12 );       
00339 
00340     // Lower 3 of 8 bits is the channel frame ID
00341     _ch_data.set_channel_frame_id( ((word & 0xff)>>5) +
00342                        (((_event_data->event_frame_id())>>3)<<3) ); 
00343 
00344     // Correct channel frame id roll-over w.r.t. event frame id
00345     _ch_data.set_channel_frame_id(round_diff(_event_data->event_frame_id(),
00346                          _ch_data.channel_frame_id(),
00347                          0x7));
00348     _channel_header_count++;
00349       }else if(last_word_class==PMT::CHANNEL_WORD     ) {
00350     // Second of 2 channel header words. Record the values & inspect them.
00351     _ch_data.set_timeslice(_ch_data.timeslice() + (word & 0xfff)); // This gives lower 12 bits of 20-bit timeslice number
00352     _channel_header_count++;
00353 
00354     if(_verbosity[MSG::INFO]){
00355       sprintf(_buf,"Read-in headers for Ch. %-3d!",_ch_data.channel_number());
00356       Message::send(MSG::INFO,_buf);
00357     }
00358       }
00359 
00360       // If this is channel's last word, store & clear channel info
00361       if(word_class==PMT::CHANNEL_LAST_WORD){
00362     if(_verbosity[MSG::INFO]){
00363       sprintf(_buf,"Encountered the last word (%x) for channel %d",word,_ch_data.channel_number());
00364       Message::send(MSG::INFO,_buf);
00365       sprintf(_buf,"Event frame  : %d",_event_data->event_frame_id());
00366       Message::send(MSG::INFO,_buf);
00367       sprintf(_buf,"PMT frame    : %d",_ch_data.channel_frame_id());
00368       Message::send(MSG::INFO,_buf);
00369       sprintf(_buf,"Disc. ID     : %d",_ch_data.disc_id());
00370       Message::send(MSG::INFO,_buf);
00371       sprintf(_buf,"Start Time   : %d",_ch_data.timeslice());
00372       Message::send(MSG::INFO,_buf);
00373       sprintf(_buf,"# ADC sample : %zd",_ch_data.size());
00374       Message::send(MSG::INFO,_buf);
00375     }
00376     store_ch_data();
00377       }
00378     }
00379     break;
00380   }
00381 
00382   return status;
00383 
00384 }
00385 
00386 void algo_pmt_xmit::store_ch_data(){
00387 
00388   _event_data->push_back(_ch_data);
00389   
00390   // Store this waveform's channel number and discriminator id.
00391   // This may be used in the next pulse in case the next pulse is coming with no time space in between.
00392   // In such case, the next pulse is missing the channel very first header word because it is supposed
00393   // to be combined.
00394   _last_channel_number=_ch_data.channel_number();
00395   _last_disc_id=_ch_data.disc_id();
00396 
00397   _channel_header_count=0;
00398   _ch_data.clear_data();
00399 
00400 }
00401 
00402 
00403 #endif

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