Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,8 @@ constexpr int TRACKLETENDMARKER = 0x10001000; // marker for the end of tracklets
constexpr int DIGITENDMARKER = 0x0; // marker for the end of digits in raw data, 2 of these
constexpr int MAXDATAPERLINK32 = 13824; // max number of 32 bit words per link ((21x12+2+4)*64) 64 mcm, 21 channels, 10 words per channel 2 header words(DigitMCMHeader DigitMCMADCmask) 4 words for tracklets.
constexpr int MAXDATAPERLINK256 = 1728; // max number of linkwords per cru link. (256bit words)

constexpr int MAXEVENTCOUNTERSEPERATION = 200; // how far appart can subsequent mcmheader event counters be before we flag for concern, used as a sanity check in rawreader.
constexpr int MAXMCMCOUNT = 69120; // at most mcm count maxchamber x nrobc1 nmcmrob
} //namespace constants
} // namespace trd
} // namespace o2
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,11 @@ struct HelperMethods {
static int getStack(int det)
{
return det % (constants::NSTACK * constants::NLAYER) / constants::NLAYER;
};
}
static int getLayer(int det)
{
return det % constants::NLAYER;
};
}

static int getORIinSuperModule(int detector, int readoutboard)
{
Expand Down Expand Up @@ -112,7 +112,7 @@ struct HelperMethods {
}
//see TDP for explanation of mapping TODO should probably come from CCDB
return ori;
};
}

static int getLinkIDfromHCID(int hcid)
{
Expand All @@ -125,7 +125,23 @@ struct HelperMethods {
int ori = -1;
// now offset for supermodule (+60*supermodule);
return HelperMethods::getORIinSuperModule(detector, chamberside) + 60 * supermodule; // it takes readoutboard but only cares if its odd or even hence side here.
};
}

inline static void swapByteOrder(unsigned int& word)
{
word = (word >> 24) |
((word << 8) & 0x00FF0000) |
((word >> 8) & 0x0000FF00) |
(word << 24);
}
inline static unsigned int swapByteOrderreturn(unsigned int word)
{
// word = (word >> 24) |
// ((word << 8) & 0x00FF0000) |
// ((word >> 8) & 0x0000FF00) |
// (word << 24);
return word;
}
};

} // namespace trd
Expand Down
8 changes: 5 additions & 3 deletions DataFormats/Detectors/TRD/include/DataFormatsTRD/RawData.h
Original file line number Diff line number Diff line change
Expand Up @@ -307,10 +307,10 @@ struct DigitMCMADCMask {
union {
uint32_t word; //MCM ADC MASK header
struct {
uint32_t n : 2; // unused always 0x3
uint32_t c : 5; // unused always 0x1f
uint32_t j : 4; // 0xc
uint32_t adcmask : 21;
uint32_t j : 4; // unused always 0xc
uint32_t c : 5; // ~(number of bits set in adcmask)
uint32_t n : 2; // 0b01
} __attribute__((__packed__));
};
};
Expand Down Expand Up @@ -440,6 +440,8 @@ std::ostream& operator<<(std::ostream& stream, const HalfCRUHeader& halfcru);
bool trackletMCMHeaderSanityCheck(o2::trd::TrackletMCMHeader& header);
bool trackletHCHeaderSanityCheck(o2::trd::TrackletHCHeader& header);
bool digitMCMHeaderSanityCheck(o2::trd::DigitMCMHeader* header);
bool digitMCMADCMaskSanityCheck(o2::trd::DigitMCMADCMask& mask, int numberofbitsset);
bool digitMCMWordSanityCheck(o2::trd::DigitMCMData* word, int adcchannel);
void printDigitMCMHeader(o2::trd::DigitMCMHeader& header);
void printDigitHCHeader(o2::trd::DigitHCHeader& header);
DigitMCMADCMask buildBlankADCMask();
Expand Down
72 changes: 66 additions & 6 deletions DataFormats/Detectors/TRD/src/RawData.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ uint32_t getQFromRaw(const o2::trd::TrackletMCMHeader* header, const o2::trd::Tr
qa = header->pid2;
break;
default:
LOG(warn) << " unknown trackletindex to getQFromRaw : " << pidindex;
LOG(warn) << " unknown trackletindex of " << trackletindex << " to getQFromRaw : " << pidindex;
break;
}
//qa is 6bits of Q2 and 2 bits of Q1
Expand Down Expand Up @@ -253,6 +253,10 @@ void printHalfCRUHeader(o2::trd::HalfCRUHeader& halfcru)
for (int i = 0; i < 15; i++) {
LOGF(INFO, "Link %d size: %ul eflag: 0x%02x", i, sizes[i], errorflags[i]);
}
LOG(INFO) << "Raw: " << std::hex << halfcru.word0 << " " << halfcru.word12[0] << " " << halfcru.word12[1] << " " << halfcru.word3 << " " << halfcru.word47[0] << " " << halfcru.word47[1] << " " << halfcru.word47[2] << " " << halfcru.word47[3];
for (int i = 0; i < 15; i++) {
LOGF(INFO, "Raw: %d word: %ul x", i, sizes[i], errorflags[i]);
}
}

