Skip to content
Snippets Groups Projects
Commit 368e7a5e authored by Dominik Smith's avatar Dominik Smith Committed by Pierre-Alain Loizeau
Browse files

Added TOF unpacker in algo namespace. Modified CMakeLists to compile new TOF and T0 unpackers.

parent 9d827faa
No related branches found
No related tags found
1 merge request!923TOF and T0 unpackers in algo namespace.
......@@ -11,7 +11,11 @@ set(SRCS
detectors/much/MuchReadoutConfig.cxx
detectors/much/UnpackMuch.cxx
detectors/tof/HitFinderTof.cxx
)
detectors/tof/TofReadoutConfig.cxx
detectors/tof/UnpackTof.cxx
detectors/t0/T0ReadoutConfig.cxx
detectors/t0/UnpackT0.cxx
)
add_library(Algo SHARED ${SRCS})
......
/* Copyright (C) 2022 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
SPDX-License-Identifier: GPL-3.0-only
Authors: Dominik Smith [committer] */
#include "TofReadoutConfig.h"
#include "CbmTofAddress.h"
#include <Logger.h>
#include <bitset>
#include <iomanip>
#include "gDpbMessv100.h"
using namespace std;
namespace cbm::algo
{
// --- Constructor ------------------------------------------------------------------
TofReadoutConfig::TofReadoutConfig() { Init(); }
// ------------------------------------------------------------------------------------
// --- Destructor -----------------------------------------------------------------
TofReadoutConfig::~TofReadoutConfig() {}
// ------------------------------------------------------------------------------------
// --- Equipment IDs --------------------------------------------------------------
std::vector<uint16_t> TofReadoutConfig::GetEquipmentIds()
{
std::vector<uint16_t> result;
for (auto& entry : fReadoutMap)
result.push_back(entry.first);
return result;
}
// ------------------------------------------------------------------------------------
// --- Number of elinks for a component / equipment -------------------------------
size_t TofReadoutConfig::GetNumElinks(uint16_t equipmentId)
{
size_t result = 0;
auto it = fReadoutMap.find(equipmentId);
if (it != fReadoutMap.end()) result = fReadoutMap[equipmentId].size();
return result;
}
// ------------------------------------------------------------------------------------
// --- Mapping (equimentId, elink) -> address[channel] ------------------------------
std::vector<uint32_t> TofReadoutConfig::Map(uint16_t equipmentId, uint16_t elinkId)
{
std::vector<uint32_t> result;
auto equipIter = fReadoutMap.find(equipmentId);
if (equipIter != fReadoutMap.end()) {
if (elinkId < equipIter->second.size()) { result = equipIter->second.at(elinkId); }
}
return result;
}
// ------------------------------------------------------------------------------------
void TofReadoutConfig::Init()
{
// This here refers to the mCBM 2022 setup.
// Taken from CbmMcbm2018TofPar in combination with macro/beamtime/mcbm2022/mTofCriParNickel.par
// Array to hold the unique IDs (equipment ID) for all TOF DPBs
uint16_t eqId[numComp] = {0xabc0, 0xabc1, 0xabc2, 0xabc3, 0xabc4, 0xabc5, 0xabc6, 0xabc7};
// Constructing the map (equipmentId, eLink, channel) -> (TOF address)
const uint32_t numChanPerComp = numChanPerAsic * numElinksPerComp;
// Constructs the fviRpcChUId array
BuildChannelsUidMap();
for (uint16_t comp = 0; comp < numComp; comp++) {
uint16_t equipment = eqId[comp];
fReadoutMap[equipment].resize(numElinksPerComp);
for (uint16_t elink = 0; elink < numElinksPerComp; elink++) {
fReadoutMap[equipment][elink].resize(numChanPerAsic);
const uint32_t asicId = ElinkIdxToGet4Idx(elink);
for (uint16_t channel = 0; channel < numChanPerAsic; channel++) {
const uint32_t febId = (asicId / numAsicsPerFeb);
const uint32_t chanInFeb = (asicId % numAsicsPerFeb) * numChanPerAsic + channel;
const uint32_t remappedChan = comp * numChanPerComp + febId * numChanPerFeb + Get4ChanToPadiChan(chanInFeb);
const uint32_t chanUId = fviRpcChUId[remappedChan];
fReadoutMap[equipment][elink][channel] = chanUId;
} //# channel
} //# elink
} //# component
}
int32_t TofReadoutConfig::ElinkIdxToGet4Idx(uint32_t elink)
{
if (gdpbv100::kuChipIdMergedEpoch == elink) return elink;
else if (elink < numElinksPerComp)
return elink2Asic[elink % numElinksPerCrob] + numElinksPerCrob * (elink / numElinksPerCrob);
else {
LOG(fatal) << "CbmMcbm2018TofPar::ElinkIdxToGet4Idx => Index out of bound, " << elink << " vs "
<< static_cast<uint32_t>(numElinksPerComp) << ", returning crazy value!";
return -1;
}
}
// -------------------------------------------------------------------------
// -------------------------------------------------------------------------
int32_t TofReadoutConfig::Get4ChanToPadiChan(uint32_t channelInFee)
{
if (channelInFee < numChanPerFeb) return asic2PadI[channelInFee];
else {
LOG(fatal) << "CbmMcbm2018TofPar::Get4ChanToPadiChan => Index out of bound, " << channelInFee << " vs "
<< static_cast<uint32_t>(numChanPerFeb) << ", returning crazy value!";
return -1;
}
}
// -------------------------------------------------------------------------
// -------------------------------------------------------------------------
void TofReadoutConfig::BuildChannelsUidMap()
{
uint32_t uNrOfGet4 = numComp * numFebsPerComp * numAsicsPerFeb;
uint32_t uNrOfChannels = uNrOfGet4 * numChanPerAsic;
fviRpcChUId.resize(uNrOfChannels);
uint32_t uCh = 0;
for (uint32_t uGbtx = 0; uGbtx < numCrob; ++uGbtx) {
uint32_t uCh0 = uCh;
switch (rpcType[uGbtx]) {
case 2: // intended fall-through
case 0: {
// CBM modules
BuildChannelsUidMapCbm(uCh, uGbtx);
break;
}
case 1: {
// STAR eTOF modules
BuildChannelsUidMapStar(uCh, uGbtx);
break;
}
case 78: {
// cern-20-gap + ceramic module
BuildChannelsUidMapCern(uCh, uGbtx);
}
[[fallthrough]]; // fall through is intended
case 8: // ceramics
{
BuildChannelsUidMapCera(uCh, uGbtx);
break;
}
case 69:
case 6: // Buc box
{
BuildChannelsUidMapBuc(uCh, uGbtx);
if (rpcType[uGbtx] == 6) break;
}
[[fallthrough]];
case 4: // intended fallthrough
[[fallthrough]];
case 7: [[fallthrough]];
case 9: // Star2 boxes
{
if (rpcType[uGbtx] == 69) uCh -= 80;
BuildChannelsUidMapStar2(uCh, uGbtx);
if (rpcType[uGbtx] == 69) uCh -= 80;
break;
}
case -1: {
LOG(info) << " Found unused GBTX link at uCh = " << uCh;
uCh += 160;
break;
}
default: {
LOG(error) << "Invalid Tof Type specifier for GBTx " << std::setw(2) << uGbtx << ": " << rpcType[uGbtx];
}
} // switch (rpcType[uGbtx])
if ((int32_t)(uCh - uCh0) != numFebsPerComp * numAsicsPerFeb * numChanPerAsic / 2) {
LOG(fatal) << "Tof mapping error for Gbtx " << uGbtx << ", diff = " << uCh - uCh0 << ", type "
<< rpcType[uGbtx];
}
} // for (UInt_t uGbtx = 0; uGbtx < numCrob; ++uGbtx)
}
// -------------------------------------------------------------------------
// -------------------------------------------------------------------------
void TofReadoutConfig::BuildChannelsUidMapCbm(uint32_t& uCh, uint32_t uGbtx)
{
LOG(info) << " Map mTof box " << moduleId[uGbtx] << " at GBTX " << uGbtx << " - uCh = " << uCh;
if (rpcSide[uGbtx] < 2) { // mTof modules
LOG(debug) << " Map mTof box " << moduleId[uGbtx] << " at GBTX - uCh = " << uCh;
const int32_t RpcMap[5] = {4, 2, 0, 3, 1};
for (int32_t iRpc = 0; iRpc < numRpc[uGbtx]; iRpc++) {
int32_t iStrMax = 32;
uint32_t uChNext = 1;
for (int32_t iStr = 0; iStr < iStrMax; iStr++) {
int32_t iStrMap = iStr;
int32_t iRpcMap = RpcMap[iRpc];
if (rpcSide[uGbtx] == 0) iStrMap = 31 - iStr;
if (moduleId[uGbtx] > -1)
fviRpcChUId[uCh] =
CbmTofAddress::GetUniqueAddress(moduleId[uGbtx], iRpcMap, iStrMap, rpcSide[uGbtx], rpcType[uGbtx]);
else
fviRpcChUId[uCh] = 0;
uCh += uChNext;
} // for (int32_t iStr = 0; iStr < iStrMax; iStr++)
} // for (int32_t iRpc = 0; iRpc < numRpc[uGbtx]; iRpc++)
} // if (rpcSide[uGbtx] < 2)
}
// -------------------------------------------------------------------------
void TofReadoutConfig::BuildChannelsUidMapStar(uint32_t& uCh, uint32_t uGbtx)
{
if (rpcSide[uGbtx] < 2) {
// mTof modules
LOG(info) << "Start eTOF module side " << rpcSide[uGbtx] << " at " << uCh;
const int32_t RpcMap[3] = {0, 1, 2};
for (int32_t iRpc = 0; iRpc < numRpc[uGbtx]; iRpc++) {
int32_t iStrMax = 32;
int32_t uChNext = 1;
for (int32_t iStr = 0; iStr < iStrMax; iStr++) {
int32_t iStrMap = iStr;
int32_t iRpcMap = RpcMap[iRpc];
if (rpcSide[uGbtx] == 0) iStrMap = 31 - iStr;
if (moduleId[uGbtx] > -1)
fviRpcChUId[uCh] =
CbmTofAddress::GetUniqueAddress(moduleId[uGbtx], iRpcMap, iStrMap, rpcSide[uGbtx], rpcType[uGbtx]);
else
fviRpcChUId[uCh] = 0;
uCh += uChNext;
}
}
}
uCh += 64;
}
// -------------------------------------------------------------------------
void TofReadoutConfig::BuildChannelsUidMapCern(uint32_t& uCh, uint32_t)
{
LOG(info) << " Map CERN 20 gap at GBTX - uCh = " << uCh;
// clang-format off
const int32_t StrMap[32] = {0, 1, 2, 3, 4, 31, 5, 6, 7, 30, 8,
9, 10, 29, 11, 12, 13, 14, 28, 15, 16, 17,
18, 27, 26, 25, 24, 23, 22, 21, 20, 19};
// clang-format on
int32_t iModuleId = 0;
int32_t iModuleType = 7;
int32_t iRpcMap = 0;
for (int32_t iFeet = 0; iFeet < 2; iFeet++) {
for (int32_t iStr = 0; iStr < 32; iStr++) {
int32_t iStrMap = 31 - 12 - StrMap[iStr];
int32_t iSideMap = iFeet;
if (iStrMap < 20)
fviRpcChUId[uCh] = CbmTofAddress::GetUniqueAddress(iModuleId, iRpcMap, iStrMap, iSideMap, iModuleType);
else
fviRpcChUId[uCh] = 0;
uCh++;
}
}
LOG(info) << " Map end CERN 20 gap at GBTX - uCh = " << uCh;
}
// -------------------------------------------------------------------------
void TofReadoutConfig::BuildChannelsUidMapCera(uint32_t& uCh, uint32_t)
{
int32_t iModuleId = 0;
int32_t iModuleType = 8;
for (int32_t iRpc = 0; iRpc < 8; iRpc++) {
fviRpcChUId[uCh] = CbmTofAddress::GetUniqueAddress(iModuleId, 7 - iRpc, 0, 0, iModuleType);
uCh++;
}
uCh += (24 + 2 * 32);
LOG(info) << " Map end ceramics box at GBTX - uCh = " << uCh;
}
// -------------------------------------------------------------------------
void TofReadoutConfig::BuildChannelsUidMapStar2(uint32_t& uCh, uint32_t uGbtx)
{
LOG(info) << " Map Star2 box " << moduleId[uGbtx] << " at GBTX " << uGbtx << " - uCh = " << uCh;
const int32_t iRpc[5] = {1, -1, 1, 0, 0};
const int32_t iSide[5] = {1, -1, 0, 1, 0};
for (int32_t iFeet = 0; iFeet < 5; iFeet++) {
for (int32_t iStr = 0; iStr < 32; iStr++) {
int32_t iStrMap = iStr;
int32_t iRpcMap = iRpc[iFeet];
int32_t iSideMap = iSide[iFeet];
if (iSideMap == 0) iStrMap = 31 - iStr;
switch (rpcSide[uGbtx]) {
case 0:; break;
case 1:;
iRpcMap = 1 - iRpcMap; // swap counters
break;
case 2:
switch (iFeet) {
case 1:
iRpcMap = iRpc[4];
iSideMap = iSide[4];
iStrMap = 31 - iStrMap;
break;
case 4:
iRpcMap = iRpc[1];
iSideMap = iSide[1];
break;
default:;
}
break;
case 3: // direct beam 20210524
switch (iFeet) {
case 0:
iRpcMap = 0;
iSideMap = 0;
iStrMap = iStr;
break;
case 1:
iRpcMap = 0;
iSideMap = 1;
iStrMap = 31 - iStr;
break;
default: iSideMap = -1;
}
break;
}
if (iSideMap > -1)
fviRpcChUId[uCh] =
CbmTofAddress::GetUniqueAddress(moduleId[uGbtx], iRpcMap, iStrMap, iSideMap, rpcType[uGbtx]);
else
fviRpcChUId[uCh] = 0;
uCh++;
}
}
}
// -------------------------------------------------------------------------
void TofReadoutConfig::BuildChannelsUidMapBuc(uint32_t& uCh, uint32_t uGbtx)
{
LOG(info) << " Map Buc box " << moduleId[uGbtx] << " at GBTX " << uGbtx << " - uCh = " << uCh;
int32_t iModuleIdMap = moduleId[uGbtx];
const int32_t iRpc[5] = {0, -1, 0, 1, 1};
const int32_t iSide[5] = {1, -1, 0, 1, 0};
for (int32_t iFeet = 0; iFeet < 5; iFeet++) {
for (int32_t iStr = 0; iStr < 32; iStr++) {
int32_t iStrMap = iStr;
int32_t iRpcMap = iRpc[iFeet];
int32_t iSideMap = iSide[iFeet];
switch (rpcSide[uGbtx]) {
case 0:; break;
case 1: // HD cosmic 2019, Buc2018, v18n
iStrMap = 31 - iStr;
iRpcMap = 1 - iRpcMap;
break;
case 2: // v18m_cosmicHD
// iStrMap=31-iStr;
iSideMap = 1 - iSideMap;
break;
case 3:
iStrMap = 31 - iStr;
iRpcMap = 1 - iRpcMap;
iSideMap = 1 - iSideMap;
break;
case 4: // HD cosmic 2019, Buc2018, v18o
iRpcMap = 1 - iRpcMap;
break;
case 5: // HD cosmic 2020, Buc2018, v20a
iStrMap = 31 - iStr;
break;
case 6: //BUC special
{
switch (moduleId[uGbtx]) {
case 0: iRpcMap = 0; break;
case 1: iRpcMap = 1; break;
}
if (iFeet % 2 == 1) iModuleIdMap = 1;
else
iModuleIdMap = 0;
switch (iFeet) {
case 0:
case 3: iSideMap = 0; break;
case 1:
case 2: iSideMap = 1; break;
}
} break;
case 7: {
// clang-format off
const int32_t iChMap[160]={
124, 125, 126, 127, 12, 13, 14, 15, 4, 5, 6, 7, 28, 29, 30, 31, 120, 121, 122, 123, 8, 9, 10, 11, 104, 105, 106, 107, 108, 109, 110, 111,
36, 37, 38, 39, 52, 53, 54, 55, 60, 61, 62, 63, 128, 129, 130, 131, 40, 41, 42, 43, 148, 149, 150, 151, 56, 57, 58, 59, 132, 133, 134, 135,
136, 137, 138, 139, 140, 141, 142, 143, 96, 97, 98, 99, 64, 65, 66, 67, 100, 101, 102, 103, 84, 85, 86, 87, 152, 153, 154, 155, 68, 69, 70, 71,
156, 157, 158, 159, 144, 145, 146, 147, 44, 45, 46, 47, 76, 77, 78, 79, 48, 49, 50, 51, 20, 21, 22, 23, 32, 33, 34, 35, 116, 117, 118, 119,
75, 74, 73, 72, 92, 93, 94, 95, 16, 17, 18, 19, 80, 81, 82, 83, 115, 114, 113, 112, 24, 25, 26, 27, 88, 89, 90, 91, 0, 1, 2, 3
};
// clang-format on
int32_t iInd = iFeet * 32 + iStr;
int32_t i = 0;
for (; i < 160; i++)
if (iInd == iChMap[i]) break;
iStrMap = i % 32;
int32_t iFeetInd = (i - iStrMap) / 32;
switch (iFeetInd) {
case 0:
iRpcMap = 0;
iSideMap = 1;
break;
case 1:
iRpcMap = 1;
iSideMap = 1;
break;
case 2:
iRpcMap = 1;
iSideMap = 0;
break;
case 3:
iRpcMap = 0;
iSideMap = 0;
break;
case 4: iSideMap = -1; break;
}
iModuleIdMap = moduleId[uGbtx];
} break;
default:;
} // switch (rpcSide[uGbtx])
if (iSideMap > -1)
fviRpcChUId[uCh] = CbmTofAddress::GetUniqueAddress(iModuleIdMap, iRpcMap, iStrMap, iSideMap, rpcType[uGbtx]);
else
fviRpcChUId[uCh] = 0;
uCh++;
} // for (int32_t iStr = 0; iStr < 32; iStr++)
} // for (int32_t iFeet = 0; iFeet < 5; iFeet++)
}
// -------------------------------------------------------------------------
} /* namespace cbm::algo */
/* Copyright (C) 2022 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
SPDX-License-Identifier: GPL-3.0-only
Authors: Dominik Smith [committer] */
#ifndef ALGO_DETECTORS_TOF_TOFREADOUTCONFIG_H
#define ALGO_DETECTORS_TOF_TOFREADOUTCONFIG_H
#include <cstdint>
#include <map>
#include <vector>
namespace cbm::algo
{
class TofReadoutConfig {
public:
/** @brief Constructor **/
TofReadoutConfig();
/** @brief Destructor **/
virtual ~TofReadoutConfig();
/** @brief Equipment in the configuration
** @return Vector of equipment IDs
**/
std::vector<uint16_t> GetEquipmentIds();
/** @brief Number of elinks of a component
** @param Equipment ID
** @return Number of elinks
**/
size_t GetNumElinks(uint16_t equipmentId);
/** @brief API: Mapping from component and elink to addresses per channel
** @param equipId Equipment identifier (component)
** @param elink Elink number within component
** @return Vector of TOF addresses, indexed via channel number
*/
std::vector<uint32_t> Map(uint16_t equipId, uint16_t elink);
private:
// --- TOF readout map
// --- Map index: (equipment, elink, channel), map value: (TOF address)
std::map<uint16_t, std::vector<std::vector<uint32_t>>> fReadoutMap = {};
/** @brief Initialisation of readout map **/
void Init();
/// Mapping to eLink to ASIC number within DPB. Mapping is the same for each DPB.
int32_t ElinkIdxToGet4Idx(uint32_t elink);
int32_t Get4ChanToPadiChan(uint32_t channelInFee);
/// Constants
/// Taken from mTofCriParNickel_withBmon.par
static const uint16_t numComp = 8; // Total number of TOF DPBs in system
static const uint32_t numFebsPerComp = 10; // Number of FEEs which are connected to one GDPB
static const uint32_t numAsicsPerFeb = 8; // Number of ASICs connected in each FEB for TOF
static const uint32_t numChanPerAsic = 4; // Number of channels in each ASIC
static const uint32_t numCrob = 16; // Total number of Gbtx links
// Module Identifier connected to Gbtx link, has to match geometry
const int32_t moduleId[numCrob] = {0, 0, 1, 1, 0, 0, 2, 2, 3, 3, 4, 4, 0 - 1, 0, 0};
// type of Rpcs connected to Gbtx link
const int32_t rpcType[numCrob] = {0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 9, 9, 6, 9};
// side of Rpcs connected to Gbtx link, i.e. 0 or 1
const int32_t rpcSide[numCrob] = {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 8, 0};
// number of Rpcs connected to Gbtx link, i.e. 3 or 5
const int32_t numRpc[numCrob] = {5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5};
//// Taken from CbmMcbm2018TofPar.h (fixed numCrobPerComp)
static const uint32_t numCrobPerComp = 2; // Number of CROBs possible per DPB
static const uint32_t numFebsPerCrob = 5; // Number of FEBs connected to each CROB for mTof 2019
static const uint32_t numChanPerFeb = numChanPerAsic * numAsicsPerFeb;
static const uint32_t numElinksPerCrob = numAsicsPerFeb * numFebsPerCrob;
static const uint32_t numElinksPerComp = numElinksPerCrob * numCrobPerComp;
// Mapping to eLink to ASIC number within CROB. Mapping is the same for each CROB.
const uint32_t elink2Asic[numElinksPerCrob] = {27, 2, 7, 3, 31, 26, 30, 1, 33, 37, 32, 13, 9, 14,
10, 15, 17, 21, 16, 35, 34, 38, 25, 24, 0, 6, 20, 23,
18, 22, 28, 4, 29, 5, 19, 36, 39, 8, 12, 11};
// Mapping in Readout chain PCBs
const uint32_t asic2PadI[numChanPerFeb] = {
3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12,
19, 18, 17, 16, 23, 22, 21, 20, 27, 26, 25, 24, 31, 30, 29, 28}; //! Map from GET4 channel to PADI channel
std::vector<int32_t> fviRpcChUId = {}; // UID/address for each channel, build from type, side and module
void BuildChannelsUidMap();
void BuildChannelsUidMapCbm(uint32_t& uCh, uint32_t uGbtx);
void BuildChannelsUidMapStar(uint32_t& uCh, uint32_t uGbtx);
void BuildChannelsUidMapCern(uint32_t& uCh, uint32_t uGbtx);
void BuildChannelsUidMapCera(uint32_t& uCh, uint32_t uGbtx);
void BuildChannelsUidMapStar2(uint32_t& uCh, uint32_t uGbtx);
void BuildChannelsUidMapBuc(uint32_t& uCh, uint32_t uGbtx);
};
} /* namespace cbm::algo */
#endif //ALGO_DETECTORS_TOF_TOFREADOUTCONFIG_H
/* Copyright (C) 2022 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
SPDX-License-Identifier: GPL-3.0-only
Authors: Dominik Smith [committer] */
#include "UnpackTof.h"
#include <cassert>
#include <utility>
#include <vector>
#include <cmath>
using std::unique_ptr;
using std::vector;
namespace cbm::algo
{
// ---- Algorithm execution ---------------------------------------------
UnpackTof::resultType UnpackTof::operator()(const uint8_t* msContent, const fles::MicrosliceDescriptor& msDescr,
const uint64_t tTimeslice)
{
// --- Output data
resultType result = {};
// --- Current Timeslice start time in epoch units. Note that it is always a multiple of epochs
// --- and the epoch is a multiple of ns.
fCurrentTsTime = static_cast<uint64_t>(tTimeslice / critof001::kuEpochInNs) % critof001::kulEpochCycleEp;
// --- Number of messages in microslice
auto msSize = msDescr.size;
if (msSize % sizeof(critof001::Message) != 0) {
result.second.fNumErrInvalidMsSize++;
return result;
}
const uint32_t numMessages = msSize / sizeof(critof001::Message);
if (numMessages < 2) {
result.second.fNumErrInvalidMsSize++;
return result;
}
// --- Interpret MS content as sequence of Critof messages
auto message = reinterpret_cast<const critof001::Message*>(msContent);
// --- The first message in the MS is expected to be of type EPOCH.
if (message[0].getMessageType() != critof001::MSG_EPOCH) {
result.second.fNumErrInvalidFirstMessage++;
return result;
}
{ // --- Check that first epoch matches with the microslice index
const uint64_t msStartEpoch =
static_cast<uint64_t>(msDescr.idx / critof001::kuEpochInNs) % critof001::kulEpochCycleEp;
if (message[0].getGdpbEpEpochNb() != msStartEpoch) {
result.second.fNumErrInvalidStartEpoch++;
return result;
}
}
// --- The last message in the MS is expected to be EndOfMs.
if (!message[numMessages - 1].isEndOfMs()) {
result.second.fNumErrInvalidLastMessage++;
return result;
}
// Check if last message is "EndOfMs"!! Maybe loop to messageNr < numMessages - 1
// --- Message loop
for (uint32_t messageNr = 0; messageNr < numMessages; messageNr++) {
// --- Action depending on message type
switch (message[messageNr].getMessageType()) {
case critof001::MSG_HIT: {
ProcessHitMessage(message[messageNr], result.first, result.second);
break;
}
case critof001::MSG_EPOCH: {
ProcessEpochMessage(message[messageNr]);
break;
}
case critof001::MSG_SLOWC: {
// Fill error
break;
}
case critof001::MSG_SYST: {
// Fill error
break;
}
default: {
result.second.fNumNonHitOrTsbMessage++;
break;
}
} //? Message type
} //# Messages
return result;
}
// --------------------------------------------------------------------------
// ----- Process hit message --------------------------------------------
inline void UnpackTof::ProcessHitMessage(const critof001::Message& message, vector<CbmTofDigi>& digiVec,
UnpackTofMonitorData& monitor) const
{
// --- Check eLink and get parameters
const uint32_t elink = message.getGet4Idx();
if (elink >= fParams.fElinkParams.size()) {
monitor.fNumErrElinkOutOfRange++;
return;
}
const UnpackTofElinkPar& elinkPar = fParams.fElinkParams.at(elink);
const uint32_t channel = message.getGdpbHitChanId();
const uint32_t channelUId = (elinkPar.fChannelUId)[channel];
double messageTime = message.getMsgFullTimeD(fCurrentEpochInTs) - elinkPar.fTimeOffset;
const double charge = (double) message.getGdpbHit32Tot(); //cast from uint32_t
{ // weird address hack (probably should not be in final version)
std::unique_ptr<CbmTofDigi> digi(new CbmTofDigi(channelUId, messageTime, charge));
int iSmType = 8;
int iSm = -1;
int iRpc = 0;
int iDetId = 0;
if (digi->GetType() == 6 && digi->GetRpc() == 1) {
switch ((int) (digi->GetChannel() * 2 + digi->GetSide())) {
case 62: //800
iSm = 0;
break;
case 46: //810
iSm = 1;
break;
default:;
}
if (iSm > -1) {
iDetId = CbmTofAddress::GetUniqueAddress(iSm, iRpc, 0, 0, iSmType);
digi->SetAddress(iDetId);
}
}
if (digi) digiVec.emplace_back(*std::move(digi));
} //special remapping end
// --- Create output digi
//digiVec.emplace_back(channelUId, messageTime, charge); ((restore this))
}
// --------------------------------------------------------------------------
// ----- Process an epoch message ---------------------------------------
inline void UnpackTof::ProcessEpochMessage(const critof001::Message& message)
{
const uint64_t epoch = message.getGdpbEpEpochNb();
// --- Calculate epoch relative to timeslice start time; correct for epoch cycles
if (fCurrentTsTime <= epoch) { fCurrentEpochInTs = epoch - fCurrentTsTime; }
else {
fCurrentEpochInTs = epoch + critof001::kulEpochCycleEp - fCurrentTsTime;
}
//Problem if MS spans multiple epoch cycles?
}
// --------------------------------------------------------------------------
} /* namespace cbm::algo */
/* Copyright (C) 2022 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
SPDX-License-Identifier: GPL-3.0-only
Authors: Dominik Smith [committer] */
#ifndef CBM_ALGO_UNPACKTOF_H
#define CBM_ALGO_UNPACKTOF_H 1
#include "CbmTofDigi.h"
#include "MicrosliceDescriptor.hpp"
#include "Timeslice.hpp"
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <memory>
#include <vector>
#include "CriGet4Mess001.h"
namespace cbm::algo
{
/** @struct UnpackTofElinkPar
** @author Volker Friese <v.friese@gsi.de>
** @since 25 November 2021
** @brief TOF Unpacking parameters for one eLink / ASIC
**/
struct UnpackTofElinkPar {
std::vector<uint32_t> fChannelUId; ///< CbmTofAddress for different channels
uint64_t fTimeOffset = 0.; ///< Time calibration parameter
};
/** @struct UnpackTofPar
** @author Volker Friese <v.friese@gsi.de>
** @since 25 November 2021
** @brief Parameters required for the STS unpacking (specific to one component)
**/
struct UnpackTofPar {
uint32_t fNumChansPerAsic = 0; ///< Number of channels per ASIC
uint32_t fNumAsicsPerModule = 0; ///< Number of ASICS per module
std::vector<UnpackTofElinkPar> fElinkParams = {}; ///< Parameters for each eLink
};
/** @struct UnpackTofMoni
** @author Volker Friese <v.friese@gsi.de>
** @since 2 December 2021
** @brief Monitoring data for STS unpacking
**/
struct UnpackTofMonitorData {
uint32_t fNumNonHitOrTsbMessage = 0;
uint32_t fNumErrElinkOutOfRange = 0; ///< Elink not contained in parameters
uint32_t fNumErrInvalidFirstMessage = 0; ///< First message is not EPOCH
uint32_t fNumErrInvalidLastMessage = 0; ///< Last message is not EndOfMs
uint32_t fNumErrInvalidMsSize = 0; ///< Microslice size is not multiple of message size
uint32_t fNumErrTimestampOverflow = 0; ///< Overflow in 64 bit time stamp
uint32_t fNumErrInvalidStartEpoch = 0; ///< Microslice index doesn't match first epoch
bool HasErrors()
{
uint32_t numErrors = fNumNonHitOrTsbMessage + fNumErrElinkOutOfRange + fNumErrInvalidFirstMessage
+ fNumErrInvalidLastMessage + fNumErrInvalidMsSize + fNumErrTimestampOverflow
+ fNumErrInvalidStartEpoch;
return (numErrors > 0 ? true : false);
}
};
/** @class UnpackTof
** @author Pierre-Alain Loizeau <p.-a.loizeau@gsi.de>
** @author Volker Friese <v.friese@gsi.de>
** @since 25 November 2021
** @brief Unpack algorithm for STS
**/
class UnpackTof {
public:
typedef std::pair<std::vector<CbmTofDigi>, UnpackTofMonitorData> resultType;
/** @brief Default constructor **/
UnpackTof() {};
/** @brief Destructor **/
~UnpackTof() {};
/** @brief Algorithm execution
** @param msContent Microslice payload
** @param msDescr Microslice descriptor
** @param tTimeslice Unix start time of timeslice [ns]
** @return STS digi data
**/
resultType operator()(const uint8_t* msContent, const fles::MicrosliceDescriptor& msDescr,
const uint64_t tTimeslice);
/** @brief Set the parameter container
** @param params Pointer to parameter container
**/
void SetParams(std::unique_ptr<UnpackTofPar> params) { fParams = *(std::move(params)); }
private: // methods
/** @brief Process a hit message
** @param message SMX message (32-bit word)
** @param digiVec Vector to append the created digi to
** @param monitor Reference to monitor object
**/
void ProcessHitMessage(const critof001::Message& message, std::vector<CbmTofDigi>& digiVec,
UnpackTofMonitorData& monitor) const;
/** @brief Process an epoch message
** @param message SMX message (32-bit word)
**/
void ProcessEpochMessage(const critof001::Message& message);
private: // members
uint64_t fCurrentTsTime = 0; ///< Unix time of timeslice in units of epoch length
uint32_t fCurrentEpochInTs = 0; ///< Current epoch number relative to timeslice start epoch
UnpackTofPar fParams = {}; ///< Parameter container
};
} /* namespace cbm::algo */
#endif /* CBM_ALGO_UNPACKTOF_H */
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment