CMS 3D CMS Logo

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