Project
Loading...
Searching...
No Matches
ELinkDataShaper.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
16
18
21
22namespace o2
23{
24namespace mid
25{
26
27ELinkDataShaper::ELinkDataShaper(bool isDebugMode, bool isLoc, uint8_t uniqueId, const ElectronicsDelay& electronicsDelay) : mUniqueId(uniqueId), mElectronicsDelay(electronicsDelay)
28{
30 if (isDebugMode) {
31 if (isLoc) {
32 mOnDone = &ELinkDataShaper::onDoneLocDebug;
33 } else {
34 mOnDone = &ELinkDataShaper::onDoneRegDebug;
35 }
36 } else {
37 if (isLoc) {
38 mOnDone = &ELinkDataShaper::onDoneLoc;
39 } else {
40 mOnDone = &ELinkDataShaper::onDoneReg;
41 }
42 }
43 mLocalToBCSelfTrig = mElectronicsDelay.localToBC;
44 mElectronicsDelay.calibToFET += mElectronicsDelay.localToBC;
45 if (!isLoc) {
46 mLocalToBCSelfTrig -= electronicsDelay.localToReg;
47 }
48}
49
50void ELinkDataShaper::set(uint32_t orbit, uint32_t trigger)
51{
53
54 if (mIR.isDummy()) {
55 // First initialization
56 mIR.bc = 0;
57 mIR.orbit = orbit - 1;
59 } else if ((trigger & o2::trigger::TF || trigger & o2::trigger::SOT) && mRDHOrbit != orbit) {
60 // At TF limit, the CRU UL ensures that the first event is the answer of the electronics to a HB trigger,
61 // so it is the right time to synch with the orbit in the RDH.
62 // This also allows to consistently run on EPNs, since EPN receive packets of TFs
63 // and the orbit is not consecutive from one packet to the other.
64 // Notice that we subtract 1 to the orbit value, since the TF starts with the answer to a HB trigger,
65 // and the value will be therefore correctly incremented.
66 // Notice also that we might receive several RDH pages
67 // (at least two since there is always an empty stop page),
68 // but we want to set the orbit only for the first one.
69 // The easiest way to do it is to check that the current orbit differs from the last saved RDH orbit.
70 mIR.orbit = orbit - 1;
71 }
72 mRDHOrbit = orbit;
73}
74
75bool ELinkDataShaper::checkLoc(const ELinkDecoder& decoder)
76{
78 return (decoder.getId() == (mUniqueId & 0xF));
79}
80
81EventType ELinkDataShaper::processSelfTriggered(InteractionRecord& ir)
82{
84
85 // This is a self-triggered event.
86 // The physics data arrives with a delay compared to the BC,
87 // which is due to the travel time of muons up to the MID chambers
88 // plus the travel time of the signal to the readout electronics.
89 // In the case of regional cards, a further delay is expected
90 // since this card needs to wait for the tracklet decision of each local card.
91 // For simplicity, this delay is added to the localToBC in the constructor.
92 // In both cases, we need to correct for the delay in order to go back to the real BC.
93 applyElectronicsDelay(ir.orbit, ir.bc, mLocalToBCSelfTrig, mMaxBunches);
94 if (ir == mExpectedFET) {
95 return EventType::FET;
96 }
98}
99
100EventType ELinkDataShaper::processCalibrationTrigger(const InteractionRecord& ir)
101{
103 mExpectedFET = ir;
104 applyElectronicsDelay(mExpectedFET.orbit, mExpectedFET.bc, mElectronicsDelay.calibToFET, mMaxBunches);
105 return EventType::Calib;
106}
107
108void ELinkDataShaper::processHBTrigger(uint16_t localClock, uint8_t triggerWord)
109{
111
112 // The local clock is reset: we are now in synch with the new HB
113 ++mIR.orbit;
114 // The local clock value in an answer to the orbit trigger corresponds to the number of clocks elapsed since last reset.
115 // Since the HB trigger is reset at each orbit, this corresponds to the number of bunches.
116 // We need to add one because the local clock starts from 0.
117 mMaxBunches = localClock + 1;
118}
119
120bool ELinkDataShaper::processTrigger(const ELinkDecoder& decoder, EventType& eventType, InteractionRecord& ir)
121{
125 auto localClock = decoder.getCounter();
126
127 // FIXME: So far the bc information is not used
128 // since it seems that it is always equal to 0
129 // (at least in the RDH of the first page, which is what we need).
130 // In this case the local clock and the BC coincide.
131 // If this is not the case, the bc of the orbit trigger should be correctly taken into account
132 ir.bc = localClock;
133 // ir.bc = mIR.bc + localClock;
134 ir.orbit = mIR.orbit;
135
136 if (decoder.getTriggerWord() == 0) {
137 // This is a self-triggered event
138 eventType = processSelfTriggered(ir);
139 return true;
140 }
141
142 // From here we treat triggered events
143 bool goOn = false;
144 eventType = EventType::Standard;
145
146 if (decoder.getTriggerWord() & raw::sORB) {
147 // This is the answer to an HB trigger
148 processHBTrigger(localClock, decoder.getTriggerWord());
149 }
150
151 if (decoder.getTriggerWord() & raw::sCALIBRATE) {
152 // This is an answer to a calibration trigger
153 eventType = processCalibrationTrigger(ir);
154 goOn = true;
155 }
156
157 return goOn;
158}
159
160void ELinkDataShaper::addLoc(const ELinkDecoder& decoder, EventType eventType, InteractionRecord ir, std::vector<ROBoard>& data, std::vector<ROFRecord>& rofs)
161{
163 auto firstEntry = data.size();
164 data.push_back({decoder.getStatusWord(), decoder.getTriggerWord(), mUniqueId, decoder.getInputs()});
165 rofs.emplace_back(ir, eventType, firstEntry, 1);
166 for (int ich = 0; ich < 4; ++ich) {
167 if ((data.back().firedChambers & (1 << ich))) {
168 data.back().patternsBP[ich] = decoder.getPattern(0, ich);
169 data.back().patternsNBP[ich] = decoder.getPattern(1, ich);
170 }
171 }
172}
173
174void ELinkDataShaper::onDoneLoc(const ELinkDecoder& decoder, std::vector<ROBoard>& data, std::vector<ROFRecord>& rofs)
175{
177 EventType eventType;
178 InteractionRecord ir;
179 if (processTrigger(decoder, eventType, ir) && checkLoc(decoder)) {
180 addLoc(decoder, eventType, ir, data, rofs);
181 }
182}
183
184void ELinkDataShaper::onDoneLocDebug(const ELinkDecoder& decoder, std::vector<ROBoard>& data, std::vector<ROFRecord>& rofs)
185{
187 EventType eventType;
188 InteractionRecord ir;
189 processTrigger(decoder, eventType, ir);
190 addLoc(decoder, eventType, ir, data, rofs);
191}
192
193void ELinkDataShaper::onDoneRegDebug(const ELinkDecoder& decoder, std::vector<ROBoard>& data, std::vector<ROFRecord>& rofs)
194{
196 EventType eventType;
197 InteractionRecord ir;
198 processTrigger(decoder, eventType, ir);
199 // If we want to distinguish the two regional e-links, we can use the link ID instead
200 auto firstEntry = data.size();
201 data.push_back({decoder.getStatusWord(), decoder.getTriggerWord(), mUniqueId, decoder.getInputs()});
202 rofs.emplace_back(ir, eventType, firstEntry, 1);
203}
204
205} // namespace mid
206} // namespace o2
Definition of the 32 Central Trigger System (CTS) Trigger Types defined in https://twiki....
Properly formats and sets the absolute timestamp of the raw data.
uint64_t orbit
Definition RawEventData.h:6
Header to collect LHC related constants.
ELinkDataShaper(bool isDebugMode, bool isLoc, uint8_t uniqueId, const ElectronicsDelay &electronicsDelay)
void set(uint32_t orbit, uint32_t trigger)
uint8_t getId() const
Gets the card ID.
GLboolean * data
Definition glcorearb.h:298
constexpr int LHCMaxBunches
void applyElectronicsDelay(uint32_t &orbit, uint16_t &bc, int16_t delay, uint16_t maxBunches=constants::lhc::LHCMaxBunches)
constexpr uint32_t SOT
Definition Triggers.h:33
constexpr uint32_t TF
Definition Triggers.h:37
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
uint32_t orbit
LHC orbit.
uint16_t bc
bunch crossing ID of interaction
int16_t localToReg
Delay between regional board and local board answers.
int16_t calibToFET
Delay between FET and calibration event.
int16_t localToBC
Delay between collision BC and local clock.
o2::InteractionRecord ir(0, 0)