Skip to content
Snippets Groups Projects
Commit 46213614 authored by Volker Friese's avatar Volker Friese Committed by Jan de Cuveland
Browse files

First, boiled-down version of STS unpack algorithm. Neglects all monitoring...

First, boiled-down version of STS unpack algorithm. Neglects all monitoring and exception catching. Refs #2268.
parent 4585ae97
No related branches found
No related tags found
1 merge request!750Initial version of STS unpacker algo plus integration by task. Refs #2268. Refs #2272.
......@@ -6,6 +6,7 @@ add_subdirectory (test)
set(SRCS
evbuild/EventBuilder.cxx
trigger/TimeClusterTrigger.cxx
detectors/sts/UnpackSts.cxx
)
add_library(Algo SHARED ${SRCS})
......
/* Copyright (C) 2021 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
SPDX-License-Identifier: GPL-3.0-only
Authors: Pierre-Alain Loizeau, Volker Friese [committer] */
#include "UnpackSts.h"
#include <cassert>
#include <vector>
#include <cmath>
#include "StsXyterMessage.h"
using std::vector;
namespace cbm::algo
{
// ---- Algorithm execution ---------------------------------------------
vector<CbmStsDigi> UnpackSts::operator()(const uint8_t* msContent, const fles::MicrosliceDescriptor& msDescr,
const uint64_t tTimeslice)
{
// --- Assert that parameters are set
assert(fParams);
fCurrentTsTime = tTimeslice;
// --- Output vector
vector<CbmStsDigi> digiVec;
// --- Current TS_MSB epoch cycle
auto msTime = msDescr.idx; // Unix time of MS in ns
fCurrentCycle = std::ldiv(msTime, fCycleLength).quot;
// --- Get first TS_MSB (first message in microslice must be of type ts_msb)
const stsxyter::Message firstMessage(msContent[0]);
assert(firstMessage.GetMessType() == stsxyter::MessType::TsMsb);
ProcessTsmsbMessage(firstMessage);
// --- Number of messages in microslice
auto msSize = msDescr.size;
assert(msSize % sizeof(stsxyter::Message) == 0);
const uint32_t numMessages = msSize / sizeof(stsxyter::Message);
// --- Message loop
for (uint32_t messageNr = 1; messageNr < numMessages; messageNr++) {
// --- Cast MS content to STSXYTER message
const stsxyter::Message message(msContent[messageNr]);
const stsxyter::MessType type = message.GetMessType();
// --- Action depending on message type
switch (type) {
case stsxyter::MessType::Hit: {
ProcessHitMessage(message, digiVec);
break;
}
case stsxyter::MessType::TsMsb: {
ProcessTsmsbMessage(message);
break;
}
default: {
break;
}
} //? Message type
} //# Messages
return digiVec;
}
// --------------------------------------------------------------------------
// ----- Process hit message --------------------------------------------
void UnpackSts::ProcessHitMessage(const stsxyter::Message& message, vector<CbmStsDigi>& digiVec) const
{
uint16_t elink = message.GetLinkIndexHitBinning();
const UnpackStsElinkPar& elinkPar = fParams->GetElinkPar(elink);
uint32_t asicNr = elinkPar.fAsicNr;
uint32_t numChansPerModule = fParams->fNumAsicsPerModule * fParams->fNumChansPerAsic;
// --- Hardware-to-software address
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;
}
// --- Time stamp
// --- Expand to full Unix time in clock cycles
uint64_t timeCC = message.GetHitTimeBinning() + fCurrentEpochTime;
// --- Convert time into ns
assert(timeCC >> 59 == 0); // avoid overflow in 64 bit
uint64_t timeNs = (timeCC * fParams->fClockCycleNom) / fParams->fClockCycleDen;
// --- Correct ASIC-wise offsets
timeNs -= elinkPar.fTimeOffset;
// --- Calculate time relative to timeslice
timeNs -= fCurrentTsTime;
// --- 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, timeNs, charge);
}
// --------------------------------------------------------------------------
// ----- Process an epoch (TS_MSB) message ------------------------------
void UnpackSts::ProcessTsmsbMessage(const stsxyter::Message& message)
{
auto epoch = message.GetTsMsbValBinning();
// --- Cycle wrap
if (epoch < fCurrentEpoch) fCurrentCycle++;
// --- Update current epoch
fCurrentEpoch = epoch;
fCurrentEpochTime = (fCurrentCycle * fParams->fEpochsPerCycle + epoch) * fParams->fEpochLength;
}
// --------------------------------------------------------------------------
} /* 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_UNPACKSTS_H
#define CBM_ALGO_UNPACKSTS_H 1
#include "CbmStsDigi.h"
#include "MicrosliceDescriptor.hpp"
#include "Timeslice.hpp"
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <memory>
#include <vector>
#include "StsXyterMessage.h"
namespace cbm::algo
{
/** @struct UnpackStsAsicPar
** @author Volker Friese <v.friese@gsi.de>
** @since 25 November 2021
** @brief Unpacking parameters for one eLink / ASIC
**/
struct UnpackStsElinkPar {
uint32_t fAddress = 0; ///< CbmStsAddress 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 UnpackStsPar
** @author Volker Friese <v.friese@gsi.de>
** @since 25 November 2021
** @brief Parameters required for the STS unpacking (specific to one component)
**/
struct UnpackStsPar {
uint32_t fNumChansPerAsic = 0; ///< Number of channels per ASIC
uint32_t fNumAsicsPerModule = 0; ///< Number of ASICS per module
uint64_t fEpochsPerCycle = 0; ///< TS_MSB epochs per epoch cycle
uint64_t fEpochLength = 0; ///< Length of TS_MSB epoch in clock cycles
uint32_t fClockCycleNom = 0; ///< Clock cycle nominator [ns]
uint32_t fClockCycleDen = 0.; ///< Clock cycle denominator
std::vector<UnpackStsElinkPar> fElinkParams; ///< Parameters for each eLink
size_t GetNumElinks() const { return fElinkParams.size(); }
const UnpackStsElinkPar& GetElinkPar(size_t eLink) const
{
assert(eLink < GetNumElinks());
return fElinkParams[eLink];
}
};
/** @class UnpackSts
** @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 UnpackSts {
public:
/** @brief Default constructor **/
UnpackSts() {};
/** @brief Destructor **/
~UnpackSts() {};
/** @brief Algorithm execution
** @param msContent Microslice payload
** @param msDescr Microslice descriptor
** @param tTimeslice Unix start time of timeslice [ns]
** @return STS digi data
**/
std::vector<CbmStsDigi> 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<UnpackStsPar> params)
{
fParams = std::move(params);
fCycleLength = (fParams->fEpochsPerCycle * fParams->fEpochLength * fParams->fClockCycleNom);
fCycleLength /= fParams->fClockCycleDen;
}
private:
/** @brief Process an epoch message (TS_MSB)
** @param message SMX message (32-bit word)
** @param digiVec Vector to append the created digi to
**/
void ProcessTsmsbMessage(const stsxyter::Message& message);
/** @brief Process a hit message
** @param message SMX message (32-bit word)
** @param digiVec Vector to append the created digi to
**/
void ProcessHitMessage(const stsxyter::Message& message, std::vector<CbmStsDigi>& digiVec) const;
private:
uint64_t fCurrentTsTime = 0; ///< Unix time of timeslice in ns
uint64_t fCurrentCycle = 0; ///< Current epoch cycle
uint32_t fCurrentEpoch = 0; ///< Current epoch number within epoch cycle
uint64_t fCurrentEpochTime = 0; ///< Unix time of current epoch in clock cycles
uint64_t fCycleLength = 0; ///< Epoch cycle length in ns
std::unique_ptr<UnpackStsPar> fParams = nullptr; ///< Parameter container
};
} /* 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