Skip to content

Commit 91c0186

Browse files
authored
MCH: digit time from TF start (#5530)
* [MCH] implemented decoding of HeartBeat packets * [MCH] changed definition of digit time * [MCH] implemented sending of full TimeFrames in MCH data reader The TimeFrames are sent for each CRU link separately, so this is not a real replacement of the StfBuilder. An "overlap" option allows to have N HeartBeat frames in common between consecutive TimeFrames. * [MCH] improved help messages * [MCH] simplified digit time computation * [MCH] fixed clang formatting * [MCH] added unit test for time computation functions Also added setter/getter functions for the " saturated" flag * [MCH] fixed clang formatting * [MCH] fixed code formatting
1 parent 2885d22 commit 91c0186

File tree

21 files changed

+867
-110
lines changed

21 files changed

+867
-110
lines changed

Detectors/MUON/MCH/Base/include/MCHBase/Digit.h

Lines changed: 13 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -28,34 +28,22 @@ namespace mch
2828
class Digit
2929
{
3030
public:
31-
struct Time {
32-
union {
33-
// default value
34-
uint64_t time = 0x0000000000000000;
35-
struct { ///
36-
uint32_t sampaTime : 10; /// bit 0 to 9: sampa time
37-
uint32_t bunchCrossing : 20; /// bit 10 to 29: bunch crossing counter
38-
uint32_t reserved : 2; /// bit 30 to 31: reserved
39-
uint32_t orbit; /// bit 32 to 63: orbit
40-
}; ///
41-
};
42-
uint64_t getBXTime()
43-
{
44-
return (bunchCrossing + (sampaTime * 4));
45-
}
46-
};
47-
4831
Digit() = default;
4932

50-
Digit(int detid, int pad, unsigned long adc, Time time, uint16_t nSamples = 1);
33+
Digit(int detid, int pad, unsigned long adc, int32_t time, uint16_t nSamples = 1);
5134
~Digit() = default;
5235

5336
bool operator==(const Digit&) const;
5437

55-
Time getTime() const { return mTime; }
38+
// time in bunch crossing units, relative to the beginning of the TimeFrame
39+
void setTime(int32_t t) { mTFtime = t; }
40+
int32_t getTime() const { return mTFtime; }
41+
42+
void setNofSamples(uint16_t n);
43+
uint16_t nofSamples() const { return (mNofSamples & 0x7FFF); }
5644

57-
uint16_t nofSamples() const { return mNofSamples; }
58-
void setNofSamples(uint16_t n) { mNofSamples = n; }
45+
void setSaturated(bool sat);
46+
bool isSaturated() const { return ((mNofSamples & 0x8000) > 0); }
5947

6048
int getDetID() const { return mDetID; }
6149

@@ -66,11 +54,11 @@ class Digit
6654
void setADC(unsigned long adc) { mADC = adc; }
6755

6856
private:
69-
Time mTime;
57+
int32_t mTFtime; /// time since the beginning of the time frame, in bunch crossing units
7058
uint16_t mNofSamples; /// number of samples in the signal
71-
int mDetID;
72-
int mPadID; /// PadIndex to which the digit corresponds to
73-
unsigned long mADC; /// Amplitude of signal
59+
int mDetID; /// ID of the Detection Element to which the digit corresponds to
60+
int mPadID; /// PadIndex to which the digit corresponds to
61+
unsigned long mADC; /// Amplitude of signal
7462

7563
ClassDefNV(Digit, 2);
7664
}; //class Digit

Detectors/MUON/MCH/Base/src/Digit.cxx

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,17 +19,33 @@ bool closeEnough(double x, double y, double eps = 1E-6)
1919
return std::fabs(x - y) <= eps * std::max(1.0, std::max(std::fabs(x), std::fabs(y)));
2020
}
2121

22-
Digit::Digit(int detid, int pad, unsigned long adc, Time time, uint16_t nSamples)
23-
: mDetID(detid), mPadID(pad), mADC(adc), mTime(time), mNofSamples(nSamples)
22+
Digit::Digit(int detid, int pad, unsigned long adc, int32_t time, uint16_t nSamples)
23+
: mTFtime(time), mNofSamples(nSamples), mDetID(detid), mPadID(pad), mADC(adc)
2424
{
25+
setSaturated(false);
26+
}
27+
28+
void Digit::setNofSamples(uint16_t n)
29+
{
30+
uint16_t sat = mNofSamples & 0x8000;
31+
mNofSamples = (n & 0x7FFF) + sat;
32+
}
33+
34+
void Digit::setSaturated(bool sat)
35+
{
36+
if (sat) {
37+
mNofSamples |= 0x8000;
38+
} else {
39+
mNofSamples &= 0x7FFF;
40+
}
2541
}
2642

2743
bool Digit::operator==(const Digit& other) const
2844
{
2945
return mDetID == other.mDetID &&
3046
mPadID == other.mPadID &&
3147
mADC == other.mADC &&
32-
mTime.time == other.mTime.time &&
48+
mTFtime == other.mTFtime &&
3349
mNofSamples == other.mNofSamples;
3450
}
3551

