DQM configure file
[u/mrichter/AliRoot.git] / MUON / AliMUONTrackerDDLDecoderEventHandler.h
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.
36 extern "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.
44 struct 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.
57 struct 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.
72 struct 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
95 class AliMUONTrackerDDLDecoderEventHandler
96 {
97 public:
98
99         /// The only reason for a virtual destructor is to make -Weffc++ shutup.
100         /// This should not really be here since we do not need or use virtual methods.
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.
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.
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.
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         
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.
156         void OnEndOfBuffer(const void* /*buffer*/, UInt_t /*bufferSize*/) {}
157         
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.
160         /// - param const AliMUONBlockHeaderStruct* This is a pointer to the block header
161         ///                as found in the DDL payload.
162         /// - param const void* This is a pointer to the start of the block's contents.
163         /// Note: both pointers point into the memory buffer being parsed, so the
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         
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.
179         void OnEndOfBlock(const AliMUONBlockHeaderStruct* /*header*/, const void* /*data*/) {}
180         
181         /// OnNewDSP is called whenever a new DSP header is found in the payload.
182         /// Every DSP header received by a call to OnNewDSP is associated to the
183         /// block header received in the most recent call to OnNewBlock.
184         /// The default behaviour of this method is to do nothing.
185         /// - param const AliMUONDSPHeaderStruct*  This is a pointer to the DSP header
186         ///                as found in the DDL payload.
187         /// - param const void*  This is a pointer to the start of the DSP's contents.
188         /// Note: both pointers point into the memory buffer being parsed, so the
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         
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.
203         void OnEndOfDSP(const AliMUONDSPHeaderStruct* /*header*/, const void* /*data*/) {}
204         
205         /// OnNewBusPatch is called whenever a new bus patch header is found in
206         /// the payload. Every bus patch received by a call to OnNewBusPatch is
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.
209         /// - param const AliMUONBusPatchHeaderStruct*  This is a pointer to the bus patch
210         ///                header as found in the DDL payload.
211         /// - param const void*  This is a pointer to the start of the bus patch's contents,
212         ///              specifically the raw data words.
213         /// Note: both pointers point into the memory buffer being parsed, so the
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         
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.
229         void OnEndOfBusPatch(const AliMUONBusPatchHeaderStruct* /*header*/, const void* /*data*/) {}
230         
231         /// OnData is called for every raw data word found within a bus patch.
232         /// Every data ward received by a call to OnData is associated to the bus patch
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.
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
238         ///       AliMUONTrackerDDLDecoder class was set to false.
239         void OnData(UInt_t /*data*/, bool /*parityError*/) {}
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
243         /// immediately at the point this error is discovered.
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
251         /// can be calculated by: storing the buffer pointer received in OnNewBuffer
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
274         /// representation for printing purposes.
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
286 //_____________________________________________________________________________
287
288 inline 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";
317         case kNoDDLTrailerWords: return "kNoDDLTrailerWords";
318         case kTooFewDDLTrailerWords: return "kTooFewDDLTrailerWords";
319         case kUnknownDspError: return "kUnknownDspError";
320         case kTokenLost: return "kTokenLost";
321         case kGlitchFound: return "kGlitchFound";
322         case kBadPaddingWord: return "kBadPaddingWord";
323         case kParityError: return "kParityError";
324         default: return "INVALID";
325         }
326 }
327
328
329 inline 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.";
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.";
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.";
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
408 inline 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
418 #endif // ALIMUONTRACKERDDLDECODEREVENTHANDLER_H
419