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