Detectors/MUON/MCH/Clustering/src/ClusterFinderOriginal.cxx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ void ClusterFinderOriginal::resetPreCluster(gsl::span<const Digit>& digits)
174174
double dx = mSegmentation->padSizeX(padID) / 2.;
175175
double dy = mSegmentation->padSizeY(padID) / 2.;
176176
double charge = static_cast<double>(digit.getADC()) / static_cast<double>(std::numeric_limits<unsigned long>::max()) * 1024;
177-
bool isSaturated = digit.getTime().time > 0;
177+
bool isSaturated = digit.isSaturated();
178178
int plane = mSegmentation->isBendingPad(padID) ? 0 : 1;
179179

180180
if (charge <= 0.) {

Detectors/MUON/MCH/Raw/Decoder/CMakeLists.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,4 +35,10 @@ if(BUILD_TESTING)
3535
LABELS "muon;mch;raw"
3636
PUBLIC_LINK_LIBRARIES O2::MCHRawDecoder Boost::boost)
3737

38+
o2_add_test(digits-time-computation
39+
SOURCES src/testDigitsTimeComputation.cxx
40+
COMPONENT_NAME mchraw
41+
LABELS "muon;mch;raw"
42+
PUBLIC_LINK_LIBRARIES O2::MCHRawDecoder Boost::boost)
43+
3844
endif()

Detectors/MUON/MCH/Raw/Decoder/include/MCHRawDecoder/DataDecoder.h

Lines changed: 63 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
#include <gsl/span>
1919
#include <unordered_set>
20+
#include <unordered_map>
2021

2122
#include "Headers/RDHAny.h"
2223
#include "MCHBase/Digit.h"
@@ -40,17 +41,62 @@ struct OrbitInfoHash {
4041
}
4142
};
4243

44+
void dumpOrbits(const std::unordered_set<OrbitInfo, OrbitInfoHash>& mOrbits);
45+
4346
//_________________________________________________________________
4447
//
4548
// Data decoder
4649
//_________________________________________________________________
4750
class DataDecoder
4851
{
4952
public:
53+
struct SampaInfo {
54+
union {
55+
uint32_t id = 0;
56+
struct {
57+
uint32_t chip : 1;
58+
uint32_t ds : 6;
59+
uint32_t solar : 16;
60+
uint32_t unused : 9;
61+
};
62+
};
63+
64+
union {
65+
// default value
66+
uint64_t time = 0x0000000000000000;
67+
struct { ///
68+
uint32_t sampaTime : 10; /// bit 0 to 9: sampa time
69+
uint32_t bunchCrossing : 20; /// bit 10 to 29: bunch crossing counter
70+
uint32_t reserved : 2; /// bit 30 to 31: reserved
71+
uint32_t orbit; /// bit 32 to 63: orbit
72+
}; ///
73+
};
74+
uint32_t getBXTime()
75+
{
76+
return (bunchCrossing + (sampaTime * 4));
77+
}
78+
};
79+
80+
struct SampaTimeFrameStart {
81+
SampaTimeFrameStart(uint32_t orbit, uint32_t bunchCrossing) : mOrbit(orbit), mBunchCrossing(bunchCrossing) {}
82+
83+
uint32_t mOrbit{0};
84+
int32_t mBunchCrossing{0};
85+
};
86+
87+
using SampaTimeFrameStarts = std::unordered_map<uint32_t, std::optional<SampaTimeFrameStart>>;
88+
5089
DataDecoder(SampaChannelHandler channelHandler, RdhHandler rdhHandler, std::string mapCRUfile, std::string mapFECfile, bool ds2manu, bool verbose);
5190

5291
void reset();
53-
void decodeBuffer(gsl::span<const std::byte> page);
92+
void decodeBuffer(gsl::span<const std::byte> buf);
93+
94+
static int32_t digitsTimeDiff(uint32_t orbit1, uint32_t bc1, uint32_t orbit2, uint32_t bc2);
95+
static void computeDigitsTime_(std::vector<o2::mch::Digit>& digits, std::vector<SampaInfo>& sampaInfo, SampaTimeFrameStarts& sampaTimeFrameStarts, bool debug);
96+
void computeDigitsTime()
97+
{
98+
computeDigitsTime_(mOutputDigits, mSampaInfos, mSampaTimeFrameStarts, mDebug);
99+
}
54100

55101
const std::vector<o2::mch::Digit>& getOutputDigits() const { return mOutputDigits; }
56102
const std::unordered_set<OrbitInfo, OrbitInfoHash>& getOrbits() const { return mOrbits; }
@@ -59,22 +105,28 @@ class DataDecoder
59105
void initElec2DetMapper(std::string filename);
60106
void initFee2SolarMapper(std::string filename);
61107
void init();
108+
void decodePage(gsl::span<const std::byte> page);
109+
void dumpDigits(bool bending);
62110

63-
Elec2DetMapper mElec2Det{nullptr};
64-
FeeLink2SolarMapper mFee2Solar{nullptr};
65-
o2::mch::raw::PageDecoder mDecoder;
66-
size_t mNrdhs{0};
67-
std::vector<o2::mch::Digit> mOutputDigits;
68-
std::unordered_set<OrbitInfo, OrbitInfoHash> mOrbits; ///< list of orbits in the processed buffer
111+
Elec2DetMapper mElec2Det{nullptr}; ///< front-end electronics mapping
112+
FeeLink2SolarMapper mFee2Solar{nullptr}; ///< CRU electronics mapping
113+
std::string mMapFECfile; ///< optional text file with custom front-end electronics mapping
114+
std::string mMapCRUfile; ///< optional text file with custom CRU mapping
69115

70-
SampaChannelHandler mChannelHandler;
71-
std::function<void(o2::header::RDHAny*)> mRdhHandler;
116+
o2::mch::raw::PageDecoder mDecoder; ///< CRU page decoder
117+
118+
std::vector<o2::mch::Digit> mOutputDigits; ///< vector of decoded digits
119+
std::vector<SampaInfo> mSampaInfos; ///< vector of auxiliary SampaInfo objects
120+
121+
std::unordered_set<OrbitInfo, OrbitInfoHash> mOrbits; ///< list of orbits in the processed buffer
122+
SampaTimeFrameStarts mSampaTimeFrameStarts; ///< time stamps of the TimeFrames in the processed buffer
72123

73-
std::string mMapCRUfile;
74-
std::string mMapFECfile;
124+
SampaChannelHandler mChannelHandler; ///< optional user function to be called for each decoded SAMPA hit
125+
std::function<void(o2::header::RDHAny*)> mRdhHandler; ///< optional user function to be called for each RDH
75126

76127
bool mDebug{false};
77128
bool mDs2manu{false};
129+
uint32_t mOrbit{0};
78130
};
79131

