Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:11:02

0001 #ifndef EventFilter_SiStripRawToDigi_SiStripFEDBufferComponents_H
0002 #define EventFilter_SiStripRawToDigi_SiStripFEDBufferComponents_H
0003 
0004 #include <ostream>
0005 #include <memory>
0006 #include <cstring>
0007 #include <vector>
0008 #include "DataFormats/FEDRawData/interface/FEDRawData.h"
0009 #include "DataFormats/SiStripCommon/interface/ConstantsForHardwareSystems.h"
0010 #include "FWCore/Utilities/interface/Exception.h"
0011 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0012 #include <cstdint>
0013 
0014 namespace sistrip {
0015 
0016   //
0017   // Constants
0018   //
0019 
0020   static const uint8_t INVALID = 0xFF;
0021 
0022   static const uint8_t APV_MAX_ADDRESS = 192;
0023 
0024   static const uint16_t SCOPE_MODE_MAX_SCOPE_LENGTH = 1022;
0025 
0026   enum FEDBufferFormat {
0027     BUFFER_FORMAT_INVALID = INVALID,
0028     BUFFER_FORMAT_OLD_VME,
0029     BUFFER_FORMAT_OLD_SLINK,
0030     BUFFER_FORMAT_NEW
0031   };
0032   //these are the values which appear in the buffer.
0033   static const uint8_t BUFFER_FORMAT_CODE_OLD = 0xED;
0034   static const uint8_t BUFFER_FORMAT_CODE_NEW = 0xC5;
0035 
0036   //enum values are values which appear in buffer. DO NOT CHANGE!
0037   enum FEDHeaderType {
0038     HEADER_TYPE_INVALID = INVALID,
0039     HEADER_TYPE_FULL_DEBUG = 1,
0040     HEADER_TYPE_APV_ERROR = 2,
0041     HEADER_TYPE_NONE = 4  //spy channel
0042   };
0043 
0044   //enum values are values which appear in buffer. DO NOT CHANGE!
0045   enum FEDReadoutMode {
0046     READOUT_MODE_INVALID = INVALID,
0047     READOUT_MODE_SCOPE = 0x1,
0048     READOUT_MODE_VIRGIN_RAW = 0x2,
0049     READOUT_MODE_ZERO_SUPPRESSED_LITE10 = 0x3,
0050     READOUT_MODE_ZERO_SUPPRESSED_LITE10_CMOVERRIDE = 0x4,
0051     READOUT_MODE_ZERO_SUPPRESSED_LITE8_TOPBOT = 0x5,
0052     READOUT_MODE_PROC_RAW = 0x6,
0053     READOUT_MODE_ZERO_SUPPRESSED_LITE8_TOPBOT_CMOVERRIDE = 0x7,
0054     READOUT_MODE_ZERO_SUPPRESSED_LITE8_CMOVERRIDE = 0x8,
0055     READOUT_MODE_ZERO_SUPPRESSED_LITE8_BOTBOT = 0x9,
0056     READOUT_MODE_ZERO_SUPPRESSED = 0xA,
0057     READOUT_MODE_ZERO_SUPPRESSED_FAKE = 0xB,
0058     READOUT_MODE_ZERO_SUPPRESSED_LITE8 = 0xC,
0059     READOUT_MODE_ZERO_SUPPRESSED_LITE8_BOTBOT_CMOVERRIDE = 0xD,
0060     READOUT_MODE_SPY = 0xE,
0061     READOUT_MODE_PREMIX_RAW = 0xF
0062   };
0063 
0064   enum FEDLegacyReadoutMode {
0065     READOUT_MODE_LEGACY_INVALID = INVALID,
0066     READOUT_MODE_LEGACY_SCOPE = 0x1,
0067     READOUT_MODE_LEGACY_VIRGIN_RAW_REAL = 0x2,
0068     READOUT_MODE_LEGACY_VIRGIN_RAW_FAKE = 0x3,
0069     READOUT_MODE_LEGACY_PROC_RAW_REAL = 0x6,
0070     READOUT_MODE_LEGACY_PROC_RAW_FAKE = 0x7,
0071     READOUT_MODE_LEGACY_ZERO_SUPPRESSED_REAL = 0xA,
0072     READOUT_MODE_LEGACY_ZERO_SUPPRESSED_FAKE = 0xB,
0073     READOUT_MODE_LEGACY_ZERO_SUPPRESSED_LITE_REAL = 0xC,
0074     READOUT_MODE_LEGACY_ZERO_SUPPRESSED_LITE_FAKE = 0xD,
0075     READOUT_MODE_LEGACY_SPY = 0xE,
0076     READOUT_MODE_LEGACY_PREMIX_RAW = 0xF
0077   };
0078 
0079   static const uint8_t PACKET_CODE_SCOPE = 0xE1;
0080   static const uint8_t PACKET_CODE_VIRGIN_RAW = 0xE6;
0081   static const uint8_t PACKET_CODE_VIRGIN_RAW10 = 0x86;
0082   static const uint8_t PACKET_CODE_VIRGIN_RAW8_BOTBOT = 0xC6;  //FIXME need to implement this!
0083   static const uint8_t PACKET_CODE_VIRGIN_RAW8_TOPBOT = 0xA6;
0084   static const uint8_t PACKET_CODE_PROC_RAW = 0xF2;
0085   static const uint8_t PACKET_CODE_PROC_RAW10 = 0x92;  //FIXME need to implement this!
0086   static const uint8_t PACKET_CODE_PROC_RAW8_BOTBOT = 0xCA;
0087   static const uint8_t PACKET_CODE_PROC_RAW8_TOPBOT = 0xB2;
0088   static const uint8_t PACKET_CODE_ZERO_SUPPRESSED = 0xEA;
0089   static const uint8_t PACKET_CODE_ZERO_SUPPRESSED10 = 0x8A;
0090   static const uint8_t PACKET_CODE_ZERO_SUPPRESSED8_BOTBOT = 0xCA;
0091   static const uint8_t PACKET_CODE_ZERO_SUPPRESSED8_TOPBOT = 0xAA;
0092 
0093   //enum values are values which appear in buffer. DO NOT CHANGE!
0094   //see http://cmsdoc.cern.ch/cms/TRIDAS/horizontal/RUWG/DAQ_IF_guide/DAQ_IF_guide.html
0095   enum FEDDAQEventType {
0096     DAQ_EVENT_TYPE_PHYSICS = 0x1,
0097     DAQ_EVENT_TYPE_CALIBRATION = 0x2,
0098     DAQ_EVENT_TYPE_TEST = 0x3,
0099     DAQ_EVENT_TYPE_TECHNICAL = 0x4,
0100     DAQ_EVENT_TYPE_SIMULATED = 0x5,
0101     DAQ_EVENT_TYPE_TRACED = 0x6,
0102     DAQ_EVENT_TYPE_ERROR = 0xF,
0103     DAQ_EVENT_TYPE_INVALID = INVALID
0104   };
0105 
0106   //enum values are values which appear in buffer. DO NOT CHANGE!
0107   //see http://cmsdoc.cern.ch/cms/TRIDAS/horizontal/RUWG/DAQ_IF_guide/DAQ_IF_guide.html
0108   enum FEDTTSBits {
0109     TTS_DISCONNECTED0 = 0x0,
0110     TTS_WARN_OVERFLOW = 0x1,
0111     TTS_OUT_OF_SYNC = 0x2,
0112     TTS_BUSY = 0x4,
0113     TTS_READY = 0x8,
0114     TTS_ERROR = 0x12,
0115     TTS_DISCONNECTED1 = 0xF,
0116     TTS_INVALID = INVALID
0117   };
0118 
0119   //enum values are values which appear in buffer. DO NOT CHANGE!
0120   enum FEDBufferState {
0121     BUFFER_STATE_UNSET = 0x0,
0122     BUFFER_STATE_EMPTY = 0x1,
0123     BUFFER_STATE_PARTIAL_FULL = 0x4,
0124     BUFFER_STATE_FULL = 0x8
0125   };
0126 
0127   //enum values are values which appear in buffer. DO NOT CHANGE!
0128   enum FEDChannelStatus {
0129     CHANNEL_STATUS_LOCKED = 0x20,
0130     CHANNEL_STATUS_IN_SYNC = 0x10,
0131     CHANNEL_STATUS_APV1_ADDRESS_GOOD = 0x08,
0132     CHANNEL_STATUS_APV0_NO_ERROR_BIT = 0x04,
0133     CHANNEL_STATUS_APV0_ADDRESS_GOOD = 0x02,
0134     CHANNEL_STATUS_APV1_NO_ERROR_BIT = 0x01,
0135     CHANNEL_STATUS_NO_PROBLEMS = CHANNEL_STATUS_LOCKED | CHANNEL_STATUS_IN_SYNC | CHANNEL_STATUS_APV1_ADDRESS_GOOD |
0136                                  CHANNEL_STATUS_APV0_NO_ERROR_BIT | CHANNEL_STATUS_APV0_ADDRESS_GOOD |
0137                                  CHANNEL_STATUS_APV1_NO_ERROR_BIT
0138   };
0139 
0140   enum class FEDBufferStatusCode {
0141     // for FEDBufferBase
0142     SUCCESS = 0,
0143     BUFFER_NULL,
0144     BUFFER_TOO_SHORT,
0145     UNRECOGNIZED_FORMAT,
0146     // for FEDBuffer and FEDSpyBuffer
0147     EXPECT_NOT_SPY,
0148     EXPECT_SPY,
0149     // for FEDBuffer
0150     WRONG_HEADERTYPE,
0151     CHANNEL_BEGIN_BEYOND_PAYLOAD,
0152     CHANNEL_TOO_SHORT,
0153     CHANNEL_END_BEYOND_PAYLOAD,
0154   };
0155 
0156   //
0157   // Global function declarations
0158   //
0159 
0160   //used by these classes
0161   uint8_t internalFEDChannelNum(const uint8_t internalFEUnitNum, const uint8_t internalFEUnitChannelNum);
0162   void printHex(const void* pointer, const size_t length, std::ostream& os);
0163   //calculate the CRC for a FED buffer
0164   uint16_t calculateFEDBufferCRC(const uint8_t* buffer, const size_t lengthInBytes);
0165   //to make enums printable
0166   std::ostream& operator<<(std::ostream& os, const FEDBufferFormat& value);
0167   std::ostream& operator<<(std::ostream& os, const FEDHeaderType& value);
0168   std::ostream& operator<<(std::ostream& os, const FEDLegacyReadoutMode& value);
0169   std::ostream& operator<<(std::ostream& os, const FEDReadoutMode& value);
0170   std::ostream& operator<<(std::ostream& os, const FEDDAQEventType& value);
0171   std::ostream& operator<<(std::ostream& os, const FEDTTSBits& value);
0172   std::ostream& operator<<(std::ostream& os, const FEDBufferState& value);
0173   std::ostream& operator<<(std::ostream& os, const FEDChannelStatus& value);
0174   std::ostream& operator<<(std::ostream& os, const FEDBufferStatusCode& value);
0175   //convert name of an element of enum to enum value (useful for getting values from config)
0176   FEDBufferFormat fedBufferFormatFromString(const std::string& bufferFormatString);
0177   FEDHeaderType fedHeaderTypeFromString(const std::string& headerTypeString);
0178   FEDReadoutMode fedReadoutModeFromString(const std::string& readoutModeString);
0179   uint8_t packetCodeFromString(const std::string& packetCodeString, FEDReadoutMode mode);
0180   FEDDAQEventType fedDAQEventTypeFromString(const std::string& daqEventTypeString);
0181 
0182   //
0183   // Class definitions
0184   //
0185 
0186   //handles conversion between order of data in buffer in VR/PR modes (readout order) and strip order (physical order)
0187   class FEDStripOrdering {
0188   public:
0189     //convert strip/sample index in channel (ie 0-255) between physical and readout order
0190     static uint8_t physicalOrderForStripInChannel(const uint8_t readoutOrderStripIndexInChannel);
0191     static uint8_t readoutOrderForStripInChannel(const uint8_t physicalOrderStripIndexInChannel);
0192     //convert strip/sample index in APV (ie 0-127) between physical and readout order
0193     static uint8_t physicalOrderForStripInAPV(const uint8_t readoutOrderStripIndexInAPV);
0194     static uint8_t readoutOrderForStripInAPV(const uint8_t physicalOrderStripIndexInAPV);
0195   };
0196 
0197   //see http://cmsdoc.cern.ch/cms/TRIDAS/horizontal/RUWG/DAQ_IF_guide/DAQ_IF_guide.html
0198   class FEDDAQHeader {
0199   public:
0200     FEDDAQHeader() {}
0201     explicit FEDDAQHeader(const uint8_t* header);
0202     //0x5 in first fragment
0203     uint8_t boeNibble() const;
0204     uint8_t eventTypeNibble() const;
0205     FEDDAQEventType eventType() const;
0206     uint32_t l1ID() const;
0207     uint16_t bxID() const;
0208     uint16_t sourceID() const;
0209     uint8_t version() const;
0210     //0 if current header word is last, 1 otherwise
0211     bool hBit() const;
0212     bool lastHeader() const;
0213     void print(std::ostream& os) const;
0214     //used by digi2Raw
0215     const uint8_t* data() const;
0216     FEDDAQHeader& setEventType(const FEDDAQEventType evtType);
0217     FEDDAQHeader& setL1ID(const uint32_t l1ID);
0218     FEDDAQHeader& setBXID(const uint16_t bxID);
0219     FEDDAQHeader& setSourceID(const uint16_t sourceID);
0220     FEDDAQHeader(const uint32_t l1ID,
0221                  const uint16_t bxID,
0222                  const uint16_t sourceID,
0223                  const FEDDAQEventType evtType = DAQ_EVENT_TYPE_PHYSICS);
0224 
0225   private:
0226     uint8_t header_[8];
0227   };
0228 
0229   //see http://cmsdoc.cern.ch/cms/TRIDAS/horizontal/RUWG/DAQ_IF_guide/DAQ_IF_guide.html
0230   class FEDDAQTrailer {
0231   public:
0232     FEDDAQTrailer() {}
0233     explicit FEDDAQTrailer(const uint8_t* trailer);
0234     //0xA in first fragment
0235     uint8_t eoeNibble() const;
0236     uint32_t eventLengthIn64BitWords() const;
0237     uint32_t eventLengthInBytes() const;
0238     uint16_t crc() const;
0239     //set to 1 if FRL detects a transmission error over S-link
0240     bool cBit() const;
0241     bool slinkTransmissionError() const { return cBit(); }
0242     //set to 1 if the FED ID is not the one expected by the FRL
0243     bool fBit() const;
0244     bool badSourceID() const { return fBit(); }
0245     uint8_t eventStatusNibble() const;
0246     uint8_t ttsNibble() const;
0247     FEDTTSBits ttsBits() const;
0248     //0 if the current trailer is the last, 1 otherwise
0249     bool tBit() const;
0250     bool lastTrailer() const { return !tBit(); }
0251     //set to 1 if the S-link sender card detects a CRC error (the CRC it computes is put in the CRC field)
0252     bool rBit() const;
0253     bool slinkCRCError() const { return rBit(); }
0254     void print(std::ostream& os) const;
0255     //used by digi2Raw
0256     const uint8_t* data() const;
0257     FEDDAQTrailer& setEventLengthIn64BitWords(const uint32_t eventLengthIn64BitWords);
0258     FEDDAQTrailer& setCRC(const uint16_t crc);
0259     FEDDAQTrailer& setSLinkTransmissionErrorBit(const bool bitSet);
0260     FEDDAQTrailer& setBadSourceIDBit(const bool bitSet);
0261     FEDDAQTrailer& setSLinkCRCErrorBit(const bool bitSet);
0262     FEDDAQTrailer& setEventStatusNibble(const uint8_t eventStatusNibble);
0263     FEDDAQTrailer& setTTSBits(const FEDTTSBits ttsBits);
0264     FEDDAQTrailer(const uint32_t eventLengthIn64BitWords,
0265                   const uint16_t crc = 0,
0266                   const FEDTTSBits ttsBits = TTS_READY,
0267                   const bool slinkTransmissionError = false,
0268                   const bool badFEDID = false,
0269                   const bool slinkCRCError = false,
0270                   const uint8_t eventStatusNibble = 0);
0271 
0272   private:
0273     uint8_t trailer_[8];
0274   };
0275 
0276   class FEDStatusRegister {
0277   public:
0278     FEDStatusRegister(const uint16_t fedStatusRegister);
0279     bool slinkFullFlag() const;
0280     bool trackerHeaderMonitorDataReadyFlag() const;
0281     bool qdrMemoryFullFlag() const;
0282     bool qdrMemoryPartialFullFlag() const;
0283     bool qdrMemoryEmptyFlag() const;
0284     bool l1aBxFIFOFullFlag() const;
0285     bool l1aBxFIFOPartialFullFlag() const;
0286     bool l1aBxFIFOEmptyFlag() const;
0287     FEDBufferState qdrMemoryState() const;
0288     FEDBufferState l1aBxFIFOState() const;
0289     bool feDataMissingFlag(const uint8_t internalFEUnitNum) const;
0290     void print(std::ostream& os) const;
0291     void printFlags(std::ostream& os) const;
0292     operator uint16_t() const;
0293     //used by digi2Raw
0294     FEDStatusRegister& setSLinkFullFlag(const bool bitSet);
0295     FEDStatusRegister& setTrackerHeaderMonitorDataReadyFlag(const bool bitSet);
0296     FEDStatusRegister& setQDRMemoryBufferState(const FEDBufferState state);
0297     FEDStatusRegister& setL1ABXFIFOBufferState(const FEDBufferState state);
0298     FEDStatusRegister(const FEDBufferState qdrMemoryBufferState = BUFFER_STATE_UNSET,
0299                       const FEDBufferState l1aBxFIFOBufferState = BUFFER_STATE_UNSET,
0300                       const bool trackerHeaderMonitorDataReadyFlagSet = false,
0301                       const bool slinkFullFlagSet = false);
0302 
0303   private:
0304     bool getBit(const uint8_t num) const;
0305     void setBit(const uint8_t num, const bool bitSet);
0306     void setQDRMemoryFullFlag(const bool bitSet);
0307     void setQDRMemoryPartialFullFlag(const bool bitSet);
0308     void setQDRMemoryEmptyFlag(const bool bitSet);
0309     void setL1ABXFIFOFullFlag(const bool bitSet);
0310     void setL1ABXFIFOPartialFullFlag(const bool bitSet);
0311     void setL1ABXFIFOEmptyFlag(const bool bitSet);
0312     uint16_t data_;
0313   };
0314 
0315   class TrackerSpecialHeader {
0316   public:
0317     TrackerSpecialHeader();
0318     //construct with a pointer to the data. The data will be coppied and swapped if necessary.
0319     explicit TrackerSpecialHeader(const uint8_t* headerPointer);
0320     uint8_t bufferFormatByte() const;
0321     FEDBufferFormat bufferFormat() const;
0322     uint8_t headerTypeNibble() const;
0323     FEDHeaderType headerType() const;
0324     uint8_t trackerEventTypeNibble() const;
0325     FEDReadoutMode readoutMode() const;
0326     FEDLegacyReadoutMode legacyReadoutMode() const;
0327     uint8_t apveAddress() const;
0328     uint8_t apvAddressErrorRegister() const;
0329     bool majorityAddressErrorForFEUnit(const uint8_t internalFEUnitNum) const;
0330     uint8_t feEnableRegister() const;
0331     bool feEnabled(const uint8_t internalFEUnitNum) const;
0332     uint8_t feOverflowRegister() const;
0333     bool feOverflow(const uint8_t internalFEUnitNum) const;
0334     uint16_t fedStatusRegisterWord() const;
0335     FEDStatusRegister fedStatusRegister() const;
0336     void print(std::ostream& os) const;
0337     //used by digi2Raw
0338     //returns ordered buffer (ie this may need to be swapped to get original order)
0339     const uint8_t* data() const;
0340     bool wasSwapped() const;
0341     TrackerSpecialHeader& setBufferFormat(const FEDBufferFormat newBufferFormat);
0342     TrackerSpecialHeader& setHeaderType(const FEDHeaderType headerType);
0343     TrackerSpecialHeader& setReadoutMode(const FEDReadoutMode readoutMode);
0344     TrackerSpecialHeader& setAPVEAddress(const uint8_t address);
0345     TrackerSpecialHeader& setAPVEAddressErrorRegister(const uint8_t addressErrorRegister);
0346     TrackerSpecialHeader& setAPVAddressErrorForFEUnit(const uint8_t internalFEUnitNum, const bool error);
0347     TrackerSpecialHeader& setFEEnableRegister(const uint8_t feEnableRegister);
0348     TrackerSpecialHeader& setFEEnableForFEUnit(const uint8_t internalFEUnitNum, const bool enabled);
0349     TrackerSpecialHeader& setFEOverflowRegister(const uint8_t feOverflowRegister);
0350     TrackerSpecialHeader& setFEOverflowForFEUnit(const uint8_t internalFEUnitNum, const bool overflow);
0351     TrackerSpecialHeader& setFEDStatusRegister(const FEDStatusRegister fedStatusRegister);
0352     TrackerSpecialHeader(const FEDBufferFormat bufferFormat,
0353                          const FEDReadoutMode readoutMode,
0354                          const FEDHeaderType headerType,
0355                          const uint8_t address = 0x00,
0356                          const uint8_t addressErrorRegister = 0x00,
0357                          const uint8_t feEnableRegister = 0xFF,
0358                          const uint8_t feOverflowRegister = 0x00,
0359                          const FEDStatusRegister fedStatusRegister = FEDStatusRegister());
0360 
0361     // detect the buffer format without constructing the full header
0362     static FEDBufferFormat bufferFormat(const uint8_t* headerPointer) {
0363       if (headerPointer[BUFFERFORMAT] == BUFFER_FORMAT_CODE_NEW) {
0364         return BUFFER_FORMAT_NEW;
0365       } else if (headerPointer[BUFFERFORMAT] == BUFFER_FORMAT_CODE_OLD) {
0366         return BUFFER_FORMAT_OLD_SLINK;
0367       } else if (headerPointer[BUFFERFORMAT ^ 4] == BUFFER_FORMAT_CODE_OLD) {
0368         // same case as used to detect "wordSwapped_" in the constructor
0369         return BUFFER_FORMAT_OLD_VME;
0370       } else {
0371         return BUFFER_FORMAT_INVALID;
0372       }
0373     }
0374 
0375   private:
0376     void setBufferFormatByte(const FEDBufferFormat newBufferFormat);
0377     void setHeaderTypeNibble(const uint8_t value);
0378     void setReadoutModeBits(const uint8_t value);
0379     enum byteIndicies {
0380       FEDSTATUS = 0,
0381       FEOVERFLOW = 2,
0382       FEENABLE = 3,
0383       ADDRESSERROR = 4,
0384       APVEADDRESS = 5,
0385       BUFFERTYPE = 6,
0386       BUFFERFORMAT = 7
0387     };
0388     //copy of header, 32 bit word swapped if needed
0389     uint8_t specialHeader_[8];
0390     //was the header word swapped wrt order in buffer?
0391     bool wordSwapped_;
0392   };
0393 
0394   class FEDBackendStatusRegister {
0395   public:
0396     FEDBackendStatusRegister(const uint32_t backendStatusRegister);
0397     bool internalFreezeFlag() const;
0398     bool slinkDownFlag() const;
0399     bool slinkFullFlag() const;
0400     bool backpressureFlag() const;
0401     bool ttcReadyFlag() const;
0402     bool trackerHeaderMonitorDataReadyFlag() const;
0403     FEDBufferState qdrMemoryState() const;
0404     FEDBufferState frameAddressFIFOState() const;
0405     FEDBufferState totalLengthFIFOState() const;
0406     FEDBufferState trackerHeaderFIFOState() const;
0407     FEDBufferState l1aBxFIFOState() const;
0408     FEDBufferState feEventLengthFIFOState() const;
0409     FEDBufferState feFPGABufferState() const;
0410     void print(std::ostream& os) const;
0411     void printFlags(std::ostream& os) const;
0412     operator uint32_t() const;
0413     //used by digi2Raw
0414     FEDBackendStatusRegister& setInternalFreezeFlag(const bool bitSet);
0415     FEDBackendStatusRegister& setSLinkDownFlag(const bool bitSet);
0416     FEDBackendStatusRegister& setSLinkFullFlag(const bool bitSet);
0417     FEDBackendStatusRegister& setBackpressureFlag(const bool bitSet);
0418     FEDBackendStatusRegister& setTTCReadyFlag(const bool bitSet);
0419     FEDBackendStatusRegister& setTrackerHeaderMonitorDataReadyFlag(const bool bitSet);
0420     FEDBackendStatusRegister& setQDRMemoryState(const FEDBufferState state);
0421     FEDBackendStatusRegister& setFrameAddressFIFOState(const FEDBufferState state);
0422     FEDBackendStatusRegister& setTotalLengthFIFOState(const FEDBufferState state);
0423     FEDBackendStatusRegister& setTrackerHeaderFIFOState(const FEDBufferState state);
0424     FEDBackendStatusRegister& setL1ABXFIFOState(const FEDBufferState state);
0425     FEDBackendStatusRegister& setFEEventLengthFIFOState(const FEDBufferState state);
0426     FEDBackendStatusRegister& setFEFPGABufferState(const FEDBufferState state);
0427     FEDBackendStatusRegister(const FEDBufferState qdrMemoryBufferState = BUFFER_STATE_UNSET,
0428                              const FEDBufferState frameAddressFIFOBufferState = BUFFER_STATE_UNSET,
0429                              const FEDBufferState totalLengthFIFOBufferState = BUFFER_STATE_UNSET,
0430                              const FEDBufferState trackerHeaderFIFOBufferState = BUFFER_STATE_UNSET,
0431                              const FEDBufferState l1aBxFIFOBufferState = BUFFER_STATE_UNSET,
0432                              const FEDBufferState feEventLengthFIFOBufferState = BUFFER_STATE_UNSET,
0433                              const FEDBufferState feFPGABufferState = BUFFER_STATE_UNSET,
0434                              const bool backpressure = false,
0435                              const bool slinkFull = false,
0436                              const bool slinkDown = false,
0437                              const bool internalFreeze = false,
0438                              const bool trackerHeaderMonitorDataReady = false,
0439                              const bool ttcReady = true);
0440 
0441   private:
0442     bool getBit(const uint8_t num) const;
0443     void setBit(const uint8_t num, const bool bitSet);
0444     //get the state of the buffer in position 'bufferPosition'
0445     FEDBufferState getBufferState(const uint8_t bufferPosition) const;
0446     //set the state of the buffer in position 'bufferPosition' to state 'state'
0447     void setBufferSate(const uint8_t bufferPosition, const FEDBufferState state);
0448     void printFlagsForBuffer(const FEDBufferState bufferState, const std::string name, std::ostream& os) const;
0449     //constants marking order of flags in buffer
0450     //eg. bit offset for L1A/BX FIFO Partial full flag is STATE_OFFSET_PARTIAL_FULL+BUFFER_POSITION_L1ABX_FIFO
0451     //    bit offset for total length FIFO empty flag is STATE_OFFSET_EMPTY+BUFFER_POSITION_TOTAL_LENGTH_FIFO
0452     //see BE FPGA technical description
0453     enum bufferPositions {
0454       BUFFER_POSITION_QDR_MEMORY = 0,
0455       BUFFER_POSITION_FRAME_ADDRESS_FIFO = 1,
0456       BUFFER_POSITION_TOTAL_LENGTH_FIFO = 2,
0457       BUFFER_POSITION_TRACKER_HEADER_FIFO = 3,
0458       BUFFER_POSITION_L1ABX_FIFO = 4,
0459       BUFFER_POSITION_FE_EVENT_LENGTH_FIFO = 5,
0460       BUFFER_POSITION_FE_FPGA_BUFFER = 6
0461     };
0462     enum stateOffsets { STATE_OFFSET_FULL = 8, STATE_OFFSET_PARTIAL_FULL = 16, STATE_OFFSET_EMPTY = 24 };
0463     uint32_t data_;
0464   };
0465 
0466   class FEDFEHeader {
0467   public:
0468     //factory function: allocates new FEDFEHeader derrivative of appropriate type
0469     static std::unique_ptr<FEDFEHeader> newFEHeader(const FEDHeaderType headerType, const uint8_t* headerBuffer);
0470     //used by digi2Raw
0471     static std::unique_ptr<FEDFEHeader> newFEHeader(const FEDHeaderType headerType);
0472     //create a buffer to use with digi2Raw
0473     static std::unique_ptr<FEDFEHeader> newFEFakeHeader(const FEDHeaderType headerType);
0474     virtual ~FEDFEHeader();
0475     //the length of the header
0476     virtual size_t lengthInBytes() const = 0;
0477     //check that there are no errors indicated in which ever error bits are available in the header
0478     //check bits for both APVs on a channel
0479     bool checkChannelStatusBits(const uint8_t internalFEUnitNum, const uint8_t internalFEUnitChannelNum) const;
0480     virtual bool checkChannelStatusBits(const uint8_t internalFEDChannelNum) const = 0;
0481     //check bits for one APV
0482     bool checkStatusBits(const uint8_t internalFEUnitNum,
0483                          const uint8_t internalFEUnitChannelNum,
0484                          const uint8_t apvNum) const;
0485     virtual bool checkStatusBits(const uint8_t internalFEDChannelNum, const uint8_t apvNum) const = 0;
0486     virtual void print(std::ostream& os) const = 0;
0487     virtual FEDFEHeader* clone() const = 0;
0488     //used by digi2Raw
0489     virtual const uint8_t* data() const = 0;
0490     virtual void setChannelStatus(const uint8_t internalFEDChannelNum, const FEDChannelStatus status) = 0;
0491     virtual void setFEUnitMajorityAddress(const uint8_t internalFEUnitNum, const uint8_t address) = 0;
0492     virtual void setBEStatusRegister(const FEDBackendStatusRegister beStatusRegister) = 0;
0493     virtual void setDAQRegister(const uint32_t daqRegister) = 0;
0494     virtual void setDAQRegister2(const uint32_t daqRegister2) = 0;
0495     virtual void set32BitReservedRegister(const uint8_t internalFEUnitNum, const uint32_t reservedRegister) = 0;
0496     virtual void setFEUnitLength(const uint8_t internalFEUnitNum, const uint16_t length) = 0;
0497     void setChannelStatus(const uint8_t internalFEUnitNum,
0498                           const uint8_t internalFEUnitChannelNum,
0499                           const FEDChannelStatus status);
0500   };
0501 
0502   class FEDAPVErrorHeader final : public FEDFEHeader {
0503   public:
0504     explicit FEDAPVErrorHeader(const uint8_t* headerBuffer);
0505     ~FEDAPVErrorHeader() override;
0506     size_t lengthInBytes() const override;
0507     bool checkChannelStatusBits(const uint8_t internalFEDChannelNum) const override;
0508     bool checkStatusBits(const uint8_t internalFEDChannelNum, const uint8_t apvNum) const override;
0509     void print(std::ostream& os) const override;
0510     FEDAPVErrorHeader* clone() const override;
0511     //used by digi2Raw
0512     const uint8_t* data() const override;
0513     FEDAPVErrorHeader& setAPVStatusBit(const uint8_t internalFEDChannelNum, const uint8_t apvNum, const bool apvGood);
0514     FEDAPVErrorHeader& setAPVStatusBit(const uint8_t internalFEUnitNum,
0515                                        const uint8_t internalFEUnitChannelNum,
0516                                        const uint8_t apvNum,
0517                                        const bool apvGood);
0518     FEDAPVErrorHeader(const std::vector<bool>& apvsGood = std::vector<bool>(APVS_PER_FED, true));
0519     //Information which is not present in APVError mode is allowed to be set here so that the methods can be called on the base class without caring
0520     //if the values need to be set.
0521     void setChannelStatus(const uint8_t internalFEDChannelNum, const FEDChannelStatus status) override;
0522     void setFEUnitMajorityAddress(const uint8_t internalFEUnitNum, const uint8_t address) override;
0523     void setBEStatusRegister(const FEDBackendStatusRegister beStatusRegister) override;
0524     void setDAQRegister(const uint32_t daqRegister) override;
0525     void setDAQRegister2(const uint32_t daqRegister2) override;
0526     void set32BitReservedRegister(const uint8_t internalFEUnitNum, const uint32_t reservedRegister) override;
0527     void setFEUnitLength(const uint8_t internalFEUnitNum, const uint16_t length) override;
0528 
0529   private:
0530     static const size_t APV_ERROR_HEADER_SIZE_IN_64BIT_WORDS = 3;
0531     static const size_t APV_ERROR_HEADER_SIZE_IN_BYTES = APV_ERROR_HEADER_SIZE_IN_64BIT_WORDS * 8;
0532     uint8_t header_[APV_ERROR_HEADER_SIZE_IN_BYTES];
0533   };
0534 
0535   class FEDFullDebugHeader final : public FEDFEHeader {
0536   public:
0537     explicit FEDFullDebugHeader(const uint8_t* headerBuffer);
0538     ~FEDFullDebugHeader() override;
0539     size_t lengthInBytes() const override;
0540     bool checkChannelStatusBits(const uint8_t internalFEDChannelNum) const override;
0541     bool checkStatusBits(const uint8_t internalFEDChannelNum, const uint8_t apvNum) const override;
0542     void print(std::ostream& os) const override;
0543     FEDFullDebugHeader* clone() const override;
0544 
0545     uint8_t feUnitMajorityAddress(const uint8_t internalFEUnitNum) const;
0546     FEDBackendStatusRegister beStatusRegister() const;
0547     uint32_t daqRegister() const;
0548     uint32_t daqRegister2() const;
0549     uint16_t feUnitLength(const uint8_t internalFEUnitNum) const;
0550     bool fePresent(const uint8_t internalFEUnitNum) const;
0551 
0552     FEDChannelStatus getChannelStatus(const uint8_t internalFEDChannelNum) const;
0553     FEDChannelStatus getChannelStatus(const uint8_t internalFEUnitNum, const uint8_t internalFEUnitChannelNum) const;
0554 
0555     //These methods return true if there was an error of the appropriate type (ie if the error bit is 0).
0556     //They return false if the error could not occur due to a more general error.
0557     //was channel unlocked
0558     bool unlocked(const uint8_t internalFEDChannelNum) const;
0559     bool unlocked(const uint8_t internalFEUnitNum, const uint8_t internalFEUnitChannelNum) const;
0560     //was channel out of sync if it was unlocked
0561     bool outOfSync(const uint8_t internalFEDChannelNum) const;
0562     bool outOfSync(const uint8_t internalFEUnitNum, const uint8_t internalFEUnitChannelNum) const;
0563     //was there an internal APV error if it was in sync
0564     bool apvError(const uint8_t internalFEDChannelNum, const uint8_t apvNum) const;
0565     bool apvError(const uint8_t internalFEUnitNum, const uint8_t internalFEUnitChannelNum, const uint8_t apvNum) const;
0566     //was the APV address wrong if it was in sync (does not depend on APV internal error bit)
0567     bool apvAddressError(const uint8_t internalFEDChannelNum, const uint8_t apvNum) const;
0568     bool apvAddressError(const uint8_t internalFEUnitNum,
0569                          const uint8_t internalFEUnitChannelNum,
0570                          const uint8_t apvNum) const;
0571 
0572     //used by digi2Raw
0573     const uint8_t* data() const override;
0574     void setChannelStatus(const uint8_t internalFEDChannelNum, const FEDChannelStatus status) override;
0575     void setFEUnitMajorityAddress(const uint8_t internalFEUnitNum, const uint8_t address) override;
0576     void setBEStatusRegister(const FEDBackendStatusRegister beStatusRegister) override;
0577     void setDAQRegister(const uint32_t daqRegister) override;
0578     void setDAQRegister2(const uint32_t daqRegister2) override;
0579     void set32BitReservedRegister(const uint8_t internalFEUnitNum, const uint32_t reservedRegister) override;
0580     void setFEUnitLength(const uint8_t internalFEUnitNum, const uint16_t length) override;
0581     static uint32_t get32BitWordFrom(const uint8_t* startOfWord);
0582     uint8_t* feWord(const uint8_t internalFEUnitNum);
0583     const uint8_t* feWord(const uint8_t internalFEUnitNum) const;
0584     FEDFullDebugHeader(const std::vector<uint16_t>& feUnitLengths = std::vector<uint16_t>(FEUNITS_PER_FED, 0),
0585                        const std::vector<uint8_t>& feMajorityAddresses = std::vector<uint8_t>(FEUNITS_PER_FED, 0),
0586                        const std::vector<FEDChannelStatus>& channelStatus =
0587                            std::vector<FEDChannelStatus>(FEDCH_PER_FED, CHANNEL_STATUS_NO_PROBLEMS),
0588                        const FEDBackendStatusRegister beStatusRegister = FEDBackendStatusRegister(),
0589                        const uint32_t daqRegister = 0,
0590                        const uint32_t daqRegister2 = 0);
0591 
0592   private:
0593     bool getBit(const uint8_t internalFEDChannelNum, const uint8_t bit) const;
0594     static void set32BitWordAt(uint8_t* startOfWord, const uint32_t value);
0595     void setBit(const uint8_t internalFEDChannelNum, const uint8_t bit, const bool value);
0596 
0597     //These methods return true if there was an error of the appropriate type (ie if the error bit is 0).
0598     //They ignore any previous errors which make the status bits meaningless and return the value of the bit anyway.
0599     //In general, the methods above which only return an error for the likely cause are more useful.
0600     bool unlockedFromBit(const uint8_t internalFEDChannelNum) const;
0601     bool outOfSyncFromBit(const uint8_t internalFEDChannelNum) const;
0602     bool apvErrorFromBit(const uint8_t internalFEDChannelNum, const uint8_t apvNum) const;
0603     bool apvAddressErrorFromBit(const uint8_t internalFEDChannelNum, const uint8_t apvNum) const;
0604 
0605     //following methods set the bits to 1 (no error) if value is false
0606     void setUnlocked(const uint8_t internalFEDChannelNum, const bool value);
0607     void setOutOfSync(const uint8_t internalFEDChannelNum, const bool value);
0608     void setAPVAddressError(const uint8_t internalFEDChannelNum, const uint8_t apvNum, const bool value);
0609     void setAPVError(const uint8_t internalFEDChannelNum, const uint8_t apvNum, const bool value);
0610     static const size_t FULL_DEBUG_HEADER_SIZE_IN_64BIT_WORDS = FEUNITS_PER_FED * 2;
0611     static const size_t FULL_DEBUG_HEADER_SIZE_IN_BYTES = FULL_DEBUG_HEADER_SIZE_IN_64BIT_WORDS * 8;
0612     uint8_t header_[FULL_DEBUG_HEADER_SIZE_IN_BYTES];
0613   };
0614 
0615   //holds information about position of a channel in the buffer for use by unpacker
0616   class FEDChannel {
0617   public:
0618     FEDChannel(const uint8_t* const data, const uint32_t offset, const uint16_t length);
0619     //gets length from first 2 bytes (assuming normal FED channel)
0620     FEDChannel(const uint8_t* const data, const uint32_t offset);
0621     uint16_t length() const;
0622     const uint8_t* data() const;
0623     uint32_t offset() const;
0624     /**
0625      * Retrieve the APV CM median for a non-lite zero-suppressed channel
0626      *
0627      * apvIndex should be either 0 or 1 (there are, by construction, two APVs on every channel)
0628      * No additional checks are done here, so the caller should check
0629      * the readout mode and/or packet code.
0630      */
0631     uint16_t cmMedian(const uint8_t apvIndex) const;
0632     //third byte of channel data for normal FED channels
0633     uint8_t packetCode() const;
0634 
0635   private:
0636     friend class FEDBuffer;
0637     const uint8_t* data_;
0638     uint32_t offset_;
0639     uint16_t length_;
0640   };
0641 
0642   //base class for sistrip FED buffers which have a DAQ header/trailer and tracker special header
0643   class FEDBufferBase {
0644   public:
0645     /**
0646      * constructor from a FEDRawData buffer
0647      *
0648      * The sistrip::preconstructCheckFEDBufferBase() method should be used to check
0649      * the validity of the fedBuffer before constructing a sistrip::FEDBufferBase.
0650      *
0651      * @see sistrip::preconstructCheckFEDBufferBase()
0652      */
0653     explicit FEDBufferBase(const FEDRawData& fedBuffer);
0654     virtual ~FEDBufferBase();
0655     //dump buffer to stream
0656     void dump(std::ostream& os) const;
0657     //dump original buffer before word swapping
0658     void dumpOriginalBuffer(std::ostream& os) const;
0659     virtual void print(std::ostream& os) const;
0660     //calculate the CRC from the buffer
0661     uint16_t calcCRC() const;
0662 
0663     //methods to get parts of the buffer
0664     FEDDAQHeader daqHeader() const;
0665     FEDDAQTrailer daqTrailer() const;
0666     size_t bufferSize() const;
0667     TrackerSpecialHeader trackerSpecialHeader() const;
0668     //methods to get info from DAQ header
0669     FEDDAQEventType daqEventType() const;
0670     uint32_t daqLvl1ID() const;
0671     uint16_t daqBXID() const;
0672     uint16_t daqSourceID() const;
0673     uint16_t sourceID() const;
0674     //methods to get info from DAQ trailer
0675     uint32_t daqEventLengthIn64bitWords() const;
0676     uint32_t daqEventLengthInBytes() const;
0677     uint16_t daqCRC() const;
0678     FEDTTSBits daqTTSState() const;
0679     //methods to get info from the tracker special header
0680     FEDBufferFormat bufferFormat() const;
0681     FEDHeaderType headerType() const;
0682     FEDLegacyReadoutMode legacyReadoutMode() const;
0683     FEDReadoutMode readoutMode() const;
0684     uint8_t packetCode(bool legacy = false, const uint8_t internalFEDChannelNum = 0) const;
0685     uint8_t apveAddress() const;
0686     bool majorityAddressErrorForFEUnit(const uint8_t internalFEUnitNum) const;
0687     bool feEnabled(const uint8_t internalFEUnitNum) const;
0688     uint8_t nFEUnitsEnabled() const;
0689     bool feOverflow(const uint8_t internalFEUnitNum) const;
0690     FEDStatusRegister fedStatusRegister() const;
0691 
0692     //check that channel has no errors
0693     virtual bool channelGood(const uint8_t internalFEDChannelNum) const;
0694     bool channelGood(const uint8_t internalFEUnitNum, const uint8_t internalChannelNum) const;
0695     //return channel object for channel
0696     const FEDChannel& channel(const uint8_t internalFEDChannelNum) const;
0697     const FEDChannel& channel(const uint8_t internalFEUnitNum, const uint8_t internalChannelNum) const;
0698 
0699     //summary checks
0700     //check that tracker special header is valid (does not check for FE unit errors indicated in special header)
0701     bool doTrackerSpecialHeaderChecks() const;
0702     //check for errors in DAQ heaqder and trailer (not including bad CRC)
0703     bool doDAQHeaderAndTrailerChecks() const;
0704     //do both
0705     bool doChecks() const;
0706     //print the result of all detailed checks
0707     virtual std::string checkSummary() const;
0708 
0709     //detailed checks
0710     bool checkCRC() const;
0711     bool checkMajorityAddresses() const;
0712     //methods to check tracker special header
0713     bool checkBufferFormat() const;
0714     bool checkHeaderType() const;
0715     bool checkReadoutMode() const;
0716     bool checkAPVEAddressValid() const;
0717     bool checkNoFEOverflows() const;
0718     //methods to check daq header and trailer
0719     bool checkNoSlinkCRCError() const;
0720     bool checkNoSLinkTransmissionError() const;
0721     bool checkSourceIDs() const;
0722     bool checkNoUnexpectedSourceID() const;
0723     bool checkNoExtraHeadersOrTrailers() const;
0724     bool checkLengthFromTrailer() const;
0725 
0726   protected:
0727     const uint8_t* getPointerToDataAfterTrackerSpecialHeader() const;
0728     const uint8_t* getPointerToByteAfterEndOfPayload() const;
0729     FEDBufferBase(const FEDRawData& fedBuffer, const bool fillChannelVector);
0730     std::vector<FEDChannel> channels_;
0731 
0732   private:
0733     void init();
0734     const uint8_t* originalBuffer_;
0735     const uint8_t* orderedBuffer_;
0736     const size_t bufferSize_;
0737     FEDDAQHeader daqHeader_;
0738     FEDDAQTrailer daqTrailer_;
0739     TrackerSpecialHeader specialHeader_;
0740   };
0741 
0742   //
0743   // Inline function definitions
0744   //
0745 
0746   /**
0747    * Check if a FEDRawData object satisfies the requirements for constructing a sistrip::FEDBufferBase
0748    *
0749    * These are:
0750    *   - FEDRawData::data() is non-null
0751    *   - FEDRawData::size() is large enough (at least big enough to hold a sistrip::TrackerSpecialHeader)
0752    *   - (unless checkRecognizedFormat is false) the buffer format (inside the sistrip::TrackerSpecialHeader) is recognized
0753    *
0754    * In case any check fails, a value different from sistrip::FEDBufferStatusCode::SUCCESS
0755    * is returned, and detailed information printed to LogDebug("FEDBuffer"), if relevant.
0756    */
0757   inline FEDBufferStatusCode preconstructCheckFEDBufferBase(const FEDRawData& fedBuffer,
0758                                                             bool checkRecognizedFormat = true) {
0759     if (!fedBuffer.data())
0760       return FEDBufferStatusCode::BUFFER_NULL;
0761     //min buffer length. DAQ header, DAQ trailer, tracker special header.
0762     static const size_t MIN_BUFFER_SIZE = 8 + 8 + 8;
0763     //check size is non zero
0764     if (fedBuffer.size() < MIN_BUFFER_SIZE) {
0765       LogDebug("FEDBuffer") << "Buffer is too small. Min size is " << MIN_BUFFER_SIZE << ". Buffer size is "
0766                             << fedBuffer.size() << ". ";
0767       return FEDBufferStatusCode::BUFFER_TOO_SHORT;
0768     }
0769     if (checkRecognizedFormat) {
0770       if (BUFFER_FORMAT_INVALID == TrackerSpecialHeader::bufferFormat(fedBuffer.data() + 8)) {
0771         LogDebug("FEDBuffer") << "Buffer format not recognized. Tracker special header: "
0772                               << TrackerSpecialHeader(fedBuffer.data() + 8);
0773         return FEDBufferStatusCode::UNRECOGNIZED_FORMAT;
0774       }
0775     }
0776     return FEDBufferStatusCode::SUCCESS;
0777   }
0778 
0779   inline std::ostream& operator<<(std::ostream& os, const FEDBufferBase& obj) {
0780     obj.print(os);
0781     os << obj.checkSummary();
0782     return os;
0783   }
0784 
0785   inline uint8_t internalFEDChannelNum(const uint8_t internalFEUnitNum, const uint8_t internalFEUnitChannelNum) {
0786     return (internalFEUnitNum * FEDCH_PER_FEUNIT + internalFEUnitChannelNum);
0787   }
0788 
0789   inline std::ostream& operator<<(std::ostream& os, const FEDDAQHeader& obj) {
0790     obj.print(os);
0791     return os;
0792   }
0793   inline std::ostream& operator<<(std::ostream& os, const FEDDAQTrailer& obj) {
0794     obj.print(os);
0795     return os;
0796   }
0797   inline std::ostream& operator<<(std::ostream& os, const TrackerSpecialHeader& obj) {
0798     obj.print(os);
0799     return os;
0800   }
0801   inline std::ostream& operator<<(std::ostream& os, const FEDStatusRegister& obj) {
0802     obj.print(os);
0803     return os;
0804   }
0805   inline std::ostream& operator<<(std::ostream& os, const FEDFEHeader& obj) {
0806     obj.print(os);
0807     return os;
0808   }
0809 
0810   //FEDStripOrdering
0811 
0812   inline uint8_t FEDStripOrdering::physicalOrderForStripInChannel(const uint8_t readoutOrderStripIndexInChannel) {
0813     return physicalOrderForStripInAPV(readoutOrderStripIndexInChannel / 2) +
0814            (readoutOrderStripIndexInChannel % 2) * STRIPS_PER_APV;
0815   }
0816 
0817   inline uint8_t FEDStripOrdering::readoutOrderForStripInChannel(const uint8_t physicalOrderStripIndexInChannel) {
0818     return (readoutOrderForStripInAPV(physicalOrderStripIndexInChannel % 128) * 2 +
0819             (physicalOrderStripIndexInChannel / 128));
0820   }
0821 
0822   inline uint8_t FEDStripOrdering::physicalOrderForStripInAPV(const uint8_t readout_order) {
0823     return ((32 * (readout_order % 4)) + (8 * static_cast<uint16_t>(static_cast<float>(readout_order) / 4.0)) -
0824             (31 * static_cast<uint16_t>(static_cast<float>(readout_order) / 16.0)));
0825   }
0826 
0827   inline uint8_t FEDStripOrdering::readoutOrderForStripInAPV(const uint8_t physical_order) {
0828     return (4 * ((static_cast<uint16_t>((static_cast<float>(physical_order) / 8.0))) % 4) +
0829             static_cast<uint16_t>(static_cast<float>(physical_order) / 32.0) + 16 * (physical_order % 8));
0830   }
0831 
0832   //TrackerSpecialHeader
0833 
0834   inline TrackerSpecialHeader::TrackerSpecialHeader() : wordSwapped_(false) {}
0835 
0836   inline uint8_t TrackerSpecialHeader::bufferFormatByte() const { return specialHeader_[BUFFERFORMAT]; }
0837 
0838   inline uint8_t TrackerSpecialHeader::headerTypeNibble() const { return ((specialHeader_[BUFFERTYPE] & 0xF0) >> 4); }
0839 
0840   inline FEDHeaderType TrackerSpecialHeader::headerType() const {
0841     const auto nibble = headerTypeNibble();
0842     switch (nibble) {
0843       case HEADER_TYPE_FULL_DEBUG:
0844       case HEADER_TYPE_APV_ERROR:
0845       case HEADER_TYPE_NONE:
0846         return FEDHeaderType(nibble);
0847       default:
0848         return HEADER_TYPE_INVALID;
0849     }
0850   }
0851 
0852   inline uint8_t TrackerSpecialHeader::trackerEventTypeNibble() const { return (specialHeader_[BUFFERTYPE] & 0x0F); }
0853 
0854   inline FEDReadoutMode TrackerSpecialHeader::readoutMode() const {
0855     const auto nibble = trackerEventTypeNibble();
0856     //if it is scope mode then return as is (it cannot be fake data)
0857     //if it is premix then return as is: stripping last bit would make it spy data !
0858     if ((nibble == READOUT_MODE_SCOPE) || (nibble == READOUT_MODE_PREMIX_RAW))  // 0x or 0xf
0859       return FEDReadoutMode(nibble);
0860     //if not then ignore the last bit which indicates if it is real or fake
0861     else {
0862       const uint8_t mode = (nibble & 0xF);
0863       switch (mode) {
0864         case READOUT_MODE_VIRGIN_RAW:
0865         case READOUT_MODE_PROC_RAW:
0866         case READOUT_MODE_ZERO_SUPPRESSED:
0867         case READOUT_MODE_ZERO_SUPPRESSED_FAKE:
0868         case READOUT_MODE_ZERO_SUPPRESSED_LITE10:
0869         //case READOUT_MODE_ZERO_SUPPRESSED_CMOVERRIDE:
0870         case READOUT_MODE_ZERO_SUPPRESSED_LITE10_CMOVERRIDE:
0871         case READOUT_MODE_ZERO_SUPPRESSED_LITE8:
0872         case READOUT_MODE_ZERO_SUPPRESSED_LITE8_CMOVERRIDE:
0873         case READOUT_MODE_ZERO_SUPPRESSED_LITE8_TOPBOT:
0874         case READOUT_MODE_ZERO_SUPPRESSED_LITE8_TOPBOT_CMOVERRIDE:
0875         case READOUT_MODE_ZERO_SUPPRESSED_LITE8_BOTBOT:
0876         case READOUT_MODE_ZERO_SUPPRESSED_LITE8_BOTBOT_CMOVERRIDE:
0877         case READOUT_MODE_SPY:
0878           return FEDReadoutMode(mode);
0879         default:
0880           return READOUT_MODE_INVALID;
0881       }
0882     }
0883   }
0884 
0885   inline uint8_t TrackerSpecialHeader::apveAddress() const { return specialHeader_[APVEADDRESS]; }
0886 
0887   inline uint8_t TrackerSpecialHeader::apvAddressErrorRegister() const { return specialHeader_[ADDRESSERROR]; }
0888 
0889   inline bool TrackerSpecialHeader::majorityAddressErrorForFEUnit(const uint8_t internalFEUnitNum) const {
0890     return (!(readoutMode() == READOUT_MODE_SCOPE) && !((0x1 << internalFEUnitNum) & apvAddressErrorRegister()));
0891   }
0892 
0893   inline uint8_t TrackerSpecialHeader::feEnableRegister() const { return specialHeader_[FEENABLE]; }
0894 
0895   inline bool TrackerSpecialHeader::feEnabled(const uint8_t internalFEUnitNum) const {
0896     return ((0x1 << internalFEUnitNum) & feEnableRegister());
0897   }
0898 
0899   inline uint8_t TrackerSpecialHeader::feOverflowRegister() const { return specialHeader_[FEOVERFLOW]; }
0900 
0901   inline bool TrackerSpecialHeader::feOverflow(const uint8_t internalFEUnitNum) const {
0902     return ((0x1 << internalFEUnitNum) & feOverflowRegister());
0903   }
0904 
0905   inline uint16_t TrackerSpecialHeader::fedStatusRegisterWord() const {
0906     //get 16 bits
0907     uint16_t statusRegister = ((specialHeader_[(FEDSTATUS + 1)] << 8) | specialHeader_[FEDSTATUS]);
0908     return statusRegister;
0909   }
0910 
0911   inline FEDStatusRegister TrackerSpecialHeader::fedStatusRegister() const {
0912     return FEDStatusRegister(fedStatusRegisterWord());
0913   }
0914 
0915   inline void TrackerSpecialHeader::print(std::ostream& os) const { printHex(specialHeader_, 8, os); }
0916 
0917   inline const uint8_t* TrackerSpecialHeader::data() const { return specialHeader_; }
0918 
0919   inline bool TrackerSpecialHeader::wasSwapped() const { return wordSwapped_; }
0920 
0921   inline void TrackerSpecialHeader::setHeaderTypeNibble(const uint8_t value) {
0922     specialHeader_[BUFFERTYPE] = ((specialHeader_[BUFFERTYPE] & 0x0F) | ((value << 4) & 0xF0));
0923   }
0924 
0925   inline void TrackerSpecialHeader::setReadoutModeBits(const uint8_t value) {
0926     specialHeader_[BUFFERTYPE] = ((specialHeader_[BUFFERTYPE] & (~0x0F)) | (value & 0x0F));
0927   }
0928 
0929   inline TrackerSpecialHeader& TrackerSpecialHeader::setAPVEAddress(const uint8_t address) {
0930     specialHeader_[APVEADDRESS] = address;
0931     return *this;
0932   }
0933 
0934   inline TrackerSpecialHeader& TrackerSpecialHeader::setAPVEAddressErrorRegister(const uint8_t addressErrorRegister) {
0935     specialHeader_[ADDRESSERROR] = addressErrorRegister;
0936     return *this;
0937   }
0938 
0939   inline TrackerSpecialHeader& TrackerSpecialHeader::setFEEnableRegister(const uint8_t feEnableRegister) {
0940     specialHeader_[FEENABLE] = feEnableRegister;
0941     return *this;
0942   }
0943 
0944   inline TrackerSpecialHeader& TrackerSpecialHeader::setFEOverflowRegister(const uint8_t feOverflowRegister) {
0945     specialHeader_[FEOVERFLOW] = feOverflowRegister;
0946     return *this;
0947   }
0948 
0949   inline TrackerSpecialHeader& TrackerSpecialHeader::setFEDStatusRegister(const FEDStatusRegister fedStatusRegister) {
0950     specialHeader_[FEDSTATUS] = (static_cast<uint16_t>(fedStatusRegister) & 0x00FF);
0951     specialHeader_[FEDSTATUS + 1] = ((static_cast<uint16_t>(fedStatusRegister) & 0xFF00) >> 8);
0952     return *this;
0953   }
0954 
0955   //FEDStatusRegister
0956 
0957   inline FEDStatusRegister::FEDStatusRegister(const uint16_t fedStatusRegister) : data_(fedStatusRegister) {}
0958 
0959   inline FEDStatusRegister::operator uint16_t() const { return data_; }
0960 
0961   inline bool FEDStatusRegister::getBit(const uint8_t num) const { return ((0x1 << num) & (data_)); }
0962 
0963   inline bool FEDStatusRegister::slinkFullFlag() const { return getBit(0); }
0964 
0965   inline bool FEDStatusRegister::trackerHeaderMonitorDataReadyFlag() const { return getBit(1); }
0966 
0967   inline bool FEDStatusRegister::qdrMemoryFullFlag() const { return getBit(2); }
0968 
0969   inline bool FEDStatusRegister::qdrMemoryPartialFullFlag() const { return getBit(3); }
0970 
0971   inline bool FEDStatusRegister::qdrMemoryEmptyFlag() const { return getBit(4); }
0972 
0973   inline bool FEDStatusRegister::l1aBxFIFOFullFlag() const { return getBit(5); }
0974 
0975   inline bool FEDStatusRegister::l1aBxFIFOPartialFullFlag() const { return getBit(6); }
0976 
0977   inline bool FEDStatusRegister::l1aBxFIFOEmptyFlag() const { return getBit(7); }
0978 
0979   inline bool FEDStatusRegister::feDataMissingFlag(const uint8_t internalFEUnitNum) const {
0980     return getBit(8 + internalFEUnitNum);
0981   }
0982 
0983   inline void FEDStatusRegister::print(std::ostream& os) const { printHex(&data_, 2, os); }
0984 
0985   inline FEDStatusRegister& FEDStatusRegister::setSLinkFullFlag(const bool bitSet) {
0986     setBit(0, bitSet);
0987     return *this;
0988   }
0989 
0990   inline FEDStatusRegister& FEDStatusRegister::setTrackerHeaderMonitorDataReadyFlag(const bool bitSet) {
0991     setBit(1, bitSet);
0992     return *this;
0993   }
0994 
0995   inline void FEDStatusRegister::setQDRMemoryFullFlag(const bool bitSet) { setBit(2, bitSet); }
0996 
0997   inline void FEDStatusRegister::setQDRMemoryPartialFullFlag(const bool bitSet) { setBit(3, bitSet); }
0998 
0999   inline void FEDStatusRegister::setQDRMemoryEmptyFlag(const bool bitSet) { setBit(4, bitSet); }
1000 
1001   inline void FEDStatusRegister::setL1ABXFIFOFullFlag(const bool bitSet) { setBit(5, bitSet); }
1002 
1003   inline void FEDStatusRegister::setL1ABXFIFOPartialFullFlag(const bool bitSet) { setBit(6, bitSet); }
1004 
1005   inline void FEDStatusRegister::setL1ABXFIFOEmptyFlag(const bool bitSet) { setBit(7, bitSet); }
1006 
1007   inline FEDStatusRegister::FEDStatusRegister(const FEDBufferState qdrMemoryBufferState,
1008                                               const FEDBufferState l1aBxFIFOBufferState,
1009                                               const bool trackerHeaderMonitorDataReadyFlagSet,
1010                                               const bool slinkFullFlagSet)
1011       : data_(0x0000) {
1012     setSLinkFullFlag(slinkFullFlagSet);
1013     setTrackerHeaderMonitorDataReadyFlag(trackerHeaderMonitorDataReadyFlagSet);
1014     setQDRMemoryBufferState(qdrMemoryBufferState);
1015     setL1ABXFIFOBufferState(l1aBxFIFOBufferState);
1016   }
1017 
1018   //FEDBackendStatusRegister
1019 
1020   inline FEDBackendStatusRegister::FEDBackendStatusRegister(const uint32_t backendStatusRegister)
1021       : data_(backendStatusRegister) {}
1022 
1023   inline FEDBackendStatusRegister::operator uint32_t() const { return data_; }
1024 
1025   inline void FEDBackendStatusRegister::print(std::ostream& os) const { printHex(&data_, 4, os); }
1026 
1027   inline bool FEDBackendStatusRegister::getBit(const uint8_t num) const { return ((0x1 << num) & (data_)); }
1028 
1029   inline bool FEDBackendStatusRegister::internalFreezeFlag() const { return getBit(1); }
1030 
1031   inline bool FEDBackendStatusRegister::slinkDownFlag() const { return getBit(2); }
1032 
1033   inline bool FEDBackendStatusRegister::slinkFullFlag() const { return getBit(3); }
1034 
1035   inline bool FEDBackendStatusRegister::backpressureFlag() const { return getBit(4); }
1036 
1037   inline bool FEDBackendStatusRegister::ttcReadyFlag() const { return getBit(6); }
1038 
1039   inline bool FEDBackendStatusRegister::trackerHeaderMonitorDataReadyFlag() const { return getBit(7); }
1040 
1041   inline FEDBackendStatusRegister& FEDBackendStatusRegister::setInternalFreezeFlag(const bool bitSet) {
1042     setBit(1, bitSet);
1043     return *this;
1044   }
1045 
1046   inline FEDBackendStatusRegister& FEDBackendStatusRegister::setSLinkDownFlag(const bool bitSet) {
1047     setBit(2, bitSet);
1048     return *this;
1049   }
1050 
1051   inline FEDBackendStatusRegister& FEDBackendStatusRegister::setSLinkFullFlag(const bool bitSet) {
1052     setBit(3, bitSet);
1053     return *this;
1054   }
1055 
1056   inline FEDBackendStatusRegister& FEDBackendStatusRegister::setBackpressureFlag(const bool bitSet) {
1057     setBit(4, bitSet);
1058     return *this;
1059   }
1060 
1061   inline FEDBackendStatusRegister& FEDBackendStatusRegister::setTTCReadyFlag(const bool bitSet) {
1062     setBit(6, bitSet);
1063     return *this;
1064   }
1065 
1066   inline FEDBackendStatusRegister& FEDBackendStatusRegister::setTrackerHeaderMonitorDataReadyFlag(const bool bitSet) {
1067     setBit(7, bitSet);
1068     return *this;
1069   }
1070 
1071   inline FEDBufferState FEDBackendStatusRegister::qdrMemoryState() const {
1072     return getBufferState(BUFFER_POSITION_QDR_MEMORY);
1073   }
1074 
1075   inline FEDBufferState FEDBackendStatusRegister::frameAddressFIFOState() const {
1076     return getBufferState(BUFFER_POSITION_FRAME_ADDRESS_FIFO);
1077   }
1078 
1079   inline FEDBufferState FEDBackendStatusRegister::totalLengthFIFOState() const {
1080     return getBufferState(BUFFER_POSITION_TOTAL_LENGTH_FIFO);
1081   }
1082 
1083   inline FEDBufferState FEDBackendStatusRegister::trackerHeaderFIFOState() const {
1084     return getBufferState(BUFFER_POSITION_TRACKER_HEADER_FIFO);
1085   }
1086 
1087   inline FEDBufferState FEDBackendStatusRegister::l1aBxFIFOState() const {
1088     return getBufferState(BUFFER_POSITION_L1ABX_FIFO);
1089   }
1090 
1091   inline FEDBufferState FEDBackendStatusRegister::feEventLengthFIFOState() const {
1092     return getBufferState(BUFFER_POSITION_FE_EVENT_LENGTH_FIFO);
1093   }
1094 
1095   inline FEDBufferState FEDBackendStatusRegister::feFPGABufferState() const {
1096     return getBufferState(BUFFER_POSITION_FE_FPGA_BUFFER);
1097   }
1098 
1099   inline FEDBackendStatusRegister& FEDBackendStatusRegister::setQDRMemoryState(const FEDBufferState state) {
1100     setBufferSate(BUFFER_POSITION_QDR_MEMORY, state);
1101     return *this;
1102   }
1103 
1104   inline FEDBackendStatusRegister& FEDBackendStatusRegister::setFrameAddressFIFOState(const FEDBufferState state) {
1105     setBufferSate(BUFFER_POSITION_FRAME_ADDRESS_FIFO, state);
1106     return *this;
1107   }
1108 
1109   inline FEDBackendStatusRegister& FEDBackendStatusRegister::setTotalLengthFIFOState(const FEDBufferState state) {
1110     setBufferSate(BUFFER_POSITION_TOTAL_LENGTH_FIFO, state);
1111     return *this;
1112   }
1113 
1114   inline FEDBackendStatusRegister& FEDBackendStatusRegister::setTrackerHeaderFIFOState(const FEDBufferState state) {
1115     setBufferSate(BUFFER_POSITION_TRACKER_HEADER_FIFO, state);
1116     return *this;
1117   }
1118 
1119   inline FEDBackendStatusRegister& FEDBackendStatusRegister::setL1ABXFIFOState(const FEDBufferState state) {
1120     setBufferSate(BUFFER_POSITION_L1ABX_FIFO, state);
1121     return *this;
1122   }
1123 
1124   inline FEDBackendStatusRegister& FEDBackendStatusRegister::setFEEventLengthFIFOState(const FEDBufferState state) {
1125     setBufferSate(BUFFER_POSITION_FE_EVENT_LENGTH_FIFO, state);
1126     return *this;
1127   }
1128 
1129   inline FEDBackendStatusRegister& FEDBackendStatusRegister::setFEFPGABufferState(const FEDBufferState state) {
1130     setBufferSate(BUFFER_POSITION_FE_FPGA_BUFFER, state);
1131     return *this;
1132   }
1133 
1134   //FEDFEHeader
1135 
1136   inline std::unique_ptr<FEDFEHeader> FEDFEHeader::newFEHeader(const FEDHeaderType headerType,
1137                                                                const uint8_t* headerBuffer) {
1138     switch (headerType) {
1139       case HEADER_TYPE_FULL_DEBUG:
1140         return std::unique_ptr<FEDFEHeader>(new FEDFullDebugHeader(headerBuffer));
1141       case HEADER_TYPE_APV_ERROR:
1142         return std::unique_ptr<FEDFEHeader>(new FEDAPVErrorHeader(headerBuffer));
1143       default:
1144         return std::unique_ptr<FEDFEHeader>();
1145     }
1146   }
1147 
1148   inline std::unique_ptr<FEDFEHeader> FEDFEHeader::newFEHeader(const FEDHeaderType headerType) {
1149     switch (headerType) {
1150       case HEADER_TYPE_FULL_DEBUG:
1151         return std::unique_ptr<FEDFEHeader>(new FEDFullDebugHeader());
1152       case HEADER_TYPE_APV_ERROR:
1153         return std::unique_ptr<FEDFEHeader>(new FEDAPVErrorHeader());
1154       default:
1155         return std::unique_ptr<FEDFEHeader>();
1156     }
1157   }
1158 
1159   inline std::unique_ptr<FEDFEHeader> FEDFEHeader::newFEFakeHeader(const FEDHeaderType headerType) {
1160     switch (headerType) {
1161       case HEADER_TYPE_FULL_DEBUG:
1162         return std::unique_ptr<FEDFEHeader>(new FEDFullDebugHeader);
1163       case HEADER_TYPE_APV_ERROR:
1164         return std::unique_ptr<FEDFEHeader>(new FEDAPVErrorHeader);
1165       default:
1166         return std::unique_ptr<FEDFEHeader>();
1167     }
1168   }
1169 
1170   inline bool FEDFEHeader::checkChannelStatusBits(const uint8_t internalFEUnitNum,
1171                                                   const uint8_t internalFEUnitChannelNum) const {
1172     return checkChannelStatusBits(internalFEDChannelNum(internalFEUnitNum, internalFEUnitChannelNum));
1173   }
1174 
1175   inline bool FEDFEHeader::checkStatusBits(const uint8_t internalFEUnitNum,
1176                                            const uint8_t internalFEUnitChannelNum,
1177                                            const uint8_t apvNum) const {
1178     return checkStatusBits(internalFEDChannelNum(internalFEUnitNum, internalFEUnitChannelNum), apvNum);
1179   }
1180 
1181   inline void FEDFEHeader::setChannelStatus(const uint8_t internalFEUnitNum,
1182                                             const uint8_t internalFEUnitChannelNum,
1183                                             const FEDChannelStatus status) {
1184     this->setChannelStatus(internalFEDChannelNum(internalFEUnitNum, internalFEUnitChannelNum), status);
1185   }
1186 
1187   inline FEDAPVErrorHeader::FEDAPVErrorHeader(const uint8_t* headerBuffer) {
1188     memcpy(header_, headerBuffer, APV_ERROR_HEADER_SIZE_IN_BYTES);
1189   }
1190 
1191   inline FEDAPVErrorHeader& FEDAPVErrorHeader::setAPVStatusBit(const uint8_t internalFEUnitNum,
1192                                                                const uint8_t internalFEUnitChannelNum,
1193                                                                const uint8_t apvNum,
1194                                                                const bool apvGood) {
1195     return setAPVStatusBit(internalFEDChannelNum(internalFEUnitNum, internalFEUnitChannelNum), apvNum, apvGood);
1196   }
1197 
1198   inline FEDFullDebugHeader::FEDFullDebugHeader(const uint8_t* headerBuffer) {
1199     memcpy(header_, headerBuffer, FULL_DEBUG_HEADER_SIZE_IN_BYTES);
1200   }
1201 
1202   inline uint8_t FEDFullDebugHeader::feUnitMajorityAddress(const uint8_t internalFEUnitNum) const {
1203     return feWord(internalFEUnitNum)[9];
1204   }
1205 
1206   inline FEDBackendStatusRegister FEDFullDebugHeader::beStatusRegister() const {
1207     return FEDBackendStatusRegister(get32BitWordFrom(feWord(0) + 10));
1208   }
1209 
1210   inline uint32_t FEDFullDebugHeader::daqRegister() const { return get32BitWordFrom(feWord(7) + 10); }
1211 
1212   inline uint32_t FEDFullDebugHeader::daqRegister2() const { return get32BitWordFrom(feWord(6) + 10); }
1213 
1214   inline uint16_t FEDFullDebugHeader::feUnitLength(const uint8_t internalFEUnitNum) const {
1215     return ((feWord(internalFEUnitNum)[15] << 8) | (feWord(internalFEUnitNum)[14]));
1216   }
1217 
1218   inline bool FEDFullDebugHeader::fePresent(const uint8_t internalFEUnitNum) const {
1219     return (feUnitLength(internalFEUnitNum) != 0);
1220   }
1221 
1222   inline bool FEDFullDebugHeader::unlocked(const uint8_t internalFEDChannelNum) const {
1223     return unlockedFromBit(internalFEDChannelNum);
1224   }
1225 
1226   inline bool FEDFullDebugHeader::unlocked(const uint8_t internalFEUnitNum,
1227                                            const uint8_t internalFEUnitChannelNum) const {
1228     return unlocked(internalFEDChannelNum(internalFEUnitNum, internalFEUnitChannelNum));
1229   }
1230 
1231   inline bool FEDFullDebugHeader::outOfSync(const uint8_t internalFEDChannelNum) const {
1232     return (!unlocked(internalFEDChannelNum) && outOfSyncFromBit(internalFEDChannelNum));
1233   }
1234 
1235   inline bool FEDFullDebugHeader::outOfSync(const uint8_t internalFEUnitNum,
1236                                             const uint8_t internalFEUnitChannelNum) const {
1237     return outOfSync(internalFEDChannelNum(internalFEUnitNum, internalFEUnitChannelNum));
1238   }
1239 
1240   inline bool FEDFullDebugHeader::apvError(const uint8_t internalFEDChannelNum, const uint8_t apvNum) const {
1241     return (!unlockedFromBit(internalFEDChannelNum) && !outOfSyncFromBit(internalFEDChannelNum) &&
1242             apvErrorFromBit(internalFEDChannelNum, apvNum));
1243   }
1244 
1245   inline bool FEDFullDebugHeader::apvError(const uint8_t internalFEUnitNum,
1246                                            const uint8_t internalFEUnitChannelNum,
1247                                            const uint8_t apvNum) const {
1248     return apvError(internalFEDChannelNum(internalFEUnitNum, internalFEUnitChannelNum), apvNum);
1249   }
1250 
1251   inline bool FEDFullDebugHeader::apvAddressError(const uint8_t internalFEDChannelNum, const uint8_t apvNum) const {
1252     return (!unlockedFromBit(internalFEDChannelNum) && !outOfSyncFromBit(internalFEDChannelNum) &&
1253             apvAddressErrorFromBit(internalFEDChannelNum, apvNum));
1254   }
1255 
1256   inline bool FEDFullDebugHeader::apvAddressError(const uint8_t internalFEUnitNum,
1257                                                   const uint8_t internalFEUnitChannelNum,
1258                                                   const uint8_t apvNum) const {
1259     return apvAddressError(internalFEDChannelNum(internalFEUnitNum, internalFEUnitChannelNum), apvNum);
1260   }
1261 
1262   inline FEDChannelStatus FEDFullDebugHeader::getChannelStatus(const uint8_t internalFEUnitNum,
1263                                                                const uint8_t internalFEUnitChannelNum) const {
1264     return getChannelStatus(internalFEDChannelNum(internalFEUnitNum, internalFEUnitChannelNum));
1265   }
1266 
1267   inline bool FEDFullDebugHeader::unlockedFromBit(const uint8_t internalFEDChannelNum) const {
1268     return !getBit(internalFEDChannelNum, 5);
1269   }
1270 
1271   inline bool FEDFullDebugHeader::outOfSyncFromBit(const uint8_t internalFEDChannelNum) const {
1272     return !getBit(internalFEDChannelNum, 4);
1273   }
1274 
1275   inline bool FEDFullDebugHeader::apvErrorFromBit(const uint8_t internalFEDChannelNum, const uint8_t apvNum) const {
1276     //Discovered March 2012: two bits inverted in firmware. Decided
1277     //to update documentation but keep firmware identical for
1278     //backward compatibility. So status bit order is actually:
1279     //apvErr1 - apvAddrErr0 - apvErr0 - apvAddrErr1 - OOS - unlocked.
1280     //Before, it was: return !getBit(internalFEDChannelNum,0+2*apvNum);
1281 
1282     return !getBit(internalFEDChannelNum, 0 + 2 * (1 - apvNum));
1283   }
1284 
1285   inline bool FEDFullDebugHeader::apvAddressErrorFromBit(const uint8_t internalFEDChannelNum,
1286                                                          const uint8_t apvNum) const {
1287     return !getBit(internalFEDChannelNum, 1 + 2 * apvNum);
1288   }
1289 
1290   inline bool FEDFullDebugHeader::getBit(const uint8_t internalFEDChannelNum, const uint8_t bit) const {
1291     const uint8_t* pFEWord = feWord(internalFEDChannelNum / FEDCH_PER_FEUNIT);
1292     const uint8_t bitInFeWord = ((FEDCH_PER_FEUNIT - 1) - (internalFEDChannelNum % FEDCH_PER_FEUNIT)) * 6 + bit;
1293     return (pFEWord[bitInFeWord / 8] & (0x1 << (bitInFeWord % 8)));
1294   }
1295 
1296   inline uint32_t FEDFullDebugHeader::get32BitWordFrom(const uint8_t* startOfWord) {
1297     return (startOfWord[0] | (startOfWord[1] << 8) | (startOfWord[2] << 16) | (startOfWord[3] << 24));
1298   }
1299 
1300   inline void FEDFullDebugHeader::set32BitWordAt(uint8_t* startOfWord, const uint32_t value) {
1301     memcpy(startOfWord, &value, 4);
1302   }
1303 
1304   inline const uint8_t* FEDFullDebugHeader::feWord(const uint8_t internalFEUnitNum) const {
1305     return header_ + internalFEUnitNum * 2 * 8;
1306   }
1307 
1308   //re-use const method
1309   inline uint8_t* FEDFullDebugHeader::feWord(const uint8_t internalFEUnitNum) {
1310     return const_cast<uint8_t*>(std::as_const(*this).feWord(internalFEUnitNum));
1311   }
1312 
1313   inline void FEDFullDebugHeader::setUnlocked(const uint8_t internalFEDChannelNum, const bool value) {
1314     setBit(internalFEDChannelNum, 5, !value);
1315   }
1316 
1317   inline void FEDFullDebugHeader::setOutOfSync(const uint8_t internalFEDChannelNum, const bool value) {
1318     setBit(internalFEDChannelNum, 4, !value);
1319   }
1320 
1321   inline void FEDFullDebugHeader::setAPVAddressError(const uint8_t internalFEDChannelNum,
1322                                                      const uint8_t apvNum,
1323                                                      const bool value) {
1324     setBit(internalFEDChannelNum, 1 + 2 * apvNum, !value);
1325   }
1326 
1327   inline void FEDFullDebugHeader::setAPVError(const uint8_t internalFEDChannelNum,
1328                                               const uint8_t apvNum,
1329                                               const bool value) {
1330     //Discovered March 2012: two bits inverted in firmware. Decided
1331     //to update documentation but keep firmware identical for
1332     //backward compatibility. So status bit order is actually:
1333     //apvErr1 - apvAddrErr0 - apvErr0 - apvAddrErr1 - OOS - unlocked.
1334     //Before, it was: return !getBit(internalFEDChannelNum,0+2*apvNum);
1335 
1336     setBit(internalFEDChannelNum, 0 + 2 * (1 - apvNum), !value);
1337   }
1338 
1339   //FEDDAQHeader
1340 
1341   inline FEDDAQHeader::FEDDAQHeader(const uint8_t* header) { memcpy(header_, header, 8); }
1342 
1343   inline uint8_t FEDDAQHeader::boeNibble() const { return ((header_[7] & 0xF0) >> 4); }
1344 
1345   inline uint8_t FEDDAQHeader::eventTypeNibble() const { return (header_[7] & 0x0F); }
1346 
1347   inline uint32_t FEDDAQHeader::l1ID() const { return (header_[4] | (header_[5] << 8) | (header_[6] << 16)); }
1348 
1349   inline uint16_t FEDDAQHeader::bxID() const { return ((header_[3] << 4) | ((header_[2] & 0xF0) >> 4)); }
1350 
1351   inline uint16_t FEDDAQHeader::sourceID() const { return (((header_[2] & 0x0F) << 8) | header_[1]); }
1352 
1353   inline uint8_t FEDDAQHeader::version() const { return ((header_[0] & 0xF0) >> 4); }
1354 
1355   inline bool FEDDAQHeader::hBit() const { return (header_[0] & 0x8); }
1356 
1357   inline bool FEDDAQHeader::lastHeader() const { return !hBit(); }
1358 
1359   inline const uint8_t* FEDDAQHeader::data() const { return header_; }
1360 
1361   inline void FEDDAQHeader::print(std::ostream& os) const { printHex(header_, 8, os); }
1362 
1363   //FEDDAQTrailer
1364 
1365   inline FEDDAQTrailer::FEDDAQTrailer(const uint8_t* trailer) { memcpy(trailer_, trailer, 8); }
1366 
1367   inline uint8_t FEDDAQTrailer::eoeNibble() const { return ((trailer_[7] & 0xF0) >> 4); }
1368 
1369   inline uint32_t FEDDAQTrailer::eventLengthIn64BitWords() const {
1370     return (trailer_[4] | (trailer_[5] << 8) | (trailer_[6] << 16));
1371   }
1372 
1373   inline uint32_t FEDDAQTrailer::eventLengthInBytes() const { return eventLengthIn64BitWords() * 8; }
1374 
1375   inline uint16_t FEDDAQTrailer::crc() const { return (trailer_[2] | (trailer_[3] << 8)); }
1376 
1377   inline bool FEDDAQTrailer::cBit() const { return (trailer_[1] & 0x80); }
1378 
1379   inline bool FEDDAQTrailer::fBit() const { return (trailer_[1] & 0x40); }
1380 
1381   inline uint8_t FEDDAQTrailer::eventStatusNibble() const { return (trailer_[1] & 0x0F); }
1382 
1383   inline uint8_t FEDDAQTrailer::ttsNibble() const { return ((trailer_[0] & 0xF0) >> 4); }
1384 
1385   inline bool FEDDAQTrailer::tBit() const { return (trailer_[0] & 0x08); }
1386 
1387   inline bool FEDDAQTrailer::rBit() const { return (trailer_[0] & 0x04); }
1388 
1389   inline void FEDDAQTrailer::print(std::ostream& os) const { printHex(trailer_, 8, os); }
1390 
1391   inline const uint8_t* FEDDAQTrailer::data() const { return trailer_; }
1392 
1393   //FEDBufferBase
1394 
1395   inline void FEDBufferBase::dump(std::ostream& os) const { printHex(orderedBuffer_, bufferSize_, os); }
1396 
1397   inline void FEDBufferBase::dumpOriginalBuffer(std::ostream& os) const { printHex(originalBuffer_, bufferSize_, os); }
1398 
1399   inline uint16_t FEDBufferBase::calcCRC() const { return calculateFEDBufferCRC(orderedBuffer_, bufferSize_); }
1400 
1401   inline FEDDAQHeader FEDBufferBase::daqHeader() const { return daqHeader_; }
1402 
1403   inline FEDDAQTrailer FEDBufferBase::daqTrailer() const { return daqTrailer_; }
1404 
1405   inline size_t FEDBufferBase::bufferSize() const { return bufferSize_; }
1406 
1407   inline TrackerSpecialHeader FEDBufferBase::trackerSpecialHeader() const { return specialHeader_; }
1408 
1409   inline FEDDAQEventType FEDBufferBase::daqEventType() const { return daqHeader_.eventType(); }
1410 
1411   inline uint32_t FEDBufferBase::daqLvl1ID() const { return daqHeader_.l1ID(); }
1412 
1413   inline uint16_t FEDBufferBase::daqBXID() const { return daqHeader_.bxID(); }
1414 
1415   inline uint16_t FEDBufferBase::daqSourceID() const { return daqHeader_.sourceID(); }
1416 
1417   inline uint32_t FEDBufferBase::daqEventLengthIn64bitWords() const { return daqTrailer_.eventLengthIn64BitWords(); }
1418 
1419   inline uint32_t FEDBufferBase::daqEventLengthInBytes() const { return daqTrailer_.eventLengthInBytes(); }
1420 
1421   inline uint16_t FEDBufferBase::daqCRC() const { return daqTrailer_.crc(); }
1422 
1423   inline FEDTTSBits FEDBufferBase::daqTTSState() const { return daqTrailer_.ttsBits(); }
1424 
1425   inline FEDBufferFormat FEDBufferBase::bufferFormat() const { return specialHeader_.bufferFormat(); }
1426 
1427   inline FEDHeaderType FEDBufferBase::headerType() const { return specialHeader_.headerType(); }
1428 
1429   inline FEDLegacyReadoutMode FEDBufferBase::legacyReadoutMode() const { return specialHeader_.legacyReadoutMode(); }
1430 
1431   inline FEDReadoutMode FEDBufferBase::readoutMode() const { return specialHeader_.readoutMode(); }
1432 
1433   inline bool FEDBufferBase::doChecks() const {
1434     return doTrackerSpecialHeaderChecks() && doDAQHeaderAndTrailerChecks();
1435   }
1436 
1437   inline uint8_t FEDBufferBase::packetCode(bool legacy, const uint8_t internalFEDChannelNum) const {
1438     if (legacy) {
1439       FEDLegacyReadoutMode mode = legacyReadoutMode();
1440       switch (mode) {
1441         case READOUT_MODE_LEGACY_SCOPE:
1442           return PACKET_CODE_SCOPE;
1443         case READOUT_MODE_LEGACY_VIRGIN_RAW_REAL:
1444         case READOUT_MODE_LEGACY_VIRGIN_RAW_FAKE:
1445           return PACKET_CODE_VIRGIN_RAW;
1446         case READOUT_MODE_LEGACY_PROC_RAW_REAL:
1447         case READOUT_MODE_LEGACY_PROC_RAW_FAKE:
1448           return PACKET_CODE_PROC_RAW;
1449         case READOUT_MODE_LEGACY_ZERO_SUPPRESSED_REAL:
1450         case READOUT_MODE_LEGACY_ZERO_SUPPRESSED_FAKE:
1451           return PACKET_CODE_ZERO_SUPPRESSED;
1452         case READOUT_MODE_LEGACY_ZERO_SUPPRESSED_LITE_REAL:
1453         case READOUT_MODE_LEGACY_ZERO_SUPPRESSED_LITE_FAKE:
1454         case READOUT_MODE_LEGACY_PREMIX_RAW:
1455         case READOUT_MODE_LEGACY_SPY:
1456         case READOUT_MODE_LEGACY_INVALID:
1457         default:
1458           return 0;
1459       }
1460     } else {
1461       FEDReadoutMode mode = readoutMode();
1462       switch (mode) {
1463         case READOUT_MODE_SCOPE:
1464           return PACKET_CODE_SCOPE;
1465         case READOUT_MODE_VIRGIN_RAW:
1466           return channel(internalFEDChannelNum).packetCode();
1467         case READOUT_MODE_PROC_RAW:
1468           return PACKET_CODE_PROC_RAW;
1469         case READOUT_MODE_ZERO_SUPPRESSED:
1470           return channel(internalFEDChannelNum).packetCode();
1471         case READOUT_MODE_ZERO_SUPPRESSED_LITE10:
1472         case READOUT_MODE_ZERO_SUPPRESSED_LITE10_CMOVERRIDE:
1473         case READOUT_MODE_ZERO_SUPPRESSED_LITE8_BOTBOT:
1474         case READOUT_MODE_ZERO_SUPPRESSED_LITE8_BOTBOT_CMOVERRIDE:
1475         case READOUT_MODE_ZERO_SUPPRESSED_LITE8_TOPBOT:
1476         case READOUT_MODE_ZERO_SUPPRESSED_LITE8_TOPBOT_CMOVERRIDE:
1477         case READOUT_MODE_ZERO_SUPPRESSED_LITE8:
1478         case READOUT_MODE_ZERO_SUPPRESSED_LITE8_CMOVERRIDE:
1479         case READOUT_MODE_PREMIX_RAW:
1480         case READOUT_MODE_SPY:
1481         case READOUT_MODE_INVALID:
1482         default:
1483           return 0;
1484       }
1485     }
1486   }
1487 
1488   inline uint8_t FEDBufferBase::apveAddress() const { return specialHeader_.apveAddress(); }
1489 
1490   inline bool FEDBufferBase::majorityAddressErrorForFEUnit(const uint8_t internalFEUnitNum) const {
1491     return (specialHeader_.majorityAddressErrorForFEUnit(internalFEUnitNum) && (specialHeader_.apveAddress() != 0x00));
1492   }
1493 
1494   inline bool FEDBufferBase::feEnabled(const uint8_t internalFEUnitNum) const {
1495     return specialHeader_.feEnabled(internalFEUnitNum);
1496   }
1497 
1498   inline bool FEDBufferBase::feOverflow(const uint8_t internalFEUnitNum) const {
1499     return specialHeader_.feOverflow(internalFEUnitNum);
1500   }
1501 
1502   inline FEDStatusRegister FEDBufferBase::fedStatusRegister() const { return specialHeader_.fedStatusRegister(); }
1503 
1504   inline bool FEDBufferBase::channelGood(const uint8_t internalFEUnitNum, const uint8_t internalChannelNum) const {
1505     return channelGood(internalFEDChannelNum(internalFEUnitNum, internalChannelNum));
1506   }
1507 
1508   inline const FEDChannel& FEDBufferBase::channel(const uint8_t internalFEDChannelNum) const {
1509     return channels_[internalFEDChannelNum];
1510   }
1511 
1512   inline const FEDChannel& FEDBufferBase::channel(const uint8_t internalFEUnitNum,
1513                                                   const uint8_t internalChannelNum) const {
1514     return channel(internalFEDChannelNum(internalFEUnitNum, internalChannelNum));
1515   }
1516 
1517   inline bool FEDBufferBase::doTrackerSpecialHeaderChecks() const {
1518     return (checkBufferFormat() && checkHeaderType() && checkReadoutMode() &&
1519             //checkAPVEAddressValid() &&
1520             checkNoFEOverflows());
1521   }
1522 
1523   inline bool FEDBufferBase::doDAQHeaderAndTrailerChecks() const {
1524     return (checkNoSLinkTransmissionError() && checkSourceIDs() && checkNoUnexpectedSourceID() &&
1525             checkNoExtraHeadersOrTrailers() && checkLengthFromTrailer());
1526   }
1527 
1528   inline bool FEDBufferBase::checkCRC() const { return (checkNoSlinkCRCError() && (calcCRC() == daqCRC())); }
1529 
1530   inline bool FEDBufferBase::checkBufferFormat() const { return (bufferFormat() != BUFFER_FORMAT_INVALID); }
1531 
1532   inline bool FEDBufferBase::checkHeaderType() const { return (headerType() != HEADER_TYPE_INVALID); }
1533 
1534   inline bool FEDBufferBase::checkReadoutMode() const { return (readoutMode() != READOUT_MODE_INVALID); }
1535 
1536   inline bool FEDBufferBase::checkAPVEAddressValid() const { return (apveAddress() <= APV_MAX_ADDRESS); }
1537 
1538   inline bool FEDBufferBase::checkNoFEOverflows() const { return !specialHeader_.feOverflowRegister(); }
1539 
1540   inline bool FEDBufferBase::checkNoSlinkCRCError() const { return !daqTrailer_.slinkCRCError(); }
1541 
1542   inline bool FEDBufferBase::checkNoSLinkTransmissionError() const { return !daqTrailer_.slinkTransmissionError(); }
1543 
1544   inline bool FEDBufferBase::checkNoUnexpectedSourceID() const { return !daqTrailer_.badSourceID(); }
1545 
1546   inline bool FEDBufferBase::checkNoExtraHeadersOrTrailers() const {
1547     return ((daqHeader_.boeNibble() == 0x5) && (daqTrailer_.eoeNibble() == 0xA));
1548   }
1549 
1550   inline bool FEDBufferBase::checkLengthFromTrailer() const { return (bufferSize() == daqEventLengthInBytes()); }
1551 
1552   inline const uint8_t* FEDBufferBase::getPointerToDataAfterTrackerSpecialHeader() const { return orderedBuffer_ + 16; }
1553 
1554   inline const uint8_t* FEDBufferBase::getPointerToByteAfterEndOfPayload() const {
1555     return orderedBuffer_ + bufferSize_ - 8;
1556   }
1557 
1558   //FEDChannel
1559 
1560   inline FEDChannel::FEDChannel(const uint8_t* const data, const uint32_t offset) : data_(data), offset_(offset) {
1561     length_ = (data_[(offset_) ^ 7] + (data_[(offset_ + 1) ^ 7] << 8));
1562   }
1563 
1564   inline FEDChannel::FEDChannel(const uint8_t* const data, const uint32_t offset, const uint16_t length)
1565       : data_(data), offset_(offset), length_(length) {}
1566 
1567   inline uint16_t FEDChannel::length() const { return length_; }
1568 
1569   inline uint8_t FEDChannel::packetCode() const { return data_[(offset_ + 2) ^ 7]; }
1570 
1571   inline uint16_t FEDChannel::cmMedian(const uint8_t apvIndex) const {
1572     uint16_t result = 0;
1573     //CM median is 10 bits with lowest order byte first. First APV CM median starts in 4th byte of channel data
1574     result |= data_[(offset_ + 3 + 2 * apvIndex) ^ 7];
1575     result |= (((data_[(offset_ + 4 + 2 * apvIndex) ^ 7]) << 8) & 0x300);
1576     return result;
1577   }
1578 
1579   inline const uint8_t* FEDChannel::data() const { return data_; }
1580 
1581   inline uint32_t FEDChannel::offset() const { return offset_; }
1582 }  // namespace sistrip
1583 
1584 #endif  //ndef EventFilter_SiStripRawToDigi_FEDBufferComponents_H