void dumpHalfCRUHeader(o2::trd::HalfCRUHeader& halfcru)
Expand Down Expand Up @@ -357,6 +361,56 @@ bool digitMCMHeaderSanityCheck(o2::trd::DigitMCMHeader* header)
return goodheader;
}

bool digitMCMADCMaskSanityCheck(o2::trd::DigitMCMADCMask& mask, int numberofbitsset)
{
bool goodadcmask = true;
uint32_t count = (unsigned int)mask.c;
count = ~count;
/* if(count != numberofbitsset){
goodadcmask=false;
LOG(warn) << "***DigitMCMADCMask bad bit count maskcount:" << ~mask.c << " bitscounting:" << numberofbitsset;
}*/
if (mask.n != 0x1) {
goodadcmask = false;
LOG(warn) << "***DigitMCMADCMask bad n value should be 0x01 but:0x" << std::hex << mask.n;
}
if (mask.j != 0xc) {
goodadcmask = false;
LOG(warn) << "***DigitMCMADCMask bad j value should be 0xc but:0x" << std::hex << mask.c;
}
return goodadcmask;
}

bool digitMCMWordSanityCheck(o2::trd::DigitMCMData* word, int adcchannel)
{
bool gooddata = true;
// DigitMCMWord0x3 is odd 10 for odd adc channels and 11 for even, counted as the first of the 3.
switch (word->c) {
case 3: // even adc channnel
if (adcchannel % 2 == 0) {
gooddata = true;
} else {
gooddata = false;
}
break;
case 2: // odd adc channel
if (adcchannel % 2 == 1) {
gooddata = true;
} else {
gooddata = false;
}
break;
case 1: // error
gooddata = false;
break;
case 0: // error
gooddata = false;
break;
// no default all cases taken care of
}
return gooddata;
}

