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 <string>
5 #include <vector>
6 #include <memory>
7 #include <ostream>
8 #include <cstring>
9 #include <cmath>
11 
13 #include <cstdint>
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  public:
25  //construct from buffer
26  //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
27  FEDBuffer(const uint8_t* fedBuffer, const uint16_t fedBufferSize, const bool allowBadBuffer = false);
28  ~FEDBuffer() override;
29  void print(std::ostream& os) const override;
30  const FEDFEHeader* feHeader() const;
31  //check that a FE unit is enabled, has a good majority address and, if in full debug mode, that it is present
32  bool feGood(const uint8_t internalFEUnitNum) const;
33  bool feGoodWithoutAPVEmulatorCheck(const uint8_t internalFEUnitNum) const;
34  //check that a FE unit is present in the data.
35  //The high order byte of the FEDStatus register in the tracker special header is used in APV error mode.
36  //The FE length from the full debug header is used in full debug mode.
37  bool fePresent(uint8_t internalFEUnitNum) const;
38  //check that a channel is present in data, found, on a good FE unit and has no errors flagged in status bits
40  virtual bool channelGood(const uint8_t internalFEDannelNum, const bool doAPVeCheck = true) const;
41  void setLegacyMode(bool legacy) { legacyUnpacker_ = legacy; }
42 
43  //functions to check buffer. All return true if there is no problem.
44  //minimum checks to do before using buffer
46  virtual bool doChecks(bool doCRC = true) const;
47 
48  //additional checks to check for corrupt buffers
49  //check channel lengths fit inside to buffer length
50  bool checkChannelLengths() const;
51  //check that channel lengths add up to buffer length (this does the previous check as well)
53  //check channel packet codes match readout mode
54  bool checkChannelPacketCodes() const;
55  //check FE unit lengths in FULL DEBUG header match the lengths of their channels
56  bool checkFEUnitLengths() const;
57  //check FE unit APV addresses in FULL DEBUG header are equal to the APVe address if the majority was good
58  bool checkFEUnitAPVAddresses() const;
59  //do all corrupt buffer checks
60  virtual bool doCorruptBufferChecks() const;
61 
62  //check that there are no errors in channel, APV or FEUnit status bits
63  //these are done by channelGood(). Channels with bad status bits may be disabled so bad status bits do not usually indicate an error
64  bool checkStatusBits(const uint8_t internalFEDChannelNum) const;
65  bool checkStatusBits(const uint8_t internalFEUnitNum, const uint8_t internalChannelNum) const;
66  //same but for all channels on enabled FE units
67  bool checkAllChannelStatusBits() const;
68 
69  //check that all FE unit payloads are present
70  bool checkFEPayloadsPresent() const;
71 
72  //print a summary of all checks
73  std::string checkSummary() const override;
74 
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  public:
91  static FEDZSChannelUnpacker zeroSuppressedModeUnpacker(const FEDChannel& channel);
92  static FEDZSChannelUnpacker zeroSuppressedLiteModeUnpacker(const FEDChannel& channel);
93  static FEDZSChannelUnpacker preMixRawModeUnpacker(const FEDChannel& channel);
95  uint8_t sampleNumber() const;
96  uint8_t adc() const;
97  uint16_t adcPreMix() const;
98  bool hasData() const;
99  FEDZSChannelUnpacker& operator++();
100  FEDZSChannelUnpacker& operator++(int);
101 
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,
105  const uint16_t channelPayloadOffset,
106  const int16_t channelPayloadLength,
107  const uint16_t offsetIncrement = 1);
108  void readNewClusterInfo();
109  static void throwBadChannelLength(const uint16_t length);
110  void throwBadClusterLength();
111  static void throwUnorderedData(const uint8_t currentStrip, const uint8_t firstStripOfNewCluster);
112  const uint8_t* data_;
113  uint16_t currentOffset_;
115  uint8_t currentStrip_;
119  };
120 
121  //class for unpacking data from raw FED channels
123  public:
126  return FEDRawChannelUnpacker(channel);
127  }
129  return FEDRawChannelUnpacker(channel);
130  }
131  explicit FEDRawChannelUnpacker(const FEDChannel& channel);
132  uint8_t sampleNumber() const;
133  uint16_t adc() const;
134  bool hasData() const;
135  FEDRawChannelUnpacker& operator++();
136  FEDRawChannelUnpacker& operator++(int);
137 
138  private:
139  static void throwBadChannelLength(const uint16_t length);
140  const uint8_t* data_;
141  uint16_t currentOffset_;
142  uint8_t currentStrip_;
143  uint16_t valuesLeft_;
144  };
145 
146  //class for unpacking data from any FED channels with a non-integer words bits stripping mode
148  public:
149  static FEDBSChannelUnpacker virginRawModeUnpacker(const FEDChannel& channel, uint16_t num_bits);
150  static FEDBSChannelUnpacker zeroSuppressedModeUnpacker(const FEDChannel& channel, uint16_t num_bits);
151  static FEDBSChannelUnpacker zeroSuppressedLiteModeUnpacker(const FEDChannel& channel, uint16_t num_bits);
153  uint8_t sampleNumber() const;
154  uint16_t adc() const;
155  bool hasData() const;
156  FEDBSChannelUnpacker& operator++();
157  FEDBSChannelUnpacker& operator++(int);
158 
159  private:
160  //pointer to beginning of FED or FE data, offset of start of channel payload in data and length of channel payload
161  FEDBSChannelUnpacker(const uint8_t* payload,
162  const uint16_t channelPayloadOffset,
163  const int16_t channelPayloadLength,
164  const uint16_t offsetIncrement,
165  bool useZS);
166  void readNewClusterInfo();
167  static void throwBadChannelLength(const uint16_t length);
168  static void throwBadWordLength(const uint16_t word_length);
169  static void throwUnorderedData(const uint8_t currentStrip, const uint8_t firstStripOfNewCluster);
170  const uint8_t* data_;
171  uint16_t oldWordOffset_;
175  uint8_t currentStrip_;
178  bool useZS_;
180  };
181 
182  //
183  // Inline function definitions
184  //
185 
186  //FEDBuffer
187 
188  inline const FEDFEHeader* FEDBuffer::feHeader() const { return feHeader_.get(); }
189 
190  inline bool FEDBuffer::feGood(const uint8_t internalFEUnitNum) const {
191  return (!majorityAddressErrorForFEUnit(internalFEUnitNum) && !feOverflow(internalFEUnitNum) &&
192  fePresent(internalFEUnitNum));
193  }
194 
195  inline bool FEDBuffer::feGoodWithoutAPVEmulatorCheck(const uint8_t internalFEUnitNum) const {
196  return (!feOverflow(internalFEUnitNum) && fePresent(internalFEUnitNum));
197  }
198 
199  inline bool FEDBuffer::fePresent(uint8_t internalFEUnitNum) const { return fePresent_[internalFEUnitNum]; }
200 
201  inline bool FEDBuffer::checkStatusBits(const uint8_t internalFEDChannelNum) const {
202  return feHeader_->checkChannelStatusBits(internalFEDChannelNum);
203  }
204 
205  inline bool FEDBuffer::checkStatusBits(const uint8_t internalFEUnitNum, const uint8_t internalChannelNum) const {
206  return checkStatusBits(internalFEDChannelNum(internalFEUnitNum, internalChannelNum));
207  }
208 
209  //FEDBSChannelUnpacker
210 
212  : data_(nullptr),
213  oldWordOffset_(0),
214  currentWordOffset_(0),
215  currentLocalBitOffset_(0),
216  bitOffsetIncrement_(10),
217  currentStrip_(0),
218  channelPayloadOffset_(0),
219  channelPayloadLength_(0),
220  useZS_(false),
221  valuesLeftInCluster_(0) {}
222 
224  const uint16_t channelPayloadOffset,
225  const int16_t channelPayloadLength,
226  const uint16_t offsetIncrement,
227  bool useZS)
228  : data_(payload),
229  oldWordOffset_(0),
230  currentWordOffset_(channelPayloadOffset),
232  bitOffsetIncrement_(offsetIncrement),
233  currentStrip_(0),
234  channelPayloadOffset_(channelPayloadOffset),
235  channelPayloadLength_(channelPayloadLength),
236  useZS_(useZS),
238  if (bitOffsetIncrement_ > 16)
239  throwBadWordLength(bitOffsetIncrement_); // more than 2 words... still to be implemented
242  }
243 
245  uint16_t num_bits) {
246  uint16_t length = channel.length();
247  if (length & 0xF000)
248  throwBadChannelLength(length);
249  if (num_bits <= 0 or num_bits > 16)
250  throwBadWordLength(num_bits);
251  FEDBSChannelUnpacker result(channel.data(), channel.offset() + 3, length - 3, num_bits, false);
252  return result;
253  }
254 
256  uint16_t num_bits) {
257  uint16_t length = channel.length();
258  if (length & 0xF000)
259  throwBadChannelLength(length);
260  FEDBSChannelUnpacker result(channel.data(), channel.offset() + 7, length - 7, num_bits, true);
261  return result;
262  }
263 
265  uint16_t num_bits) {
266  uint16_t length = channel.length();
267  if (length & 0xF000)
268  throwBadChannelLength(length);
269  FEDBSChannelUnpacker result(channel.data(), channel.offset() + 2, length - 2, num_bits, true);
270  return result;
271  }
272 
273  inline uint8_t FEDBSChannelUnpacker::sampleNumber() const { return currentStrip_; }
274 
275  inline uint16_t FEDBSChannelUnpacker::adc() const {
276  uint16_t bits_missing = (bitOffsetIncrement_ - BITS_PER_BYTE) + currentLocalBitOffset_;
277  uint16_t adc = (data_[currentWordOffset_ ^ 7] << bits_missing);
279  adc += ((data_[(currentWordOffset_ + 1) ^ 7] >> (BITS_PER_BYTE - bits_missing)));
280  }
281  return (adc & ((1 << bitOffsetIncrement_) - 1));
282  }
283 
284  inline bool FEDBSChannelUnpacker::hasData() const {
285  const uint16_t nextChanWordOffset = channelPayloadOffset_ + channelPayloadLength_;
286  if (currentWordOffset_ + 1 < nextChanWordOffset) {
287  return true; // fast case: 2 bytes always fit an ADC (even if offset)
288  } else { // close to end
289  const uint16_t plusOneBitOffset = currentLocalBitOffset_ + bitOffsetIncrement_;
290  const uint16_t plusOneWordOffset = currentWordOffset_ + plusOneBitOffset / BITS_PER_BYTE;
291  return (plusOneBitOffset % BITS_PER_BYTE) ? (plusOneWordOffset < nextChanWordOffset)
292  : (plusOneWordOffset <= nextChanWordOffset);
293  }
294  }
295 
299  while (currentLocalBitOffset_ >= BITS_PER_BYTE) {
302  }
303  if (useZS_) {
304  if (valuesLeftInCluster_) {
305  currentStrip_++;
307  } else {
308  if (hasData()) {
309  const uint8_t oldStrip = currentStrip_;
311  if (!(currentStrip_ > oldStrip))
313  }
314  }
315  } else {
316  currentStrip_++;
317  }
318  return (*this);
319  }
320 
322  ++(*this);
323  return *this;
324  }
325 
330  }
333  }
334 
335  //FEDRawChannelUnpacker
336 
338  : data_(channel.data()),
339  currentOffset_(channel.offset() + 3),
340  currentStrip_(0),
341  valuesLeft_((channel.length() - 3) / 2) {
342  if ((channel.length() - 3) % 2)
343  throwBadChannelLength(channel.length());
344  }
345 
346  inline uint8_t FEDRawChannelUnpacker::sampleNumber() const { return currentStrip_; }
347 
348  inline uint16_t FEDRawChannelUnpacker::adc() const {
349  return (data_[currentOffset_ ^ 7] + ((data_[(currentOffset_ + 1) ^ 7] & 0x03) << 8));
350  }
351 
352  inline bool FEDRawChannelUnpacker::hasData() const { return valuesLeft_; }
353 
355  currentOffset_ += 2;
356  currentStrip_++;
357  valuesLeft_--;
358  return (*this);
359  }
360 
362  ++(*this);
363  return *this;
364  }
365 
366  //FEDZSChannelUnpacker
367 
369  : data_(nullptr),
370  offsetIncrement_(1),
371  valuesLeftInCluster_(0),
372  channelPayloadOffset_(0),
373  channelPayloadLength_(0) {}
374 
376  const uint16_t channelPayloadOffset,
377  const int16_t channelPayloadLength,
378  const uint16_t offsetIncrement)
379  : data_(payload),
380  currentOffset_(channelPayloadOffset),
381  offsetIncrement_(offsetIncrement),
382  currentStrip_(0),
384  channelPayloadOffset_(channelPayloadOffset),
385  channelPayloadLength_(channelPayloadLength) {
388  }
389 
391  uint16_t length = channel.length();
392  if (length & 0xF000)
393  throwBadChannelLength(length);
394  FEDZSChannelUnpacker result(channel.data(), channel.offset() + 7, length - 7);
395  return result;
396  }
397 
399  uint16_t length = channel.length();
400  if (length & 0xF000)
401  throwBadChannelLength(length);
402  FEDZSChannelUnpacker result(channel.data(), channel.offset() + 2, length - 2);
403  return result;
404  }
405 
407  //CAMM - to modify more ?
408  uint16_t length = channel.length();
409  if (length & 0xF000)
410  throwBadChannelLength(length);
411  FEDZSChannelUnpacker result(channel.data(), channel.offset() + 7, length - 7, 2);
412  return result;
413  }
414 
415  inline uint8_t FEDZSChannelUnpacker::sampleNumber() const { return currentStrip_; }
416 
417  inline uint8_t FEDZSChannelUnpacker::adc() const { return data_[currentOffset_ ^ 7]; }
418 
419  inline uint16_t FEDZSChannelUnpacker::adcPreMix() const {
420  return (data_[currentOffset_ ^ 7] + ((data_[(currentOffset_ + 1) ^ 7] & 0x03) << 8));
421  }
422 
423  inline bool FEDZSChannelUnpacker::hasData() const {
425  }
426 
428  if (valuesLeftInCluster_) {
429  currentStrip_++;
432  } else {
434  if (hasData()) {
435  const uint8_t oldStrip = currentStrip_;
437  if (!(currentStrip_ > oldStrip))
439  }
440  }
441  return (*this);
442  }
443 
445  ++(*this);
446  return *this;
447  }
448 
452  }
453 
454 } // namespace sistrip
455 
456 #endif //ndef EventFilter_SiStripRawToDigi_SiStripFEDBuffer_H
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)
#define nullptr
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)
const FEDFEHeader * feHeader() const
virtual bool channelGood(const uint8_t internalFEDannelNum, const bool doAPVeCheck=true) const
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
constexpr int adc(sample_type sample)
get the ADC sample (12 bits)
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:79
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++()
#define constexpr
void print(std::ostream &os) const override
bool feOverflow(const uint8_t internalFEUnitNum) const