12#ifndef O2_MCH_RAW_BARE_ELINK_DECODER_H
13#define O2_MCH_RAW_BARE_ELINK_DECODER_H
20#include <fmt/format.h>
21#include <fmt/printf.h>
41template <
typename CHARGESUM>
57 void append(
bool bit0,
bool bit1);
77 enum class State :
int {
87 void appendOneBit(
bool bit);
88 void changeState(State newState,
int newCheckpoint);
89 void changeToReadingData();
90 void clear(
int checkpoint);
92 void handlReadClusterSum();
94 void handleReadClusterSum();
95 void handleReadData();
96 void handleReadSample();
97 void handleReadTimestamp();
98 void oneLess10BitWord();
104 template <
typename T>
117 uint64_t mNofBitSeen;
118 uint64_t mNofHeaderSeen;
119 uint64_t mNofHammingErrors;
120 uint64_t mNofHeaderParityErrors;
123 uint64_t mCheckpoint;
124 uint16_t mNof10BitsWordsToRead;
127 uint16_t mNofSamples;
129 std::vector<uint16_t> mSamples;
130 uint32_t mClusterSum;
140template <
typename CHARGESUM>
144 mDecodedDataHandlers{decodedDataHandlers},
151 mNofHeaderParityErrors{},
152 mCheckpoint{(static_cast<uint64_t>(1) <<
HEADERSIZE)},
153 mNof10BitsWordsToRead{},
159 mState{State::LookingForSync},
164template <
typename CHARGESUM>
169 mBitBuffer += bit * mMask;
172 if (mMask == mCheckpoint) {
177template <
typename CHARGESUM>
184template <
typename CHARGESUM>
188 clear(newCheckpoint);
191template <
typename CHARGESUM>
192void BareElinkDecoder<CHARGESUM>::clear(
int checkpoint)
195 mCheckpoint =
static_cast<uint64_t
>(1) << checkpoint;
204template <
typename CHARGESUM>
205void BareElinkDecoder<CHARGESUM>::findSync()
207 assert(mState == State::LookingForSync);
213 changeState(State::LookingForHeader,
HEADERSIZE);
217template <
typename CHARGESUM>
218void BareElinkDecoder<CHARGESUM>::handleHeader()
220 assert(mState == State::LookingForHeader);
222 mSampaHeader.uint64(mBitBuffer);
226 if (mSampaHeader.hasError()) {
230 switch (mSampaHeader.packetType()) {
240 mNof10BitsWordsToRead = mSampaHeader.nof10BitWords();
241 changeState(State::ReadingNofSamples, 10);
248 if (mSampaHeader.isHeartbeat()) {
250 changeState(State::LookingForHeader,
HEADERSIZE);
256 throw std::logic_error(
"that should not be possible");
261template <
typename CHARGESUM>
262void BareElinkDecoder<CHARGESUM>::handleReadClusterSum()
264 mClusterSum = mBitBuffer;
268 if (mNof10BitsWordsToRead) {
269 changeState(State::ReadingNofSamples, 10);
271 changeState(State::LookingForHeader,
HEADERSIZE);
275template <
typename CHARGESUM>
276void BareElinkDecoder<CHARGESUM>::handleReadData()
278 assert(mState == State::ReadingTimestamp || mState == State::ReadingSample);
279 if (mState == State::ReadingTimestamp) {
280 mTimestamp = mBitBuffer;
283 changeToReadingData();
286template <
typename CHARGESUM>
287void BareElinkDecoder<CHARGESUM>::handleReadSample()
289 mSamples.push_back(mBitBuffer);
290 if (mNofSamples > 0) {
295 changeToReadingData();
298 if (mNof10BitsWordsToRead) {
299 changeState(State::ReadingNofSamples, 10);
301 changeState(State::LookingForHeader,
HEADERSIZE);
306template <
typename CHARGESUM>
307void BareElinkDecoder<CHARGESUM>::handleReadTimestamp()
309 assert(mState == State::ReadingNofSamples);
311 mNofSamples = mBitBuffer;
312 mClusterSize = mNofSamples;
313 changeState(State::ReadingTimestamp, 10);
316template <
typename CHARGESUM>
319 return static_cast<int>(std::floor(log2(1.0 * mMask)) + 1);
322template <
typename CHARGESUM>
326 case State::LookingForSync:
327 return "LookingForSync";
329 case State::LookingForHeader:
330 return "LookingForHeader";
332 case State::ReadingNofSamples:
333 return "ReadingNofSamples";
335 case State::ReadingTimestamp:
336 return "ReadingTimestamp";
338 case State::ReadingSample:
339 return "ReadingSample";
341 case State::ReadingClusterSum:
342 return "ReadingClusterSum";
347template <
typename CHARGESUM>
348void BareElinkDecoder<CHARGESUM>::oneLess10BitWord()
350 if (mNof10BitsWordsToRead > 0) {
351 --mNof10BitsWordsToRead;
356template <
typename CHARGESUM>
357void BareElinkDecoder<CHARGESUM>::process()
360 case State::LookingForSync:
363 case State::LookingForHeader:
366 case State::ReadingNofSamples:
367 handleReadTimestamp();
369 case State::ReadingTimestamp:
372 case State::ReadingSample:
375 case State::ReadingClusterSum:
376 handleReadClusterSum();
381template <
typename CHARGESUM>
382void BareElinkDecoder<CHARGESUM>::softReset()
387template <
typename CHARGESUM>
391 mState = State::LookingForSync;
394template <
typename CHARGESUM>
397 os << fmt::format(
"ID{:2d} cruId {:2d} sync {:6d} cp 0x{:6x} mask 0x{:6x} state {:17s} len {:6d} nseen {:6d} errH {:6} errP {:6} head {:6d} n10w {:6d} nsamples {:6d} mode {} bbuf {:s}",
398 e.mLinkId, e.mCruId, e.mNofSync, e.mCheckpoint, e.mMask,
400 e.
len(), e.mNofBitSeen,
403 e.mNofHeaderParityErrors,
404 e.mNof10BitsWordsToRead,
406 (e.mClusterSumMode ?
"CLUSUM" :
"SAMPLE"),
411template <
typename CHARGESUM>
412void BareElinkDecoder<CHARGESUM>::sendHBPacket()
416 handler(mDsId, mSampaHeader.chipAddress() % 2, mSampaHeader.bunchCrossingCounter());
Main element of the MCH Bare Raw Data Format decoder.
BareElinkDecoder(DsElecId dsId, DecodedDataHandlers decodedDataHandlers)
int len() const
Current number of bits we're holding.
void append(bool bit0, bool bit1)
Append two bits (from the same dual sampa, one per sampa) to the Elink.
friend std::ostream & operator<<(std::ostream &os, const o2::mch::raw::BareElinkDecoder< T > &e)
GLuint const GLchar * name
constexpr uint64_t sampaSyncWord
@ DataTriggerTooEarlyNumWords
@ DataTruncatedTriggerTooEarly
std::string bitBufferString(const std::bitset< 50 > &bs, int imax)
std::function< void(DsElecId dsId, uint8_t chip, uint20_t bunchCrossing)> SampaHeartBeatHandler
std::ostream & operator<<(std::ostream &stream, o2::InteractionRecord const &ir)