Skip to content

Commit bf10504

Browse files
committed
Changed the decoding and encoding of CMVs, removed grouping per side
1 parent 4471254 commit bf10504

File tree

3 files changed

+24
-50
lines changed

3 files changed

+24
-50
lines changed

DataFormats/Detectors/TPC/include/DataFormatsTPC/CMV.h

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,21 +15,21 @@
1515

1616
/// The data is sent by the CRU as 256+16 bit words. The CMV data layout is as follows:
1717
/// - 256-bit Header: [version:8][packetID:8][errorCode:8][magicWord:8][heartbeatOrbit:32][heartbeatBC:16][padding:176]
18-
/// - 16-bit CMV value: [CMV:16]
18+
/// - 16-bit CMV value: [sign:1][I8F7:15] where bit 15 is the sign (1=positive, 0=negative) and the lower 15 bits are a fixed point I8F7 value (8 integer bits, 7 fractional bits)
19+
/// Float conversion: sign ? (value & 0x7FFF) / 128.0 : -(value & 0x7FFF) / 128.0
1920

2021
#ifndef ALICEO2_DATAFORMATSTPC_CMV_H
2122
#define ALICEO2_DATAFORMATSTPC_CMV_H
2223

2324
#include <cstdint>
25+
#include <cmath>
2426

