12#ifndef O2_MCH_RAW_PAYLOAD_ENCODER_IMPL_H
13#define O2_MCH_RAW_PAYLOAD_ENCODER_IMPL_H
25#include <fmt/format.h>
46template <
typename FORMAT,
typename CHARGESUM,
int VERSION>
53 const std::vector<SampaCluster>&
data)
override;
64 void closeHeartbeatFrame(uint32_t
orbit, uint16_t bunchCrossing);
65 void gbts2buffer(uint32_t
orbit, uint16_t bunchCrossing);
66 std::unique_ptr<ElementaryEncoder>& assertGBT(uint16_t solarId);
70 uint16_t mBunchCrossing;
71 std::vector<std::byte> mBuffer;
72 std::map<uint16_t, std::unique_ptr<ElementaryEncoder>> mGBTs;
77template <
typename FORMAT,
typename CHARGESUM,
int VERSION>
84 mSolar2FeeLink{solar2feelink}
88template <
typename FORMAT,
typename CHARGESUM,
int VERSION>
89std::unique_ptr<typename PayloadEncoderImpl<FORMAT, CHARGESUM, VERSION>::ElementaryEncoder>&
92 auto gbt = mGBTs.find(solarId);
93 if (gbt == mGBTs.end()) {
94 auto f = mSolar2FeeLink(solarId);
96 throw std::invalid_argument(fmt::format(
"Could not get fee,link for solarId={}\n", solarId));
98 mGBTs.emplace(solarId, std::make_unique<ElementaryEncoder>(
f->linkId()));
99 gbt = mGBTs.find(solarId);
104template <
typename FORMAT,
typename CHARGESUM,
int VERSION>
108 auto& gbt = assertGBT(solarId);
113template <
typename FORMAT,
typename CHARGESUM,
int VERSION>
119 for (
auto& p : mGBTs) {
120 auto& gbt = p.second;
121 std::vector<std::byte> gbtBuffer;
123 if (gbtBuffer.empty()) {
126 assert(gbtBuffer.size() % 4 == 0);
127 DataBlockHeader header{
orbit, bunchCrossing, p.first, gbtBuffer.size()};
129 mBuffer.insert(mBuffer.end(), gbtBuffer.begin(), gbtBuffer.end());
133template <
typename FORMAT,
typename CHARGESUM,
int VERSION>
136 closeHeartbeatFrame(mOrbit, mBunchCrossing);
137 buffer.insert(
buffer.end(), mBuffer.begin(), mBuffer.end());
138 auto s = mBuffer.size();
143template <
typename FORMAT,
typename CHARGESUM,
int VERSION>
146 gbts2buffer(
orbit, bunchCrossing);
149template <
typename FORMAT,
typename CHARGESUM,
int VERSION>
154 if (!mFirstHBFrame) {
155 closeHeartbeatFrame(mOrbit, mBunchCrossing);
157 mFirstHBFrame =
false;
160 mBunchCrossing = bunchCrossing;
167template <
typename FORMAT,
typename CHARGESUM,
int VERSION>
176 for (
auto dsElecId : dsids) {
177 auto solarId = dsElecId.solarId();
178 auto& gbt = assertGBT(solarId);
179 gbt->addHeartbeat(dsElecId.elinkGroupId(), dsElecId.elinkIndexInGroup(), sampaBXCount);
static const HBFUtils & Instance()
constexpr uint16_t solarId() const
solarId is an identifier that uniquely identify a solar board
constexpr uint8_t elinkIndexInGroup() const
constexpr uint8_t elinkGroupId() const
A GBTEncoder manages 40 ElinkEncoder to encode the data of one GBT.
(Default) implementation of Encoder
size_t moveToBuffer(std::vector< std::byte > &buffer) override
void startHeartbeatFrame(uint32_t orbit, uint16_t bunchCrossing) override
PayloadEncoderImpl(Solar2FeeLinkMapper solar2feelink)
void addChannelData(DsElecId dsId, DualSampaChannelId dsChId, const std::vector< SampaCluster > &data) override
void addHeartbeatHeaders(const std::set< DsElecId > &dsids) override
A PayloadEncoder builds MCH raw data (payload part only)
void assertNofBits(std::string_view msg, T value, int n)
int assertIsInRange(std::string what, uint64_t value, uint64_t min, uint64_t max)
uint20_t sampaBunchCrossingCounter(uint32_t orbit, uint16_t bc, uint32_t firstOrbit)
void appendDataBlockHeader(std::vector< std::byte > &outBuffer, DataBlockHeader header)
Convert the header into bytes.
uint6_t DualSampaChannelId
std::function< std::optional< FeeLinkId >(uint16_t solarId)> Solar2FeeLinkMapper
From solarId to (feeId,linkId)
IR getFirstSampledTFIR() const
get TF and HB (abs) for this IR