CMS 3D CMS Logo

SiStripFEDBuffer.h
Go to the documentation of this file.
1 #ifndef EventFilter_SiStripRawToDigi_SiStripFEDBuffer_H
2 #define EventFilter_SiStripRawToDigi_SiStripFEDBuffer_H
3 
4 #include "boost/cstdint.hpp"
5 #include <string>
6 #include <vector>
7 #include <memory>
8 #include <ostream>
9 #include <cstring>
10 #include <cmath>
12 
14 
15 namespace sistrip {
16  constexpr uint16_t BITS_PER_BYTE = 8;
17 
18  //
19  // Class definitions
20  //
21 
22  //class representing standard (non-spy channel) FED buffers
23  class FEDBuffer final : public FEDBufferBase
24  {
25  public:
26  //construct from buffer
27  //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
28  FEDBuffer(const uint8_t* fedBuffer, const uint16_t fedBufferSize, const bool allowBadBuffer = false);
29  ~FEDBuffer() override;
30  void print(std::ostream& os) const override;
31  const FEDFEHeader* feHeader() const;
32  //check that a FE unit is enabled, has a good majority address and, if in full debug mode, that it is present
33  bool feGood(const uint8_t internalFEUnitNum) const;
34  bool feGoodWithoutAPVEmulatorCheck(const uint8_t internalFEUnitNum) const;
35  //check that a FE unit is present in the data.
36  //The high order byte of the FEDStatus register in the tracker special header is used in APV error mode.
37  //The FE length from the full debug header is used in full debug mode.
38  bool fePresent(uint8_t internalFEUnitNum) const;
39  //check that a channel is present in data, found, on a good FE unit and has no errors flagged in status bits
41  virtual bool channelGood(const uint8_t internalFEDannelNum, const bool doAPVeCheck=true) const;
42  void setLegacyMode(bool legacy) { legacyUnpacker_ = legacy;}
43 
44  //functions to check buffer. All return true if there is no problem.
45  //minimum checks to do before using buffer
47  virtual bool doChecks(bool doCRC=true) const;
48 
49  //additional checks to check for corrupt buffers
50  //check channel lengths fit inside to buffer length
51  bool checkChannelLengths() const;
52  //check that channel lengths add up to buffer length (this does the previous check as well)
54  //check channel packet codes match readout mode
55  bool checkChannelPacketCodes() const;
56  //check FE unit lengths in FULL DEBUG header match the lengths of their channels
57  bool checkFEUnitLengths() const;
58  //check FE unit APV addresses in FULL DEBUG header are equal to the APVe address if the majority was good
59  bool checkFEUnitAPVAddresses() const;
60  //do all corrupt buffer checks
61  virtual bool doCorruptBufferChecks() const;
62 
63  //check that there are no errors in channel, APV or FEUnit status bits
64  //these are done by channelGood(). Channels with bad status bits may be disabled so bad status bits do not usually indicate an error
65  bool checkStatusBits(const uint8_t internalFEDChannelNum) const;
66  bool checkStatusBits(const uint8_t internalFEUnitNum, const uint8_t internalChannelNum) const;
67  //same but for all channels on enabled FE units
68  bool checkAllChannelStatusBits() const;
69 
70  //check that all FE unit payloads are present
71  bool checkFEPayloadsPresent() const;
72 
73  //print a summary of all checks
74  std::string checkSummary() const override;
75  private:
76  uint8_t nFEUnitsPresent() const;
77  void findChannels();
78  inline uint8_t getCorrectPacketCode() const { return packetCode(legacyUnpacker_); }
79  uint16_t calculateFEUnitLength(const uint8_t internalFEUnitNumber) const;
80  std::unique_ptr<FEDFEHeader> feHeader_;
81  const uint8_t* payloadPointer_;
82  uint16_t payloadLength_;
83  uint8_t validChannels_;
85  bool legacyUnpacker_=false;
86  };
87 
88  //class for unpacking data from ZS FED channels
90  {
91  public:
92  static FEDZSChannelUnpacker zeroSuppressedModeUnpacker(const FEDChannel& channel);
93  static FEDZSChannelUnpacker zeroSuppressedLiteModeUnpacker(const FEDChannel& channel);
94  static FEDZSChannelUnpacker preMixRawModeUnpacker(const FEDChannel& channel);
96  uint8_t sampleNumber() const;
97  uint8_t adc() const;
98  uint16_t adcPreMix() const;
99  bool hasData() const;
100  FEDZSChannelUnpacker& operator ++ ();
101  FEDZSChannelUnpacker& operator ++ (int);
102  private:
103  //pointer to beginning of FED or FE data, offset of start of channel payload in data and length of channel payload
104  FEDZSChannelUnpacker(const uint8_t* payload, const uint16_t channelPayloadOffset, const int16_t channelPayloadLength, const uint16_t offsetIncrement=1);
105  void readNewClusterInfo();
106  static void throwBadChannelLength(const uint16_t length);
107  void throwBadClusterLength();
108  static void throwUnorderedData(const uint8_t currentStrip, const uint8_t firstStripOfNewCluster);
109  const uint8_t* data_;
110  uint16_t currentOffset_;
112  uint8_t currentStrip_;
116  };
117 
118  //class for unpacking data from raw FED channels
120  {
121  public:
125  explicit FEDRawChannelUnpacker(const FEDChannel& channel);
126  uint8_t sampleNumber() const;
127  uint16_t adc() const;
128  bool hasData() const;
129  FEDRawChannelUnpacker& operator ++ ();
130  FEDRawChannelUnpacker& operator ++ (int);
131  private:
132  static void throwBadChannelLength(const uint16_t length);
133  const uint8_t* data_;
134  uint16_t currentOffset_;
135  uint8_t currentStrip_;
136  uint16_t valuesLeft_;
137  };
138 
139  //class for unpacking data from any FED channels with a non-integer words bits stripping mode
141  {
142  public:
143  static FEDBSChannelUnpacker virginRawModeUnpacker(const FEDChannel& channel, uint16_t num_bits);
144  static FEDBSChannelUnpacker zeroSuppressedModeUnpacker(const FEDChannel& channel, uint16_t num_bits);
145  static FEDBSChannelUnpacker zeroSuppressedLiteModeUnpacker(const FEDChannel& channel, uint16_t num_bits);
147  uint8_t sampleNumber() const;
148  uint16_t adc() const;
149  bool hasData() const;
150  FEDBSChannelUnpacker& operator ++ ();
151  FEDBSChannelUnpacker& operator ++ (int);
152  private:
153  //pointer to beginning of FED or FE data, offset of start of channel payload in data and length of channel payload
154  FEDBSChannelUnpacker(const uint8_t* payload, const uint16_t channelPayloadOffset, const int16_t channelPayloadLength, const uint16_t offsetIncrement, bool useZS);
155  void readNewClusterInfo();
156  static void throwBadChannelLength(const uint16_t length);
157  static void throwBadWordLength(const uint16_t word_length);
158  static void throwUnorderedData(const uint8_t currentStrip, const uint8_t firstStripOfNewCluster);
159  const uint8_t* data_;
160  uint16_t oldWordOffset_;
164  uint8_t currentStrip_;
167  bool useZS_;
169  };
170 
171  //
172  // Inline function definitions
173  //
174 
175  //FEDBuffer
176 
177  inline const FEDFEHeader* FEDBuffer::feHeader() const
178  {
179  return feHeader_.get();
180  }
181 
182  inline bool FEDBuffer::feGood(const uint8_t internalFEUnitNum) const
183  {
184  return ( !majorityAddressErrorForFEUnit(internalFEUnitNum) && !feOverflow(internalFEUnitNum) && fePresent(internalFEUnitNum) );
185  }
186 
187  inline bool FEDBuffer::feGoodWithoutAPVEmulatorCheck(const uint8_t internalFEUnitNum) const
188  {
189  return ( !feOverflow(internalFEUnitNum) && fePresent(internalFEUnitNum) );
190  }
191 
192  inline bool FEDBuffer::fePresent(uint8_t internalFEUnitNum) const
193  {
194  return fePresent_[internalFEUnitNum];
195  }
196 
197  inline bool FEDBuffer::checkStatusBits(const uint8_t internalFEDChannelNum) const
198  {
199  return feHeader_->checkChannelStatusBits(internalFEDChannelNum);
200  }
201 
202  inline bool FEDBuffer::checkStatusBits(const uint8_t internalFEUnitNum, const uint8_t internalChannelNum) const
203  {
204  return checkStatusBits(internalFEDChannelNum(internalFEUnitNum,internalChannelNum));
205  }
206 
207  //FEDBSChannelUnpacker
208 
210  : data_(nullptr),
211  oldWordOffset_(0), currentWordOffset_(0),
212  currentLocalBitOffset_(0),
213  bitOffsetIncrement_(10),
214  currentStrip_(0),
215  channelPayloadOffset_(0), channelPayloadLength_(0),
216  useZS_(false), valuesLeftInCluster_(0)
217  { }
218 
219  inline FEDBSChannelUnpacker::FEDBSChannelUnpacker(const uint8_t* payload, const uint16_t channelPayloadOffset, const int16_t channelPayloadLength, const uint16_t offsetIncrement, bool useZS)
220  : data_(payload),
221  oldWordOffset_(0), currentWordOffset_(channelPayloadOffset),
223  bitOffsetIncrement_(offsetIncrement),
224  currentStrip_(0),
225  channelPayloadOffset_(channelPayloadOffset),
226  channelPayloadLength_(channelPayloadLength),
227  useZS_(useZS), valuesLeftInCluster_(0)
228  {
229  if (bitOffsetIncrement_>16) throwBadWordLength(bitOffsetIncrement_); // more than 2 words... still to be implemented
231  }
232 
234  {
235  uint16_t length = channel.length();
236  if (length & 0xF000) throwBadChannelLength(length);
237  if (num_bits<=0 or num_bits>16) throwBadWordLength(num_bits);
238  FEDBSChannelUnpacker result(channel.data(), channel.offset()+3, length-3, num_bits, false);
239  return result;
240  }
241 
243  {
244  uint16_t length = channel.length();
245  if (length & 0xF000) throwBadChannelLength(length);
246  FEDBSChannelUnpacker result(channel.data(), channel.offset()+7, length-7, num_bits, true);
247  return result;
248  }
249 
251  {
252  uint16_t length = channel.length();
253  if (length & 0xF000) throwBadChannelLength(length);
254  FEDBSChannelUnpacker result(channel.data(), channel.offset()+2, length-2, num_bits, true);
255  return result;
256  }
257 
258  inline uint8_t FEDBSChannelUnpacker::sampleNumber() const
259  {
260  return currentStrip_;
261  }
262 
263  inline uint16_t FEDBSChannelUnpacker::adc() const
264  {
265  uint16_t bits_missing = (bitOffsetIncrement_-BITS_PER_BYTE)+currentLocalBitOffset_;
266  uint16_t adc = (data_[currentWordOffset_^7]<<bits_missing);
268  adc += ( (data_[(currentWordOffset_+1)^7]>>(BITS_PER_BYTE-bits_missing)) );
269  }
270  return (adc&((1<<bitOffsetIncrement_)-1));
271  }
272 
273  inline bool FEDBSChannelUnpacker::hasData() const
274  {
275  const uint16_t nextChanWordOffset = channelPayloadOffset_+channelPayloadLength_;
276  if ( currentWordOffset_ + 1 < nextChanWordOffset ) {
277  return true; // fast case: 2 bytes always fit an ADC (even if offset)
278  } else { // close to end
279  const uint16_t plusOneBitOffset = currentLocalBitOffset_+bitOffsetIncrement_;
280  const uint16_t plusOneWordOffset = currentWordOffset_ + plusOneBitOffset/BITS_PER_BYTE;
281  return ( plusOneBitOffset % BITS_PER_BYTE ) ? ( plusOneWordOffset < nextChanWordOffset ) : ( plusOneWordOffset <= nextChanWordOffset );
282  }
283  }
284 
286  {
289  while (currentLocalBitOffset_>=BITS_PER_BYTE) {
292  }
293  if (useZS_) {
295  else {
296  if (hasData()) {
297  const uint8_t oldStrip = currentStrip_;
299  if ( !(currentStrip_ > oldStrip) ) throwUnorderedData(oldStrip,currentStrip_);
300  }
301  }
302  } else { currentStrip_++; }
303  return (*this);
304  }
305 
307  {
308  ++(*this); return *this;
309  }
310 
312  {
313  if ( currentLocalBitOffset_ ) {
316  }
319  }
320 
321 
322  //FEDRawChannelUnpacker
323 
325  : data_(channel.data()),
326  currentOffset_(channel.offset()+3),
327  currentStrip_(0),
328  valuesLeft_((channel.length()-3)/2)
329  {
330  if ((channel.length()-3)%2) throwBadChannelLength(channel.length());
331  }
332 
333  inline uint8_t FEDRawChannelUnpacker::sampleNumber() const
334  {
335  return currentStrip_;
336  }
337 
338  inline uint16_t FEDRawChannelUnpacker::adc() const
339  {
340  return ( data_[currentOffset_^7] + ((data_[(currentOffset_+1)^7]&0x03)<<8) );
341  }
342 
343  inline bool FEDRawChannelUnpacker::hasData() const
344  {
345  return valuesLeft_;
346  }
347 
349  {
350  currentOffset_ += 2;
351  currentStrip_++;
352  valuesLeft_--;
353  return (*this);
354  }
355 
357  {
358  ++(*this); return *this;
359  }
360 
361  //FEDZSChannelUnpacker
362 
364  : data_(nullptr),
365  offsetIncrement_(1),
366  valuesLeftInCluster_(0),
367  channelPayloadOffset_(0),
368  channelPayloadLength_(0)
369  { }
370 
371  inline FEDZSChannelUnpacker::FEDZSChannelUnpacker(const uint8_t* payload, const uint16_t channelPayloadOffset, const int16_t channelPayloadLength, const uint16_t offsetIncrement)
372  : data_(payload),
373  currentOffset_(channelPayloadOffset),
374  offsetIncrement_(offsetIncrement),
375  currentStrip_(0),
377  channelPayloadOffset_(channelPayloadOffset),
378  channelPayloadLength_(channelPayloadLength)
379  {
381  }
382 
384  {
385  uint16_t length = channel.length();
386  if (length & 0xF000) throwBadChannelLength(length);
387  FEDZSChannelUnpacker result(channel.data(),channel.offset()+7,length-7);
388  return result;
389  }
390 
392  {
393  uint16_t length = channel.length();
394  if (length & 0xF000) throwBadChannelLength(length);
395  FEDZSChannelUnpacker result(channel.data(),channel.offset()+2,length-2);
396  return result;
397  }
398 
400  {
401  //CAMM - to modify more ?
402  uint16_t length = channel.length();
403  if (length & 0xF000) throwBadChannelLength(length);
404  FEDZSChannelUnpacker result(channel.data(),channel.offset()+7,length-7,2);
405  return result;
406  }
407 
408  inline uint8_t FEDZSChannelUnpacker::sampleNumber() const
409  {
410  return currentStrip_;
411  }
412 
413  inline uint8_t FEDZSChannelUnpacker::adc() const
414  {
415  return data_[currentOffset_^7];
416  }
417 
418  inline uint16_t FEDZSChannelUnpacker::adcPreMix() const
419  {
420  return ( data_[currentOffset_^7] + ((data_[(currentOffset_+1)^7]&0x03)<<8) );
421  }
422 
423  inline bool FEDZSChannelUnpacker::hasData() const
424  {
426  }
427 
429  {
430  if (valuesLeftInCluster_) {
431  currentStrip_++;
434  } else {
436  if (hasData()) {
437  const uint8_t oldStrip = currentStrip_;
439  if ( !(currentStrip_ > oldStrip) ) throwUnorderedData(oldStrip,currentStrip_);
440  }
441  }
442  return (*this);
443  }
444 
446  {
447  ++(*this); return *this;
448  }
449 
451  {
454  }
455 
456 }
457 
458 #endif //ndef EventFilter_SiStripRawToDigi_SiStripFEDBuffer_H
int adc(sample_type sample)
get the ADC sample (12 bits)
static FEDRawChannelUnpacker procRawModeUnpacker(const FEDChannel &channel)
static void throwUnorderedData(const uint8_t currentStrip, const uint8_t firstStripOfNewCluster)
bool checkFEUnitLengths() const
static FEDZSChannelUnpacker zeroSuppressedModeUnpacker(const FEDChannel &channel)
bool checkStatusBits(const uint8_t internalFEDChannelNum) const
static void throwBadChannelLength(const uint16_t length)
virtual bool doCorruptBufferChecks() const
static void throwBadWordLength(const uint16_t word_length)
bool checkFEPayloadsPresent() const
static FEDZSChannelUnpacker preMixRawModeUnpacker(const FEDChannel &channel)
static FEDRawChannelUnpacker scopeModeUnpacker(const FEDChannel &channel)
static FEDRawChannelUnpacker virginRawModeUnpacker(const FEDChannel &channel)
FEDRawChannelUnpacker(const FEDChannel &channel)
uint8_t internalFEDChannelNum(const uint8_t internalFEUnitNum, const uint8_t internalFEUnitChannelNum)
static FEDBSChannelUnpacker zeroSuppressedModeUnpacker(const FEDChannel &channel, uint16_t num_bits)
static void throwBadChannelLength(const uint16_t length)
uint16_t BITS_PER_BYTE
static void throwUnorderedData(const uint8_t currentStrip, const uint8_t firstStripOfNewCluster)
static FEDBSChannelUnpacker zeroSuppressedLiteModeUnpacker(const FEDChannel &channel, uint16_t num_bits)
static FEDBSChannelUnpacker virginRawModeUnpacker(const FEDChannel &channel, uint16_t num_bits)
#define nullptr
const FEDFEHeader * feHeader() const
virtual bool channelGood(const uint8_t internalFEDannelNum, const bool doAPVeCheck=true) const
#define constexpr
sistrip classes
bool feGoodWithoutAPVEmulatorCheck(const uint8_t internalFEUnitNum) const
bool fePresent_[FEUNITS_PER_FED]
void setLegacyMode(bool legacy)
const uint8_t * payloadPointer_
bool fePresent(uint8_t internalFEUnitNum) const
bool majorityAddressErrorForFEUnit(const uint8_t internalFEUnitNum) const
static const uint16_t FEUNITS_PER_FED
uint8_t packetCode(bool legacy=false, const uint8_t internalFEDChannelNum=0) const
const FEDChannel & channel(const uint8_t internalFEDChannelNum) const
FEDRawChannelUnpacker & operator++()
bool checkChannelPacketCodes() const
FEDZSChannelUnpacker & operator++()
static FEDZSChannelUnpacker zeroSuppressedLiteModeUnpacker(const FEDChannel &channel)
uint8_t nFEUnitsPresent() const
std::unique_ptr< FEDFEHeader > feHeader_
bool checkFEUnitAPVAddresses() const
std::string checkSummary() const override
const uint8_t * data() const
FEDBuffer(const uint8_t *fedBuffer, const uint16_t fedBufferSize, const bool allowBadBuffer=false)
uint8_t getCorrectPacketCode() const
bool checkChannelLengthsMatchBufferLength() const
char data[epos_bytes_allocation]
Definition: EPOS_Wrapper.h:82
bool checkAllChannelStatusBits() const
static void throwBadChannelLength(const uint16_t length)
virtual bool channelGood(const uint8_t internalFEDChannelNum) const
uint16_t calculateFEUnitLength(const uint8_t internalFEUnitNumber) const
bool checkChannelLengths() const
bool feGood(const uint8_t internalFEUnitNum) const
FEDBSChannelUnpacker & operator++()
void print(std::ostream &os) const override
bool feOverflow(const uint8_t internalFEUnitNum) const