2527
namespace o2::tpc::cmv
2628
{
2729

2830
static constexpr uint32_t NTimeBinsPerPacket = 3564; ///< number of time bins (covering 8 heartbeats)
2931
static constexpr uint32_t NPacketsPerTFPerCRU = 4; ///< 4 packets per timeframe
3032
static constexpr uint32_t NTimeBinsPerTF = NTimeBinsPerPacket * NPacketsPerTFPerCRU; ///< maximum number of timebins per timeframe (14256)
31-
static constexpr uint32_t SignificantBits = 2; ///< number of bits used for floating point precision
32-
static constexpr float FloatConversion = 1.f / float(1 << SignificantBits); ///< conversion factor from integer representation to float
3333

3434
/// Header definition of the CMVs
3535
struct Header {
@@ -83,18 +83,25 @@ struct Header {
8383

8484
/// CMV single data container
8585
struct Data {
86-
uint16_t CMV{0}; ///< 16bit ADC value
86+
uint16_t CMV{0}; ///< 16-bit signed fixed point value: bit 15 = sign (1=positive, 0=negative), bits 14-0 = I8F7 magnitude
8787

88-
// Raw integer accessors
89-
uint16_t getCMV() const { return CMV; }
90-
void setCMV(uint16_t value) { CMV = value; }
88+
uint16_t getCMV() const { return CMV; } ///< raw 16-bit integer representation
89+
void setCMV(uint16_t value) { CMV = value; } ///< set raw 16-bit integer representation
9190

92-
// Float helpers using SignificantBits for fixed-point conversion
93-
float getCMVFloat() const { return static_cast<float>(CMV) * FloatConversion; }
91+
// Decode to float: sign-magnitude with 7 fractional bits, range ±255.992
92+
float getCMVFloat() const
93+
{
94+
const bool positive = (CMV >> 15) & 1; // bit 15: sign (1=positive, 0=negative)
95+
const float magnitude = (CMV & 0x7FFF) / 128.f; // lower 15 bits, shift right by 7 (divide by 2^7)
96+
return positive ? magnitude : -magnitude;
97+
}
98+
99+
// Encode from float: clamps magnitude to 15 bits, range ±255.992
94100
void setCMVFloat(float value)
95101
{
96-
// round to nearest representable fixed-point value
97-
setCMV(uint32_t((value + 0.5f * FloatConversion) / FloatConversion));
102+
const bool positive = (value >= 0.f);
103+
const uint16_t magnitude = static_cast<uint16_t>(std::abs(value) * 128.f + 0.5f) & 0x7FFF;
104+
CMV = (positive ? 0x8000 : 0x0000) | magnitude;
98105
}
99106
};
100107

@@ -110,7 +117,7 @@ struct Container {
110117
const Data* getData() const { return data; }
111118
Data* getData() { return data; }
112119

113-
// Per-time-bin CMV accessors
120+
// Per timebin CMV accessors
114121
uint16_t getCMV(uint32_t timeBin) const { return data[timeBin].getCMV(); }
115122
void setCMV(uint32_t timeBin, uint16_t value) { data[timeBin].setCMV(value); }
116123

Detectors/TPC/workflow/include/TPCWorkflow/TPCDistributeCMVSpec.h

Lines changed: 2 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525
#include "Headers/DataHeader.h"
2626
#include "Framework/ConfigParamRegistry.h"
2727
#include "TPCWorkflow/TPCFLPCMVSpec.h"
28-
#include "TPCBase/CRU.h"
2928
#include "MemoryResources/MemoryResources.h"
3029
#include "TPCWorkflow/ProcessingHelpers.h"
3130
#include "DetectorsBase/GRPGeomHelper.h"
@@ -38,27 +37,6 @@ using namespace o2::tpc;
3837
namespace o2::tpc
3938
{
4039

41-
inline std::vector<Side> getCMVSides(const std::vector<uint32_t>& crus)
42-
{
43-
bool hasA = false, hasC = false;
44-
for (const auto cru : crus) {
45-
const Side side = CRU(cru).side();
46-
if (side == Side::A) {
47-
hasA = true;
48-
} else {
49-
hasC = true;
50-
}
51-
}
52-
std::vector<Side> sides;
53-
if (hasA) {
54-
sides.emplace_back(Side::A);
55-
}
56-
if (hasC) {
57-
sides.emplace_back(Side::C);
58-
}
59-
return sides;
60-
}
61-
6240
class TPCDistributeCMVSpec : public o2::framework::Task
6341
{
6442
public:
@@ -84,11 +62,7 @@ class TPCDistributeCMVSpec : public o2::framework::Task
8462
}
8563
}
8664

87-
const auto sides = getCMVSides(mCRUs);
88-
for (auto side : sides) {
89-
const std::string name = (side == Side::A) ? "cmvsgroupa" : "cmvsgroupc";
90-
mFilter.emplace_back(InputSpec{name.data(), ConcreteDataTypeMatcher{o2::header::gDataOriginTPC, TPCFLPCMVDevice::getDataDescriptionCMVGroup(side)}, Lifetime::Sporadic});
91-
}
65+
mFilter.emplace_back(InputSpec{"cmvsgroup", ConcreteDataTypeMatcher{gDataOriginTPC, TPCFLPCMVDevice::getDataDescriptionCMVGroup()}, Lifetime::Sporadic});
9266
};
9367

9468
void init(o2::framework::InitContext& ic) final
@@ -364,11 +338,7 @@ class TPCDistributeCMVSpec : public o2::framework::Task
364338
DataProcessorSpec getTPCDistributeCMVSpec(const int ilane, const std::vector<uint32_t>& crus, const unsigned int timeframes, const unsigned int outlanes, const int firstTF, const bool sendPrecisetimeStamp = false, const int nTFsBuffer = 1)
365339
{
366340
std::vector<InputSpec> inputSpecs;
367-
const auto sides = getCMVSides(crus);
368-
for (auto side : sides) {
369-
const std::string name = (side == Side::A) ? "cmvsgroupa" : "cmvsgroupc";
370-
inputSpecs.emplace_back(InputSpec{name.data(), ConcreteDataTypeMatcher{gDataOriginTPC, TPCFLPCMVDevice::getDataDescriptionCMVGroup(side)}, Lifetime::Sporadic});
371-
}
341+
inputSpecs.emplace_back(InputSpec{"cmvsgroup", ConcreteDataTypeMatcher{gDataOriginTPC, TPCFLPCMVDevice::getDataDescriptionCMVGroup()}, Lifetime::Sporadic});
372342

373343
std::vector<OutputSpec> outputSpecs;
374344
outputSpecs.reserve(outlanes);

Detectors/TPC/workflow/include/TPCWorkflow/TPCFLPCMVSpec.h

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -90,9 +90,7 @@ class TPCFLPCMVDevice : public o2::framework::Task
9090
ec.services().get<ControlService>().readyToQuit(QuitRequest::Me);
9191
}
9292

93-
static constexpr header::DataDescription getDataDescriptionCMVGroup(const Side side) { return (side == Side::A) ? getDataDescriptionCMVGroupA() : getDataDescriptionCMVGroupC(); }
94-
static constexpr header::DataDescription getDataDescriptionCMVGroupA() { return header::DataDescription{"CMVGROUPA"}; }
95-
static constexpr header::DataDescription getDataDescriptionCMVGroupC() { return header::DataDescription{"CMVGROUPC"}; }
93+
static constexpr header::DataDescription getDataDescriptionCMVGroup() { return header::DataDescription{"CMVGROUP"}; }
9694

9795
private:
9896
const int mLane{}; ///< lane number of processor
@@ -106,7 +104,7 @@ class TPCFLPCMVDevice : public o2::framework::Task
106104
void sendOutput(DataAllocator& output, const uint32_t cru)
107105
{
108106
const header::DataHeader::SubSpecificationType subSpec{cru << 7};
109-
output.adoptContainer(Output{gDataOriginTPC, getDataDescriptionCMVGroup(CRU(cru).side()), subSpec}, std::move(mCMVs[cru]));
107+
output.adoptContainer(Output{gDataOriginTPC, getDataDescriptionCMVGroup(), subSpec}, std::move(mCMVs[cru]));
110108
}
111109
};
112110

@@ -120,8 +118,7 @@ DataProcessorSpec getTPCFLPCMVSpec(const int ilane, const std::vector<uint32_t>&
120118
for (const auto& cru : crus) {
121119
const header::DataHeader::SubSpecificationType subSpec{cru << 7};
122120
inputSpecs.emplace_back(InputSpec{"cmvs", gDataOriginTPC, "CMVVECTOR", subSpec, Lifetime::Timeframe});
123-
const Side side = CRU(cru).side();
124-
outputSpecs.emplace_back(ConcreteDataMatcher{gDataOriginTPC, TPCFLPCMVDevice::getDataDescriptionCMVGroup(side), subSpec}, Lifetime::Sporadic);
121+
outputSpecs.emplace_back(ConcreteDataMatcher{gDataOriginTPC, TPCFLPCMVDevice::getDataDescriptionCMVGroup(), subSpec}, Lifetime::Sporadic);
125122
}
126123

127124
const auto id = fmt::format("tpc-flp-cmv-{:02}", ilane);

0 commit comments

Comments
 (0)