Make the Scan method public
[u/mrichter/AliRoot.git] / MUON / AliMUONTrackerDDLDecoderEventHandler.h
CommitLineData
e3a2b9c9 1#ifndef ALIMUONTRACKERDDLDECODEREVENTHANDLER_H
2#define ALIMUONTRACKERDDLDECODEREVENTHANDLER_H
3/**************************************************************************
4 * This file is property of and copyright by the ALICE HLT Project *
5 * All rights reserved. *
6 * *
7 * Primary Authors: *
8 * Artur Szostak <artursz@iafrica.com> *
9 * *
10 * Permission to use, copy, modify and distribute this software and its *
11 * documentation strictly for non-commercial purposes is hereby granted *
12 * without fee, provided that the above copyright notice appears in all *
13 * copies and that both the copyright notice and this permission notice *
14 * appear in the supporting documentation. The authors make no claims *
15 * about the suitability of this software for any purpose. It is *
16 * provided "as is" without express or implied warranty. *
17 **************************************************************************/
18
19/* $Id$ */
20
21///
22/// \file AliMUONTrackerDDLDecoderEventHandler.h
23/// \author Artur Szostak <artursz@iafrica.com>
24/// \date 28-11-2007
25/// \brief Implementation of a high performance DDL decoder event handler
26/// for the muon tracking stations.
27///
28
29#include <cassert>
30#include <ostream>
31#include <Rtypes.h>
32
33
34// We use C binding for the structures because C is more uniform with its application
35// binary interface (ABI) between compilers.
36extern "C"
37{
38
39// The following structures are the headers found in the DDL payload from the
40// muon tracking chambers. The specification is defined in ALICE-INT-2005-012
41// (https://edms.cern.ch/file/591904/1/ALICE-INT-2005-012.pdf)
42
43/// The block header structure of the Tracker DDL payload.
44struct AliMUONBlockHeaderStruct
45{
46 UInt_t fDataKey; ///< Data key word for CRT header
47 UInt_t fTotalLength; ///< total length of block structure (w/o padding word)
48 UInt_t fLength; ///< length of raw data
49 UInt_t fDSPId; ///< DSP id
50 UInt_t fL0Trigger; ///< L0 trigger word
51 UInt_t fMiniEventId; ///< Bunch Crossing for mini-event id (see TDR chapter 8)
52 UInt_t fEventId1; ///< Event Id in bunch crossing
53 UInt_t fEventId2; ///< Event Id in orbit number
54};
55
56/// The DSP header structure of the Tracker DDL payload.
57struct AliMUONDSPHeaderStruct
58{
59 UInt_t fDataKey; ///< Data key word for FRT header
60 UInt_t fTotalLength; ///< total length of block structure
61 UInt_t fLength; ///< length of raw data
62 UInt_t fDSPId; ///< DSP id
63 UInt_t fBlkL1ATrigger; ///< L1 accept in Block Structure (CRT)
64 UInt_t fMiniEventId; ///< Mini Event Id in bunch crossing
65 UInt_t fL1ATrigger; ///< Number of L1 accept in DSP Structure (FRT)
66 UInt_t fL1RTrigger; ///< Number of L1 reject in DSP Structure (FRT)
67 UInt_t fPaddingWord; ///< padding dummy word for 64 bits transfer
68 UInt_t fErrorWord; ///< Error word
69};
70
71/// The bus patch header structure of the Tracker DDL payload.
72struct AliMUONBusPatchHeaderStruct
73{
74 UInt_t fDataKey; ///< Data key word for bus patch header
75 UInt_t fTotalLength; ///< total length of bus patch structure
76 UInt_t fLength; ///< length of raw data
77 UInt_t fBusPatchId; ///< bus patch id
78};
79
80} // extern "C"
81
82
83/// \ingroup raw
84/// \class AliMUONTrackerDDLDecoderEventHandler
85/// \brief Callback event handler class for the AliMUONTrackerDDLDecoder.
86///
87/// This class is the base class defining what methods the event handler for the
88/// high performance decoder should have. This handler actually does nothing.
89/// The user of this decoder will have to derive from this class a custom event
90/// handler that actually does something within the callback methods OnNewBusPatch,
91/// OnData, OnError etc...
92///
93/// \author Artur Szostak <artursz@iafrica.com>
94
95class AliMUONTrackerDDLDecoderEventHandler
96{
97public:
98
99 /// The only reason for a virtual destructor is to make -Weffc++ shutup.
8a0dae7c 100 /// This should not really be here since we do not need or use virtual methods.
e3a2b9c9 101 virtual ~AliMUONTrackerDDLDecoderEventHandler() {}
102
103 /// All the possible error codes for the parsing.
104 enum ErrorCode
105 {
106 kNoError = 0, /// Decoding was successful.
107 // Offset our error codes to stay clear of any common codes in AliMUONRawStreamTracker:
108 kBufferTooBig = 10, /// The DDL raw data is larger than indicated by the headers; extra bytes are probably just garbage.
109 kTooManyBlocks = 11, /// Too many block structures found.
110 kTooManyDSPs = 12, /// Too many DSP structures found in the block.
111 kTooManyBusPatches = 13, /// Too many bus patch structures found in the DSP structure.
112 kNoBlockHeader = 14, /// Missing a block header.
113 kBadBlockKey = 15, /// The block header key word does not contain the correct value.
114 kBadBlockLength = 16, /// The block length field points past the end of the raw data size.
115 kBadBlockTotalLength = 17, /// The total block length field points past the end of the raw data size.
116 kBlockLengthMismatch = 18, /// The block length and total length fields do not correspond. One or both of these values is incorrect.
117 kNoDSPHeader = 19, /// Missing a DSP header.
118 kBadDSPKey = 20, /// The DSP header key word does not contain the correct value.
119 kBadDSPLength = 21, /// The DSP structure length field points past the end of the block structure.
120 kBadDSPTotalLength = 22, /// The total DSP structure length field points past the end of the block structure.
121 kDSPLengthMismatch = 23, /// The DSP structure length and total length fields do not correspond. One or both of these values is incorrect.
122 kNoBusPatchHeader = 24, /// Missing a bus patch header.
123 kBadBusPatchKey = 25, /// The bus patch header key word does not contain the correct value.
124 kBadBusPatchLength = 26, /// The bus patch length field points past the end of the DSP structure.
125 kBadBusPatchTotalLength = 27, /// The total bus patch length field points past the end of the DSP structure.
126 kBusPatchLengthMismatch = 28, /// The bus patch length and total length fields do not correspond. One or both of these values is incorrect.
29b6be6a 127 kNoDDLTrailerWords = 29, /// No end of DDL markers found in the trailer words.
128 kTooFewDDLTrailerWords = 30, /// Only one end of DDL marker trailer word found but expected two.
74585128 129 kUnknownDspError = 31, /// The DSP error code is non-zero but of an unrecognised format.
130 kTokenLost = 32, /// The DSP contains a token lost error code that can affect the deadtime.
e3a2b9c9 131 // match up error codes with AliMUONRawStreamTracker:
132 kGlitchFound = 1, /// Found a glitch. This means a 1 byte word has been randomly inserted into the raw data by mistake.
133 kBadPaddingWord = 2, /// The padding word does not contain the correct value.
134 kParityError = 3 /// Found a parity error in the data word.
135 };
136
137 // The following methods should be overridden for specific processing to
138 // take place in your event handler.
139
140 /// The OnNewBuffer method will be called whenever a new buffer containing
141 /// a DDL payload is about to be processed.
142 /// The default behaviour of this method is to do nothing.
143 /// - param const void* The pointer to the start of the memory buffer storing
144 /// the DDL payload.
145 /// - param UInt_t The size in bytes of the memory buffer.
146 void OnNewBuffer(const void* /*buffer*/, UInt_t /*bufferSize*/) {}
147
e0173291 148 /// The OnEndOfBuffer method will be called whenever the buffer containing
149 /// a DDL payload has been processed. For each OnNewBuffer method call a
150 /// symmetric call to OnEndOfBuffer is made at the end of processing (after
151 /// the last call to OnData)
152 /// The default behaviour of this method is to do nothing.
153 /// - param const void* The pointer to the start of the memory buffer storing
154 /// the DDL payload.
155 /// - param UInt_t The size in bytes of the memory buffer.
8a0dae7c 156 void OnEndOfBuffer(const void* /*buffer*/, UInt_t /*bufferSize*/) {}
157
e3a2b9c9 158 /// OnNewBlock is called whenever a new block header is found in the payload.
159 /// The default behaviour of this method is to do nothing.
e0173291 160 /// - param const AliMUONBlockHeaderStruct* This is a pointer to the block header
161 /// as found in the DDL payload.
e3a2b9c9 162 /// - param const void* This is a pointer to the start of the block's contents.
e0173291 163 /// Note: both pointers point into the memory buffer being parsed, so the
e3a2b9c9 164 /// contents must not be modified. On the other hand this is very efficient
165 /// because no memory copying is required.
166 void OnNewBlock(const AliMUONBlockHeaderStruct* /*header*/, const void* /*data*/) {}
167
e0173291 168 /// OnEndOfBlock is called whenever a block has been processed. Symmetric
169 /// calls are made to OnEndOfBlock after each call to OnNewBlock. This happens
170 /// once all DSP structures contained inside the current block have been
171 /// processed.
172 /// The default behaviour of this method is to do nothing.
173 /// - param const AliMUONBlockHeaderStruct* This is a pointer to the processed
174 /// block header as found in the DDL payload.
175 /// - param const void* This is a pointer to the start of the block's contents.
176 /// Note: both pointers point into the memory buffer being parsed, so the
177 /// contents must not be modified. On the other hand this is very efficient
178 /// because no memory copying is required.
8a0dae7c 179 void OnEndOfBlock(const AliMUONBlockHeaderStruct* /*header*/, const void* /*data*/) {}
180
e3a2b9c9 181 /// OnNewDSP is called whenever a new DSP header is found in the payload.
24a0fe9f 182 /// Every DSP header received by a call to OnNewDSP is associated to the
e3a2b9c9 183 /// block header received in the most recent call to OnNewBlock.
184 /// The default behaviour of this method is to do nothing.
e0173291 185 /// - param const AliMUONDSPHeaderStruct* This is a pointer to the DSP header
186 /// as found in the DDL payload.
e3a2b9c9 187 /// - param const void* This is a pointer to the start of the DSP's contents.
e0173291 188 /// Note: both pointers point into the memory buffer being parsed, so the
e3a2b9c9 189 /// contents must not be modified. On the other hand this is very efficient
190 /// because no memory copying is required.
191 void OnNewDSP(const AliMUONDSPHeaderStruct* /*header*/, const void* /*data*/) {}
192
e0173291 193 /// OnEndOfDSP is called whenever a DSP header has already been processed.
194 /// For every call to OnNewDSP a symmetric call to OnEndOfDSP is made once
195 /// all the bus patch structured contained in the DSP are processed.
196 /// The default behaviour of this method is to do nothing.
197 /// - param const AliMUONDSPHeaderStruct* This is a pointer to the already
198 /// processed DSP header as found in the DDL payload.
199 /// - param const void* This is a pointer to the start of the DSP's contents.
200 /// Note: both pointers point into the memory buffer being parsed, so the
201 /// contents must not be modified. On the other hand this is very efficient
202 /// because no memory copying is required.
8a0dae7c 203 void OnEndOfDSP(const AliMUONDSPHeaderStruct* /*header*/, const void* /*data*/) {}
204
e3a2b9c9 205 /// OnNewBusPatch is called whenever a new bus patch header is found in
e0173291 206 /// the payload. Every bus patch received by a call to OnNewBusPatch is
e3a2b9c9 207 /// associated to the DSP header received in the most recent call to OnNewDSP.
208 /// The default behaviour of this method is to do nothing.
e0173291 209 /// - param const AliMUONBusPatchHeaderStruct* This is a pointer to the bus patch
210 /// header as found in the DDL payload.
e3a2b9c9 211 /// - param const void* This is a pointer to the start of the bus patch's contents,
212 /// specifically the raw data words.
e0173291 213 /// Note: both pointers point into the memory buffer being parsed, so the
e3a2b9c9 214 /// contents must not be modified. On the other hand this is very efficient
215 /// because no memory copying is required.
216 void OnNewBusPatch(const AliMUONBusPatchHeaderStruct* /*header*/, const void* /*data*/) {}
217
e0173291 218 /// OnEndOfBusPatch is called whenever a bus patch has been processed.
219 /// For every call to OnNewBusPatch a symmetric call to OnEndOfBusPatch is
220 /// made once the bus patch is completely processed (no more OnData calls).
221 /// The default behaviour of this method is to do nothing.
222 /// - param const AliMUONBusPatchHeaderStruct* This is a pointer to the already
223 /// processed bus patch header, as found in the DDL payload.
224 /// - param const void* This is a pointer to the start of the bus patch's contents,
225 /// specifically the raw data words.
226 /// Note: both pointers point into the memory buffer being parsed so the
227 /// contents must not be modified. On the other hand this is very efficient
228 /// because no memory copying is required.
8a0dae7c 229 void OnEndOfBusPatch(const AliMUONBusPatchHeaderStruct* /*header*/, const void* /*data*/) {}
230
e3a2b9c9 231 /// OnData is called for every raw data word found within a bus patch.
24a0fe9f 232 /// Every data ward received by a call to OnData is associated to the bus patch
e3a2b9c9 233 /// header received in the most recent call to OnNewBusPatch.
234 /// The default behaviour of this method is to do nothing.
235 /// - param UInt_t This is the raw data word as found within the bus patch payload.
8a0dae7c 236 /// - param bool Flag indicating if the raw data word had a parity error.
237 /// This will always be set to false if fSendDataOnParityError in the
e843eb88 238 /// AliMUONTrackerDDLDecoder class was set to false.
8a0dae7c 239 void OnData(UInt_t /*data*/, bool /*parityError*/) {}
e3a2b9c9 240
241 /// Whenever a parsing error of the DDL payload is encountered because of
242 /// corruption of the raw data (eg. bit flips) the OnError method is called
24a0fe9f 243 /// immediately at the point this error is discovered.
e3a2b9c9 244 /// The default behaviour of this method is to do nothing.
245 /// - param ErrorCode This is an error code indicating the kind of problem
246 /// encountered with the DDL payload.
247 /// - param const void* This is a pointer into the DDL payload memory buffer
248 /// indicating the exact location where the parsing error happened
249 /// or i.e. the location of the corruption.
250 /// Note that a relative offset in bytes from the start of the memory buffer
24a0fe9f 251 /// can be calculated by: storing the buffer pointer received in OnNewBuffer
e3a2b9c9 252 /// earlier in fBufferStart for example, and then the offset is given by:
253 /// offset = (unsigned long)location - (unsigned long)fBufferStart;
254 void OnError(ErrorCode /*error*/, const void* /*location*/) {}
255
256 /// This is a utility method which will unpack the MANU ID, channel ID and
257 /// ADC signal value from a raw data word. It should normally be used in
258 /// OnData() to unpack these fields.
259 /// [in] \param data This is the raw data word found in the DDL payload.
260 /// [out] \param manuId This is filled with the unpacked MANU ID.
261 /// [out] \param channelId This is filled with the unpacked MANU channel ID.
262 /// [out] \param adc This is filled with the unpacked ADC signal.
263 static void UnpackADC(
264 UInt_t data,
265 UShort_t& manuId, UChar_t& channelId, UShort_t& adc
266 )
267 {
268 manuId = (UShort_t)(data >> 18) & 0x7FF;
269 channelId = (Char_t)(data >> 12) & 0x3F;
270 adc = (UShort_t)(data & 0xFFF);
271 }
272
273 /// This is a utility method which converts an error code to a string
24a0fe9f 274 /// representation for printing purposes.
e3a2b9c9 275 /// \param code The error code as received in OnError for example.
276 /// \return An ANSI string containing the name of the error code symbol.
277 static const char* ErrorCodeToString(ErrorCode code);
278
279 /// This is a utility method which converts an error code to user friendly
280 /// descriptive message useful for printing to the screen.
281 /// \param code The error code as received in OnError for example.
282 /// \return An ANSI string containing a descriptive message of the error.
283 static const char* ErrorCodeToMessage(ErrorCode code);
284};
285
e0173291 286//_____________________________________________________________________________
287
288inline const char* AliMUONTrackerDDLDecoderEventHandler::ErrorCodeToString(ErrorCode code)
289{
290 /// This is a utility method which converts an error code to a string
291 /// representation for printing purposes.
292 /// \param code The error code as received in OnError for example.
293 /// \return An ANSI string containing the name of the error code symbol.
294
295 switch (code)
296 {
297 case kNoError: return "kNoError";
298 case kBufferTooBig: return "kBufferTooBig";
299 case kTooManyBlocks: return "kTooManyBlocks";
300 case kTooManyDSPs: return "kTooManyDSPs";
301 case kTooManyBusPatches: return "kTooManyBusPatches";
302 case kNoBlockHeader: return "kNoBlockHeader";
303 case kBadBlockKey: return "kBadBlockKey";
304 case kBadBlockLength: return "kBadBlockLength";
305 case kBadBlockTotalLength: return "kBadBlockTotalLength";
306 case kBlockLengthMismatch: return "kBlockLengthMismatch";
307 case kNoDSPHeader: return "kNoDSPHeader";
308 case kBadDSPKey: return "kBadDSPKey";
309 case kBadDSPLength: return "kBadDSPLength";
310 case kBadDSPTotalLength: return "kBadDSPTotalLength";
311 case kDSPLengthMismatch: return "kDSPLengthMismatch";
312 case kNoBusPatchHeader: return "kNoBusPatchHeader";
313 case kBadBusPatchKey: return "kBadBusPatchKey";
314 case kBadBusPatchLength: return "kBadBusPatchLength";
315 case kBadBusPatchTotalLength: return "kBadBusPatchTotalLength";
316 case kBusPatchLengthMismatch: return "kBusPatchLengthMismatch";
29b6be6a 317 case kNoDDLTrailerWords: return "kNoDDLTrailerWords";
318 case kTooFewDDLTrailerWords: return "kTooFewDDLTrailerWords";
74585128 319 case kUnknownDspError: return "kUnknownDspError";
320 case kTokenLost: return "kTokenLost";
e0173291 321 case kGlitchFound: return "kGlitchFound";
322 case kBadPaddingWord: return "kBadPaddingWord";
323 case kParityError: return "kParityError";
324 default: return "INVALID";
325 }
326}
327
328
329inline const char* AliMUONTrackerDDLDecoderEventHandler::ErrorCodeToMessage(ErrorCode code)
330{
331 /// This is a utility method which converts an error code to user friendly
332 /// descriptive message useful for printing to the screen.
333 /// \param code The error code as received in OnError for example.
334 /// \return An ANSI string containing a descriptive message of the error.
335
336 switch (code)
337 {
338 case kNoError:
339 return "Decoding was successful.";
340 case kBufferTooBig:
341 return "The DDL raw data is larger than indicated by the headers;"
342 " extra bytes are probably just garbage.";
343 case kTooManyBlocks:
344 return "Too many block structures found.";
345 case kTooManyDSPs:
346 return "Too many DSP structures found in the block.";
347 case kTooManyBusPatches:
348 return "Too many bus patch structures found in the DSP structure.";
349 case kNoBlockHeader:
350 return "Missing a block header.";
351 case kBadBlockKey:
352 return "The block header key word does not contain the correct value.";
353 case kBadBlockLength:
354 return "The block length field points past the end of the raw data size.";
355 case kBadBlockTotalLength:
356 return "The total block length field points past the end of the"
357 " raw data size.";
358 case kBlockLengthMismatch:
359 return "The block length and total length fields do not correspond."
360 " One or both of these values is incorrect.";
361 case kNoDSPHeader:
362 return "Missing a DSP header.";
363 case kBadDSPKey:
364 return "The DSP header key word does not contain the correct value.";
365 case kBadDSPLength:
366 return "The DSP structure length field points past the end of the"
367 " block structure.";
368 case kBadDSPTotalLength:
369 return "The total DSP structure length field points past the end of"
370 " the block structure.";
371 case kDSPLengthMismatch:
372 return "The DSP structure length and total length fields do not"
373 " correspond. One or both of these values is incorrect.";
374 case kNoBusPatchHeader:
375 return "Missing a bus patch header.";
376 case kBadBusPatchKey:
377 return "The bus patch header key word does not contain the correct value.";
378 case kBadBusPatchLength:
379 return "The bus patch length field points past the end of the"
380 " DSP structure.";
381 case kBadBusPatchTotalLength:
382 return "The total bus patch length field points past the end of"
383 " the DSP structure.";
384 case kBusPatchLengthMismatch:
385 return "The bus patch length and total length fields do not correspond."
386 " One or both of these values is incorrect.";
29b6be6a 387 case kNoDDLTrailerWords:
388 return "No end of DDL data key found in the trailer words.";
389 case kTooFewDDLTrailerWords:
390 return "Only one end of DDL data key word found in the trailer but expected two.";
74585128 391 case kUnknownDspError:
392 return "The DSP error code is non-zero but of an unrecognised format.";
393 case kTokenLost:
394 return "The DSP contains a token lost error code that can affect the deadtime.";
e0173291 395 case kGlitchFound:
396 return "Found a glitch. This means a 1 byte word has been randomly"
397 " inserted into the raw data by mistake.";
398 case kBadPaddingWord:
399 return "The padding word does not contain the correct value.";
400 case kParityError:
401 return "Found a parity error in the data word.";
402 default:
403 return "Unknown error code!";
404 }
405}
406
407
408inline std::ostream& operator << (std::ostream& os, AliMUONTrackerDDLDecoderEventHandler::ErrorCode code)
409{
410 /// This is the stream operator for std::ostream classes to be able to
411 /// easily write the error messages associated with the error codes generated
412 /// by the decoder to 'cout' or 'cerr' for example.
413
414 os << AliMUONTrackerDDLDecoderEventHandler::ErrorCodeToMessage(code);
415 return os;
416}
417
e3a2b9c9 418#endif // ALIMUONTRACKERDDLDECODEREVENTHANDLER_H
e0173291 419