CbmRoot
Loading...
Searching...
No Matches
bmon/UnpackMS.cxx
Go to the documentation of this file.
1/* Copyright (C) 2022 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
2 SPDX-License-Identifier: GPL-3.0-only
3 Authors: Dominik Smith [committer] */
4
5#include "UnpackMS.h"
6
8
9#include <cassert>
10#include <cmath>
11#include <sstream>
12#include <utility>
13#include <vector>
14
15using std::unique_ptr;
16using std::vector;
17
18namespace cbm::algo::bmon
19{
20
21 UnpackMS::UnpackMS(const UnpackPar& pars) : fParams(pars) {}
22 UnpackMS::~UnpackMS() = default;
23
24 // ---- Algorithm execution ---------------------------------------------
25 UnpackMS::Result_t UnpackMS::operator()(const uint8_t* msContent, const fles::MicrosliceDescriptor& msDescr,
26 const uint64_t tTimeslice) const
27 {
28
29 // --- Output data
30 Result_t result = {};
31
32 L_(debug) << "EQ ID 0x" << std::hex << msDescr.eq_id << std::dec;
33
34 // --- Number of messages in microslice
35 auto msSize = msDescr.size;
36 if (msSize % sizeof(critof001::Message) != 0) {
37 std::get<1>(result).fNumErrInvalidMsSize++;
38 return result;
39 }
40 const uint32_t numMessages = msSize / sizeof(critof001::Message);
41 if (numMessages < 2) {
42 std::get<1>(result).fNumErrInvalidMsSize++;
43 return result;
44 }
45
46 // --- Interpret MS content as sequence of SMX messages
47 auto message = reinterpret_cast<const critof001::Message*>(msContent);
48
49 const uint32_t maxDigis = numMessages - 2; // -2 for the TS_MSB and EPOCH messages
50 std::get<0>(result).reserve(maxDigis);
51
52 // --- The first message in the MS is expected to be of type EPOCH.
53 if (message[0].getMessageType() != critof001::MSG_EPOCH) {
54 std::get<1>(result).fNumErrInvalidFirstMessage++;
55 return result;
56 }
57
58 { // --- Check that first epoch matches with the microslice index
59 const uint64_t msStartEpoch =
60 static_cast<uint64_t>(msDescr.idx / critof001::kuEpochInNs) % critof001::kulEpochCycleEp;
61 if (message[0].getGdpbEpEpochNb() != msStartEpoch) {
62 std::get<1>(result).fNumErrInvalidStartEpoch++;
63 return result;
64 }
65 }
66
67 TimeSpec time;
68
69 // --- Current Timeslice start time in epoch units. Note that it is always a multiple of epochs
70 // --- and the epoch is a multiple of ns.
71 time.currentTsTime = static_cast<uint64_t>(tTimeslice / critof001::kuEpochInNs) % critof001::kulEpochCycleEp;
72 ProcessEpochMessage(message[0], time);
73
74 // --- The last message in the MS is expected to be EndOfMs.
75 if (!message[numMessages - 1].isEndOfMs()) {
76 std::get<1>(result).fNumErrInvalidLastMessage++;
77 return result;
78 }
79 //Check if last message is "EndOfMs"!! Maybe loop to messageNr < numMessages - 1
80
81 // --- Message loop
82 for (uint32_t messageNr = 1; messageNr < numMessages; messageNr++) {
83
84 // --- Action depending on message type
85 switch (message[messageNr].getMessageType()) {
86
87 case critof001::MSG_HIT: {
88 ProcessHitMessage(message[messageNr], time, std::get<0>(result), std::get<1>(result));
89 break;
90 }
92 if (critof001::kuChipIdMergedEpoch == message[messageNr].getGet4Idx()) {
93 ProcessEpochMessage(message[messageNr], time);
94 } // if this epoch message is a merged one valid for all chips
95 else {
97 std::get<1>(result).fNumErrInvalidAsicEpochs++;
98 continue;
99 } // if single chip epoch message
100 break;
101 }
103 std::get<1>(result).fNumNonHitOrTsbMessage++;
104 break;
105 }
106 case critof001::MSG_SYST: {
107 std::get<1>(result).fNumNonHitOrTsbMessage++;
108 break;
109 }
110 default: {
111 std::get<1>(result).fNumNonHitOrTsbMessage++;
112 break;
113 }
114 } //? Message type
115 } //# Messages
116
117 return result;
118 }
119 // --------------------------------------------------------------------------
120
121
122 // ----- Process hit message --------------------------------------------
123 inline void UnpackMS::ProcessHitMessage(const critof001::Message& message, const TimeSpec& time,
124 vector<CbmBmonDigi>& digiVec, UnpackMonitorData& monitor) const
125 {
126 // IGNORES:
127 // - Duplicate messages
128 // - (fviRpcChUId.size() < uRemappedChannelNrInSys)
129 // - successive digis with same time
130 // (these are filtered in original version but not here)
131 // also: does not apply new "remap digis" hack, and always includes timeslice overlap
132
133 // --- Check eLink and get parameters
134 const uint32_t elink = message.getGet4Idx();
135 if (elink >= fParams.fElinkParams.size()) {
136 monitor.fNumErrElinkOutOfRange++;
137 return;
138 }
139 const UnpackElinkPar& elinkPar = fParams.fElinkParams.at(elink);
140
141 const uint32_t channel = message.getGdpbHitChanId();
142 const uint32_t channelUId = (elinkPar.fChannelUId)[channel];
143
144 L_(debug) << "GET4 Idx " << elink << " channel " << channel << " 0x" << std::hex << channelUId << std::dec;
145 if (0 < channelUId) {
146 double messageTime = message.getMsgFullTimeD(time.currentEpochInTs) - elinkPar.fTimeOffset;
147 const double charge = (double) message.getGdpbHit32Tot(); //cast from uint32_t
148
149 // --- Create output digi
150 digiVec.emplace_back(channelUId, messageTime, charge);
151 }
152 else {
153 L_(debug) << "Ignoring digi on unmapped channel";
154 }
155 }
156 // --------------------------------------------------------------------------
157
158
159 // ----- Process an epoch message ---------------------------------------
160 inline void UnpackMS::ProcessEpochMessage(const critof001::Message& message, TimeSpec& time) const
161 {
162 const uint64_t epoch = message.getGdpbEpEpochNb();
163
164 // --- Calculate epoch relative to timeslice start time; correct for epoch cycles
165 if (time.currentTsTime <= epoch) {
166 time.currentEpochInTs = epoch - time.currentTsTime;
167 }
168 else {
170 }
171 //Problem if MS spans multiple epoch cycles?
172 }
173 // --------------------------------------------------------------------------
174
175
176} // namespace cbm::algo::bmon
#define L_(level)
std::tuple< std::vector< Digi_t >, Monitor_t, Aux_t > Result_t
UnpackPar fParams
Parameter container.
UnpackMS(const UnpackPar &pars)
Construct from parameters.
~UnpackMS() override
Destructor.
void ProcessHitMessage(const critof001::Message &message, const TimeSpec &time, std::vector< CbmBmonDigi > &digiVec, UnpackMonitorData &monitor) const
Process a hit message.
Result_t operator()(const uint8_t *msContent, const fles::MicrosliceDescriptor &msDescr, const uint64_t tTimeslice) const override
Algorithm execution.
void ProcessEpochMessage(const critof001::Message &message, TimeSpec &time) const
Process an epoch message (TS_MSB)
uint16_t getGdpbHit32Tot() const
uint16_t getGet4Idx() const
uint16_t getGdpbHitChanId() const
uint32_t getGdpbEpEpochNb() const
double getMsgFullTimeD(uint64_t epoch) const
Returns expanded and adjusted time of message in double (in ns)
const uint64_t kulEpochCycleEp
const uint32_t kuChipIdMergedEpoch
const double kuEpochInNs
Bmon Unpacking parameters for one eLink / ASIC.
int32_t fTimeOffset
Time calibration parameter.
std::vector< uint32_t > fChannelUId
CbmBmonAddress for different channels.
uint64_t currentTsTime
Unix time of timeslice in units of epoch length.
uint32_t currentEpochInTs
Current epoch number relative to timeslice start epoch.
uint32_t fNumErrElinkOutOfRange
Elink not contained in parameters.
Parameters required for the BMON unpacking (specific to one component)
std::vector< UnpackElinkPar > fElinkParams
Parameters for each eLink.