CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_4_2_9_HLT1_bphpatch4/src/EventFilter/SiStripRawToDigi/interface/SiStripFEDBuffer.h

Go to the documentation of this file.
00001 #ifndef EventFilter_SiStripRawToDigi_SiStripFEDBuffer_H
00002 #define EventFilter_SiStripRawToDigi_SiStripFEDBuffer_H
00003 
00004 #include "boost/cstdint.hpp"
00005 #include <string>
00006 #include <vector>
00007 #include <memory>
00008 #include <ostream>
00009 #include <cstring>
00010 #include "EventFilter/SiStripRawToDigi/interface/SiStripFEDBufferComponents.h"
00011 
00012 namespace sistrip {
00013 
00014   //
00015   // Class definitions
00016   //
00017 
00018   //class representing standard (non-spy channel) FED buffers
00019   class FEDBuffer : public FEDBufferBase
00020     {
00021     public:
00022       //construct from buffer
00023       //if allowBadBuffer is set to true then exceptions will not be thrown if the channel lengths do not make sense or the event format is not recognized
00024       FEDBuffer(const uint8_t* fedBuffer, const size_t fedBufferSize, const bool allowBadBuffer = false);
00025       virtual ~FEDBuffer();
00026       virtual void print(std::ostream& os) const;
00027       const FEDFEHeader* feHeader() const;
00028       //check that a FE unit is enabled, has a good majority address and, if in full debug mode, that it is present
00029       bool feGood(const uint8_t internalFEUnitNum) const;
00030       //check that a FE unit is present in the data.
00031       //The high order byte of the FEDStatus register in the tracker special header is used in APV error mode.
00032       //The FE length from the full debug header is used in full debug mode.
00033       bool fePresent(uint8_t internalFEUnitNum) const;
00034       //check that a channel is present in data, found, on a good FE unit and has no errors flagged in status bits
00035       virtual bool channelGood(const uint8_t internalFEDannelNum) const;
00036 
00037       //functions to check buffer. All return true if there is no problem.
00038       //minimum checks to do before using buffer
00039       virtual bool doChecks() const;
00040   
00041       //additional checks to check for corrupt buffers
00042       //check channel lengths fit inside to buffer length
00043       bool checkChannelLengths() const;
00044       //check that channel lengths add up to buffer length (this does the previous check as well)
00045       bool checkChannelLengthsMatchBufferLength() const;
00046       //check channel packet codes match readout mode
00047       bool checkChannelPacketCodes() const;
00048       //check FE unit lengths in FULL DEBUG header match the lengths of their channels
00049       bool checkFEUnitLengths() const;
00050       //check FE unit APV addresses in FULL DEBUG header are equal to the APVe address if the majority was good
00051       bool checkFEUnitAPVAddresses() const;
00052       //do all corrupt buffer checks
00053       virtual bool doCorruptBufferChecks() const;
00054   
00055       //check that there are no errors in channel, APV or FEUnit status bits
00056       //these are done by channelGood(). Channels with bad status bits may be disabled so bad status bits do not usually indicate an error
00057       bool checkStatusBits(const uint8_t internalFEDChannelNum) const;
00058       bool checkStatusBits(const uint8_t internalFEUnitNum, const uint8_t internalChannelNum) const;
00059       //same but for all channels on enabled FE units
00060       bool checkAllChannelStatusBits() const;
00061       
00062       //check that all FE unit payloads are present
00063       bool checkFEPayloadsPresent() const;
00064   
00065       //print a summary of all checks
00066       virtual std::string checkSummary() const;
00067     private:
00068       uint8_t nFEUnitsPresent() const;
00069       void findChannels();
00070       uint8_t getCorrectPacketCode() const;
00071       uint16_t calculateFEUnitLength(const uint8_t internalFEUnitNumber) const;
00072       std::auto_ptr<FEDFEHeader> feHeader_;
00073       const uint8_t* payloadPointer_;
00074       uint16_t payloadLength_;
00075       uint8_t validChannels_;
00076       bool fePresent_[FEUNITS_PER_FED];
00077     };
00078 
00079   //class for unpacking data from ZS FED channels
00080   class FEDZSChannelUnpacker
00081     {
00082     public:
00083       static FEDZSChannelUnpacker zeroSuppressedModeUnpacker(const FEDChannel& channel);
00084       static FEDZSChannelUnpacker zeroSuppressedLiteModeUnpacker(const FEDChannel& channel);
00085       FEDZSChannelUnpacker();
00086       uint8_t sampleNumber() const;
00087       uint8_t adc() const;
00088       bool hasData() const;
00089       FEDZSChannelUnpacker& operator ++ ();
00090       FEDZSChannelUnpacker& operator ++ (int);
00091     private:
00092       //pointer to begining of FED or FE data, offset of start of channel payload in data and length of channel payload
00093       FEDZSChannelUnpacker(const uint8_t* payload, const size_t channelPayloadOffset, const int16_t channelPayloadLength);
00094       void readNewClusterInfo();
00095       static void throwBadChannelLength(const uint16_t length);
00096       void throwBadClusterLength();
00097       static void throwUnorderedData(const uint8_t currentStrip, const uint8_t firstStripOfNewCluster);
00098       const uint8_t* data_;
00099       size_t currentOffset_;
00100       uint8_t currentStrip_;
00101       uint8_t valuesLeftInCluster_;
00102       uint16_t channelPayloadOffset_;
00103       uint16_t channelPayloadLength_;
00104     };
00105 
00106   //class for unpacking data from raw FED channels
00107   class FEDRawChannelUnpacker
00108     {
00109     public:
00110       static FEDRawChannelUnpacker scopeModeUnpacker(const FEDChannel& channel) { return FEDRawChannelUnpacker(channel); }
00111       static FEDRawChannelUnpacker virginRawModeUnpacker(const FEDChannel& channel) { return FEDRawChannelUnpacker(channel); }
00112       static FEDRawChannelUnpacker procRawModeUnpacker(const FEDChannel& channel) { return FEDRawChannelUnpacker(channel); }
00113       explicit FEDRawChannelUnpacker(const FEDChannel& channel);
00114       uint8_t sampleNumber() const;
00115       uint16_t adc() const;
00116       bool hasData() const;
00117       FEDRawChannelUnpacker& operator ++ ();
00118       FEDRawChannelUnpacker& operator ++ (int);
00119     private:
00120       static void throwBadChannelLength(const uint16_t length);
00121       const uint8_t* data_;
00122       size_t currentOffset_;
00123       uint8_t currentStrip_;
00124       uint16_t valuesLeft_;
00125     };
00126 
00127   //
00128   // Inline function definitions
00129   //
00130 
00131   //FEDBuffer
00132 
00133   inline const FEDFEHeader* FEDBuffer::feHeader() const
00134     {
00135       return feHeader_.get();
00136     }
00137   
00138   inline bool FEDBuffer::feGood(const uint8_t internalFEUnitNum) const
00139     {
00140       return ( !majorityAddressErrorForFEUnit(internalFEUnitNum) && !feOverflow(internalFEUnitNum) && fePresent(internalFEUnitNum) );
00141     }
00142   
00143   inline bool FEDBuffer::fePresent(uint8_t internalFEUnitNum) const
00144     {
00145       return fePresent_[internalFEUnitNum];
00146     }
00147   
00148   inline bool FEDBuffer::checkStatusBits(const uint8_t internalFEDChannelNum) const
00149     {
00150       return feHeader_->checkChannelStatusBits(internalFEDChannelNum);
00151     }
00152   
00153   inline bool FEDBuffer::checkStatusBits(const uint8_t internalFEUnitNum, const uint8_t internalChannelNum) const
00154     {
00155       return checkStatusBits(internalFEDChannelNum(internalFEUnitNum,internalChannelNum));
00156     }
00157   
00158   //FEDRawChannelUnpacker
00159 
00160   inline FEDRawChannelUnpacker::FEDRawChannelUnpacker(const FEDChannel& channel)
00161     : data_(channel.data()),
00162       currentOffset_(channel.offset()+3),
00163       currentStrip_(0),
00164       valuesLeft_((channel.length()-3)/2)
00165     {
00166       if ((channel.length()-3)%2) throwBadChannelLength(channel.length());
00167     }
00168   
00169   inline uint8_t FEDRawChannelUnpacker::sampleNumber() const
00170     {
00171       return currentStrip_;
00172     }
00173   
00174   inline uint16_t FEDRawChannelUnpacker::adc() const
00175     {
00176       return ( data_[currentOffset_^7] + ((data_[(currentOffset_+1)^7]&0x03)<<8) );
00177     }
00178   
00179   inline bool FEDRawChannelUnpacker::hasData() const
00180     {
00181       return valuesLeft_;
00182     }
00183   
00184   inline FEDRawChannelUnpacker& FEDRawChannelUnpacker::operator ++ ()
00185     {
00186       currentOffset_ += 2;
00187       currentStrip_++;
00188       valuesLeft_--;
00189       return (*this);
00190     }
00191   
00192   inline FEDRawChannelUnpacker& FEDRawChannelUnpacker::operator ++ (int)
00193     {
00194       ++(*this); return *this;
00195     }
00196 
00197   //FEDZSChannelUnpacker
00198   
00199   inline FEDZSChannelUnpacker::FEDZSChannelUnpacker()
00200     : data_(NULL),
00201       valuesLeftInCluster_(0),
00202       channelPayloadOffset_(0),
00203       channelPayloadLength_(0)
00204     { }
00205 
00206   inline FEDZSChannelUnpacker::FEDZSChannelUnpacker(const uint8_t* payload, const size_t channelPayloadOffset, const int16_t channelPayloadLength)
00207     : data_(payload),
00208       currentOffset_(channelPayloadOffset),
00209       currentStrip_(0),
00210       valuesLeftInCluster_(0),
00211       channelPayloadOffset_(channelPayloadOffset),
00212       channelPayloadLength_(channelPayloadLength)
00213     {
00214       if (channelPayloadLength_) readNewClusterInfo();
00215     }
00216   
00217   inline FEDZSChannelUnpacker FEDZSChannelUnpacker::zeroSuppressedModeUnpacker(const FEDChannel& channel)
00218     {
00219       uint16_t length = channel.length();
00220       if (length & 0xF000) throwBadChannelLength(length);
00221       FEDZSChannelUnpacker result(channel.data(),channel.offset()+7,length-7);
00222       return result;
00223     }
00224 
00225   inline FEDZSChannelUnpacker FEDZSChannelUnpacker::zeroSuppressedLiteModeUnpacker(const FEDChannel& channel)
00226     {
00227       uint16_t length = channel.length();
00228       if (length & 0xF000) throwBadChannelLength(length);
00229       FEDZSChannelUnpacker result(channel.data(),channel.offset()+2,length-2);
00230       return result;
00231     }
00232   
00233   inline uint8_t FEDZSChannelUnpacker::sampleNumber() const
00234     {
00235       return currentStrip_;
00236     }
00237   
00238   inline uint8_t FEDZSChannelUnpacker::adc() const
00239     {
00240       return data_[currentOffset_^7];
00241     }
00242   
00243   inline bool FEDZSChannelUnpacker::hasData() const
00244     {
00245       return (currentOffset_<channelPayloadOffset_+channelPayloadLength_);
00246     }
00247   
00248   inline FEDZSChannelUnpacker& FEDZSChannelUnpacker::operator ++ ()
00249     {
00250       if (valuesLeftInCluster_) {
00251         currentStrip_++;
00252         currentOffset_++;
00253         valuesLeftInCluster_--;
00254       } else {
00255         currentOffset_++;
00256         if (hasData()) {
00257           const uint8_t oldStrip = currentStrip_;
00258           readNewClusterInfo();
00259           if ( !(currentStrip_ > oldStrip) ) throwUnorderedData(oldStrip,currentStrip_);
00260         }
00261       }
00262       return (*this);
00263     }
00264   
00265   inline FEDZSChannelUnpacker& FEDZSChannelUnpacker::operator ++ (int)
00266     {
00267       ++(*this); return *this;
00268     }
00269   
00270   inline void FEDZSChannelUnpacker::readNewClusterInfo()
00271     {
00272       currentStrip_ = data_[(currentOffset_++)^7];
00273       valuesLeftInCluster_ = data_[(currentOffset_++)^7]-1;
00274     }
00275 
00276 }
00277 
00278 #endif //ndef EventFilter_SiStripRawToDigi_SiStripFEDBuffer_H