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

Started to implement new Much unpacker in algo namespace.

parent 959c14d1
No related branches found
No related tags found
1 merge request!866Much Unpacker in Algo namespace
...@@ -8,6 +8,8 @@ set(SRCS ...@@ -8,6 +8,8 @@ set(SRCS
trigger/TimeClusterTrigger.cxx trigger/TimeClusterTrigger.cxx
detectors/sts/StsReadoutConfig.cxx detectors/sts/StsReadoutConfig.cxx
detectors/sts/UnpackSts.cxx detectors/sts/UnpackSts.cxx
detectors/much/MuchReadoutConfig.cxx
detectors/much/UnpackMuch.cxx
) )
add_library(Algo SHARED ${SRCS}) add_library(Algo SHARED ${SRCS})
......
/* Copyright (C) 2017-2021 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
SPDX-License-Identifier: GPL-3.0-only
Authors: Pierre-Alain Loizeau, Ajit Kumar, Florian Uhlig [committer] */
#include "MuchReadoutConfig.h"
//#include "FairDetParIo.h"
//#include "FairParIo.h"
//#include "FairParamList.h"
#include <Logger.h>
//#include "TMath.h"
//#include "TString.h"
using namespace std;
namespace cbm::algo
{
/*
// ----- Public method clear -------------------------------------------
void MuchReadoutConfig::clear()
{
status = false;
resetInputVersions();
}
// -------------------------------------------------------------------------
// -------------------------------------------------------------------------
void MuchReadoutConfig::putParams(FairParamList* l)
{
if (!l) return;
l->add("NrOfDpbs", fuNrOfDpbs);
l->add("DbpIdArray", fiDbpIdArray);
l->add("CrobActiveFlag", fiCrobActiveFlag);
l->add("NrOfFebsInGemA", fuFebsInGemA);
l->add("nFebsIdsArrayA", fnFebsIdsArrayGemA);
l->add("NrOfFebsInGemB", fuFebsInGemB);
l->add("nFebsIdsArrayB", fnFebsIdsArrayGemB);
l->add("NrOfFebsInRpc", fuFebsInRpc);
l->add("nFebsIdsArrayRpc", fnFebsIdsArrayRpc);
l->add("ChannelsToPadXA", fChannelsToPadXA);
l->add("ChannelsToPadYA", fChannelsToPadYA);
l->add("ChannelsToPadXB", fChannelsToPadXB);
l->add("ChannelsToPadYB", fChannelsToPadYB);
l->add("ChannelsToPadXRpc", fChannelsToPadXRpc);
l->add("ChannelsToPadYRpc", fChannelsToPadYRpc);
l->add("RealX", fRealX);
l->add("PadSize", fRealPadSize);
}
// -------------------------------------------------------------------------
bool MuchReadoutConfig::getParams(FairParamList* l)
{
if (!l) return false;
if (!l->fill("NrOfDpbs", &fuNrOfDpbs)) return false;
fiDbpIdArray.Set(fuNrOfDpbs);
if (!l->fill("DbpIdArray", &fiDbpIdArray)) return false;
fiCrobActiveFlag.Set(fuNrOfDpbs * kuNbCrobsPerDpb);
if (!l->fill("CrobActiveFlag", &fiCrobActiveFlag)) return false;
if (!l->fill("NrOfFebsInGemA", &fuFebsInGemA)) return false;
fnFebsIdsArrayGemA.Set(GetNrOfFebsInGemA());
if (!l->fill("nFebsIdsArrayA", &fnFebsIdsArrayGemA)) return false;
if (!l->fill("NrOfFebsInGemB", &fuFebsInGemB)) return false;
fnFebsIdsArrayGemB.Set(GetNrOfFebsInGemB());
if (!l->fill("nFebsIdsArrayB", &fnFebsIdsArrayGemB)) return false;
if (!l->fill("NrOfFebsInRpc", &fuFebsInRpc)) return false;
fnFebsIdsArrayRpc.Set(GetNrOfFebsInRpc());
if (!l->fill("nFebsIdsArrayRpc", &fnFebsIdsArrayRpc)) return false;
fChannelsToPadXA.Set(GetNrOfFebs() * kuNbChanPerAsic);
if (!l->fill("ChannelsToPadXA", &fChannelsToPadXA)) return false;
fChannelsToPadYA.Set(GetNrOfFebs() * kuNbChanPerAsic);
if (!l->fill("ChannelsToPadYA", &fChannelsToPadYA)) return false;
fChannelsToPadXB.Set(GetNrOfFebs() * kuNbChanPerAsic);
if (!l->fill("ChannelsToPadXB", &fChannelsToPadXB)) return false;
fChannelsToPadYB.Set(GetNrOfFebs() * kuNbChanPerAsic);
if (!l->fill("ChannelsToPadYB", &fChannelsToPadYB)) return false;
fChannelsToPadXRpc.Set(GetNrOfFebsInRpc() * kuNbChanPerAsic);
if (!l->fill("ChannelsToPadXRpc", &fChannelsToPadXRpc)) return false;
fChannelsToPadYRpc.Set(GetNrOfFebsInRpc() * kuNbChanPerAsic);
if (!l->fill("ChannelsToPadYRpc", &fChannelsToPadYRpc)) return false;
fRealX.Set(2232); // Number of Sectors in one GEM Module
if (!l->fill("RealX", &fRealX)) return false;
fRealPadSize.Set(2232); // Number of Sectors in one GEM Module
if (!l->fill("PadSize", &fRealPadSize)) return false;
return true;
}
*/
// -------------------------------------------------------------------------
int16_t MuchReadoutConfig::ElinkIdxToFebIdx(uint16_t uElink)
{
if (uElink < kuNbElinksPerCrob) return kiCrobMapElinkFebIdx[uElink];
else {
LOG(warning) << "MuchReadoutConfig::ElinkIdxToFebIdx => Index out of bound, "
<< "Elink is " << uElink << " returning crazy value!";
return -1;
}
}
// -------------------------------------------------------------------------
uint16_t MuchReadoutConfig::GetDpbId(uint16_t uDpbIdx)
{
if (uDpbIdx < fuNrOfDpbs) return fiDbpIdArray[uDpbIdx];
else {
LOG(warning) << "MuchReadoutConfig::GetDpbId => Index out of bound, "
<< "DPB Id is " << std::hex << uDpbIdx << " returning crazy value!";
return 0xFFFFFFFF;
}
}
bool MuchReadoutConfig::IsCrobActive(uint16_t uDpbIdx, uint16_t uCrobIdx)
{
if (uDpbIdx < fuNrOfDpbs) {
if (uCrobIdx < kuNbCrobsPerDpb) return 0 < fiCrobActiveFlag[uDpbIdx * kuNbCrobsPerDpb + uCrobIdx] ? true : false;
else {
LOG(warning) << "MuchReadoutConfig::IsCrobActive => Crob Index out of bound, "
<< "returning default inactive!";
return false;
}
}
else {
LOG(warning) << "MuchReadoutConfig::IsCrobActive => Dpb Index out of bound, "
<< "returning default inactive!";
return false;
}
}
bool MuchReadoutConfig::IsFebActive(uint16_t uFebInSystIdx)
{
if (uFebInSystIdx < GetNrOfFebs()) {
/// Always return true for now
return true;
}
else {
LOG(warning) << "MuchReadoutConfig::IsFebActive => Feb Index out of bound, "
<< "returning default inactive!";
return false;
}
}
bool MuchReadoutConfig::IsFebActive(uint16_t uDpbIdx, uint16_t uCrobIdx, uint16_t uFebIdx)
{
if (uDpbIdx < fuNrOfDpbs) {
if (uCrobIdx < kuNbCrobsPerDpb) {
if (uFebIdx < kuNbFebsPerCrob) {
uint16_t uIdx = (uDpbIdx * kuNbCrobsPerDpb + uCrobIdx) * kuNbFebsPerCrob + uFebIdx;
return IsFebActive(uIdx);
}
else {
LOG(warning) << "MuchReadoutConfig::IsFebActive => Feb Index out of bound, "
<< "returning default inactive!";
return false;
}
}
else {
LOG(warning) << "MuchReadoutConfig::IsFebActive => Crob Index out of bound, "
<< "returning default inactive!";
return false;
}
}
else {
LOG(warning) << "MuchReadoutConfig::IsFebActive => Dpb Index out of bound, "
<< "returning default inactive!";
return false;
}
}
int8_t MuchReadoutConfig::GetPadXA(uint8_t febid, uint8_t channelid)
{
if (fChannelsToPadXA.size() <= static_cast<int16_t>((febid * kuNbChanPerAsic) + channelid)) {
LOG(debug) << "MuchReadoutConfig::GetPadXA => Index out of bounds: " << ((febid * kuNbChanPerAsic) + channelid)
<< " VS " << fChannelsToPadXA.size() << " (" << febid << " and " << channelid << ")";
return -2;
}
return fChannelsToPadXA[(febid * kuNbChanPerAsic) + channelid];
}
int8_t MuchReadoutConfig::GetPadYA(uint8_t febid, uint8_t channelid)
{
if (fChannelsToPadYA.size() <= static_cast<int16_t>((febid * kuNbChanPerAsic) + channelid)) {
LOG(debug) << "MuchReadoutConfig::GetPadYA => Index out of bounds: " << ((febid * kuNbChanPerAsic) + channelid)
<< " VS " << fChannelsToPadYA.size() << " (" << febid << " and " << channelid << ")";
return -2;
}
return fChannelsToPadYA[(febid * kuNbChanPerAsic) + channelid];
}
int8_t MuchReadoutConfig::GetPadXB(uint8_t febid, uint8_t channelid)
{
if (fChannelsToPadXB.size() <= static_cast<int16_t>((febid * kuNbChanPerAsic) + channelid)) {
LOG(debug) << "MuchReadoutConfig::GetPadXB => Index out of bounds: " << ((febid * kuNbChanPerAsic) + channelid)
<< " VS " << fChannelsToPadXB.size() << " (" << febid << " and " << channelid << ")";
return -2;
}
return fChannelsToPadXB[(febid * kuNbChanPerAsic) + channelid];
}
int8_t MuchReadoutConfig::GetPadYB(uint8_t febid, uint8_t channelid)
{
if (fChannelsToPadYB.size() <= static_cast<int16_t>((febid * kuNbChanPerAsic) + channelid)) {
LOG(debug) << "MuchReadoutConfig::GetPadYB => Index out of bounds: " << ((febid * kuNbChanPerAsic) + channelid)
<< " VS " << fChannelsToPadYB.size() << " (" << febid << " and " << channelid << ")";
return -2;
}
return fChannelsToPadYB[(febid * kuNbChanPerAsic) + channelid];
}
int8_t MuchReadoutConfig::GetPadXRpc(uint8_t febid, uint8_t channelid)
{
if (fChannelsToPadXRpc.size() <= static_cast<int16_t>((febid * kuNbChanPerAsic) + channelid)) {
LOG(debug) << "CbmMcbm2018MuchPar::GetPadXRpc => Index out of bounds: " << ((febid * kuNbChanPerAsic) + channelid)
<< " VS " << fChannelsToPadXRpc.size() << " (" << febid << " and " << channelid << ")";
return -2;
}
return fChannelsToPadXRpc[(febid * kuNbChanPerAsic) + channelid];
}
int8_t MuchReadoutConfig::GetPadYRpc(uint8_t febid, uint8_t channelid)
{
if (fChannelsToPadYRpc.size() <= static_cast<int16_t>((febid * kuNbChanPerAsic) + channelid)) {
LOG(debug) << "CbmMcbm2018MuchPar::GetPadYRpc => Index out of bounds: " << ((febid * kuNbChanPerAsic) + channelid)
<< " VS " << fChannelsToPadYRpc.size() << " (" << febid << " and " << channelid << ")";
return -2;
}
return fChannelsToPadYRpc[(febid * kuNbChanPerAsic) + channelid];
}
int32_t MuchReadoutConfig::GetFebId(uint16_t uAsicIdx)
{
if (uAsicIdx >= GetNrOfFebsInGemA() && uAsicIdx < (GetNrOfFebsInGemA() + GetNrOfFebsInRpc())) //Check
return fnFebsIdsArrayRpc[uAsicIdx - GetNrOfFebsInGemA()]; //Check Vikas
else if (uAsicIdx >= (GetNrOfFebsInGemA() + GetNrOfFebsInRpc())
&& uAsicIdx < (GetNrOfFebsInGemA() + GetNrOfFebsInRpc() + GetNrOfFebsInGemB())) //Check
return fnFebsIdsArrayGemB[uAsicIdx - (GetNrOfFebsInGemA() + GetNrOfFebsInRpc())];
else if (uAsicIdx < GetNrOfFebsInGemA())
return fnFebsIdsArrayGemA[uAsicIdx];
else {
LOG(warning) << "MuchReadoutConfig::GetFebId => provided uAsicIdx : " << uAsicIdx
<< " not in the range of :" << (GetNrOfFebsInGemA() + GetNrOfFebsInRpc() + GetNrOfFebsInGemB())
<< "Returning large value -2";
return -2;
}
}
//GetModule() is not used in unpacker
uint16_t MuchReadoutConfig::GetModule(uint16_t uAsicIdx)
{
if (uAsicIdx >= GetNrOfFebsInGemA()) {
if ((uAsicIdx % GetNrOfFebsInGemA()) < GetNrOfFebsInRpc()) return 1;
else
return 2;
}
else
return 0;
}
double MuchReadoutConfig::GetRealX(int16_t SectorIndex)
{
if (SectorIndex < 0 || SectorIndex <= 97) {
LOG(debug) << "MuchReadoutConfig::GetRealX => Index out of bounds: ";
return -2;
}
return fRealX[SectorIndex];
}
double MuchReadoutConfig::GetRealPadSize(int16_t SectorIndex)
{
if (SectorIndex < 0 || SectorIndex <= 97) {
LOG(debug) << "MuchReadoutConfig::GetRealX => Index out of bounds: ";
return -2;
}
return fRealPadSize[SectorIndex];
}
double MuchReadoutConfig::GetRealX(int16_t Channel, int16_t Sector)
{
int16_t PadIndex = Channel + 97 * Sector;
if (Channel < 0 || Sector < 0) return -2;
if (fRealX.size() <= PadIndex) {
LOG(info) << "MuchReadoutConfig::GetRealX => Index out of bounds: " << Channel << " " << Sector << " "
<< PadIndex;
return -1;
}
return fRealX[PadIndex];
}
double MuchReadoutConfig::GetRealPadSize(int16_t Channel, int16_t Sector)
{
int16_t PadIndex = Channel + 97 * Sector;
if (Channel < 0 || Sector < 0) return -2;
if (fRealPadSize.size() <= PadIndex) {
LOG(info) << "MuchReadoutConfig::GetRealPadSize => Index out of bounds: " << Channel << " " << Sector << " "
<< PadIndex;
return -1;
}
return fRealPadSize[PadIndex];
}
} /* namespace cbm::algo */
/* Copyright (C) 2021 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
SPDX-License-Identifier: GPL-3.0-only
Authors: Florian Uhlig [committer] */
// -------------------------------------------------------------------------
// ----- MuchReadoutConfig header file -----
// ----- Created 22/02/22 by P.-A. Loizeau -----
// ----- Modified 07/12/18 by A Kumar -----
// -------------------------------------------------------------------------
#ifndef ALGO_DETECTORS_MUCH_MUCHREADOUTCONFIG_H
#define ALGO_DETECTORS_MUCH_MUCHREADOUTCONFIG_H
//#include "FairParGenericSet.h"
#include <cstdint>
#include <vector>
//#include "TArrayD.h"
//#include "TArrayI.h"
//class FairParIo;
//class FairParamList;
namespace cbm::algo
{
//class MuchReadoutConfig : public FairParGenericSet {
class MuchReadoutConfig {
public:
/** Standard constructor **/
MuchReadoutConfig() {};
/** Destructor **/
~MuchReadoutConfig() {};
/** Reset all parameters **/
virtual void clear();
/*
void putParams(FairParamList*);
bool getParams(FairParamList*);
*/
static constexpr uint16_t GetNbCrobsPerDpb() { return kuNbCrobsPerDpb; }
static constexpr uint16_t GetNbElinkPerCrob() { return kuNbElinksPerCrob; }
static constexpr uint16_t GetNbElinkPerDpb() { return kuNbCrobsPerDpb * kuNbElinksPerCrob; }
static constexpr uint16_t GetNbFebsPerCrob() { return kuNbFebsPerCrob; }
static constexpr uint16_t GetNbFebsPerDpb() { return kuNbCrobsPerDpb * kuNbFebsPerCrob; }
static constexpr uint16_t GetNbAsicsPerFeb() { return kuNbAsicsPerFeb; }
static constexpr uint16_t GetNbAsicsPerCrob() { return kuNbFebsPerCrob * kuNbAsicsPerFeb; }
static constexpr uint16_t GetNbAsicsPerDpb() { return kuNbCrobsPerDpb * GetNbAsicsPerCrob(); }
static constexpr uint16_t GetNbChanPerAsic() { return kuNbChanPerAsic; }
static constexpr uint16_t GetNbChanPerFeb() { return kuNbAsicsPerFeb * kuNbChanPerAsic; }
//! Convert from eLink index to FEB Connection ( 0 to kuNbFebsPerCrob)
int16_t ElinkIdxToFebIdx(uint16_t uElink);
uint16_t GetNrOfDpbs() { return fuNrOfDpbs; }
uint16_t GetDpbId(uint16_t uDpbIdx);
uint16_t GetNrOfCrobs() { return fuNrOfDpbs * kuNbCrobsPerDpb; }
uint16_t GetNrOfFebs() { return GetNrOfCrobs() * kuNbFebsPerCrob; }
uint16_t GetNrOfAsics() { return GetNrOfFebs() * kuNbAsicsPerFeb; }
uint16_t GetNrOfFebsInGemA() { return fuFebsInGemA; }
uint16_t GetNrOfFebsInGemB() { return fuFebsInGemB; }
int16_t GetNrOfChannels() { return kuNbChanPerAsic; }
int32_t GetFebId(uint16_t);
uint16_t GetModule(uint16_t);
int8_t GetPadXA(uint8_t febid, uint8_t channelid);
int8_t GetPadYA(uint8_t febid, uint8_t channelid);
int8_t GetPadXB(uint8_t febid, uint8_t channelid);
int8_t GetPadYB(uint8_t febid, uint8_t channelid);
double GetRealX(int16_t);
double GetRealPadSize(int16_t);
double GetRealX(int16_t Channel, int16_t Sector);
double GetRealPadSize(int16_t Channel, int16_t Sector);
//RPC Module Related Functions
uint16_t GetNrOfFebsInRpc() { return fuFebsInRpc; }
int8_t GetPadXRpc(uint8_t febid, uint8_t channelid);
int8_t GetPadYRpc(uint8_t febid, uint8_t channelid);
bool IsCrobActive(uint16_t uDpbIdx, uint16_t uCrobIdx);
bool IsFebActive(uint16_t uFebInSystIdx);
bool IsFebActive(uint16_t uDpbIdx, uint16_t uCrobIdx, uint16_t uFebIdx);
bool IsFebPulser(uint16_t uFebInSystIdx);
bool IsFebPulser(uint16_t uDpbIdx, uint16_t uCrobIdx, uint16_t uFebIdx);
double GetFebAdcGain(uint16_t uDpbIdx, uint16_t uCrobIdx, uint16_t uFebIdx);
double GetFebAdcOffset(uint16_t uDpbIdx, uint16_t uCrobIdx, uint16_t uFebIdx);
private:
/// Constants
static const uint16_t kuNbCrobsPerDpb = 1; // Number of CROBs possible per DPB
static const uint16_t kuNbElinksPerCrob = 42; // Number of elinks in each CROB ?
static const uint16_t kuNbFebsPerCrob = 9; // Number of FEBs connected to each CROB for mMuch 2019
static const uint16_t kuNbAsicsPerFeb = 1; // Number of ASICs connected in each FEB for MUCH
static const uint16_t kuNbChanPerAsic = 128; // Number of channels in each ASIC
// static constexpr uint16_t kuCrobMapElinkFebIdx[ kuNbElinksPerCrob ] = {
const int16_t kiCrobMapElinkFebIdx[kuNbElinksPerCrob] = {0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2,
3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5,
6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 8, 8, 8, 8};
//! Map from eLink index to ASIC index within CROB ( 0 to kuNbFebsPerCrob * kuNbAsicPerFeb )
/// Variables
uint16_t fuNrOfDpbs = 0; // Total number of MUCH DPBs in system
std::vector<int16_t> fiDbpIdArray; // Array to hold the unique IDs (equipment ID) for all MUCH DPBs
std::vector<int16_t> fiCrobActiveFlag; // Array to hold the active flag for all CROBs, [ NbDpb * kuNbCrobPerDpb ]
uint16_t fuFebsInGemA = 0; // Number of FEBs connected in GEM Module A
uint16_t fuFebsInGemB = 0; // Number of FEBs connected in GEM Module B
uint16_t fuFebsInRpc = 0; // Number of FEBs connected in RPC Module
std::vector<int16_t> fnFebsIdsArrayGemA; // Array to hold FEB IDs connected to GEM Module A
std::vector<int16_t> fnFebsIdsArrayGemB; // Array to hold FEB IDs connected to GEM Module B
std::vector<int16_t> fnFebsIdsArrayRpc; // Array to hold FEB IDs connected to RPC Module
std::vector<int16_t> fChannelsToPadXA; // Array which stores the corresponding x position of PAD of entire module A
std::vector<int16_t> fChannelsToPadYA; // Array which stores the corresponding y position of PAD of entire module A
std::vector<int16_t> fChannelsToPadXB; // Array which stores the corresponding x position of PAD of entire module B
std::vector<int16_t> fChannelsToPadYB; // Array which stores the corresponding y position of PAD of entire module B
std::vector<int16_t> fChannelsToPadXRpc; // Array which stores the corresponding x position of PAD of RPC module
std::vector<int16_t> fChannelsToPadYRpc; // Array which stores the corresponding y position of PAD of RPC module
std::vector<double> fRealX; // Array which stores the Real X (starting 18.733 cm) position of PAD
std::vector<double> fRealPadSize; // Array which stores the Real Progressive size of each padX (starting .327 cm )
};
} /* namespace cbm::algo */
#endif // ALGO_DETECTORS_MUCH_MUCHREADOUTCONFIG_H
/* Copyright (C) 2021 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
SPDX-License-Identifier: GPL-3.0-only
Authors: Pierre-Alain Loizeau, Volker Friese [committer] */
#include "UnpackMuch.h"
#include <cassert>
#include <utility>
#include <vector>
#include <cmath>
#include "StsXyterMessage.h"
using std::unique_ptr;
using std::vector;
namespace cbm::algo
{
// ---- Algorithm execution ---------------------------------------------
UnpackMuch::resultType UnpackMuch::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.
const uint64_t epochLengthInNs = fkEpochLength * fkClockCycleNom / fkClockCycleDen;
fCurrentTsTime = tTimeslice / epochLengthInNs;
// --- Current TS_MSB epoch cycle
auto const msTime = msDescr.idx; // Unix time of MS in ns
fCurrentCycle = std::ldiv(msTime, fkCycleLength).quot;
// --- Number of messages in microslice
auto msSize = msDescr.size;
if (msSize % sizeof(stsxyter::Message) != 0) {
result.second.fNumErrInvalidMsSize++;
return result;
}
const uint32_t numMessages = msSize / sizeof(stsxyter::Message);
if (numMessages < 2) {
result.second.fNumErrInvalidMsSize++;
return result;
}
// --- Interpret MS content as sequence of SMX messages
auto message = reinterpret_cast<const stsxyter::Message*>(msContent);
// --- The first message in the MS is expected to be of type EPOCH and can be ignored.
if (message[0].GetMessType() != stsxyter::MessType::Epoch) {
result.second.fNumErrInvalidFirstMessage++;
return result;
}
// --- The second message must be of type ts_msb.
if (message[1].GetMessType() != stsxyter::MessType::TsMsb) {
result.second.fNumErrInvalidFirstMessage++;
return result;
}
ProcessTsmsbMessage(message[1]);
// --- Message loop
for (uint32_t messageNr = 2; messageNr < numMessages; messageNr++) {
// --- Action depending on message type
switch (message[messageNr].GetMessType()) {
case stsxyter::MessType::Hit: {
ProcessHitMessage(message[messageNr], result.first, result.second);
break;
}
case stsxyter::MessType::TsMsb: {
ProcessTsmsbMessage(message[messageNr]);
break;
}
default: {
result.second.fNumNonHitOrTsbMessage++;
break;
}
} //? Message type
} //# Messages
return result;
}
// --------------------------------------------------------------------------
// ----- Process hit message --------------------------------------------
inline void UnpackMuch::ProcessHitMessage(const stsxyter::Message& message, vector<CbmMuchDigi>& digiVec,
UnpackMuchMonitorData& monitor) const
{
// --- Check eLink and get parameters
uint16_t elink = message.GetLinkIndexHitBinning();
if (elink >= fParams.fElinkParams.size()) {
monitor.fNumErrElinkOutOfRange++;
return;
}
const UnpackMuchElinkPar& elinkPar = fParams.fElinkParams.at(elink);
uint32_t asicNr = elinkPar.fAsicNr;
// --- Hardware-to-software address
uint32_t numChansPerModule = fParams.fNumAsicsPerModule * fParams.fNumChansPerAsic;
uint32_t address = elinkPar.fAddress;
uint32_t channel = 0;
if (asicNr < fParams.fNumAsicsPerModule / 2) { // front side (n side)
channel = message.GetHitChannel() + fParams.fNumChansPerAsic * asicNr;
}
else { // back side (p side)
channel = numChansPerModule - message.GetHitChannel() + 1;
}
// --- Expand time stamp to time within timeslice (in clock cycle)
uint64_t messageTime = message.GetHitTimeBinning() + fCurrentEpochTime;
// --- Convert time stamp from clock cycles to ns. Round to nearest full ns.
messageTime = (messageTime * fkClockCycleNom + fkClockCycleDen / 2) / fkClockCycleDen;
// --- Correct ASIC-wise offsets
messageTime -= elinkPar.fTimeOffset;
// --- TODO: Add walk correction (depends on ADC)
// --- Charge
double charge = elinkPar.fAdcOffset + (message.GetHitAdc() - 1) * elinkPar.fAdcGain;
// --- Create output digi
// digiVec.emplace_back(address, channel, messageTime, charge);
}
// --------------------------------------------------------------------------
// ----- Process an epoch (TS_MSB) message ------------------------------
inline void UnpackMuch::ProcessTsmsbMessage(const stsxyter::Message& message)
{
// The compression of time is based on the hierarchy epoch cycle - epoch - message time.
// Cycles are counted from the start of Unix time and are multiples of an epoch (ts_msb).
// The epoch number is counted within each cycle. The time in the hit message is expressed
// in units of the readout clock cycle relative to the current epoch.
// The ts_msb message indicates the start of a new epoch. Its basic information is the epoch
// number within the current cycle. A cycle wrap resets the epoch number to zero, so it is
// indicated by the epoch number being smaller than the previous one (epoch messages are
// seemingly not consecutively in the data stream, but only if there are hit messages in between).
auto epoch = message.GetTsMsbValBinning();
// --- Cycle wrap
if (epoch < fCurrentEpoch) fCurrentCycle++;
// --- Update current epoch counter
fCurrentEpoch = epoch;
// --- Calculate epoch time in clocks cycles relative to timeslice start time
fCurrentEpochTime = (fCurrentCycle * fkEpochsPerCycle + epoch - fCurrentTsTime) * fkEpochLength;
}
// --------------------------------------------------------------------------
} /* namespace cbm::algo */
/* Copyright (C) 2021 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
SPDX-License-Identifier: GPL-3.0-only
Authors: Pierre-Alain Loizeau, Volker Friese [committer] */
#ifndef CBM_ALGO_UNPACKMUCH_H
#define CBM_ALGO_UNPACKMUCH_H 1
#include "CbmMuchDigi.h"
#include "MicrosliceDescriptor.hpp"
#include "Timeslice.hpp"
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <memory>
#include <vector>
#include "StsXyterMessage.h"
namespace cbm::algo
{
/** @struct UnpackMuchElinkPar
** @author Volker Friese <v.friese@gsi.de>
** @since 25 November 2021
** @brief STS Unpacking parameters for one eLink / ASIC
**/
struct UnpackMuchElinkPar {
int32_t fAddress = 0; ///< CbmMuchAddress for the connected module
uint32_t fAsicNr = 0; ///< Number of connected ASIC within the module
uint64_t fTimeOffset = 0.; ///< Time calibration parameter
double fAdcOffset = 0.; ///< Charge calibration parameter
double fAdcGain = 0.; ///< Charge calibration parameter
};
/** @struct UnpackMuchPar
** @author Volker Friese <v.friese@gsi.de>
** @since 25 November 2021
** @brief Parameters required for the STS unpacking (specific to one component)
**/
struct UnpackMuchPar {
uint32_t fNumChansPerAsic = 0; ///< Number of channels per ASIC
uint32_t fNumAsicsPerModule = 0; ///< Number of ASICS per module
std::vector<UnpackMuchElinkPar> fElinkParams = {}; ///< Parameters for each eLink
};
/** @struct UnpackMuchMoni
** @author Volker Friese <v.friese@gsi.de>
** @since 2 December 2021
** @brief Monitoring data for STS unpacking
**/
struct UnpackMuchMonitorData {
uint32_t fNumNonHitOrTsbMessage = 0;
uint32_t fNumErrElinkOutOfRange = 0; ///< Elink not contained in parameters
uint32_t fNumErrInvalidFirstMessage = 0; ///< First message is not TS_MSB or second is not EPOCH
uint32_t fNumErrInvalidMsSize = 0; ///< Microslice size is not multiple of message size
uint32_t fNumErrTimestampOverflow = 0; ///< Overflow in 64 bit time stamp
bool HasErrors()
{
uint32_t numErrors = fNumNonHitOrTsbMessage + fNumErrElinkOutOfRange + fNumErrInvalidFirstMessage
+ fNumErrInvalidMsSize + fNumErrTimestampOverflow;
return (numErrors > 0 ? true : false);
}
};
/** @class UnpackMuch
** @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 UnpackMuch {
public:
typedef std::pair<std::vector<CbmMuchDigi>, UnpackMuchMonitorData> resultType;
/** @brief Default constructor **/
UnpackMuch() {};
/** @brief Destructor **/
~UnpackMuch() {};
/** @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<UnpackMuchPar> 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 stsxyter::Message& message, std::vector<CbmMuchDigi>& digiVec,
UnpackMuchMonitorData& monitor) const;
/** @brief Process an epoch message (TS_MSB)
** @param message SMX message (32-bit word)
**/
void ProcessTsmsbMessage(const stsxyter::Message& message);
private: // members
uint64_t fCurrentTsTime = 0; ///< Unix time of timeslice in units of epoch length
uint64_t fCurrentCycle = 0; ///< Current epoch cycle
uint32_t fCurrentEpoch = 0; ///< Current epoch number within epoch cycle
uint64_t fCurrentEpochTime = 0; ///< Current epoch time relative to timeslice in clock cycles
UnpackMuchPar fParams = {}; ///< Parameter container
/** Number of TS_MSB epochs per cycle **/
static constexpr uint64_t fkEpochsPerCycle = stsxyter::kuTsMsbNbTsBinsBinning;
/** Length of TS_MSB epoch in clock cycles **/
static constexpr uint64_t fkEpochLength = stsxyter::kuHitNbTsBinsBinning;
/** Clock cycle nominator [ns] and denominator. The clock cycle in ns is nominator / denominator. **/
static constexpr uint32_t fkClockCycleNom = stsxyter::kulClockCycleNom;
static constexpr uint32_t fkClockCycleDen = stsxyter::kulClockCycleDen;
/** Epoch cycle length in ns **/
static constexpr uint64_t fkCycleLength = (fkEpochsPerCycle * fkEpochLength * fkClockCycleNom) / fkClockCycleDen;
};
} /* namespace cbm::algo */
#endif /* CBM_ALGO_UNPACKSTS_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