File indexing completed on 2026-07-16 08:13:56
0001 #ifndef Fun4All_TpcTimeFrameBuilderRun3_H
0002 #define Fun4All_TpcTimeFrameBuilderRun3_H
0003
0004 #include "TpcTimeFrameBuilderBase.h"
0005
0006 #include <algorithm>
0007 #include <array>
0008 #include <bitset>
0009 #include <cstdint>
0010 #include <deque>
0011 #include <functional>
0012 #include <iostream>
0013 #include <limits>
0014 #include <list>
0015 #include <map>
0016 #include <optional>
0017 #include <queue>
0018 #include <set>
0019 #include <string>
0020 #include <utility>
0021 #include <vector>
0022
0023 class Packet;
0024 class TpcRawHit;
0025 class TpcRawHitv3;
0026 using TpcRawHitRun3_typ = TpcRawHitv3;
0027 class PHTimer;
0028 class TH1;
0029 class TH2;
0030 class TTree;
0031
0032
0033 class TpcTimeFrameBuilderRun3 : public TpcTimeFrameBuilderBase
0034 {
0035 public:
0036 explicit TpcTimeFrameBuilderRun3(const int packet_id);
0037 ~TpcTimeFrameBuilderRun3() override;
0038
0039
0040 TpcTimeFrameBuilderRun3(const TpcTimeFrameBuilderRun3&) = delete;
0041 TpcTimeFrameBuilderRun3& operator=(const TpcTimeFrameBuilderRun3&) = delete;
0042 TpcTimeFrameBuilderRun3(TpcTimeFrameBuilderRun3&&) = delete;
0043 TpcTimeFrameBuilderRun3& operator=(TpcTimeFrameBuilderRun3&&) = delete;
0044
0045 int ProcessPacket(Packet *) override;
0046 bool isMoreDataRequired(const uint64_t >m_bco) const override;
0047 void CleanupUsedPackets(const uint64_t &bclk) override;
0048 std::vector<TpcRawHit *> &getTimeFrame(const uint64_t >m_bco) override;
0049
0050 void setVerbosity(int i) override;
0051 void setFastBCOSkip(bool fastBCOSkip = true)
0052 {
0053 m_fastBCOSkip = fastBCOSkip;
0054 }
0055
0056 void fillBadFeeMap() override;
0057
0058
0059 void SaveDigitalCurrentDebugTTree(const std::string &name) override;
0060 void SaveBXCounterSyncCDBTTree(const std::string &name) override;
0061
0062 protected:
0063
0064 static const size_t DAM_DMA_WORD_LENGTH = 16;
0065
0066 static const uint16_t FEE_PACKET_MAGIC_KEY_1 = 0xfe;
0067 static const uint16_t FEE_PACKET_MAGIC_KEY_2 = 0xed;
0068 static const uint16_t FEE_PACKET_MAGIC_KEY_3_DC = 0xdcdc;
0069
0070 static const uint16_t FEE_MAGIC_KEY = 0xba00;
0071 static const uint16_t GTM_MAGIC_KEY = 0xbb00;
0072 static const uint16_t GTM_LVL1_ACCEPT_MAGIC_KEY = 0xbbf0;
0073 static const uint16_t GTM_ENDAT_MAGIC_KEY = 0xbbf1;
0074 static const uint16_t GTM_MODEBIT_MAGIC_KEY = 0xbbf2;
0075
0076 static const uint16_t MAX_FEECOUNT = 26;
0077 static const uint16_t MAX_SAMPA = 8;
0078 static const uint16_t MAX_CHANNELS = MAX_SAMPA * 32;
0079
0080 static const uint16_t HEADER_LENGTH = 7;
0081 static const uint16_t MAX_PACKET_LENGTH = 1025;
0082
0083 static const uint16_t GL1_BCO_MATCH_WINDOW = 256;
0084
0085 int m_hitFormat = -1;
0086
0087 uint16_t reverseBits(const uint16_t x) const;
0088 std::pair<uint16_t, uint16_t> crc16_parity(const uint32_t fee, const uint16_t l) const;
0089
0090
0091 struct dma_word
0092 {
0093 uint16_t dma_header = 0;
0094 uint16_t data[DAM_DMA_WORD_LENGTH - 1] = {0};
0095 };
0096
0097 int decode_gtm_data(const dma_word >m_word);
0098 int process_fee_data(unsigned int fee_id);
0099 void process_fee_data_waveform(const unsigned int &fee_id, std::deque<uint16_t> &data_buffer);
0100 void process_fee_data_digital_current(const unsigned int &fee_id, std::deque<uint16_t> &data_buffer);
0101
0102 struct gtm_payload
0103 {
0104 uint16_t pkt_type = 0;
0105 bool is_endat = false;
0106 bool is_lvl1 = false;
0107 bool is_modebit = false;
0108 uint64_t bco = 0;
0109 uint32_t lvl1_count = 0;
0110 uint32_t endat_count = 0;
0111 uint64_t last_bco = 0;
0112 uint8_t modebits = 0;
0113 uint8_t userbits = 0;
0114 };
0115
0116 struct fee_payload
0117 {
0118 uint16_t fee_id = 0;
0119 uint16_t adc_length = 0;
0120 uint16_t sampa_address = 0;
0121 uint16_t sampa_channel = 0;
0122 uint16_t channel = 0;
0123 uint16_t type = 0;
0124 uint16_t user_word = 0;
0125 uint32_t bx_timestamp = 0;
0126 uint64_t gtm_bco = 0;
0127 bool has_clock_sync = false;
0128
0129 uint16_t data_crc = 0;
0130 uint16_t calc_crc = 0;
0131
0132 uint16_t data_parity = 0;
0133 uint16_t calc_parity = 0;
0134
0135 std::vector<std::pair<uint16_t, std::vector<uint16_t>>> waveforms;
0136 };
0137
0138 struct digital_current_payload
0139 {
0140 static const int MAX_CHANNELS = 8;
0141
0142 uint64_t gtm_bco{std::numeric_limits<uint64_t>::max()};
0143 uint32_t bx_timestamp_predicted{std::numeric_limits<uint32_t>::max()};
0144
0145 uint16_t fee{std::numeric_limits<uint16_t>::max()};
0146 uint16_t pkt_length{std::numeric_limits<uint16_t>::max()};
0147 uint16_t channel{std::numeric_limits<uint16_t>::max()};
0148
0149 uint16_t sampa_address{std::numeric_limits<uint16_t>::max()};
0150 uint32_t bx_timestamp{0};
0151 uint32_t current[MAX_CHANNELS]{0};
0152 uint32_t nsamples[MAX_CHANNELS]{0};
0153 uint16_t data_crc{std::numeric_limits<uint16_t>::max()};
0154 uint16_t calc_crc = {std::numeric_limits<uint16_t>::max()};
0155
0156 };
0157
0158 class DigitalCurrentDebugTTree
0159 {
0160 public:
0161 explicit DigitalCurrentDebugTTree(const std::string &name);
0162 virtual ~DigitalCurrentDebugTTree();
0163
0164 void fill(const digital_current_payload &payload);
0165
0166 private:
0167 digital_current_payload m_payload;
0168
0169 std::string m_name;
0170 TTree *m_tDigitalCurrent = nullptr;
0171 };
0172 DigitalCurrentDebugTTree *m_digitalCurrentDebugTTree = nullptr;
0173
0174
0175
0176
0177
0178 class BcoMatchingInformation
0179 {
0180 public:
0181
0182 explicit BcoMatchingInformation(const std::string &name);
0183
0184
0185
0186
0187
0188 int verbosity() const
0189 {
0190 return m_verbosity;
0191 }
0192
0193
0194
0195
0196
0197
0198 bool is_verified() const
0199 {
0200 return m_verified_from_modebits || m_verified_from_data;
0201 }
0202
0203
0204 using m_gtm_fee_bco_matching_pair_t = std::pair<uint64_t, uint32_t>;
0205 using m_fee_gtm_bco_matching_pair_t = std::pair<uint32_t, uint64_t>;
0206 struct BXCounterSyncObservation
0207 {
0208 uint64_t bx_counter_sync_gtm_bco = 0;
0209 uint64_t bco_reference_gtm_bco = 0;
0210 m_gtm_fee_bco_matching_pair_t m_bco_reference = {0, 0};
0211 };
0212
0213
0214 static constexpr size_t kMaxBXCounterSyncObservations = 4;
0215
0216
0217 const std::optional<m_gtm_fee_bco_matching_pair_t> &get_reference_bco() const
0218 {
0219 return m_bco_reference;
0220 }
0221
0222 const std::array<BXCounterSyncObservation, kMaxBXCounterSyncObservations> &get_bx_counter_sync_observations() const
0223 {
0224 return m_bx_counter_sync_observations;
0225 }
0226
0227 size_t get_bx_counter_sync_observation_count() const
0228 {
0229 return m_bx_counter_sync_observation_count;
0230 }
0231
0232
0233 bool isMoreDataRequired(const uint64_t >m_bco) const;
0234
0235
0236 std::optional<uint32_t> get_predicted_fee_bco(uint64_t) const;
0237
0238
0239 void print_gtm_bco_information() const;
0240
0241
0242 size_t get_gtm_bco_trig_list_size() const
0243 {
0244 return m_gtm_bco_trig_list.size();
0245 }
0246
0247
0248 size_t get_bco_heartbeat_list_size() const
0249 {
0250 return m_bco_heartbeat_list.size();
0251 }
0252
0253
0254 size_t get_gtm_bco_trigger_map_size() const
0255 {
0256 return m_gtm_bco_trigger_map.size();
0257 }
0258
0259
0260 size_t get_bco_matching_list_size() const
0261 {
0262 return m_bco_matching_list.size();
0263 }
0264
0265
0266
0267
0268
0269
0270
0271 void set_verbosity(int value)
0272 {
0273 m_verbosity = value;
0274 }
0275
0276
0277 uint64_t get_gtm_rollover_correction(const uint64_t >m_bco) const;
0278
0279
0280 std::optional<uint64_t> find_reference_heartbeat(const fee_payload &HeartBeatPacket);
0281
0282
0283 void save_gtm_bco_information(const gtm_payload >m_tagger);
0284
0285
0286
0287
0288
0289 void cleanup();
0290
0291
0292 void cleanup(uint64_t );
0293
0294 m_gtm_fee_bco_matching_pair_t find_dc_read_bco() const
0295 {
0296 return m_gtm_bco_dc_read;
0297 }
0298
0299
0300
0301 enum SampaDataType
0302 {
0303 HEARTBEAT_T = 0b000,
0304 TRUNCATED_DATA_T = 0b001,
0305 TRUNCATED_TRIG_EARLY_DATA_T = 0b011,
0306 NORMAL_DATA_T = 0b100,
0307 LARGE_DATA_T = 0b101,
0308 TRIG_EARLY_DATA_T = 0b110,
0309 TRIG_EARLY_LARGE_DATA_T = 0b111,
0310 };
0311
0312
0313
0314
0315
0316
0317
0318
0319
0320
0321
0322 enum ModeBitType
0323 {
0324 BX_COUNTER_SYNC_T = 0x1,
0325 ELINK_HEARTBEAT_T = 0x2,
0326 DC_STOP_SEND_T = 0x7
0327
0328
0329
0330 };
0331
0332
0333 template <class T>
0334 inline static constexpr T get_bco_diff(
0335 const T &first, const T &second)
0336 {
0337 return first < second ? (second - first) : (first - second);
0338 }
0339
0340
0341 inline static constexpr uint32_t get_fee_bco_diff(
0342 const uint32_t &first, const uint32_t &second)
0343 {
0344 const uint32_t diff_raw = get_bco_diff(first, second);
0345 const uint32_t half_range = 1U << (m_FEE_CLOCK_BITS - 1);
0346 const uint32_t full_range = 1U << m_FEE_CLOCK_BITS;
0347 return (diff_raw <= half_range) ? diff_raw : full_range - diff_raw;
0348 }
0349
0350 private:
0351 void save_bx_counter_sync_observation(uint64_t bx_counter_sync_gtm_bco,
0352 uint64_t bco_reference_gtm_bco,
0353 const m_gtm_fee_bco_matching_pair_t &bco_reference);
0354
0355 std::string m_name;
0356
0357
0358 unsigned int m_verbosity = 0;
0359
0360
0361 bool m_verified_from_modebits = false;
0362
0363 bool m_verified_from_data = false;
0364
0365
0366 std::list<uint64_t> m_gtm_bco_trig_list;
0367
0368
0369 m_gtm_fee_bco_matching_pair_t m_gtm_bco_dc_read = {0, 0};
0370
0371
0372 std::optional<m_gtm_fee_bco_matching_pair_t> m_bco_reference = std::nullopt;
0373
0374
0375 std::array<BXCounterSyncObservation, kMaxBXCounterSyncObservations> m_bx_counter_sync_observations;
0376 size_t m_bx_counter_sync_observation_count = 0;
0377
0378
0379
0380 std::list<m_gtm_fee_bco_matching_pair_t> m_bco_heartbeat_list;
0381 static constexpr unsigned int m_max_bco_heartbeat_list_size = 16;
0382
0383
0384
0385
0386
0387
0388 std::map<uint64_t, uint32_t> m_gtm_bco_trigger_map;
0389
0390 std::list<m_fee_gtm_bco_matching_pair_t> m_bco_matching_list;
0391
0392
0393 static constexpr int m_max_lv1_endat_bco_diff = 16;
0394
0395
0396 static constexpr unsigned int m_max_fee_bco_diff = 64;
0397
0398
0399
0400
0401 static constexpr unsigned int m_max_gtm_bco_diff = 256;
0402
0403
0404 static constexpr unsigned int m_max_matching_data_size = 10;
0405
0406
0407 static constexpr unsigned int m_max_fee_sync_time = 1024 * 8;
0408
0409
0410 static constexpr uint64_t kBXCounterSyncGtmBcoOffset = 0;
0411
0412 static constexpr uint64_t kBXCounterSyncFEEBcoOffset = 12;
0413
0414 static constexpr unsigned int m_FEE_CLOCK_BITS = 20;
0415 static constexpr unsigned int m_GTM_CLOCK_BITS = 40;
0416
0417
0418 static constexpr int64_t m_clock_ratio_numerator = 30;
0419 static constexpr int64_t m_clock_ratio_denominator = 8;
0420
0421 TH1 *m_hNorm = nullptr;
0422 TH1 *m_hFEEClockAdjustment_MatchedReference = nullptr;
0423 TH1 *m_hFEEClockAdjustment_MatchedNew = nullptr;
0424 TH1 *m_hFEEClockAdjustment_Unmatched = nullptr;
0425 TH1 *m_hGTMNewEventSpacing = nullptr;
0426
0427
0428
0429 };
0430
0431 private:
0432 std::vector<std::deque<uint16_t>> m_feeData;
0433
0434 std::map<int, std::set<int>> m_maskedFEEs;
0435
0436 int m_verbosity = 0;
0437 int m_packet_id = 0;
0438
0439
0440 std::string m_HistoPrefix;
0441 std::string m_bxCounterSyncCDBTTreeName;
0442
0443 static constexpr uint32_t kFEEClockMask = (1U << 20U) - 1U;
0444 static constexpr uint32_t kRun3FeeMatchWindow = (GL1_BCO_MATCH_WINDOW * 30U + 7U) / 8U;
0445 static constexpr int32_t kRun3ExactMatchWindow = 6;
0446 static constexpr uint32_t kRun3FEEClockPerADCClock = 2U;
0447 static constexpr uint32_t kRun3TruncatedWaveformRecoveryWindow = 1024U;
0448 static constexpr uint32_t kRun3TruncatedWaveformRecoveryFEEWindow =
0449 kRun3TruncatedWaveformRecoveryWindow * kRun3FEEClockPerADCClock;
0450 static constexpr int kRun3NormalizationBaseBinCount = 20;
0451 static constexpr int kRun3NormalizationBinCount = kRun3NormalizationBaseBinCount + MAX_FEECOUNT;
0452
0453 static int64_t get_signed_fee_bco_diff(uint32_t first, uint32_t second);
0454 static uint32_t get_fee_bco_diff(uint32_t first, uint32_t second);
0455 size_t move_time_hits(uint32_t fee_bco, uint16_t fee, std::vector<TpcRawHit *> &timeframe);
0456 size_t count_time_hits(uint32_t fee_bco, uint16_t fee) const;
0457 size_t time_hit_bucket_count() const;
0458 std::optional<uint32_t> find_fuzzy_fee_bco(uint32_t predicted_fee_bco, uint16_t fee) const;
0459 size_t recover_truncated_waveforms(uint32_t predicted_fee_bco, uint16_t fee, std::vector<TpcRawHit *> &timeframe);
0460 size_t append_shifted_waveforms(TpcRawHitRun3_typ *target, const TpcRawHit &source, uint32_t fee_clock_shift) const;
0461 void cleanup_time_hit_map(uint64_t bclk_rollover_corrected, uint32_t fee_clock_window);
0462 void flush_previous_timeframe_qa_cache(uint64_t current_gtm_bco);
0463 void fill_waveform_gl1_spacing(TH1 *waveform_adc_cache, TH2 *waveform_gl1_spacing, uint64_t gtm_bco_spacing) const;
0464 void cache_waveform_adc(TH1 *waveform_adc_cache, const std::vector<TpcRawHit *> &timeframe) const;
0465 void cache_timeframe_qa(uint64_t gtm_bco, const std::vector<TpcRawHit *> &timeframe, const std::bitset<MAX_FEECOUNT> &exact_matched_fees);
0466 void write_bx_counter_sync_cdb_tree() const;
0467
0468
0469 std::vector<std::map<uint32_t, std::vector<TpcRawHit *>>> m_timeHitMap;
0470
0471
0472 std::map<uint64_t, std::vector<TpcRawHit *>> m_timeFrameMap;
0473
0474
0475 std::optional<uint64_t> m_previousTimeFrameGtmBco;
0476 std::bitset<MAX_FEECOUNT> m_previousTimeFrameExactFees;
0477 std::bitset<MAX_FEECOUNT> m_previousTimeFrameRecoveredFees;
0478 int m_hNormTruncatedWaveformRecoveryFeeFirstBin = 0;
0479 static const size_t kMaxRawHitLimit = 10000;
0480 std::queue<uint64_t> m_UsedTimeFrameSet;
0481
0482
0483 bool m_fastBCOSkip = false;
0484
0485
0486 std::vector<BcoMatchingInformation> m_bcoMatchingInformation_vec;
0487
0488
0489
0490 PHTimer *m_packetTimer = nullptr;
0491
0492 TH1 *m_hNorm = nullptr;
0493 TH2 *m_hFEEDataStream = nullptr;
0494 TH1 *m_hFEEChannelPacketCount = nullptr;
0495 TH2 *m_hFEESAMPAADC = nullptr;
0496 TH1 *m_hFEESAMPAHeartBeatSync = nullptr;
0497
0498 TH1 *h_PacketLength = nullptr;
0499 TH1 *h_PacketLength_Padding = nullptr;
0500 TH1 *h_PacketLength_Residual = nullptr;
0501
0502 TH1 *h_GTMClockDiff_Matched = nullptr;
0503 TH1 *h_GTMClockDiff_Unmatched = nullptr;
0504 TH1 *h_GTMClockDiff_Dropped = nullptr;
0505 TH1 *h_TimeFrame_Matched_Size = nullptr;
0506 TH2 *h_Run3_FEE_GTMMatching_ClockDiff = nullptr;
0507 TH1 *h_Run3TimeFrameExactHit_FEE = nullptr;
0508 TH1 *h_Run3TimeFrameFuzzyHit_FEE = nullptr;
0509 TH1 *h_Run3PreviousTimeFrameWaveformADC = nullptr;
0510 TH1 *h_Run3PreviousTimeFrameRecoveredWaveformADC = nullptr;
0511 TH2 *h_Run3Waveform_GL1Spacing = nullptr;
0512 TH2 *h_Run3WaveformRecovered_GL1Spacing = nullptr;
0513 TH2 *h_Run3FEE_TimeFrameCount_GL1Spacing = nullptr;
0514 TH2 *h_Run3FEE_TimeFrameRecoveredCount_GL1Spacing = nullptr;
0515 TH2 *h_Run3FEE_TriggerCount_GL1Spacing = nullptr;
0516
0517 TH2 *h_ProcessPacket_Time = nullptr;
0518 };
0519
0520 #endif