From 358fdb232d99db3294c4b6c5898ea79bdc2ad1fa Mon Sep 17 00:00:00 2001 From: P-A Loizeau <p.-a.loizeau@gsi.de> Date: Fri, 16 Jul 2021 22:20:53 +0200 Subject: [PATCH] Add new raw data class for TOF CRI + Printout class and macro --- core/data/CMakeLists.txt | 1 + core/data/DataLinkDef.h | 2 + core/data/raw/CriGet4Mess001.cxx | 434 ++++++++++++++++++ core/data/raw/CriGet4Mess001.h | 385 ++++++++++++++++ fles/mcbm2018/CMakeLists.txt | 1 + fles/mcbm2018/CbmFlibMcbm2018LinkDef.h | 1 + fles/mcbm2018/unpacker/CbmCriGet4RawPrint.cxx | 316 +++++++++++++ fles/mcbm2018/unpacker/CbmCriGet4RawPrint.h | 78 ++++ macro/beamtime/mcbm2021/print_tsa_tof_data.C | 85 ++++ 9 files changed, 1303 insertions(+) create mode 100644 core/data/raw/CriGet4Mess001.cxx create mode 100644 core/data/raw/CriGet4Mess001.h create mode 100644 fles/mcbm2018/unpacker/CbmCriGet4RawPrint.cxx create mode 100644 fles/mcbm2018/unpacker/CbmCriGet4RawPrint.h create mode 100644 macro/beamtime/mcbm2021/print_tsa_tof_data.C diff --git a/core/data/CMakeLists.txt b/core/data/CMakeLists.txt index d9937f36f5..a0f1b2f63c 100644 --- a/core/data/CMakeLists.txt +++ b/core/data/CMakeLists.txt @@ -120,6 +120,7 @@ set(SRCS raw/StsXyterMessage.cxx raw/gDpbMessv100.cxx + raw/CriGet4Mess001.cxx raw/TimesliceMetaData.cxx raw/PsdGbtReader-v0.00.cxx raw/PsdGbtReader-v1.00.cxx diff --git a/core/data/DataLinkDef.h b/core/data/DataLinkDef.h index 40247ce74e..ac3e3775a2 100644 --- a/core/data/DataLinkDef.h +++ b/core/data/DataLinkDef.h @@ -96,6 +96,8 @@ #pragma link C++ class stsxyter::Message; #pragma link C++ class gdpbv100::Message; #pragma link C++ class gdpbv100::FullMessage; +#pragma link C++ class critof001::Message; +#pragma link C++ class critof001::FullMessage; #pragma link C++ class TimesliceMetaData; #pragma link C++ class PsdDataV000::PsdGbtReader; #pragma link C++ class PsdDataV100::PsdGbtReader; diff --git a/core/data/raw/CriGet4Mess001.cxx b/core/data/raw/CriGet4Mess001.cxx new file mode 100644 index 0000000000..6ac30af551 --- /dev/null +++ b/core/data/raw/CriGet4Mess001.cxx @@ -0,0 +1,434 @@ +/* Copyright (C) 2018-2020 Facility for Antiproton and Ion Research in Europe, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Pierre-Alain Loizeau [committer] */ + +#include "CriGet4Mess001.h" + +// Specific headers + +// C++11 headers +#include <cmath> + +// std C++ lib headers +#include <iomanip> +#include <iostream> +#include <sstream> + +#include <stdio.h> +#include <string.h> + +//#include <iostream> +#include <iomanip> + +//---------------------------------------------------------------------------- +/** + ** Clone of the functions in the flestool library to avoid circular dependencies + ** Replaces the following block of code which generate warnings depending on the OS + Form( "%llx", static_cast<uint64_t>(val) ); + Form( "%lx", static_cast<uint64_t>(val) ); + Form( "%0llx", static_cast<uint64_t>(val) ); + Form( "%0lx", static_cast<uint64_t>(val) ); + Form( "%016llx", static_cast<uint64_t>(val) ); + Form( "%016lx", static_cast<uint64_t>(val) ); + **/ +namespace critof001 +{ + std::string FormatHexPrintout(uint64_t ulVal, char cFill = 0, uint uWidth = 0, bool bUppercase = false) + { + std::stringstream ss; + + /// Set hex printout mode + ss << std::hex; + + /// Set fill character and/or width if provided by user + if (0 != cFill) ss << std::setfill(cFill); + if (0 < uWidth) ss << std::setw(uWidth); + if (bUppercase) ss << std::uppercase; + + /// push value + ss << ulVal << std::dec; + + /// Restore fill character if needed + if (0 != cFill) ss << std::setfill(' '); + + return ss.str(); + } +} // namespace critof001 + +//---------------------------------------------------------------------------- +//! strict weak ordering operator, assumes same epoch for both messages +bool critof001::Message::operator<(const critof001::Message& other) const +{ + uint64_t uThisTs = 0; + uint64_t uOtherTs = 0; + + uint32_t uThisType = this->getMessageType(); + uint32_t uOtherType = other.getMessageType(); + + // if both GET4 hit messages, use the full timestamp info + if (MSG_HIT == uThisType && MSG_HIT == uOtherType) { + uThisTs = this->getGdpbHitFullTs(); + uOtherTs = other.getGdpbHitFullTs(); + return uThisTs < uOtherTs; + } // both GET4 hit (32b or 24b) + + // First find the timestamp of the current message + if (MSG_HIT == uThisType) { uThisTs = (this->getGdpbHitFullTs()); } // if Hit GET4 message (24 or 32b) + else + uThisTs = 0; + + // Then find the timestamp of the current message + if (MSG_HIT == uOtherType) { uOtherTs = (this->getGdpbHitFullTs()); } // if Hit GET4 message (24 or 32b) + else + uOtherTs = 0; + + return uThisTs < uOtherTs; +} +//---------------------------------------------------------------------------- +//! equality operator, assumes same epoch for both messages +bool critof001::Message::operator==(const critof001::Message& other) const { return this->data == other.data; } +//---------------------------------------------------------------------------- +//! inequality operator, assumes same epoch for both messages +bool critof001::Message::operator!=(const critof001::Message& other) const { return this->data != other.data; } +//---------------------------------------------------------------------------- +//! Returns expanded and adjusted time of message (in ns) +uint64_t critof001::Message::getMsgFullTime(uint64_t epoch) const { return std::round(getMsgFullTimeD(epoch)); } +//---------------------------------------------------------------------------- +//! Returns expanded and adjusted time of message in double (in ns) +double critof001::Message::getMsgFullTimeD(uint64_t epoch) const +{ + switch (getMessageType()) { + case MSG_HIT: { + if (getGdpbHitIs24b()) + return (static_cast<double_t>(FullTimeStamp(epoch, (getGdpbHitCoarse() << 7))) + + (static_cast<double_t>(getGdpbHitFineTs() - 8.) * critof001::kdFtSize / critof001::kdFtBinsNb)) + * (critof001::kdClockCycleSizeNs / critof001::kdFtSize); + else + return (critof001::kdEpochInNs * static_cast<double_t>(epoch) + + static_cast<double_t>(getGdpbHitFullTs()) * critof001::kdClockCycleSizeNs / critof001::kdFtBinsNb); + } // case MSG_HIT: + case MSG_EPOCH: return critof001::kdEpochInNs * static_cast<double_t>(getGdpbEpEpochNb()); + case MSG_SLOWC: + case MSG_SYST: + case MSG_STAR_TRI_A: + case MSG_STAR_TRI_B: + case MSG_STAR_TRI_C: + case MSG_STAR_TRI_D: return critof001::kdEpochInNs * static_cast<double_t>(epoch); + default: return 0.0; + } // switch( getMessageType() ) + + // If not already dealt with => unknown type + return 0.0; +} +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +//! Returns the time difference between two expanded time stamps + +uint64_t critof001::Message::CalcDistance(uint64_t start, uint64_t stop) +{ + if (start > stop) { + stop += 0x3FFFFFFFFFFFLLU; + if (start > stop) { + printf("Epochs overflow error in CalcDistance\n"); + return 0; + } + } + + return stop - start; +} + + +//---------------------------------------------------------------------------- +//! Returns the time difference between two expanded time stamps + +double critof001::Message::CalcDistanceD(double start, double stop) +{ + if (start > stop) { + stop += 0x3FFFFFFFFFFFLLU; + if (start > stop) { + printf("Epochs overflow error in CalcDistanceD\n"); + return 0.; + } + } + + return stop - start; +} + +//---------------------------------------------------------------------------- +//! Print message in human readable format to \a cout. +/*! + * Prints a one line representation of the message in to \a cout. + * See printData(std::ostream&, unsigned, uint32_t) const for full + * documentation. + */ + +void critof001::Message::printDataCout(unsigned kind, uint32_t epoch) const { printData(msg_print_Cout, kind, epoch); } + +//---------------------------------------------------------------------------- +//! Print message in human readable format to the Fairroot logger. +/*! + * Prints a one line representation of the message in to the Fairroot logger. + * TODO: Add coloring of possible + * See printData(std::ostream&, unsigned, uint32_t) const for full + * documentation. + */ + +void critof001::Message::printDataLog(unsigned kind, uint32_t epoch) const { printData(msg_print_FairLog, kind, epoch); } + +//---------------------------------------------------------------------------- +//! Print message in binary or human readable format to a stream. +/*! + * Prints a one line representation of the message in to a stream, selected by \a outType. + * The stream is \a cout if \a outType is kFALSE and \a FairLogger if \a outType is kTRUE. + * The parameter \a kind is mask with 4 bits + * \li critof001::msg_print_Prefix (1) - message type + * \li critof001::msg_print_Data (2) - print all message specific data fields + * \li critof001::msg_print_Hex (4) - print data as hex dump + * \li critof001::msg_print_Human (8) - print in human readable format + * + * If bit msg_print_Human in \a kind is not set, raw format + * output is generated. All data fields are shown in hexadecimal. + * This is the format of choice when chasing hardware problems at the bit level. + * + * If bit msg_print_Human is set, a more human readable output is generated. + * The timestamp is shown as fully extended and adjusted time as + * returned by the getMsgFullTime(uint32_t) const method. + * All data fields are represented in decimal. + * + * \param os output stream + * \param kind mask determing output format + * \param epoch current epoch number (from last epoch message) + * + */ + +//void critof001::Message::printData(std::ostream& os, unsigned kind, uint32_t epoch) const +void critof001::Message::printData(unsigned outType, unsigned kind, uint32_t epoch, std::ostream& os) const +{ + char buf[256]; + if (kind & msg_print_Hex) { + const uint8_t* arr = reinterpret_cast<const uint8_t*>(&data); + /* + snprintf(buf, sizeof(buf), + "BE= %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X LE= " + "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X ", + arr[0], arr[1], arr[2], arr[3], arr[4], arr[5], arr[6], arr[7], arr[7], arr[6], arr[5], arr[4], arr[3], + arr[2], arr[1], arr[0]); + */ + snprintf(buf, sizeof(buf), + "LE= %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X ", + arr[7], arr[6], arr[5], arr[4], arr[3], arr[2], arr[1], arr[0]); + + + if (msg_print_Cout == outType) std::cout << buf; + else if (msg_print_File == outType) + os << buf; + + snprintf(buf, sizeof(buf), " "); + } + + if (kind & msg_print_Human) { + double timeInSec = getMsgFullTimeD(epoch) / 1.e9; + // int fifoFill = 0; + + switch (getMessageType()) { + case MSG_EPOCH: + snprintf(buf, sizeof(buf), "Msg:%u ", getMessageType()); + + if (msg_print_Cout == outType) std::cout << buf; + else if (msg_print_File == outType) + os << buf; + + snprintf(buf, sizeof(buf), + "EPOCH @%17.11f Get4:%2d Epoche2:%10u 0x%08x Sync:%x " + "Dataloss:%x Epochloss:%x Epochmissmatch:%x", + timeInSec, getGdpbGenChipId(), getGdpbEpEpochNb(), getGdpbEpEpochNb(), getGdpbEpSync(), + getGdpbEpDataLoss(), getGdpbEpEpochLoss(), getGdpbEpMissmatch()); + + if (msg_print_Cout == outType) std::cout << buf << std::endl; + else if (msg_print_File == outType) + os << buf << std::endl; + break; + case MSG_HIT: + snprintf(buf, sizeof(buf), "Msg:%u ", getMessageType()); + + if (msg_print_Cout == outType) std::cout << buf; + else if (msg_print_File == outType) + os << buf; + + if (getGdpbHitIs24b()) { + snprintf(buf, sizeof(buf), "Get4 24b @%17.11f Get4:%2d Chn:%3d Edge:%1d Ts:%7d", timeInSec, + getGdpbGenChipId(), getGdpbHitChanId(), getGdpbHit24Edge(), getGdpbHitFullTs()); + } // if( getGdpbHitIs24b() ) + else { + snprintf(buf, sizeof(buf), "Get4 24b @%17.11f Get4:%2d Chn:%3d Dll:%1d Ts:%7d", timeInSec, getGdpbGenChipId(), + getGdpbHitChanId(), getGdpbHit32DllLck(), getGdpbHitFullTs()); + } // else of if( getGdpbHitIs24b() ) + + if (msg_print_Cout == outType) std::cout << buf << std::endl; + else if (msg_print_File == outType) + os << buf << std::endl; + break; + default: + kind = kind & ~msg_print_Human; + if (kind == 0) kind = msg_print_Prefix | msg_print_Data; + } + + // return, if message was correctly printed in human-readable form + if (kind & msg_print_Human) return; + } + + if (kind & msg_print_Prefix) { + snprintf(buf, sizeof(buf), "Msg:%2u ", getMessageType()); + + if (msg_print_Cout == outType) std::cout << buf; + else if (msg_print_File == outType) + os << buf; + } + + if (kind & msg_print_Data) { + // const uint8_t* arr = reinterpret_cast<const uint8_t*> ( &data ); + switch (getMessageType()) { + case MSG_HIT: { + if (getGdpbHitIs24b()) { + snprintf(buf, sizeof(buf), "Get4 24 bits, Get4:%3d Chn:%1x Edge:%1x Ts:0x%03x", getGdpbGenChipId(), + getGdpbHitChanId(), getGdpbHit24Edge(), getGdpbHitFullTs()); + } // if( getGdpbHitIs24b() ) + else { + snprintf(buf, sizeof(buf), + "Get4 32 bits, Get4:%3d Channel %1d Ts:0x%03x Ft:0x%02x " + "Tot:0x%02x Dll %1d", + getGdpbGenChipId(), getGdpbHitChanId(), getGdpbHitCoarse(), getGdpbHitFineTs(), getGdpbHit32Tot(), + getGdpbHit32DllLck()); + } // else of if( getGdpbHitIs24b() ) + break; + } // case MSG_HIT: + case MSG_EPOCH: { + /*snprintf(buf, sizeof(buf), + "Get4:%3d Link: %1u Epoch:0x%08x Sync:%x Dataloss:%x " + "Epochloss:%x Epochmissmatch:%x", + getGdpbGenChipId(), getGdpbEpLinkId(), getGdpbEpEpochNb(), getGdpbEpSync(), getGdpbEpDataLoss(), + getGdpbEpEpochLoss(), getGdpbEpMissmatch()); + */ + snprintf(buf, sizeof(buf), + "Get4:%3d Link: %1u Epoch:0x%08x Sync:%x", + getGdpbGenChipId(), getGdpbEpLinkId(), getGdpbEpEpochNb(), getGdpbEpSync()); + + break; + } // case MSG_EPOCH: + case MSG_SLOWC: { + // GET4 slow control message, new "true" ROC support + snprintf(buf, sizeof(buf), + "Get4 Slow control, Get4:%3d => Chan:%01d Edge:%01d " + "Type:%01x Data:0x%06x", + getGdpbGenChipId(), 0x0, 0x0, 0x0, getGdpbSlcData()); + break; + } // case MSG_SLOWC: + case MSG_SYST: { + // GET4 system message, new "true" ROC support + char sysbuf[256]; + + switch (getGdpbSysSubType()) { + case SYS_GET4_ERROR: { + snprintf(sysbuf, sizeof(sysbuf), + "Get4:%3d Ch:0x%01x Edge:%01x Unused:%06x " + "ErrCode:0x%02x - GET4 V1 Error Event", + getGdpbGenChipId(), getGdpbSysErrChanId(), getGdpbSysErrEdge(), getGdpbSysErrUnused(), + getGdpbSysErrData()); + break; + } // + case SYS_GDPB_UNKWN: + snprintf(sysbuf, sizeof(sysbuf), "Unknown GET4 message, data: 0x%08x", getGdpbSysUnkwData()); + break; + case SYS_GET4_SYNC_MISS: + if (getGdpbSysFwErrResync()) + snprintf(sysbuf, sizeof(sysbuf), "GET4 Resynchronization: Get4:0x%04x", getGdpbGenChipId()); + else + snprintf(sysbuf, sizeof(sysbuf), "GET4 SYNC synchronization error"); + break; + case SYS_PATTERN: + snprintf(sysbuf, sizeof(sysbuf), "Pattern message => Type %d, Index %2d, Pattern 0x%08X", + getGdpbSysPattType(), getGdpbSysPattIndex(), getGdpbSysPattPattern()); + break; + default: snprintf(sysbuf, sizeof(sysbuf), "unknown system message type %u", getGdpbSysSubType()); + } // switch( getGdpbSysSubType() ) + snprintf(buf, sizeof(buf), "%s", sysbuf); + + break; + } // case MSG_SYST: + case MSG_STAR_TRI_A: + case MSG_STAR_TRI_B: + case MSG_STAR_TRI_C: + case MSG_STAR_TRI_D: { + // STAR trigger token, spread over 4 messages + switch (getStarTrigMsgIndex()) { + case 0: { + snprintf(buf, sizeof(buf), + // "STAR token A, gDPB TS MSB bits: 0x%010llx000000", + // getGdpbTsMsbStarA() ); + "STAR token A, gDPB TS MSB bits: 0x%s000000", + FormatHexPrintout(getGdpbTsMsbStarA(), 10, '0').c_str()); + break; + } // case 1st message: + case 1: { + snprintf( + buf, sizeof(buf), + // "STAR token B, gDPB TS LSB bits: 0x0000000000%06llx, STAR TS MSB bits: 0x%04llx000000000000", + // getGdpbTsLsbStarB(), getStarTsMsbStarB() ); + "STAR token B, gDPB TS LSB bits: 0x0000000000%s, STAR TS MSB " + "bits: 0x%s000000000000", + FormatHexPrintout(getGdpbTsLsbStarB(), 6, '0').c_str(), + FormatHexPrintout(getStarTsMsbStarB(), 4, '0').c_str()); + break; + } // case 2nd message: + case 2: { + snprintf( + buf, sizeof(buf), + // "STAR token C, , STAR TS Mid bits: 0x0000%010llx00", + // getStarTsMidStarC() ); + "STAR token C, , STAR TS Mid " + "bits: 0x0000%s00", + FormatHexPrintout(getStarTsMidStarC(), 10, '0').c_str()); + break; + } // case 3rd message: + case 3: { + snprintf( + buf, sizeof(buf), + // "STAR token D, , STAR TS LSB bits: 0x00000000000000%02llx" + "STAR token D, , STAR TS LSB " + "bits: 0x00000000000000%s" + ", Token: %03x, DAQ: %1x; TRG:%1x", + // getStarTsLsbStarD(), + FormatHexPrintout(getStarTsLsbStarD(), 2, '0').c_str(), getStarTokenStarD(), getStarDaqCmdStarD(), + getStarTrigCmdStarD()); + break; + } // case 4th message: + } // switch( getStarTrigMsgIndex() ) + + break; + } // case MSG_STAR_TRI_A || MSG_STAR_TRI_B || MSG_STAR_TRI_C || MSG_STAR_TRI_D: + default: + snprintf(buf, sizeof(buf), "Error - unexpected MessageType: %1x, full data %08X::%08X", getMessageType(), + getField(32, 32), getField(0, 32)); + } + } + + if (msg_print_Cout == outType) std::cout << buf << std::endl; + else if (msg_print_File == outType) + os << buf << std::endl; +} +//---------------------------------------------------------------------------- +//! strict weak ordering operator, including epoch for both messages +bool critof001::FullMessage::operator<(const FullMessage& other) const +{ + if (other.fulExtendedEpoch == this->fulExtendedEpoch) + // Same epoch => use Message (base) class ordering operator + return this->Message::operator<(other); + else + return this->fulExtendedEpoch < other.fulExtendedEpoch; +} +//---------------------------------------------------------------------------- +void critof001::FullMessage::PrintMessage(unsigned outType, unsigned kind) const +{ + std::cout << "Full epoch = " << std::setw(9) << fulExtendedEpoch << " "; + printDataCout(outType, kind); +} diff --git a/core/data/raw/CriGet4Mess001.h b/core/data/raw/CriGet4Mess001.h new file mode 100644 index 0000000000..338c8ac0b5 --- /dev/null +++ b/core/data/raw/CriGet4Mess001.h @@ -0,0 +1,385 @@ +/* Copyright (C) 2018-2020 Facility for Antiproton and Ion Research in Europe, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Pierre-Alain Loizeau [committer] */ + +#ifndef CRI_GET4_MESS_V0_01_DEF_H +#define CRI_GET4_MESS_V0_01_DEF_H + +#include <iostream> + +#include <stdint.h> + +namespace critof001 +{ + // Size of one clock cycle (=1 coarse bin) + const double kdClockCycleSize = 6250.0; //[ps] + const double kdClockCycleSizeNs = kdClockCycleSize / 1000.0; //[ns] + // TODO:For now make 100ps default, maybe need later an option for it + const double kdTotBinSize = 50.0; //ps + + const uint32_t kuFineTime = 0x0000007F; // Fine Counter value + const uint32_t kuFtShift = 0; // Fine Counter offset + const uint32_t kuCoarseTime = 0x0007FF80; // Coarse Counter value + const uint32_t kuCtShift = 7; // Coarse Counter offset + const uint32_t kuCtSize = 12; // Coarse Counter size in bits + + const uint32_t kuFineCounterSize = ((kuFineTime >> kuFtShift) + 1); + const uint32_t kuCoarseCounterSize = ((kuCoarseTime >> kuCtShift) + 1); + const uint32_t kuCoarseOverflowTest = kuCoarseCounterSize / 2; // Limit for overflow check + const uint32_t kuTotCounterSize = 256; + + const double kdFtSize = kuFineCounterSize; + const double kdFtBinsNb = 112.; + + // Nominal bin size of NL are neglected + const double kdBinSize = kdClockCycleSize / kdFtBinsNb; + // Epoch Size in bins + const uint32_t kuEpochInBins = kuCoarseCounterSize * kdFtBinsNb; + // Epoch Size in ps + // alternatively: (kiCoarseTime>>kiCtShift + 1)*kdClockCycleSize + const double kdEpochInPs = static_cast<double>(kuCoarseCounterSize) * kdClockCycleSize; + const double kdEpochInNs = kdEpochInPs / 1000.0; + + // Epoch counter size in epoch + const uint32_t kuEpochCounterSz = 0x7FFFFFFF; + // Epoch counter size in bin + const uint64_t kulEpochCycleBins = static_cast<uint64_t>(kuEpochCounterSz + 1) * kuEpochInBins; + // Epoch counter size in s + const double kdEpochCycleInS = static_cast<double>(kuEpochCounterSz + 1) * (kdEpochInNs / 1e9); + + // Epoch Cycle MS start message size in bits + const uint64_t kulEpochCycleFieldSz = 0x1FFFFF; // 21 bits + + const uint32_t kuChipIdMergedEpoch = 255; // 0xFF + + const uint32_t kuFeePulserChannel = 3; // Channel where a pulser can be set ON at 20 ns 500 Hz + const uint32_t kuFeePulserChannelDiam = 0; // Channel where a pulser can be set ON at 20 ns 500 Hz + + enum MessageTypes + { + MSG_HIT = 0, + MSG_EPOCH = 1, + MSG_SLOWC = 2, + MSG_SYST = 3, + MSG_STAR_TRI_A = 4, + MSG_STAR_TRI_B = 5, + MSG_STAR_TRI_C = 6, + MSG_STAR_TRI_D = 7 + }; + + enum SysMessageTypes + { + SYS_GET4_ERROR = 0, // GET4 error event + SYS_GDPB_UNKWN = 1, // Raw data from gDPB in case of unknown message type from GET4 + SYS_GET4_SYNC_MISS = 2, // Added when GET4 is missing the SYNC flag when it is expected + // SYS_SYNC_ERROR = 3 // added to data stream when the closy-sync-strobe does not match the gDPB 160MHz timestamp counter + SYS_PATTERN = 3 // added to data stream when one of the ASIC patterns (missmatch, enable, resync) changed + }; + + enum PattMessageTypes + { + PATT_MISSMATCH = 0, // Missmatch pattern, 1 bit per ASIC + PATT_ENABLE = 1, // Enable pattern, 1 bit per ASIC + PATT_RESYNC = 2, // Resync request pattern, 1 bit per ASIC + PATT_STATUS = 3 // Status pattern, 1 bit per ASIC (SW only) + }; + + enum MessagePrintMask + { + msg_print_Prefix = 1, + msg_print_Data = 2, + msg_print_Hex = 4, + msg_print_Human = 8 + }; + + enum MessagePrintType + { + msg_print_Cout = 1, + msg_print_FairLog = 2, + msg_print_File = 3 + }; + + enum Get4Message32bSlC + { + GET4_32B_SLC_SCALER = 0, + GET4_32B_SLC_DEADT = 1, + GET4_32B_SLC_SPIREAD = 2, + GET4_32B_SLC_START_SEU = 3 + }; + + enum Get4Message32bErrors + { + GET4_V2X_ERR_READ_INIT = 0x00, + GET4_V2X_ERR_SYNC = 0x01, + GET4_V2X_ERR_EP_CNT_SYNC = 0x02, + GET4_V2X_ERR_EP = 0x03, + GET4_V2X_ERR_FIFO_WRITE = 0x04, + GET4_V2X_ERR_LOST_EVT = 0x05, + GET4_V2X_ERR_CHAN_STATE = 0x06, + GET4_V2X_ERR_TOK_RING_ST = 0x07, + GET4_V2X_ERR_TOKEN = 0x08, + GET4_V2X_ERR_READOUT_ERR = 0x09, + GET4_V2X_ERR_SPI = 0x0A, + GET4_V2X_ERR_DLL_LOCK = 0x0B, + GET4_V2X_ERR_DLL_RESET = 0x0C, + GET4_V2X_ERR_TOT_OVERWRT = 0x11, // Not there anymore in manual for Get4 v2.00? + GET4_V2X_ERR_TOT_RANGE = 0x12, + GET4_V2X_ERR_EVT_DISCARD = 0x13, + GET4_V2X_ERR_ADD_RIS_EDG = 0x14, + GET4_V2X_ERR_UNPAIR_FALL = 0x15, + GET4_V2X_ERR_SEQUENCE_ER = 0x16, + GET4_V2X_ERR_EPOCH_OVERF = 0x17, // New in manual for Get4 v2.00, no description? + GET4_V2X_ERR_UNKNOWN = 0x7F + }; + + class Message { + + protected: + uint64_t data; // main and only storage field for the message + + public: + Message() : data(0) {} + + Message(const Message& src) : data(src.data) {} + + Message(uint64_t dataIn) : data(dataIn) {} + + ~Message() {}; + + void assign(const Message& src) { data = src.data; } + + Message& operator=(const Message& src) + { + assign(src); + return *this; + } + + inline void reset() { data = 0; } + + inline uint64_t getData() const { return data; } + inline void setData(uint64_t value) { data = value; } + + inline uint64_t getFieldLong(uint32_t shift, uint32_t len) const + { + return (data >> shift) & (((static_cast<uint64_t>(1)) << len) - 1); + } + + inline uint32_t getField(uint32_t shift, uint32_t len) const + { + return (data >> shift) & (((static_cast<uint64_t>(1)) << len) - 1); + } + + inline void setField(uint32_t shift, uint32_t len, uint32_t value) + { + uint64_t mask = (((static_cast<uint64_t>(1)) << len) - 1); + data = (data & ~(mask << shift)) | ((static_cast<uint64_t>(value) & mask) << shift); + } + + inline void setFieldLong(uint32_t shift, uint32_t len, uint64_t value) + { + uint64_t mask = (((static_cast<uint64_t>(1)) << len) - 1); + data = (data & ~(mask << shift)) | ((value & mask) << shift); + } + + inline uint8_t getBit(uint32_t shift) const { return (data >> shift) & 1; } + + inline void setBit(uint32_t shift, uint8_t value) + { + data = value ? (data | ((static_cast<uint64_t>(1)) << shift)) : (data & ~((static_cast<uint64_t>(1)) << shift)); + } + + + inline uint32_t getFieldBE(uint32_t shift, uint32_t len) const + { + return (dataBE() >> shift) & (((static_cast<uint32_t>(1)) << len) - 1); + } + inline uint8_t getBitBE(uint32_t shift) const { return (dataBE() >> shift) & 1; } + inline uint64_t dataBE() const + { + return ((data & 0x00000000000000FF) << 56) + ((data & 0x000000000000FF00) << 40) + + ((data & 0x0000000000FF0000) << 24) + ((data & 0x00000000FF000000) << 8) + + ((data >> 8) & 0x00000000FF000000) + ((data >> 24) & 0x0000000000FF0000) + + ((data >> 40) & 0x000000000000FF00) + ((data >> 56) & 0x00000000000000FF); + } + + // --------------------------- common fields --------------------------------- + + //! Returns the message type. Valid for all message types. 2 bit + inline uint8_t getMessageType() const { return getField(0, 3); } + + //! Sets the message type field in the current message + inline void setMessageType(uint8_t v) { setField(0, 3, v); } + + // ---------- Get4 gDPB 24b/32b ALL access methods ------------------------ + inline uint16_t getGdpbGenGdpbId() const { return getField(48, 16); } + inline void setGdpbGenGdpbId(uint32_t v) { setField(48, 16, v); } + inline uint16_t getGdpbGenChipId() const { return getField(40, 8); } + inline void setGdpbGenChipId(uint32_t v) { setField(40, 8, v); } + + // ---------- Get4 gDPB 24b/32b Hit access methods ------------------------ + inline uint16_t getGdpbHitIs24b() const { return getBit(39); } + inline uint16_t getGdpbHitChanId() const { return getField(32, 2); } + inline uint32_t getGdpbHitFullTs() const { return getField(13, 19); } + inline uint16_t getGdpbHitCoarse() const { return getField(20, 12); } + inline uint16_t getGdpbHitFineTs() const { return getField(13, 7); } + // ---------- Get4 gDPB 24b Hit access methods ---------------------------- + inline bool getGdpbHit24Edge() const { return getBit(34); } + // ---------- Get4 gDPB 32b Hit access methods ---------------------------- + inline bool getGdpbHit32DllLck() const { return getBit(12); } + inline uint16_t getGdpbHit32Tot() const { return getField(4, 8); } + + // ---------- Get4 gDPB 24b/32b Epoch access methods ---------------------- + inline bool getGdpbEpLinkId() const { return getBit(39); } + inline uint32_t getGdpbEpEpochNb() const { return getField(8, 31); } + inline bool getGdpbEpSync() const { return getBit(7); } + inline bool getGdpbEpDataLoss() const { return getBit(6); } + inline bool getGdpbEpEpochLoss() const { return getBit(5); } + inline bool getGdpbEpMissmatch() const { return getBit(4); } + + // ---------- Get4 gDPB 24b/32b Slow cont. access methods ----------------- + inline uint32_t getGdpbSlcMess() const { return getField(4, 29); } + inline uint32_t getGdpbSlcChan() const { return getField(31, 2); } + inline uint32_t getGdpbSlcEdge() const { return getBit(30); } + inline uint32_t getGdpbSlcType() const { return getField(28, 2); } + inline uint32_t getGdpbSlcData() const { return getField(4, 24); } + + // ---------- Get4 gDPB System Msg access methods ------------------------- + inline uint16_t getGdpbSysSubType() const { return getField(38, 2); } + inline bool getGdpbSysLinkId() const { return getBit(37); } + // ---------- Get4 gDPB 24b/32b Errors access methods --------------------- + inline bool getGdpbSysErrRoType() const { return getBit(36); } + inline uint16_t getGdpbSysErrUnused() const { return getField(32, 4); } + inline uint16_t getGdpbSysErrInfo() const { return getField(11, 21); } + inline uint16_t getGdpbSysErrChanId() const { return getField(12, 2); } + inline bool getGdpbSysErrEdge() const { return getBit(11); } + inline uint16_t getGdpbSysErrData() const { return getField(4, 7); } + // ---------- Get4 gDPB unknown msg type access methods ------------------- + inline uint32_t getGdpbSysUnkwData() const { return getField(4, 32); } + // ---------- FW error msg type access methods ---------------------------- + inline uint32_t getGdpbSysFwErrResync() const { return getBit(36); } + // ---------- ASIC Pattern messages access methods ------------------------ + inline uint16_t getGdpbSysPattType() const { return getField(46, 2); } + inline uint16_t getGdpbSysPattIndex() const { return getField(40, 4); } + inline uint32_t getGdpbSysPattPattern() const { return getField(4, 32); } + + // ---------- STAR Trigger messages access methods ------------------------ + inline uint16_t getStarTrigMsgIndex() const { return getField(0, 2); } + //++++// + inline uint64_t getGdpbTsMsbStarA() const { return getFieldLong(4, 40); } + //++++// + inline uint64_t getGdpbTsLsbStarB() const { return getFieldLong(20, 24); } + inline uint64_t getStarTsMsbStarB() const { return getFieldLong(4, 16); } + //++++// + inline uint64_t getStarTsMidStarC() const { return getFieldLong(4, 40); } + //++++// + inline uint64_t getStarTsLsbStarD() const { return getFieldLong(36, 8); } + /// 12 bits in between are set to 0 + inline uint32_t getStarFillerD() const { return getField(24, 12); } // Should be always 0 + inline uint32_t getStarTrigCmdStarD() const { return getField(20, 4); } + inline uint32_t getStarDaqCmdStarD() const { return getField(16, 4); } + inline uint32_t getStarTokenStarD() const { return getField(4, 12); } + + // ---------- Get4 gDPB 24b/32b Epoch setter methods ---------------------- + inline void setGdpbEpEpochNb(uint32_t v) { setField(8, 31, v); } + + // ---------- Get4 gDPB System Msg access methods ------------------------- + inline void setGdpbSysSubType(uint16_t v) { setField(38, 2, v); } + // ---------- ASIC Pattern messages access methods ------------------------ + inline void setGdpbSysPattType(uint16_t v) { setField(46, 2, v); } + inline void setGdpbSysPattIndex(uint16_t v) { setField(40, 4, v); } + inline void setGdpbSysPattPattern(uint32_t v) { setField(4, 32, v); } + + // ---------- STAR Trigger messages setter methods ------------------------ + inline void setStarTrigMsgIndex(uint8_t v) { setField(0, 2, v); } + //++++// + inline void setGdpbTsMsbStarA(uint64_t fullGdpbTs) { setFieldLong(4, 40, (fullGdpbTs >> 24)); } + //++++// + inline void setGdpbTsLsbStarB(uint64_t fullGdpbTs) { setFieldLong(20, 24, (fullGdpbTs)); } + inline void setStarTsMsbStarB(uint64_t fullStarTs) { setFieldLong(4, 16, (fullStarTs >> 48)); } + //++++// + inline void setStarTsMidStarC(uint64_t fullStarTs) { setFieldLong(4, 40, (fullStarTs >> 8)); } + //++++// + inline void setStarTsLsbStarD(uint64_t fullStarTs) { setFieldLong(36, 8, (fullStarTs)); } + /// 12 bits in between are set to 0 + inline void setStarFillerD() { setField(24, 12, 0); } // Should be always 0 + inline void setStarTrigCmdStarD(uint8_t v) { setField(20, 4, v); } + inline void setStarDaqCmdStarD(uint8_t v) { setField(16, 4, v); } + inline void setStarTokenStarD(uint16_t v) { setField(4, 12, v); } + + // ---------- Common functions ----------------------- + //! Returns \a true is message type is #MSG_HIT (Get4 hit data) + inline bool isHitMsg() const { return getMessageType() == MSG_HIT; } + //! Returns \a true is message type is #MSG_EPOCH (epoch2 marker) + inline bool isEpochMsg() const { return getMessageType() == MSG_EPOCH; } + //! Returns \a true is message type is #MSG_SLOWC (GET4 Slow Control) + inline bool isGet4SlCtrMsg() const { return getMessageType() == MSG_SLOWC; } + //! Returns \a true is message type is #MSG_SYST (system message) + inline bool isSysMsg() const { return getMessageType() == MSG_SYST; } + //! Returns \a true is message type is #MSG_STAR_TRI_A, _B, _C, _D (STAR Trigger message) + inline bool isStarTrigger() const { return MSG_STAR_TRI_A <= getMessageType(); } + + void printDataCout(unsigned kind = msg_print_Prefix | msg_print_Data, uint32_t epoch = 0) const; + void printDataLog(unsigned kind = msg_print_Prefix | msg_print_Data, uint32_t epoch = 0) const; + + void printData(unsigned outType = msg_print_Cout, unsigned kind = msg_print_Human, uint32_t epoch = 0, + std::ostream& os = std::cout) const; + + uint64_t getMsgFullTime(uint64_t epoch) const; + + double getMsgFullTimeD(uint64_t epoch) const; + + //! Expanded timestamp for 160 MHz * 19 bit (12 + 7) epochs + inline static uint64_t FullTimeStamp(uint64_t epoch, uint32_t ts) { return (epoch << 19) | (ts & 0x7ffff); } + + + static uint64_t CalcDistance(uint64_t start, uint64_t stop); + + static double CalcDistanceD(double start, double stop); + + bool operator<(const critof001::Message& other) const; + bool operator==(const critof001::Message& other) const; + bool operator!=(const critof001::Message& other) const; + }; + + class FullMessage : public Message { + protected: + uint64_t fulExtendedEpoch; // Epoch of the message, extended with 32b epoch cycle counter + + public: + FullMessage() : Message(), fulExtendedEpoch(0) {} + + FullMessage(const Message& src, uint64_t uEpIn = 0) : Message(src), fulExtendedEpoch(uEpIn) {} + + FullMessage(const FullMessage& src) : Message(src), fulExtendedEpoch(src.fulExtendedEpoch) {} + + void assign(const FullMessage& src) + { + Message::assign(src); + fulExtendedEpoch = src.fulExtendedEpoch; + } + + FullMessage& operator=(const FullMessage& src) + { + assign(src); + return *this; + } + + bool operator<(const FullMessage& other) const; + + inline void reset() + { + Message::reset(); + fulExtendedEpoch = 0; + } + + inline uint64_t getExtendedEpoch() const { return fulExtendedEpoch; } + + inline double GetFullTimeNs() const { return getMsgFullTimeD(fulExtendedEpoch); } + + void PrintMessage(unsigned outType = msg_print_Cout, unsigned kind = msg_print_Human) const; + }; + +} // namespace critof001 + + +#endif // CRI_GET4_MESS_V0_01_DEF_H diff --git a/fles/mcbm2018/CMakeLists.txt b/fles/mcbm2018/CMakeLists.txt index d94505ba4a..5a4d4e7f01 100644 --- a/fles/mcbm2018/CMakeLists.txt +++ b/fles/mcbm2018/CMakeLists.txt @@ -63,6 +63,7 @@ Set(SRCS unpacker/CbmMcbm2018RawConverterSdpb.cxx unpacker/CbmMcbm2018RawConverterGdpb.cxx + unpacker/CbmCriGet4RawPrint.cxx unpacker/CbmMcbm2018UnpackerAlgoSts.cxx unpacker/CbmMcbm2018UnpackerTaskSts.cxx diff --git a/fles/mcbm2018/CbmFlibMcbm2018LinkDef.h b/fles/mcbm2018/CbmFlibMcbm2018LinkDef.h index 674783848c..73f2fa101e 100644 --- a/fles/mcbm2018/CbmFlibMcbm2018LinkDef.h +++ b/fles/mcbm2018/CbmFlibMcbm2018LinkDef.h @@ -14,6 +14,7 @@ #pragma link C++ class CbmMcbm2018RawConverterSdpb; #pragma link C++ class CbmMcbm2018RawConverterGdpb; +#pragma link C++ class CbmCriGet4RawPrint; #pragma link C++ class CbmMcbm2018UnpackerAlgoSts; #pragma link C++ class CbmMcbm2018UnpackerTaskSts + ; diff --git a/fles/mcbm2018/unpacker/CbmCriGet4RawPrint.cxx b/fles/mcbm2018/unpacker/CbmCriGet4RawPrint.cxx new file mode 100644 index 0000000000..2284a24bbc --- /dev/null +++ b/fles/mcbm2018/unpacker/CbmCriGet4RawPrint.cxx @@ -0,0 +1,316 @@ +/* Copyright (C) 2021 Facility for Antiproton and Ion Research in Europe, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Pierre-Alain Loizeau [committer] */ + +#include "CbmCriGet4RawPrint.h" + +#include "CbmFormatMsHeaderPrintout.h" + +#include "FairParGenericSet.h" +#include "FairRootManager.h" +#include "FairRun.h" +#include "FairRunOnline.h" +#include "FairRuntimeDb.h" +#include <Logger.h> + +#include <iomanip> + +CbmCriGet4RawPrint::CbmCriGet4RawPrint() + : CbmMcbmUnpack() + , fvMsComponentsList() + , fuNbCoreMsPerTs(0) + , fuNbOverMsPerTs(0) + , fuNbMsLoop(0) + , fbIgnoreOverlapMs(kFALSE) + , fdMsSizeInNs(-1.0) + , fdTsCoreSizeInNs(-1.0) + , fulCurrentTsIdx(0) + , fulCurrentMsIdx(0) + , fdTsStartTime(0.0) + , fdTsStopTimeCore(0.0) + , fdMsTime(0.0) + , fuMsIndex(0) + , fuCurrentEquipmentId(0) +{ +} + +CbmCriGet4RawPrint::~CbmCriGet4RawPrint() {} + +Bool_t CbmCriGet4RawPrint::Init() +{ + LOG(info) << "CbmCriGet4RawPrint::Init"; + LOG(info) << "Initializing mCBM gDPB 2018 Raw Messages Converter"; + + return kTRUE; +} + +void CbmCriGet4RawPrint::SetParContainers() +{ + LOG(info) << "Setting parameter containers for " << GetName(); +} + +Bool_t CbmCriGet4RawPrint::InitContainers() +{ + LOG(info) << "Init parameter containers for " << GetName(); + + return kTRUE; +} + +Bool_t CbmCriGet4RawPrint::ReInitContainers() +{ + LOG(info) << "ReInit parameter containers for " << GetName(); + + return kTRUE; +} + +void CbmCriGet4RawPrint::AddMsComponentToList(size_t component, UShort_t usDetectorId) +{ + /// Check for duplicates and ignore if it is the case + for (UInt_t uCompIdx = 0; uCompIdx < fvMsComponentsList.size(); ++uCompIdx) + if (component == fvMsComponentsList[uCompIdx]) return; + + /// Add to list + fvMsComponentsList.push_back(component); + + LOG(info) << "CbmCriGet4RawPrint::AddMsComponentToList => Component " << component << " with detector ID 0x" + << std::hex << usDetectorId << std::dec << " added to list"; +} + +Bool_t CbmCriGet4RawPrint::DoUnpack(const fles::Timeslice& ts, size_t /*component*/) +{ + + static const uint8_t NGET4 = 80; + static const uint8_t NERROR = 0x16; + + char buf[256]; + + static uint32_t lastGlobalEpoch = 0; + uint32_t nGet4, epoch, msgType, errorCode; + static int32_t pEpochDiff[NGET4]; + int32_t epochDiff; + static uint32_t pErrorCnt[NGET4]={ 0 }; + static uint32_t pHitsCnt[NGET4]={ 0 }; + static uint32_t pTotCnt[NGET4]={ 0 }; + + static uint32_t pErrorCntMatrix[NGET4][NERROR]; + + static uint32_t procEpochUntilError = 0; + + fulCurrentTsIdx = ts.index(); + fdTsStartTime = static_cast<Double_t>(ts.descriptor(0, 0).idx); + + /// Ignore First TS as first MS is typically corrupt + if (0 == fulCurrentTsIdx) { return kTRUE; } // if( 0 == fulCurrentTsIdx ) + + /// On first TS, extract the TS parameters from header (by definition stable over time) + if (-1.0 == fdTsCoreSizeInNs) { + fuNbCoreMsPerTs = ts.num_core_microslices(); + fuNbOverMsPerTs = ts.num_microslices(0) - ts.num_core_microslices(); + fdTsCoreSizeInNs = fdMsSizeInNs * (fuNbCoreMsPerTs); + fdTsFullSizeInNs = fdMsSizeInNs * (fuNbCoreMsPerTs + fuNbOverMsPerTs); + LOG(info) << "Timeslice parameters: each TS has " << fuNbCoreMsPerTs << " Core MS and " << fuNbOverMsPerTs + << " Overlap MS, for a core duration of " << fdTsCoreSizeInNs << " ns and a full duration of " + << fdTsFullSizeInNs << " ns"; + + /// Ignore overlap ms if flag set by user + fuNbMsLoop = fuNbCoreMsPerTs; + if (kFALSE == fbIgnoreOverlapMs) fuNbMsLoop += fuNbOverMsPerTs; + LOG(info) << "In each TS " << fuNbMsLoop << " MS will be looped over"; + } // if( -1.0 == fdTsCoreSizeInNs ) + + /// Compute time of TS core end + fdTsStopTimeCore = fdTsStartTime + fdTsCoreSizeInNs; + + /// Loop over registered components + for (UInt_t uMsCompIdx = 0; uMsCompIdx < fvMsComponentsList.size(); ++uMsCompIdx) { + /// Loop over core microslices (and overlap ones if chosen) + for (fuMsIndex = 0; fuMsIndex < fuNbMsLoop; fuMsIndex++) { + UInt_t uMsComp = fvMsComponentsList[uMsCompIdx]; + + auto msDescriptor = ts.descriptor(uMsComp, fuMsIndex); + fuCurrentEquipmentId = msDescriptor.eq_id; + const uint8_t* msContent = reinterpret_cast<const uint8_t*>(ts.content(uMsComp, fuMsIndex)); + + uint32_t uSize = msDescriptor.size; + fulCurrentMsIdx = msDescriptor.idx; + // Double_t dMsTime = (1e-9) * static_cast<double>(fulCurrentMsIdx); + LOG(debug) << "Microslice: " << fulCurrentMsIdx << " from EqId " << std::hex << fuCurrentEquipmentId << std::dec + << " has size: " << uSize; + + /// Always print the MS header + LOG(info) << "---------------------------------------------------------------"; + LOG(info) << FormatMsHeaderPrintout(msDescriptor); + + /// If not integer number of message in input buffer, print warning/error + if (0 != (uSize % kuBytesPerMessage)) + LOG(error) << "The input microslice buffer does NOT " + << "contain only complete gDPB messages!"; + + /// Compute the number of complete messages in the input microslice buffer + uint32_t uNbMessages = (uSize - (uSize % kuBytesPerMessage)) / kuBytesPerMessage; + + /// Prepare variables for the loop on contents + const uint64_t* pInBuff = reinterpret_cast<const uint64_t*>(msContent); + for (uint32_t uIdx = 0; uIdx < uNbMessages; uIdx++) { + /// Fill message + uint64_t ulData = static_cast<uint64_t>(pInBuff[uIdx]); + + critof001::Message mess(ulData); + + /// TODOD: pick the options!!! + //mess.printDataCout( critof001::msg_print_Hex ); + //mess.printDataCout( critof001::msg_print_Hex | critof001::msg_print_Prefix | critof001::msg_print_Data ); + + msgType = ulData & 0xF; + nGet4 = (ulData>>40) & 0xFF; + epoch = (ulData>>8) & 0xFFFFFF; + epoch &= 0xFFFFFF; + errorCode = (ulData>>4) & 0x7F; + /*snprintf(buf, sizeof(buf), + "Data: 0x%016lx - %d - 0x06%X ", + ulData, nGet4, epoch); + + std::cout << buf << std::endl; + */ + + //if (fuCurrentEquipmentId == 0xabc0) + { + //------------------- TLAST ----------------------------// + if ((ulData & 0xFFFFFFFFFFFF)==0xdeadbeeeeeef) + { + } + //------------------- EPOCH ----------------------------// + else if (msgType == 0x01) + { + if (nGet4 == 0xFF) { + + procEpochUntilError++; + if (lastGlobalEpoch!=0xFFFFFF){ + if ((lastGlobalEpoch + 1) != epoch){ + snprintf(buf, sizeof(buf), + "Error global epoch, last epoch, current epoch, diff 0x%06x 0x%06x %d 0x%016lx %d", + lastGlobalEpoch, epoch, lastGlobalEpoch - epoch, ulData, procEpochUntilError); + + std::cout << buf << std::endl; + procEpochUntilError=0; + } + } + else{ + snprintf(buf, sizeof(buf), + "Global epoch overflow, last epoch, current epoch 0x%06x 0x%06x", + lastGlobalEpoch, epoch); + + std::cout << buf << std::endl; + } + + + lastGlobalEpoch = epoch; + snprintf(buf, sizeof(buf),"Global epoch %d",epoch); + std::cout << buf << std::endl; + + + } + else if (nGet4 <= 120){ + + if (lastGlobalEpoch > epoch) + epochDiff = lastGlobalEpoch - epoch; + else + epochDiff = 0xFFFFFF + lastGlobalEpoch - epoch; + + if (epochDiff != pEpochDiff[nGet4]){ + snprintf(buf, sizeof(buf), + "eTime %d - Error epoch drift Get4 %3d , last epoch diff, current epoch diff 0x%06x 0x%06x %d", + lastGlobalEpoch, nGet4, pEpochDiff[nGet4], epochDiff, pEpochDiff[nGet4]-epochDiff); + std::cout << buf << std::endl; + mess.printDataCout( critof001::msg_print_Hex | critof001::msg_print_Prefix | critof001::msg_print_Data ); + + } + pEpochDiff[nGet4] = epochDiff; + + } + } + /* + //------------------- CTRL ----------------------------// + else if (msgType == 0x02) + { + snprintf(buf, sizeof(buf), + "eTime %d - Ctrl Msg: 0x%016lx, Get4 %3d" , + lastGlobalEpoch, ulData, nGet4); + std::cout << buf << std::endl; + mess.printDataCout( critof001::msg_print_Hex | critof001::msg_print_Prefix | critof001::msg_print_Data ); + } + //------------------- ERROR ----------------------------// + else if (msgType == 0x03) + { + snprintf(buf, sizeof(buf), + "eTime %d - Error Msg: 0x%016lx, Get4 %3d, Error code 0x%02x", + lastGlobalEpoch, ulData, nGet4, errorCode); + std::cout << buf << std::endl; + mess.printDataCout( critof001::msg_print_Hex | critof001::msg_print_Prefix | critof001::msg_print_Data ); + + if (nGet4 < NGET4) + pErrorCnt[nGet4] = pErrorCnt[nGet4] +1; + if (errorCode == 0x12) + if (nGet4 < NGET4) + pTotCnt[nGet4]=pTotCnt[nGet4]+1; + if ( (nGet4 < NGET4) && (errorCode<NERROR) ) + pErrorCntMatrix[nGet4][errorCode]=pErrorCntMatrix[nGet4][errorCode]+1; + + } + //------------------- HITS ----------------------------// + else if (msgType == 0x0) + { + snprintf(buf, sizeof(buf), + "eTime %d - Hit Msg: 0x%016lx, Get4 %3d", + lastGlobalEpoch, ulData, nGet4); + std::cout << buf << std::endl; + mess.printDataCout( critof001::msg_print_Hex | critof001::msg_print_Prefix | critof001::msg_print_Data ); + if (nGet4 < NGET4) + pHitsCnt[nGet4]=pHitsCnt[nGet4]+1; + } + */ + /*snprintf(buf, sizeof(buf), + "Data: 0x%016lx", + ulData); + + std::cout << buf << std::endl;*/ + } + + } // for (uint32_t uIdx = 0; uIdx < uNbMessages; uIdx ++) + } // for( fuMsIndex = 0; fuMsIndex < uNbMsLoop; fuMsIndex ++ ) + } // for( UInt_t uMsCompIdx = 0; uMsCompIdx < fvMsComponentsList.size(); ++uMsCompIdx ) + + if (0 == fulCurrentTsIdx % 10000) LOG(info) << "Processed TS " << fulCurrentTsIdx; + + /* + uint32_t nPulses = 4*10000; + float effi; + for(uint32_t i =0; i < NGET4 ; i++) + { + effi = float(pHitsCnt[i])/float(nPulses) * 100.0; + snprintf(buf, sizeof(buf), + "Hit counter %d: Hits: %d Errors: %d ErrTot: %d Effi: %f", + i, pHitsCnt[i], pErrorCnt[i], pTotCnt[i], effi); + std::cout << buf << std::endl; + for(uint32_t j = 0; j<NERROR ; j++){ + if (pErrorCntMatrix[i][j] != 0){ + snprintf(buf, sizeof(buf), + "Error counter %d: error code: 0x%02x, times: %d", + i, j, pErrorCntMatrix[i][j]); + std::cout << buf << std::endl; + } + } + } + */ + + + return kTRUE; +} + +void CbmCriGet4RawPrint::Reset() +{ +} + +void CbmCriGet4RawPrint::Finish() {} + +ClassImp(CbmCriGet4RawPrint) diff --git a/fles/mcbm2018/unpacker/CbmCriGet4RawPrint.h b/fles/mcbm2018/unpacker/CbmCriGet4RawPrint.h new file mode 100644 index 0000000000..39c898f8df --- /dev/null +++ b/fles/mcbm2018/unpacker/CbmCriGet4RawPrint.h @@ -0,0 +1,78 @@ +/* Copyright (C) 2021 Facility for Antiproton and Ion Research in Europe, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Pierre-Alain Loizeau [committer] */ + +#ifndef CbmCriGet4RawPrint_H +#define CbmCriGet4RawPrint_H + +// Data +#include "Timeslice.hpp" + +#include "CriGet4Mess001.h" + +// CbmRoot +#include "CbmMcbmUnpack.h" + +// C/C++ +#include <map> +#include <vector> + +class CbmMcbm2018TofPar; + +class CbmCriGet4RawPrint : public CbmMcbmUnpack { +public: + CbmCriGet4RawPrint(); + + CbmCriGet4RawPrint(const CbmCriGet4RawPrint&) = delete; + CbmCriGet4RawPrint operator=(const CbmCriGet4RawPrint&) = delete; + + virtual ~CbmCriGet4RawPrint(); + + virtual Bool_t Init(); + virtual Bool_t DoUnpack(const fles::Timeslice& ts, size_t component); + virtual void Reset(); + + virtual void Finish(); + + void SetParContainers(); + + Bool_t InitContainers(); + + Bool_t ReInitContainers(); + + /// Temp until we change from CbmMcbmUnpack to something else + void AddMsComponentToList(size_t component, UShort_t usDetectorId); + void SetNbMsInTs(size_t /*uCoreMsNb*/, size_t /*uOverlapMsNb*/) {}; + + void SetIgnoreOverlapMs(Bool_t bFlagIn = kTRUE) { fbIgnoreOverlapMs = bFlagIn; } + +private: + /// Constants + static const Int_t kiMaxNbFlibLinks = 32; + static const UInt_t kuBytesPerMessage = 8; + + /// Parameters related to FLES containers + std::vector<size_t> fvMsComponentsList; //! + size_t fuNbCoreMsPerTs; //! + size_t fuNbOverMsPerTs; //! + size_t fuNbMsLoop; //! + Bool_t fbIgnoreOverlapMs; //! /** Ignore Overlap Ms: all fuNbOverMsPerTs MS at the end of timeslice **/ + Double_t fdMsSizeInNs; //! Size of a single MS, [nanoseconds] + Double_t fdTsCoreSizeInNs; //! Total size of the core MS in a TS, [nanoseconds] + Double_t fdTsFullSizeInNs; //! Total size of the core MS in a TS, [nanoseconds] + + /// Running indices + /// TS/MS info + ULong64_t fulCurrentTsIdx; + ULong64_t fulCurrentMsIdx; + Double_t fdTsStartTime; //! Time in ns of current TS from the index of the first MS first component + Double_t fdTsStopTimeCore; //! End Time in ns of current TS Core from the index of the first MS first component + Double_t fdMsTime; //! Start Time in ns of current MS from its index field in header + UInt_t fuMsIndex; //! Index of current MS within the TS + /// Current data properties + UInt_t fuCurrentEquipmentId; //! Current equipment ID, tells from which DPB the current MS is originating + + ClassDef(CbmCriGet4RawPrint, 1) +}; + +#endif diff --git a/macro/beamtime/mcbm2021/print_tsa_tof_data.C b/macro/beamtime/mcbm2021/print_tsa_tof_data.C new file mode 100644 index 0000000000..dc27dcc05b --- /dev/null +++ b/macro/beamtime/mcbm2021/print_tsa_tof_data.C @@ -0,0 +1,85 @@ +/* Copyright (C) 2021 Facility for Antiproton and Ion Research in Europe, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Pierre-Alain Loizeau [committer] */ + +/** @file MCBM DATA print CRI debug data from a tsa file for TOF + ** @author P.-A. Loizeau + ** @date 01.07.2019 + ** ROOT macro to read tsa files which have been produced with the new data transport + ** Convert tsa data to root data while keeping raw message format (loses the microslide meta data!). + ** Uses CbmMcbm2018Source as source task. + */ +// --- Specify number of TS to be converted. +// --- -1 means run until the end of the input file. +void print_tsa_tof_data(TString inFile = "", Int_t nrEvents = 0) +{ + TString srcDir = gSystem->Getenv("VMCWORKDIR"); + + // --- Specify number of events to be produced. + // --- -1 means run until the end of the input file. + Int_t nEvents = -1; + // --- Specify output file name (this is just an example) + TString outFile = "output.root"; + + // --- Set log output levels + FairLogger::GetLogger(); + gLogger->SetLogScreenLevel("INFO"); + //gLogger->SetLogScreenLevel("DEBUG"); + gLogger->SetLogVerbosityLevel("MEDIUM"); + + // --- Set debug level + gDebug = 0; + + std::cout << std::endl; + std::cout << ">>> convert_tsa_gdpb: output file is " << outFile << std::endl; + + // ======================================================================== + // ======================================================================== + std::cout << std::endl; + std::cout << ">>> print_tsa_data: Initialising..." << std::endl; + + CbmCriGet4RawPrint* raw_print_tof = new CbmCriGet4RawPrint(); + + raw_print_tof->SetIgnoreOverlapMs(); + + // --- Source task + CbmMcbm2018Source* source = new CbmMcbm2018Source(); + source->SetFileName(inFile); + source->AddUnpacker(raw_print_tof, 0x60, ECbmModuleId::kTof); //gDPB A & B & C + source->AddUnpacker(raw_print_tof, 0x90, ECbmModuleId::kTof); //gDPB T0 A & B + source->AddUnpacker(raw_print_tof, 0xc0, ECbmModuleId::kTof); //CRI TOF DEBUG + + // --- Run + FairRunOnline* run = new FairRunOnline(source); + run->SetOutputFile(outFile); + + run->Init(); + + // --- Start run + TStopwatch timer; + timer.Start(); + std::cout << ">>> print_tsa_data: Starting run..." << std::endl; + if (0 == nrEvents) { + run->Run(nEvents, 0); // run until end of input file + } + else { + run->Run(0, nrEvents); // process N Events + } + + timer.Stop(); + + std::cout << "Processed " << std::dec << source->GetTsCount() << " timeslices" << std::endl; + + // --- End-of-run info + Double_t rtime = timer.RealTime(); + Double_t ctime = timer.CpuTime(); + std::cout << std::endl << std::endl; + std::cout << ">>> print_tsa_data: Macro finished successfully." << std::endl; + std::cout << ">>> print_tsa_data: Output file is " << outFile << std::endl; + std::cout << ">>> print_tsa_data: Real time " << rtime << " s, CPU time " << ctime << " s" << std::endl; + std::cout << std::endl; + + /// --- Screen output for automatic tests + std::cout << " Test passed" << std::endl; + std::cout << " All ok " << std::endl; +} -- GitLab