]> git.uio.no Git - u/mrichter/AliRoot.git/blob - RAW/AliAltroRawStream.cxx
Finally a working version of raw-data event cloning. It turned out to be quite diffic...
[u/mrichter/AliRoot.git] / RAW / AliAltroRawStream.cxx
1 /**************************************************************************
2  * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3  *                                                                        *
4  * Author: The ALICE Off-line Project.                                    *
5  * Contributors are mentioned in the code where appropriate.              *
6  *                                                                        *
7  * Permission to use, copy, modify and distribute this software and its   *
8  * documentation strictly for non-commercial purposes is hereby granted   *
9  * without fee, provided that the above copyright notice appears in all   *
10  * copies and that both the copyright notice and this permission notice   *
11  * appear in the supporting documentation. The authors make no claims     *
12  * about the suitability of this software for any purpose. It is          *
13  * provided "as is" without express or implied warranty.                  *
14  **************************************************************************/
15
16 /* $Id$ */
17
18 ///////////////////////////////////////////////////////////////////////////////
19 ///
20 /// This class provides access to Altro digits in raw data.
21 ///
22 /// It loops over all Altro digits in the raw data given by the AliRawReader.
23 /// The Next method goes to the next digit. If there are no digits left
24 /// it returns kFALSE.
25 /// Several getters provide information about the current digit.
26 ///
27 ///////////////////////////////////////////////////////////////////////////////
28
29 #include "AliAltroRawStream.h"
30 #include "AliRawReader.h"
31 #include "AliLog.h"
32
33 ClassImp(AliAltroRawStream)
34
35
36 //_____________________________________________________________________________
37 AliAltroRawStream::AliAltroRawStream(AliRawReader* rawReader) :
38   fIsShortDataHeader(kFALSE),
39   fDDLNumber(-1),
40   fPrevDDLNumber(-1),
41   fRCUId(-1),
42   fPrevRCUId(-1),
43   fHWAddress(-1),
44   fPrevHWAddress(-1),
45   fTime(-1),
46   fPrevTime(-1),
47   fSignal(-1),
48   fTimeBunch(-1),
49   fRawReader(rawReader),
50   fData(NULL),
51   fPosition(0),
52   fCount(0),
53   fBunchLength(0),
54   fRCUTrailerData(NULL),
55   fRCUTrailerSize(0),
56   fFECERRA(0),
57   fFECERRB(0),
58   fERRREG2(0),
59   fERRREG3(0),
60   fERRREG4(0),
61   fActiveFECsA(0),
62   fActiveFECsB(0),
63   fAltroCFG1(0),
64   fAltroCFG2(0)
65 {
66 // create an object to read Altro raw digits
67 }
68
69 //_____________________________________________________________________________
70 AliAltroRawStream::AliAltroRawStream(const AliAltroRawStream& stream) :
71   TObject(stream),
72   fIsShortDataHeader(stream.fIsShortDataHeader),
73   fDDLNumber(stream.fDDLNumber),
74   fPrevDDLNumber(stream.fPrevDDLNumber),
75   fRCUId(stream.fRCUId),
76   fPrevRCUId(stream.fPrevRCUId),
77   fHWAddress(stream.fHWAddress),
78   fPrevHWAddress(stream.fPrevHWAddress),
79   fTime(stream.fTime),
80   fPrevTime(stream.fPrevTime),
81   fSignal(stream.fSignal),
82   fTimeBunch(stream.fTimeBunch),
83   fRawReader(stream.fRawReader),
84   fData(stream.fData),
85   fPosition(stream.fPosition),
86   fCount(stream.fCount),
87   fBunchLength(stream.fBunchLength),
88   fRCUTrailerData(stream.fRCUTrailerData),
89   fRCUTrailerSize(stream.fRCUTrailerSize),
90   fFECERRA(stream.fFECERRA),
91   fFECERRB(stream.fFECERRB),
92   fERRREG2(stream.fERRREG2),
93   fERRREG3(stream.fERRREG3),
94   fERRREG4(stream.fERRREG4),
95   fActiveFECsA(stream.fActiveFECsA),
96   fActiveFECsB(stream.fActiveFECsB),
97   fAltroCFG1(stream.fAltroCFG1),
98   fAltroCFG2(stream.fAltroCFG2)
99 {
100 }
101
102 //_____________________________________________________________________________
103 AliAltroRawStream& AliAltroRawStream::operator = (const AliAltroRawStream& stream)
104 {
105   if(&stream == this) return *this;
106
107   fIsShortDataHeader = stream.fIsShortDataHeader;
108   fDDLNumber         = stream.fDDLNumber;
109   fPrevDDLNumber     = stream.fPrevDDLNumber;
110   fRCUId             = stream.fRCUId;
111   fPrevRCUId         = stream.fPrevRCUId;
112   fHWAddress         = stream.fHWAddress;
113   fPrevHWAddress     = stream.fPrevHWAddress;
114   fTime              = stream.fTime;
115   fPrevTime          = stream.fPrevTime;
116   fSignal            = stream.fSignal;
117   fTimeBunch         = stream.fTimeBunch;
118   fRawReader         = stream.fRawReader;
119   fData              = stream.fData;
120   fPosition          = stream.fPosition;
121   fCount             = stream.fCount;
122   fBunchLength       = stream.fBunchLength;
123   fRCUTrailerData    = stream.fRCUTrailerData;
124   fRCUTrailerSize    = stream.fRCUTrailerSize;
125   fFECERRA           = stream.fFECERRA;
126   fFECERRB           = stream.fFECERRB;
127   fERRREG2           = stream.fERRREG2;
128   fERRREG3           = stream.fERRREG3;
129   fERRREG4           = stream.fERRREG4;
130   fActiveFECsA       = stream.fActiveFECsA;
131   fActiveFECsB       = stream.fActiveFECsB;
132   fAltroCFG1         = stream.fAltroCFG1;
133   fAltroCFG2         = stream.fAltroCFG2;
134
135   return *this;
136 }
137
138 //_____________________________________________________________________________
139 AliAltroRawStream::~AliAltroRawStream()
140 {
141 // clean up
142
143 }
144
145 //_____________________________________________________________________________
146 void AliAltroRawStream::Reset()
147 {
148 // reset altro raw stream params
149
150   fPosition = fCount = fBunchLength = 0;
151
152   fRCUTrailerData = NULL;
153   fRCUTrailerSize = 0;
154
155   fFECERRA = fFECERRB = fERRREG2 = fERRREG3 = fERRREG4 = fActiveFECsA = fActiveFECsB = fAltroCFG1 = fAltroCFG2 = 0;
156
157   fDDLNumber = fPrevDDLNumber = fRCUId = fPrevRCUId = fHWAddress = fPrevHWAddress = fTime = fPrevTime = fSignal = fTimeBunch = -1;
158
159   if (fRawReader) fRawReader->Reset();
160 }
161
162 //_____________________________________________________________________________
163 Bool_t AliAltroRawStream::Next()
164 {
165 // read the next raw digit
166 // returns kFALSE if there is no digit left
167
168   fPrevDDLNumber = fDDLNumber;
169   fPrevRCUId = fRCUId;
170   fPrevHWAddress = fHWAddress;
171   fPrevTime = fTime;
172
173   while (fCount == 0) {  // next trailer
174     while (fPosition <= 0) {  // next payload
175       do {
176         if (!fRawReader->ReadNextData(fData)) return kFALSE;
177       } while (fRawReader->GetDataSize() == 0);
178
179       fDDLNumber = fRawReader->GetDDLID();
180
181       fPosition = GetPosition();
182     }
183
184     ReadTrailer();
185
186     fBunchLength = 0;
187   }
188
189   if (fBunchLength == 0) ReadBunch();
190   else fTime--;
191
192   ReadAmplitude();
193
194   return kTRUE;
195 }
196
197 //_____________________________________________________________________________
198 Bool_t AliAltroRawStream::NextDDL(UChar_t *data)
199 {
200   if (!data) {
201     do {
202       if (!fRawReader->ReadNextData(fData)) return kFALSE;
203     } while (fRawReader->GetDataSize() == 0);
204   }
205   else {
206     fData = data;
207   }
208
209   fDDLNumber = fRawReader->GetDDLID();
210   fPosition = GetPosition();
211
212   return kTRUE;
213 }
214
215 //_____________________________________________________________________________
216 Bool_t AliAltroRawStream::NextChannel()
217 {
218   if (fPosition <= 0) return kFALSE;
219
220   ReadTrailer();
221
222   return kTRUE;
223 }
224
225 //_____________________________________________________________________________
226 Bool_t AliAltroRawStream::NextBunch(UShort_t *bunchData,
227                                     Int_t &bunchLength,
228                                     Int_t &startTimeBin)
229 {
230   if (fCount == 0) return kFALSE;
231
232   ReadBunch();
233   bunchLength = fTimeBunch;
234   startTimeBin = fTime;
235
236   while (fBunchLength > 0) {
237     ReadAmplitude();
238     bunchData[bunchLength-fBunchLength-1] = fSignal;
239   }
240
241   return kTRUE;
242 }
243
244 //_____________________________________________________________________________
245 void AliAltroRawStream::SelectRawData(Int_t detId)
246 {
247   // Select the raw data for specific
248   // detector id
249   AliDebug(1,Form("Selecting raw data for detector %d",detId));
250   fRawReader->Select(detId);
251 }
252
253 //_____________________________________________________________________________
254 void AliAltroRawStream::SelectRawData(const char *detName)
255 {
256   // Select the raw data for specific
257   // detector name
258   AliDebug(1,Form("Selecting raw data for detector %s",detName));
259   fRawReader->Select(detName);
260 }
261
262 //_____________________________________________________________________________
263 UShort_t AliAltroRawStream::GetNextWord()
264 {
265   // Read the next 10 bit word in backward direction
266   // The input stream access is given by fData and fPosition
267
268   fPosition--;
269
270   Int_t iBit = fPosition * 10;
271   Int_t iByte = iBit / 8;
272   Int_t shift = iBit % 8;
273
274   // the raw data is written as integers where the low bits are filled first
275   // -> little endian is assumed here !
276   Int_t iByteLow = iByte;
277   iByte++;
278   Int_t iByteHigh  = iByte;
279   return ((fData[iByteHigh] * 256 + fData[iByteLow]) >> shift) & 0x03FF;
280 }
281
282 //_____________________________________________________________________________
283 Bool_t AliAltroRawStream::ReadTrailer()
284 {
285   //Read a trailer of 40 bits in the backward reading mode
286   //First reading filling words
287   UShort_t temp;
288   Int_t nFillWords = 0;
289   while ((temp = GetNextWord()) == 0x2AA) nFillWords++;
290   if (nFillWords == 0) {
291     fRawReader->AddMajorErrorLog(kAltroTrailerErr,"no 0x2AA");
292     //    PrintDebug();
293     AliWarning(Form("Incorrect trailer found ! Expected 0x2AA not found (0x%x != 0x2AA) ! Current position %d, DDL=%d",
294                     temp,fPosition,fDDLNumber));
295     // trying to recover and find the next bunch
296     while ((fPosition > 2) && (temp != 0x2AA)) temp = GetNextWord();
297     if (temp != 0x2AA) {
298       fCount = fPosition = 0;
299       return kFALSE;
300     }
301     temp = GetNextWord();
302   }
303
304   //Then read the trailer
305   if (fPosition < 2) {
306     fRawReader->AddMajorErrorLog(kAltroTrailerErr,Form("size %d < 5",
307                                                        fPosition));
308     //    PrintDebug();
309     AliWarning(Form("Incorrect raw data size ! Expected at least 5 words but found %d !",fPosition));
310     fCount = fPosition = 0;
311     return kFALSE;
312   }
313
314   fCount = (temp << 4) & 0x3FF;
315   if ((temp >> 6) != 0xA) {
316     fRawReader->AddMajorErrorLog(kAltroTrailerErr,"no 0xA");
317     //    PrintDebug();
318     AliWarning(Form("Incorrect trailer found ! Expecting 0xA but found 0x%x !",temp >> 6));
319     fCount = 0;
320     return kFALSE;
321   }
322
323   temp = GetNextWord();
324   fHWAddress = (temp & 0x3) << 10;
325   if (((temp >> 2) & 0xF) != 0xA) {
326     fRawReader->AddMajorErrorLog(kAltroTrailerErr,"no second 0xA");
327     //    PrintDebug();
328     AliWarning(Form("Incorrect trailer found ! Expecting second 0xA but found 0x%x !",(temp >> 2) & 0xF));
329     fCount = 0;
330     return kFALSE;
331   }
332   fCount |= ((temp & 0x3FF) >> 6);
333
334   if (fCount >= fPosition) {
335     fRawReader->AddMajorErrorLog(kAltroTrailerErr,"invalid size");
336     //    PrintDebug();
337     AliWarning(Form("Incorrect trailer found ! The altro payload size is invalid (%d >= %d) !",fCount,fPosition));
338     fCount = 0;
339     return kFALSE;
340   }
341   temp = GetNextWord();
342   fHWAddress |= temp;
343
344   fPosition -= (4 - (fCount % 4)) % 4;  // skip fill words
345
346   return kTRUE;
347 }
348
349 //_____________________________________________________________________________
350 void AliAltroRawStream::ReadBunch()
351 {
352   // Read altro payload in 
353   // backward direction
354   if (fCount <= 2) {
355     fRawReader->AddMinorErrorLog(kBunchLengthReadErr,"");
356     //    PrintDebug();
357     AliWarning(Form("Could not read bunch length and time bin ! Only %d 10-bit words are left !",fCount));
358     fBunchLength = fTimeBunch = fCount = 0;
359     return;
360   }
361
362   fBunchLength = GetNextWord() - 2;
363   if (fBunchLength > fCount) {
364     fRawReader->AddMinorErrorLog(kBunchLengthReadErr,Form("bl=%d",fBunchLength));
365     //    PrintDebug();
366     AliWarning(Form("Could not read bunch length ! Bunch length = %d (>%d)",fBunchLength,fCount));
367     fBunchLength = fTimeBunch = fCount = 0;
368     return;
369   }
370   fTimeBunch = fBunchLength;
371   fCount--;
372
373   fTime = GetNextWord();
374   fCount--;
375
376   return;
377 }
378
379 //_____________________________________________________________________________
380 void AliAltroRawStream::ReadAmplitude()
381 {
382   // Read next time bin amplitude
383   if (fCount <= 0) {
384     fRawReader->AddMinorErrorLog(kAmplitudeReadErr,"");
385     //    PrintDebug();
386     AliWarning("Could not read sample amplitude !");
387     fCount = fSignal = fBunchLength = 0;
388     return;
389   }
390
391   fSignal = GetNextWord();
392
393   fCount--;
394   fBunchLength--;
395
396   return;
397 }
398
399 //_____________________________________________________________________________
400 Int_t AliAltroRawStream::GetPosition()
401 {
402   // Sets the position in the
403   // input stream
404   // Read the RCU trailer
405   // This includes the trailer size,
406   // RCU identifier and raw data payload.
407   // The RCU trailer format is described
408   // in details in the RCU manual.
409
410   // We use the last word of the payload
411   // in order to decide which RCU firmware
412   // was used during the data taking.
413   // The firmware v2 adds 0xAAAA as 16
414   // most significant bits and since the
415   // payload size (firmware v1) can not be
416   // that big, we use this as a unique
417   // label of the firmware version.
418
419   Int_t index = fRawReader->GetDataSize();
420   UInt_t word = Get32bitWord(index);
421   if (((word >> 16) == 0xaaaa) || (word == 2)) {
422     // This is RCU formware v2
423     // The statement word==2 is needed only temporary
424     // in order to be able to read previously generated
425     // aliroot raw data
426
427     Int_t trailerSize = 0;
428     if (word == 2) {
429       AliInfo("Old simulated raw data is assumed!");
430       trailerSize = 2;
431       fRCUId = 0;
432     }
433     else {
434       // First read 32-bit word with the
435       // trailer size (7 bits), RCU ID (9 bits) and
436       // 0xAAA (the rest - 16 bits)
437       fRCUId = (Int_t)((word >> 7) & 0x1ff);
438       trailerSize = (word & 0x7F);
439     }
440
441     // Now read the beginning of the trailer
442     // where the payload size is written
443     if (trailerSize < 2) {
444       fRawReader->AddMajorErrorLog(kRCUTrailerErr,Form("tr=%d bytes",
445                                                        trailerSize*4));
446       AliWarning(Form("Invalid trailer size found (%d bytes) !",
447                       trailerSize*4));
448     }
449
450     Int_t position = ReadRCUTrailer(index,trailerSize);
451     // The size is specified in a number of 40bits
452     // Therefore we need to transform it to number of bytes
453     position *= 5;
454
455     // Check the consistency of the header and trailer
456     if (((fRawReader->GetDataSize() - trailerSize*4) < position) ||
457         ((fRawReader->GetDataSize() - trailerSize*4) >= (position + 4))) {
458       fRawReader->AddMajorErrorLog(kRCUTrailerSizeErr,Form("h=%d tr=%d rcu=%d bytes",
459                                                            fRawReader->GetDataSize(),
460                                                            trailerSize*4,
461                                                            position));
462       AliWarning(Form("Inconsistent raw data size ! Raw data size - %d bytes (from the header), RCU trailer - %d bytes, raw data paylod - %d bytes !",
463                     fRawReader->GetDataSize(),
464                     trailerSize*4,
465                     position));
466       position = fRawReader->GetDataSize() - trailerSize*4;
467     }
468
469     return position * 8 / 10;
470   }
471   else {
472     // In case of the Old RCU trailer format
473     // we have to read just the size of altro payload
474     // in units of 40-bit words
475     Int_t position = (Int_t)word;
476
477     fRCUId = -1;
478     fRCUTrailerSize = 0;
479     fRCUTrailerData = NULL;
480
481     // The size is specified in a number of 40bits
482     // Therefore we need to transform it to number of bytes
483     position *= 5;
484
485     if (!fIsShortDataHeader) {
486
487       // Check the consistency of the header and trailer
488       if (((fRawReader->GetDataSize() - 4) < position) ||
489           ((fRawReader->GetDataSize() - 4) >= (position + 4))) {
490         fRawReader->AddMajorErrorLog(kRCUTrailerSizeErr,Form("h=%d rcu=%d bytes",
491                                                              fRawReader->GetDataSize()-4,
492                                                              position));
493         //      PrintDebug();
494         AliWarning(Form("Inconsistent raw data size ! Expected %d bytes (from the header), found %d bytes (in the RCU trailer)!",
495                         fRawReader->GetDataSize()-4,
496                         position));
497         position = fRawReader->GetDataSize()-4;
498       }
499     }
500     else {
501       // Check the consistency of the header and trailer
502       // In this case the header is shorter by 4 bytes
503       if ((fRawReader->GetDataSize() < position) ||
504           (fRawReader->GetDataSize() >= (position + 4))) {
505         fRawReader->AddMajorErrorLog(kRCUTrailerSizeErr,Form("h=%d rcu=%d bytes",
506                                                              fRawReader->GetDataSize(),
507                                                              position));
508         //      PrintDebug();
509         AliWarning(Form("Inconsistent raw data size ! Expected %d bytes (from the header), found %d bytes (in the RCU trailer)!",
510                         fRawReader->GetDataSize(),
511                         position));
512         position = fRawReader->GetDataSize();
513       }
514
515       // 7 32-bit words Common Data Header
516       // therefore we have to shift back by 4 bytes
517       // the pointer to the raw data payload
518       fData -= 4;
519     }
520      
521     // Return the position in units of 10-bit words
522     return position*8/10;
523   }
524 }
525
526 //_____________________________________________________________________________
527 UInt_t AliAltroRawStream::Get32bitWord(Int_t &index)
528 {
529   // This method returns the 32 bit word at a given
530   // position inside the raw data payload.
531   // The 'index' points to the beginning of the next word.
532   // The method is supposed to be endian (platform)
533   // independent.
534   if (!fData) {
535     PrintDebug();
536     AliFatal("Raw data paylod buffer is not yet initialized !");
537   }
538
539   if (index < 4) {
540     fRawReader->AddFatalErrorLog(k32bitWordReadErr,Form("pos = %d",index));
541     //    PrintDebug();
542     AliWarning(Form("Invalid raw data payload position (%d) !",index));
543   }
544
545   UInt_t word = 0;
546   word  = fData[--index] << 24;
547   word |= fData[--index] << 16;
548   word |= fData[--index] << 8;
549   word |= fData[--index];
550
551   return word;
552 }
553
554 //_____________________________________________________________________________
555 Int_t AliAltroRawStream::ReadRCUTrailer(Int_t &index, Int_t trailerSize)
556 {
557   // The method decodes the RCU trailer data
558   // according to the RCU fw ver.2 specs
559   
560   fRCUTrailerSize = trailerSize*4;
561
562   for (trailerSize -= 2; trailerSize > 0; trailerSize--) {
563     Int_t word = Get32bitWord(index);
564     Int_t parCode = word >> 26;
565     Int_t parData = word & 0x3FFFFFF;
566     switch (parCode) {
567     case 1:
568       // ERR_REG1
569       fFECERRA = ((parData >> 13) & 0x1FFF) << 7;
570       fFECERRB = ((parData & 0x1FFF)) << 7;
571       break;
572     case 2:
573       // ERR_REG2
574       fERRREG2 = parData & 0x1FF;
575       break;
576     case 3:
577       // ERR_REG3
578       fERRREG3 = parData & 0xFFF;
579       break;
580     case 4:
581       // ERR_REG4
582       fERRREG4 = parData & 0xFFF;
583       break;
584     case 5:
585       // FEC_RO_A
586       fActiveFECsA = parData & 0xFFFF;
587       break;
588     case 6:
589       // FEC_RO_B
590       fActiveFECsB = parData & 0xFFFF;
591       break;
592     case 7:
593       // RDO_CFG1
594       fAltroCFG1 = parData & 0xFFFFF;
595       break;
596     case 8:
597       // RDO_CFG2
598       fAltroCFG2 = parData & 0x1FFFFFF;
599      break;
600     default:
601       fRawReader->AddMinorErrorLog(kRCUTrailerErr,"undef word");
602       AliWarning(Form("Undefined parameter code %d, ignore it !",
603                       parCode));
604       break;
605     }
606   }
607
608   if (index < 4) {
609     fRawReader->AddMajorErrorLog(kRCUTrailerErr,Form("tr=%d raw=%d bytes",
610                                                      fRCUTrailerSize,
611                                                      fRawReader->GetDataSize()));
612     AliWarning(Form("Invalid trailer size found (%d bytes) ! The size is bigger than the raw data size (%d bytes)!",
613                     fRCUTrailerSize,
614                     fRawReader->GetDataSize()));
615   }
616   fRCUTrailerData = fData + index;
617
618   Int_t position = Get32bitWord(index);
619
620
621   return position;
622 }
623
624 //_____________________________________________________________________________
625 Double_t AliAltroRawStream::GetTSample() const
626 {
627   // Returns the sampling time
628   // in seconds. In case the rcu trailer
629   // was note read, return an invalid number (0)
630
631   if (!fRCUTrailerData) return 0.;
632
633   const Double_t kLHCTimeSample = 25.0e-9; // LHC clocks runs at 40 MHz
634   UChar_t fq = (fAltroCFG2 >> 5) & 0xF;
635   Double_t tSample;
636   switch (fq) {
637   case 0:
638     // 20 MHz
639     tSample = 2.0*kLHCTimeSample;
640     break;
641   case 1:
642     // 10 Mhz
643     tSample = 4.0*kLHCTimeSample;
644     break;
645   case 2:
646     // 5 MHz
647     tSample = 8.0*kLHCTimeSample;
648     break;
649   default:
650     AliWarning(Form("Invalid sampling frequency value %d !",
651                       fq));
652     tSample = 0.;
653     break;
654   }
655
656   return tSample;
657 }
658
659 //_____________________________________________________________________________
660 Double_t AliAltroRawStream::GetL1Phase() const
661 {
662   // Returns the L1 phase w.r.t to the
663   // LHC clock
664   if (!fRCUTrailerData) return 0.;
665
666   const Double_t kLHCTimeSample = 25.0e-9; // LHC clocks runs at 40 MHz
667   Double_t phase = ((Double_t)(fAltroCFG2 & 0x1F))*kLHCTimeSample;
668
669   Double_t tSample = GetTSample();
670   if (phase >= tSample) {
671     AliWarning(Form("Invalid L1 trigger phase (%f >= %d) !",
672                     phase,tSample));
673     phase = 0.;
674   }
675
676   return phase;
677 }
678
679 //_____________________________________________________________________________
680 void AliAltroRawStream::PrintRCUTrailer() const
681 {
682   // Prints the contents of
683   // the RCU trailer data
684   printf("RCU trailer:\n===========\n");
685   printf("FECERRA: 0x%x\nFECERRB: 0x%x\n",fFECERRA,fFECERRB);
686   printf("ERRREG2: 0x%x\n",fERRREG2);
687   printf("#channels skipped due to address mismatch: %d\n",GetNChAddrMismatch());
688   printf("#channels skipped due to bad block length: %d\n",GetNChLengthMismatch());
689   printf("Active FECs (branch A): 0x%x\nActive FECs (branch B): 0x%x\n",fActiveFECsA,fActiveFECsB);
690   printf("Baseline corr: 0x%x\n",GetBaselineCorr());
691   printf("Number of presamples: %d\nNumber of postsamples: %d\n",GetNPresamples(),GetNPostsamples());
692   printf("Second baseline corr: %d\n",GetSecondBaselineCorr());
693   printf("GlitchFilter: %d\n",GetGlitchFilter());
694   printf("Number of non-ZS postsamples: %d\nNumber of non-ZS presamples: %d\n",GetNNonZSPostsamples(),GetNNonZSPresamples());
695   printf("Number of ALTRO buffers: %d\n",GetNAltroBuffers());
696   printf("Number of pretrigger samples: %d\n",GetNPretriggerSamples());
697   printf("Number of samples per channel: %d\n",GetNSamplesPerCh());
698   printf("Sparse readout: %d\n",GetSparseRO());
699   printf("Sampling time: %e s\n",GetTSample());
700   printf("L1 Phase: %e s\n",GetL1Phase());
701   printf("AltroCFG1: 0x%x\nAltroCFG2: 0x%x\n",GetAltroCFG1(),GetAltroCFG2());
702   printf("===========\n");
703 }
704
705 //_____________________________________________________________________________
706 Bool_t AliAltroRawStream::GetRCUTrailerData(UChar_t*& data) const
707 {
708   // Return a pointer to the RCU trailer
709   // data. Should be called always after
710   // the RCU trailer was already processed
711   // in the GetPosition() method
712   if (!fRCUTrailerSize || !fRCUTrailerData) {
713     AliError("No valid RCU trailer data is found !");
714     data = NULL;
715     return kFALSE;
716   }
717
718   data = fRCUTrailerData;
719
720   return kTRUE;
721 }
722
723 //_____________________________________________________________________________
724 void AliAltroRawStream::PrintDebug() const
725 {
726   // The method prints all the available
727   // debug information.
728   // Its is used in case of decoding errors.
729
730   AliError("Start of debug printout\n--------------------");
731
732   Dump();
733   if (fRawReader) fRawReader->Dump();
734
735   AliError("End of debug printout\n--------------------");
736 }
737
738 //_____________________________________________________________________________
739 Int_t AliAltroRawStream::GetBranch() const
740 {
741   // The method provides the RCU branch index (0 or 1)
742   // for the current hardware address.
743   // In case the hardware address has not been yet
744   // initialized, the method returns -1
745   if (fHWAddress == -1) return -1;
746
747   return ((fHWAddress >> 11) & 0x1);
748 }
749
750 //_____________________________________________________________________________
751 Int_t AliAltroRawStream::GetFEC() const
752 {
753   // The method provides the front-end card index
754   // for the current hardware address.
755   // In case the hardware address has not been yet
756   // initialized, the method returns -1
757   if (fHWAddress == -1) return -1;
758
759   return ((fHWAddress >> 7) & 0xF);
760 }
761
762 //_____________________________________________________________________________
763 Int_t AliAltroRawStream::GetAltro() const
764 {
765   // The method provides the altro chip index
766   // for the current hardware address.
767   // In case the hardware address has not been yet
768   // initialized, the method returns -1
769   if (fHWAddress == -1) return -1;
770
771   return ((fHWAddress >> 4) & 0x7);
772 }
773
774 //_____________________________________________________________________________
775 Int_t AliAltroRawStream::GetChannel() const
776 {
777   // The method provides the channel index
778   // for the current hardware address.
779   // In case the hardware address has not been yet
780   // initialized, the method returns -1
781   if (fHWAddress == -1) return -1;
782
783   return (fHWAddress & 0xF);
784 }
785
786 //_____________________________________________________________________________
787 void AliAltroRawStream::AddMappingErrorLog(const char *message)
788 {
789   // Signal a mapping error
790   // The method can be used by the TPC,PHOS,EMCAL,FMD raw stream
791   // classes in order to log an error related to bad altro mapping
792
793   if (fRawReader) fRawReader->AddMinorErrorLog(kBadAltroMapping,message);
794 }