80132
} // namespace raw

Detectors/MUON/MCH/Raw/Decoder/include/MCHRawDecoder/DecodedDataHandlers.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,21 @@ using SampaChannelHandler = std::function<void(DsElecId dsId,
2828
uint8_t channel,
2929
SampaCluster)>;
3030

31-
/// A SampaChannSampaHeartBeatHandler is a function that takes a chip index and
31+
/// A SampaHeartBeatHandler is a function that takes a chip index and
3232
/// a bunch crossing counter value found in a HeartBeat packet
33+
using SampaHeartBeatHandler = std::function<void(DsElecId dsId,
34+
uint8_t chip,
35+
uint20_t bunchCrossing)>;
36+
37+
/// A SampaErrorHandler is a function that takes a chip index and
38+
/// a numerical code describing the error encountered during the decoding
3339
using SampaErrorHandler = std::function<void(DsElecId dsId,
3440
int8_t chip,
3541
uint32_t error)>;
3642

3743
struct DecodedDataHandlers {
3844
SampaChannelHandler sampaChannelHandler;
45+
SampaHeartBeatHandler sampaHeartBeatHandler;
3946
SampaErrorHandler sampaErrorHandler;
4047
};
4148

Detectors/MUON/MCH/Raw/Decoder/src/BareElinkDecoder.h

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ class BareElinkDecoder
9797
void oneLess10BitWord();
9898
void process();
9999
void sendCluster();
100+
void sendHBPacket();
100101
void softReset();
101102

102103
template <typename T>
@@ -260,8 +261,12 @@ void BareElinkDecoder<CHARGESUM>::handleHeader()
260261
softReset();
261262
break;
262263
case SampaPacketType::HeartBeat:
263-
fmt::printf("BareElinkDecoder %d: HEARTBEAT found. Should be doing sth about it ?\n", mDsId);
264-
softReset();
264+
if (mSampaHeader.isHeartbeat()) {
265+
sendHBPacket();
266+
changeState(State::LookingForHeader, HEADERSIZE);
267+
} else {
268+
softReset();
269+
}
265270
break;
266271
default:
267272
throw std::logic_error("that should not be possible");
@@ -440,6 +445,15 @@ void BareElinkDecoder<SampleMode>::sendCluster()
440445
mSamples.clear();
441446
}
442447

448+
template <typename CHARGESUM>
449+
void BareElinkDecoder<CHARGESUM>::sendHBPacket()
450+
{
451+
SampaHeartBeatHandler handler = mDecodedDataHandlers.sampaHeartBeatHandler;
452+
if (handler) {
453+
handler(mDsId, mSampaHeader.chipAddress() % 2, mSampaHeader.bunchCrossingCounter());
454+
}
455+
}
456+
443457
template <>
444458
void BareElinkDecoder<ChargeSumMode>::changeToReadingData()
445459
{

0 commit comments

Comments
 (0)