1#include "Packing/ECONDDecoder.h"
6#include "DetDescr/HcalElectronicsID.h"
16const std::array<const char*, MultiSampleECONDEventPacket::N_CORRUPTION>
17 FRAME_FLAG_NAMES = {
"resync (missing capture header)",
20 "trailer sample count mismatch",
22 "sample index mismatch",
24 "non-zero words after trailer",
25 "no sample of interest"};
27const std::array<const char*, ECONDEventPacket::N_CORRUPTION>
28 PACKET_FLAG_NAMES = {
"bad header marker (missing ECON-D header)",
32 "bad payload (link sub-packets do not fit)",
33 "truncated (T flag)"};
36template <std::
size_t N>
37int toMask(
const std::array<bool, N>& flags) {
39 for (std::size_t i{0}; i < N; i++) {
40 if (flags[i]) mask |= (1 << i);
77 info.setFrame(1 << ldmx::ECONDEventInfo::NO_FRAME, -1, 0, 0);
83 const auto& raw_binary{
87 int frame_corruption{0};
88 if (raw_binary.size() % 4 != 0) {
90 <<
" bytes which is not a multiple of 4, ignoring the "
91 << raw_binary.size() % 4 <<
" trailing bytes";
92 frame_corruption |= (1 << ldmx::ECONDEventInfo::BAD_FRAME_SIZE);
96 std::vector<uint32_t> words(raw_binary.size() / 4);
97 std::memcpy(words.data(), raw_binary.data(), words.size() * 4);
101 frame_corruption |= toMask(pkt.corruption_);
102 for (std::size_t i{0}; i < pkt.corruption_.size(); i++) {
106 bool all_good = (frame_corruption == 0) and not pkt.samples_.empty();
107 for (std::size_t i_sample{0}; i_sample < pkt.samples_.size(); i_sample++) {
108 const auto& header{pkt.headers_[i_sample]};
109 const auto& sample{pkt.samples_[i_sample]};
114 header.is_soi_, header.econd_len_);
115 int flags = (sample.passthrough_ ? 1 : 0) | (sample.expected_ ? 2 : 0) |
116 (sample.match_ ? 4 : 0) | (sample.truncated_ ? 8 : 0) |
117 (sample.subpacket_error_ ? 16 : 0);
118 sample_info.
setHeader(sample.payload_length_, flags, sample.ht_,
119 sample.ebo_, sample.bx_, sample.l1a_, sample.orbit_,
120 sample.reset_request_);
123 for (std::size_t i{0}; i < sample.corruption_.size(); i++) {
127 if (sample.isCorrupt()) {
130 }
else if (sample.isEmpty()) {
135 for (
const auto& link : sample.links_) {
138 link_info.
set(link.stat_, link.is_empty_, link.adc_cm0_, link.adc_cm1_,
140 sample_info.
addLink(link_info);
145 if (i_sample > 0 and not sample.isCorrupt() and
146 not pkt.samples_[i_sample - 1].isCorrupt() and
147 sample.l1a_ != ((pkt.samples_[i_sample - 1].l1a_ + 1) & 0x3f)) {
151 info.addSample(sample_info);
154 info.setFrame(frame_corruption, pkt.trailer_n_samples_, pkt.i_soi_,
155 pkt.n_skipped_words_);
158 std::size_t n_samples{pkt.samples_.size()};
162 std::vector<uint32_t> digi(n_samples);
163 for (
int i_link{0}; i_link <
n_links_; i_link++) {
164 for (
int i_ch{0}; i_ch < 36; i_ch++) {
165 for (std::size_t i_sample{0}; i_sample < n_samples; i_sample++) {
167 pkt.samples_[i_sample].links_[i_link].channels_[i_ch];
169 unsigned int id{
channelID(i_link, i_ch)};
175 if (not detmap.exists(eid))
continue;
176 id = detmap.get(eid).raw();
181 if (not detmap.exists(eid))
continue;
182 id = detmap.get(eid).raw();
190 info.setDigisFilled(all_good);
197 ldmx_log(info) <<
"ECON-D decoding summary for " <<
raw_data_name_;
198 ldmx_log(info) <<
" frames seen: " <<
n_frames_
201 ldmx_log(info) <<
" events without a frame: " <<
n_no_frame_;
204 ldmx_log(info) <<
" frames with size not a multiple of 4 bytes: "
209 ldmx_log(info) <<
" frames with " << FRAME_FLAG_NAMES[i] <<
": "
213 ldmx_log(info) <<
" packets seen: " <<
n_packets_
219 ldmx_log(info) <<
" packets with " << PACKET_FLAG_NAMES[i] <<
": "
224 ldmx_log(info) <<
" decoded links with bad Stat bits: "
227 ldmx_log(info) <<
" L1A jumps between samples: " <<
n_l1a_jumps_;
Classes holding the ECON-D packet data that does not fit into an HgcrocDigiCollection.
Class which contains logic for how the detector items connect to and relate with the reconstruction c...
Class that identifies a location in the Ecal readout chain.
#define DECLARE_PRODUCER(CLASS)
Macro which allows the framework to construct a producer given its name during configuration.
Class which contains logic for how the detector items connect to and relate with the reconstruction c...
Class that represents a digitized hit in a calorimeter cell readout by an HGCROC.
static constexpr const char * CONDITIONS_OBJECT_NAME
The name of the EID <-> DetID map for the ECal.
const T & getCondition(const std::string &condition_name)
Access a conditions object for the current event.
Implements an event buffer system for storing event data.
bool exists(const std::string &name, const std::string &passName, bool unique=true) const
Check for the existence of an object or collection with the given name and pass name in the event.
Class encapsulating parameters for configuring a processor.
const T & get(const std::string &name) const
Retrieve the parameter of the given name.
static constexpr const char * CONDITIONS_OBJECT_NAME
The name of the EID <-> DetID map for the ECal.
Supporting data for one event decoded from a single ECON-D.
Data from one eRx ("link") sub-packet of an ECON-D packet that is not a normal channel.
void set(int stat, bool is_empty, int adc_cm0, int adc_cm1, uint32_t calib)
Set the link data.
Capture header and ECON-D header data for one sample (L1A)
void setHeader(int payload_length, int flags, int ht, int ebo, int bx, int l1a, int orbit, int reset_request)
Set the ECON-D event header data.
void setCaptureHeader(int econ_id, int i_sample, bool is_soi, int length)
Set the capture header data.
void addLink(const ECONDLinkInfo &link)
add the data from the next link
void setCorruption(int mask)
set the corruption mask
Identifies a location in the Ecal readout chain.
Identifies a location in the Hcal readout chain.
Represents a collection of the digi hits readout by an HGCROC.
void setNumSamplesPerDigi(unsigned int n)
Set number of samples for each digi.
void setSampleOfInterestIndex(unsigned int n)
Set index of sample of interest.
void setVersion(int v)
Set the version of the ROC we have read.
void addDigi(unsigned int id, const std::vector< Sample > &digi)
Add samples to collection.
decode event packets built by ECON-D chips
int roc_version_
ROC version for the digi collection.
long n_l1a_jumps_
number of L1A jumps between consecutive samples
std::string raw_data_pass_
name of pass to get raw binary data from
long n_packets_empty_
number of empty packets (payload length 0)
void configure(framework::config::Parameters &ps) override
configure the decoder
bool translate_eid_
translate electronics IDs into detector IDs
std::string raw_data_name_
name of event object of raw binary data
int fiber_
optical fiber index used in the electronics ID
std::string digi_output_name_
output name of digi collection
int n_links_
number of enabled eRx on the ECON-D
std::string info_output_name_
output name of supporting data object
long n_links_bad_stat_
number of decoded link sub-packets with bad Stat bits
void onProcessEnd() override
print a summary of the decoding
void produce(framework::Event &event) override
decode the raw binary data into HgcrocDigiCollection that can be used later for reconstruction or ana...
long n_packets_
number of packets seen
unsigned int channelID(int i_link, int i_ch) const
get the channel ID for the input link and channel
long n_packets_corrupt_
number of corrupted packets (skipped)
std::array< long, MultiSampleECONDEventPacket::N_CORRUPTION > n_frame_flags_
number of frames with each frame-level flag
std::array< long, ECONDEventPacket::N_CORRUPTION > n_packet_flags_
number of packets with each corruption flag
long n_packets_decoded_
number of packets decoded without corruption and not empty
long n_no_frame_
number of events without an input frame
long n_bad_frame_size_
number of frames with a size that is not a multiple of 4 bytes
long n_frames_filled_
number of frames whose digis were filled
bool is_ecal_
which calorimeter subsystem we are decoding (true == Ecal, false == Hcal)
long n_frames_
number of frames seen
std::unique_ptr< MultiSampleECONDEventPacket > packet_
decoding buffer