33 const auto link = rdh_utils::getLink(feeId);
34 const auto cruID = rdh_utils::getCRU(feeId);
35 const auto endPoint = rdh_utils::getEndPoint(feeId);
37 const int fecLinkOffsetCRU = (mapper.getPartitionInfo(cru.
partition()).getNumberOfFECs() + 1) / 2;
38 int fecInPartition = link + endPoint * fecLinkOffsetCRU;
42 const int globalLinkID =
int(link) +
int(endPoint * 12);
43 const int tpcGlobalLinkID = cruID * 24 + globalLinkID;
44 static std::array<uint32_t, 360 * 24> syncOffsetLinks;
48 static int triggerBCOffset = 0;
58 while (zsdata < zsdataEnd) {
59 const auto& header = zsdata->
cont.header;
62 if (!header.hasCorrectMagicWord()) {
64 if (!header.isFillWord()) {
65 LOGP(error,
"Bad LinkZS magic word (0x{:08x}), for feeId 0x{:05x} (CRU: {:3}, link: {:2}, EP {}), orbit {} , skipping data block", header.magicWord, feeId, cruID, link, endPoint,
orbit);
66 LOGP(error,
"Full 128b word is: 0x{:016x}{:016x}", header.word1, header.word0);
72 if (header.isTriggerInfo()) {
75 const auto triggerOrbit = triggerInfo->triggerInfo.getOrbit();
76 const auto triggerBC = triggerInfo->triggerInfo.bunchCrossing;
77 triggerBCOffset = (
int(triggerOrbit) -
int(referenceOrbit)) * maxBunches + triggerBC;
78 LOGP(
debug,
"orbit: {}, triggerOrbit: {}, triggerBC: {}, triggerBCOffset: {}",
orbit, triggerOrbit, triggerBC, triggerBCOffset);
79 zsdata = zsdata->
next();
81 }
else if (header.isTriggerInfoV2()) {
84 const auto triggerOrbit = triggerInfo->orbit;
85 const auto triggerBC = triggerInfo->bunchCrossing;
86 triggerBCOffset = (
int(triggerOrbit) -
int(referenceOrbit)) * maxBunches + triggerBC;
87 LOGP(
debug,
"orbit: {}, triggerOrbit: {}, triggerBC: {}, triggerBCOffset: {}",
orbit, triggerOrbit, triggerBC, triggerBCOffset);
88 zsdata = zsdata->
next();
90 }
else if (header.isMetaHeader()) {
92 zsVersion = metaHDR.version;
93 timeOffset = metaHDR.timeOffset;
96 if (triggerInfo.hasTrigger()) {
97 const auto triggerBC = triggerInfo.getFirstBC();
98 const auto triggerOrbit =
orbit;
99 triggerBCOffset = (
int(triggerOrbit) -
int(referenceOrbit)) * maxBunches + triggerBC;
107 const uint32_t expectedWords = std::ceil(channelBits.count() * 0.1f);
109 assert(expectedWords == numberOfWords);
112 const auto syncOffset =
int(header.syncOffsetBC);
116 timeOffset = syncOffsetReference - syncOffset;
119 const int bcOffset = timeOffset + globalBCOffset + bunchCrossingHeader - triggerBCOffset;
121 using namespace std::literals::chrono_literals;
122 static std::chrono::time_point<std::chrono::steady_clock> lastReport = std::chrono::steady_clock::now();
123 const auto now = std::chrono::steady_clock::now();
124 static size_t reportedErrors = 0;
125 const size_t MAXERRORS = 10;
129 if (reportedErrors < MAXERRORS) {
131 std::string sleepInfo;
132 if (reportedErrors == MAXERRORS) {
133 sleepInfo = fmt::format(
", maximum error count ({}) reached, not reporting for the next {}", MAXERRORS,
sleepTime);
135 LOGP(warning,
"skipping time bin with negative BC offset timeOffset {} + globalBCoffset (({} - {}) * {} = {}) + bunchCrossingHeader ({}) - triggerBCOffset({}) = {}{}",
145 zsdata = zsdata->
next();
151 fecInPartition = header.fecInPartition;
154 std::size_t processedChannels = 0;
155 for (std::size_t ichannel = 0; ichannel < channelBits.size(); ++ichannel) {
156 if (!channelBits[ichannel]) {
164 int sampaOnFEC{}, channelOnSAMPA{};
166 const auto padSecPos = mapper.padSecPos(cru, fecInPartition, sampaOnFEC, channelOnSAMPA);
167 const auto& padPos = padSecPos.getPadPos();
170 fillADC(
int(cruID),
int(padPos.getRow()),
int(padPos.getPad()), timebin, adcValue);
177 zsdata = zsdata->
next();