void printDigitHCHeader(o2::trd::DigitHCHeader& header)
{
LOGF(INFO, "Digit HalfChamber Header\n Raw:0x%08x 0x%08x reserve:%01x side:%01x stack:0x%02x layer:0x%02x supermod:0x%02x numberHCW:0x%02x minor:0x%03x major:0x%03x version:0x%01x reserve:0x%02x pretriggercount=0x%02x pretriggerphase=0x%02x bunchxing:0x%05x number of timebins : 0x%03x\n",
Expand Down Expand Up @@ -440,14 +494,20 @@ void setNumberOfTrackletsInHeader(o2::trd::TrackletMCMHeader& header, int number
int nextmcmadc(unsigned int& bp, int channel)
{
//given a bitpattern (adcmask) find next channel with in the mask starting from the current channel;
while ((bp & (1 << channel)) == 0) {
channel++;
if (channel == 21) {
if (bp == 0) {
return 22;
}
int position = channel;
int m = 1 << channel;
while (!(bp & m)) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this code do the same as:

Suggested change
while (!(bp & m)) {
for (int pos=channel+1; pos<22; pos++) {
if ( bp & (1<<pos) ) {
return pos;
}
}
return 22;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure what your code does once it's at (or rather beyond) the last bit.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the newer one works properly, verified. unit tests to come.
the bit is fliped so that each time is simply looks for the next right most bit with a 1 in it, so at the end one has no bits and has a condition for finishing.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be clearer line 447,448 handles the case of no bits valid, it is possible to start on the left of the left most bit.
adding a termination at position 32;

m = m << 1;
position++;
if (position > 31) {
break;
}
}
bp &= ~(1UL << (channel));
return channel; // zero based
bp &= ~(1UL << (position));
Comment thread
tdietel marked this conversation as resolved.
return position;
}

} // namespace trd
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@ class CruRawReader
int getTrackletsFound() { return mTotalTrackletsFound; }
int sumTrackletsFound() { return mEventRecords.sumTracklets(); }
int sumDigitsFound() { return mEventRecords.sumDigits(); }
int getWordsRead() { return mTotalDigitWordsRead; }
int getWordsRejected() { return mTotalDigitWordsRejected; }
void clearall()
{
mEventRecords.clear();
Expand All @@ -108,6 +110,7 @@ class CruRawReader
mTrackletsParser.clear();
mDigitsParser.clear();
}
void OutputHalfCruRawData();

protected:
bool processHBFs(int datasizealreadyread = 0, bool verbose = false);
Expand Down Expand Up @@ -138,6 +141,8 @@ class CruRawReader
std::array<uint32_t, o2::trd::constants::HBFBUFFERMAX> mHBFPayload; //this holds the O2 payload held with in the HBFs to pass to parsing.
uint32_t mHalfCRUPayLoadRead{0}; // the words current read in for the currnt cru payload.
uint32_t mO2PayLoadRead{0}; // the words current read in for the currnt cru payload.
std::array<uint32_t, o2::trd::constants::HBFBUFFERMAX>::iterator mStartParse, mEndParse; // limits of parsing, start and end points for parsing.
std::array<uint16_t, constants::TIMEBINS> mADCValues{};
int mCurrentHalfCRULinkHeaderPoisition = 0;
// no need to waste time doing the copy std::array<uint32_t,8> mCurrentCRUWord; // data for a cru comes in words of 256 bits.
uint32_t mCurrentLinkDataPosition256; // count of data read for current link in units of 256 bits
Expand All @@ -164,7 +169,7 @@ class CruRawReader
uint16_t mCRUEndpoint; // the upper or lower half of the currently parsed cru 0-14 or 15-29
uint16_t mCRUID;
uint16_t mHCID;
uint16_t mFEEID; // current Fee ID working on
TRDFeeID mFEEID; // current Fee ID working on
std::array<uint32_t, 15> mCurrentHalfCRULinkLengths;
std::array<uint32_t, 15> mCurrentHalfCRULinkErrorFlags;
uint32_t mCRUState; // the state of what we are expecting to read currently from the data stream, *not* what we have just read.
Expand All @@ -176,6 +181,10 @@ class CruRawReader
uint32_t mDatareadfromhbf;
uint32_t mTotalHBFPayLoad = 0; // total data payload of the heart beat frame in question.
uint32_t mHBFoffset32 = 0; // total data payload of the heart beat frame in question.
uint64_t mDigitWordsRead = 0;
uint64_t mDigitWordsRejected = 0;
uint64_t mTotalDigitWordsRead = 0;
uint64_t mTotalDigitWordsRejected = 0;
//pointers to the data as we read them in, again no point in copying.
HalfCRUHeader* mhalfcruheader;
o2::InteractionRecord mIR;
Expand All @@ -198,20 +207,27 @@ class CruRawReader

EventStorage mEventRecords; // store data range indexes into the above vectors.
bool mReturnBlob{0}; // whether to return blobs or vectors;
struct TRDDataCounters_t { //thisis on a per event basis
struct TRDDataCountersPerEvent_t { //thisis on a per event basis
//TODO this should go into a dpl message for catching by qc ?? I think.
std::array<uint32_t, 1080> LinkWordCounts; //units of 256bits "cru word"
std::array<uint32_t, 1080> LinkPadWordCounts; // units of 32 bits the data pad word size.
std::array<uint32_t, 1080> LinkFreq; //units of 256bits "cru word"
std::array<uint32_t, 1080> mLinkWordCounts; //units of 256bits "cru word"
std::array<uint32_t, 1080> mLinkPadWordCounts; // units of 32 bits the data pad word size.
std::array<uint32_t, 1080> mLinkFreq; //units of 256bits "cru word"
std::array<uint8_t, 1080> mLinkErrorFlag; //units of 256bits "cru word"
//from the above you can get the stats for supermodule and detector.
std::array<bool, 1080> LinkEmpty; // Link only has padding words, probably not serious in pp.
uint32_t EmptyLinks;
std::array<bool, 1080> LinkEmpty; // Link only has padding words only, probably not serious.
//maybe change this to actual traps ?? but it will get large.
std::array<uint32_t, 1080> LinkTrackletPerTrap1; // incremented if a trap on this link has 1 tracklet
std::array<uint32_t, 1080> LinkTrackletPerTrap2; // incremented if a trap on this link has 2 tracklet
std::array<uint32_t, 1080> LinkTrackletPerTrap3; // incremented if a trap on this link has 3 tracklet
std::vector<uint32_t> EmptyTraps; // MCM indexes of traps that are empty ?? list might better
} TRDStatCounters;
std::array<uint32_t, 1080> mLinkTrackletPerTrap1; // incremented if a trap on this link has 1 tracklet
std::array<uint32_t, 1080> mLinkTrackletPerTrap2; // incremented if a trap on this link has 2 tracklet
std::array<uint32_t, 1080> mLinkTrackletPerTrap3; // incremented if a trap on this link has 3 tracklet
std::array<uint32_t, 1080> mLinkMCMsWithData;
std::array<uint16_t, 1080> MCMStatus;
std::array<uint16_t, constants::MAXMCMCOUNT> mMCMstats; // bit pattern for errors current event for a given mcm;
std::vector<uint32_t> mEmptyTraps; // MCM indexes of traps that are empty ?? list might better
} TRDStatCountersPerEvent;

struct TRDDataCountersRunning_t { //those counters that keep counting
//??
} TRDStatCountersRunning;

/** summary data **/
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ class DataReaderTask : public Task
bool mCompressedData{false}; // are we dealing with the compressed data from the flp (send via option)
bool mByteSwap{true}; // whether we are to byteswap the incoming data, mc is not byteswapped, raw data is (too be changed in cru at some point)
// o2::header::DataDescription mDataDesc; // Data description of the incoming data
uint64_t mWordsRead = 0;
uint64_t mWordsRejected = 0;
int mTrackletHCHeaderState{0}; // what to do about tracklethcheader, 0 never there, 2 always there, 1 there iff tracklet data, i.e. only there if next word is *not* endmarker 10001000.

std::string mDataDesc;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,24 +39,11 @@ class DigitsParser
DigitsParser() = default;
~DigitsParser() = default;
void setData(std::array<uint32_t, o2::trd::constants::HBFBUFFERMAX>* data) { mData = data; }
// void setLinkLengths(std::array<uint32_t, 15>& lengths) { mCurrentHalfCRULinkLengths = lengths; };
int Parse(bool verbose = false); // presupposes you have set everything up already.
int Parse(std::array<uint32_t, o2::trd::constants::HBFBUFFERMAX>* data, std::array<uint32_t, o2::trd::constants::HBFBUFFERMAX>::iterator start,
std::array<uint32_t, o2::trd::constants::HBFBUFFERMAX>::iterator end, int detector, bool cleardigits = false, bool disablebyteswap = false, bool verbose = false, bool headerverbose = false, bool dataverbose = false)
{
setData(data);
// setLinkLengths(lengths);
mStartParse = start;
mEndParse = end;
mDetector = detector;
setVerbose(verbose, headerverbose, dataverbose);
if (cleardigits) {
clearDigits();
}
setByteSwap(disablebyteswap);
mReturnVectorPos = 0;
return Parse();
};
std::array<uint32_t, o2::trd::constants::HBFBUFFERMAX>::iterator end, int detector, int stack, int layer, DigitHCHeader& hcheader,
TRDFeeID& feeid, unsigned int linkindex, bool cleardigits = false, bool disablebyteswap = false, bool verbose = false,
bool headerverbose = false, bool dataverbose = false);
enum DigitParserState { StateDigitHCHeader, // always the start of a half chamber.
StateDigitMCMHeader,
StateDigitMCMData,
Expand All @@ -77,6 +64,10 @@ class DigitsParser
std::vector<Digit>& getDigits() { return mDigits; }
void clearDigits() { mDigits.clear(); }
void clear() { mDigits.clear(); }
uint64_t getDumpedDataCount() { return mWordsDumped; }
uint64_t getDataWordsParsed() { return mDataWordsParsed; }
void tryFindMCMHeaderAndDisplay(std::array<uint32_t, o2::trd::constants::HBFBUFFERMAX>::iterator mStartParse);
void OutputIncomingData();

private:
int mState;
Expand All @@ -85,6 +76,7 @@ class DigitsParser
int mBufferLocation;
int mPaddingWordsCounter;
bool mSanityCheck{true};
bool mDumpUnknownData{false}; // if the various sanity checks fail, bail out and dump the rest of the data, keeps stats.
bool mByteOrderFix{false}; // simulated data is not byteswapped, real is, so deal with it accodringly.
bool mReturnVector{true}; // whether we are returing a vector or the raw data buffer.
// yes this is terrible design but it works,
Expand All @@ -96,8 +88,9 @@ class DigitsParser
// this means that successive calls to Parse simply appends the new digits onto the vector.
// at the end of the event the calling object must pull/copy the vector and clear or clear on next parse.
//
int mParsedWords{0}; // words parsed in data vector, last complete bit is not parsed, and left for another round of data update.
DigitHCHeader* mDigitHCHeader;
// int mParsedWords{0}; // words parsed in data vector, last complete bit is not parsed, and left for another round of data update.
uint64_t mWordsDumped{0}; // words rejected for various reasons.
DigitHCHeader mDigitHCHeader;
DigitMCMHeader* mDigitMCMHeader;
DigitMCMADCMask* mDigitMCMADCMask;
uint32_t mADCMask;
Expand All @@ -109,10 +102,15 @@ class DigitsParser
uint16_t mDetector;
uint16_t mMCM;
uint16_t mROB;
uint16_t mChannel;
uint16_t mCurrentADCChannel;
uint16_t mDigitWordCount;
uint16_t mStack;
uint16_t mLayer;
uint16_t mEventCounter;
TRDFeeID mFEEID;
std::array<uint32_t, o2::trd::constants::HBFBUFFERMAX>::iterator mStartParse, mEndParse; // limits of parsing, effectively the link limits to parse on.
// std::array<uint16_t, 60>/*constants::TIMEBINS>*/ mADCValues;
std::array<uint16_t, constants::TIMEBINS> mADCValues{};
std::array<uint16_t, constants::MAXMCMCOUNT> mMCMstats; // bit pattern for errors current event for a given mcm;
//uint32_t mCurrentLinkDataPosition256; // count of data read for current link in units of 256 bits
//uint32_t mCurrentLinkDataPosition; // count of data read for current link in units of 256 bits
//uhint32_t mCurrentHalfCRUDataPosition256; //count of data read for this half cru.
Expand Down
Loading