- Reset TProcessID count after each event
[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   fNoAltroMapping(kTRUE),
39   fIsOldRCUFormat(kFALSE),
40   fIsShortDataHeader(kFALSE),
41   fDDLNumber(-1),
42   fPrevDDLNumber(-1),
43   fRCUId(-1),
44   fPrevRCUId(-1),
45   fHWAddress(-1),
46   fPrevHWAddress(-1),
47   fTime(-1),
48   fPrevTime(-1),
49   fSignal(-1),
50   fTimeBunch(-1),
51   fRawReader(rawReader),
52   fData(NULL),
53   fPosition(0),
54   fCount(0),
55   fBunchLength(0),
56   fRCUTrailerData(NULL),
57   fRCUTrailerSize(0)
58 {
59 // create an object to read Altro raw digits
60   fSegmentation[0] = fSegmentation[1] = fSegmentation[2] = -1;
61 }
62
63 //_____________________________________________________________________________
64 AliAltroRawStream::AliAltroRawStream(const AliAltroRawStream& stream) :
65   TObject(stream),
66   fNoAltroMapping(stream.fNoAltroMapping),
67   fIsOldRCUFormat(stream.fIsOldRCUFormat),
68   fIsShortDataHeader(stream.fIsShortDataHeader),
69   fDDLNumber(stream.fDDLNumber),
70   fPrevDDLNumber(stream.fPrevDDLNumber),
71   fRCUId(stream.fRCUId),
72   fPrevRCUId(stream.fPrevRCUId),
73   fHWAddress(stream.fHWAddress),
74   fPrevHWAddress(stream.fPrevHWAddress),
75   fTime(stream.fTime),
76   fPrevTime(stream.fPrevTime),
77   fSignal(stream.fSignal),
78   fTimeBunch(stream.fTimeBunch),
79   fRawReader(stream.fRawReader),
80   fData(stream.fData),
81   fPosition(stream.fPosition),
82   fCount(stream.fCount),
83   fBunchLength(stream.fBunchLength),
84   fRCUTrailerData(stream.fRCUTrailerData),
85   fRCUTrailerSize(stream.fRCUTrailerSize)
86 {
87   fSegmentation[0]   = stream.fSegmentation[0];
88   fSegmentation[1]   = stream.fSegmentation[1];
89   fSegmentation[2]   = stream.fSegmentation[2];
90 }
91
92 //_____________________________________________________________________________
93 AliAltroRawStream& AliAltroRawStream::operator = (const AliAltroRawStream& stream)
94 {
95   if(&stream == this) return *this;
96
97   fNoAltroMapping    = stream.fNoAltroMapping;
98   fIsOldRCUFormat    = stream.fIsOldRCUFormat;
99   fIsShortDataHeader = stream.fIsShortDataHeader;
100   fDDLNumber         = stream.fDDLNumber;
101   fPrevDDLNumber     = stream.fPrevDDLNumber;
102   fRCUId             = stream.fRCUId;
103   fPrevRCUId         = stream.fPrevRCUId;
104   fHWAddress         = stream.fHWAddress;
105   fPrevHWAddress     = stream.fPrevHWAddress;
106   fTime              = stream.fTime;
107   fPrevTime          = stream.fPrevTime;
108   fSignal            = stream.fSignal;
109   fTimeBunch         = stream.fTimeBunch;
110   fRawReader         = stream.fRawReader;
111   fData              = stream.fData;
112   fPosition          = stream.fPosition;
113   fCount             = stream.fCount;
114   fBunchLength       = stream.fBunchLength;
115   fRCUTrailerData    = stream.fRCUTrailerData;
116   fRCUTrailerSize    = stream.fRCUTrailerSize;
117
118   fSegmentation[0]   = stream.fSegmentation[0];
119   fSegmentation[1]   = stream.fSegmentation[1];
120   fSegmentation[2]   = stream.fSegmentation[2];
121
122   return *this;
123 }
124
125 //_____________________________________________________________________________
126 AliAltroRawStream::~AliAltroRawStream()
127 {
128 // clean up
129
130 }
131
132 //_____________________________________________________________________________
133 void AliAltroRawStream::Reset()
134 {
135 // reset altro raw stream params
136
137   fPosition = fCount = fBunchLength = 0;
138
139   fRCUTrailerData = NULL;
140   fRCUTrailerSize = 0;
141
142   fDDLNumber = fPrevDDLNumber = fRCUId = fPrevRCUId = fHWAddress = fPrevHWAddress = fTime = fPrevTime = fSignal = fTimeBunch = -1;
143
144   if (fRawReader) fRawReader->Reset();
145
146   fSegmentation[0] = fSegmentation[1] = fSegmentation[2] = -1;
147 }
148
149 //_____________________________________________________________________________
150 Bool_t AliAltroRawStream::Next()
151 {
152 // read the next raw digit
153 // returns kFALSE if there is no digit left
154
155   fPrevDDLNumber = fDDLNumber;
156   fPrevRCUId = fRCUId;
157   fPrevHWAddress = fHWAddress;
158   fPrevTime = fTime;
159
160   while (fCount == 0) {  // next trailer
161     if (fPosition <= 0) {  // next payload
162       do {
163         if (!fRawReader->ReadNextData(fData)) return kFALSE;
164       } while (fRawReader->GetDataSize() == 0);
165
166       fDDLNumber = fRawReader->GetDDLID();
167
168       fPosition = GetPosition();
169     }
170
171     ReadTrailer();
172
173     fBunchLength = 0;
174   }
175
176   if (fBunchLength == 0) ReadBunch();
177   else fTime--;
178
179   ReadAmplitude();
180
181   return kTRUE;
182 }
183
184 //_____________________________________________________________________________
185 void AliAltroRawStream::SelectRawData(Int_t detId)
186 {
187   // Select the raw data for specific
188   // detector id
189   AliDebug(1,Form("Selecting raw data for detector %d",detId));
190   fRawReader->Select(detId);
191 }
192
193 //_____________________________________________________________________________
194 void AliAltroRawStream::SelectRawData(const char *detName)
195 {
196   // Select the raw data for specific
197   // detector name
198   AliDebug(1,Form("Selecting raw data for detector %s",detName));
199   fRawReader->Select(detName);
200 }
201
202 //_____________________________________________________________________________
203 UShort_t AliAltroRawStream::GetNextWord()
204 {
205   // Read the next 10 bit word in backward direction
206   // The input stream access is given by fData and fPosition
207
208   fPosition--;
209
210   Int_t iBit = fPosition * 10;
211   Int_t iByte = iBit / 8;
212   Int_t shift = iBit % 8;
213
214   // the raw data is written as integers where the low bits are filled first
215   // -> little endian is assumed here !
216   Int_t iByteLow = iByte;
217   iByte++;
218   Int_t iByteHigh  = iByte;
219   return ((fData[iByteHigh] * 256 + fData[iByteLow]) >> shift) & 0x03FF;
220 }
221
222 //_____________________________________________________________________________
223 Bool_t AliAltroRawStream::ReadTrailer()
224 {
225   //Read a trailer of 40 bits in the backward reading mode
226   //In case of no mapping is provided, read a dummy trailer
227   if (fNoAltroMapping) {
228     AliError("No ALTRO mapping information is loaded! Reading a dummy trailer!");
229     return ReadDummyTrailer();
230   }
231
232   //First reading filling words
233   UShort_t temp;
234   Int_t nFillWords = 0;
235   while ((temp = GetNextWord()) == 0x2AA) nFillWords++;
236   if (nFillWords == 0) {
237     fRawReader->AddMajorErrorLog(kAltroTrailerErr,"no 0x2AA");
238     //    PrintDebug();
239     AliWarning("Incorrect trailer found ! Expected 0x2AA not found !");
240     // trying to recover and find the next bunch
241     while ((fPosition > 5) && (temp != 0x2AA)) temp = GetNextWord();
242     if (temp != 0x2AA) {
243       fCount = fPosition = 0;
244       return kFALSE;
245     }
246     temp = GetNextWord();
247   }
248
249   //Then read the trailer
250   if (fPosition < 5) {
251     fRawReader->AddMajorErrorLog(kAltroTrailerErr,Form("size %d < 5",
252                                                     fPosition));
253     //    PrintDebug();
254     AliWarning(Form("Incorrect raw data size ! Expected at least 5 words but found %d !",fPosition));
255     fCount = fPosition = 0;
256     return kFALSE;
257   }
258
259   fCount = (temp << 4) & 0x3FF;
260   if ((temp >> 6) != 0xA) {
261     fRawReader->AddMajorErrorLog(kAltroTrailerErr,"no 0xA");
262     //    PrintDebug();
263     AliWarning(Form("Incorrect trailer found ! Expecting 0xA but found 0x%x !",temp >> 6));
264     fCount = 0;
265     return kFALSE;
266   }
267
268   temp = GetNextWord();
269   fHWAddress = (temp & 0x3) << 10;
270   if (((temp >> 2) & 0xF) != 0xA) {
271     fRawReader->AddMajorErrorLog(kAltroTrailerErr,"no second 0xA");
272     //    PrintDebug();
273     AliWarning(Form("Incorrect trailer found ! Expecting second 0xA but found 0x%x !",(temp >> 2) & 0xF));
274     fCount = 0;
275     return kFALSE;
276   }
277   fCount |= ((temp & 0x3FF) >> 6);
278   if (fCount == 0) return kFALSE;
279   if (fCount >= fPosition) {
280     fRawReader->AddMajorErrorLog(kAltroTrailerErr,"invalid size");
281     //    PrintDebug();
282     AliWarning(Form("Incorrect trailer found ! The altro payload size is invalid (%d >= %d) !",fCount,fPosition));
283     fCount = 0;
284     return kFALSE;
285   }
286   temp = GetNextWord();
287   fHWAddress |= temp;
288
289   fPosition -= (4 - (fCount % 4)) % 4;  // skip fill words
290
291   return kTRUE;
292 }
293
294 //_____________________________________________________________________________
295 Bool_t AliAltroRawStream::ReadDummyTrailer()
296 {
297   //Read a trailer of 40 bits in the backward reading mode
298   //In case of no mapping is provided, read a dummy trailer
299   UShort_t temp;
300   while ((temp = GetNextWord()) == 0x2AA);
301
302   fSegmentation[0] = temp;
303   fSegmentation[1] = GetNextWord();
304   fSegmentation[2] = GetNextWord();
305   fCount = GetNextWord();
306   if (fCount == 0) return kFALSE;
307   fHWAddress = -1;
308
309   fPosition -= (4 - (fCount % 4)) % 4;  // skip fill words
310
311   return kTRUE;
312 }
313
314 //_____________________________________________________________________________
315 void AliAltroRawStream::ReadBunch()
316 {
317   // Read altro payload in 
318   // backward direction
319   if (fCount <= 2) {
320     fRawReader->AddMinorErrorLog(kBunchLengthReadErr,"");
321     //    PrintDebug();
322     AliWarning(Form("Could not read bunch length and time bin ! Only %d 10-bit words are left !",fCount));
323     fBunchLength = fTimeBunch = fCount = 0;
324     return;
325   }
326
327   fBunchLength = GetNextWord() - 2;
328   if (fBunchLength > fCount) {
329     fRawReader->AddMinorErrorLog(kBunchLengthReadErr,Form("bl=%d",fBunchLength));
330     //    PrintDebug();
331     AliWarning(Form("Could not read bunch length ! Bunch length = %d (>%d)",fBunchLength,fCount));
332     fBunchLength = fTimeBunch = fCount = 0;
333     return;
334   }
335   fTimeBunch = fBunchLength;
336   fCount--;
337
338   fTime = GetNextWord();
339   fCount--;
340
341   return;
342 }
343
344 //_____________________________________________________________________________
345 void AliAltroRawStream::ReadAmplitude()
346 {
347   // Read next time bin amplitude
348   if (fCount <= 0) {
349     fRawReader->AddMinorErrorLog(kAmplitudeReadErr,"");
350     //    PrintDebug();
351     AliWarning("Could not read sample amplitude !");
352     fCount = fSignal = fBunchLength = 0;
353     return;
354   }
355
356   fSignal = GetNextWord();
357
358   fCount--;
359   fBunchLength--;
360
361   return;
362 }
363
364 //_____________________________________________________________________________
365 Int_t AliAltroRawStream::GetPosition()
366 {
367   // Sets the position in the
368   // input stream
369   // Read the RCU trailer
370   // This includes the trailer size,
371   // RCU identifier and raw data payload.
372   // The RCU trailer format is described
373   // in details in the RCU manual.
374
375   if (!fIsOldRCUFormat) {
376     // First read 32-bit word with the
377     // trailer size (22 bits) and RCU ID (the rest)
378     Int_t index = fRawReader->GetDataSize();
379     UInt_t word = Get32bitWord(index);
380     fRCUId = (Int_t)(word >> 22);
381     Int_t trailerSize = (word & 0x3FFFFF);
382
383     // Now read the beginning of the trailer
384     // where the payload size is written
385     if (trailerSize < 2) {
386       fRawReader->AddMajorErrorLog(kRCUTrailerErr,Form("tr=%d bytes",
387                                                        trailerSize*4));
388       AliWarning(Form("Invalid trailer size found (%d bytes) !",
389                       trailerSize*4));
390     }
391     fRCUTrailerSize = (trailerSize-2)*4;
392     index -= fRCUTrailerSize;
393     if (index < 4) {
394       fRawReader->AddMajorErrorLog(kRCUTrailerErr,Form("tr=%d raw=%d bytes",
395                                                        trailerSize*4,
396                                                        fRawReader->GetDataSize()));
397       AliWarning(Form("Invalid trailer size found (%d bytes) ! The size is bigger than the raw data size (%d bytes)!",
398                       trailerSize*4,
399                       fRawReader->GetDataSize()));
400     }
401     fRCUTrailerData = fData + index;
402     Int_t position = Get32bitWord(index);
403     // The size is specified in a number of 40bits
404     // Therefore we need to transform it to number of bytes
405     position *= 5;
406
407     // Check the consistency of the header and trailer
408     if (((fRawReader->GetDataSize() - trailerSize*4) < position) ||
409         ((fRawReader->GetDataSize() - trailerSize*4) >= (position + 4))) {
410       fRawReader->AddMajorErrorLog(kRCUTrailerSizeErr,Form("h=%d tr=%d rcu=%d bytes",
411                                                            fRawReader->GetDataSize(),
412                                                            trailerSize*4,
413                                                            position));
414       AliWarning(Form("Inconsistent raw data size ! Raw data size - %d bytes (from the header), RCU trailer - %d bytes, raw data paylod - %d bytes !",
415                     fRawReader->GetDataSize(),
416                     trailerSize*4,
417                     position));
418       position = fRawReader->GetDataSize() - trailerSize*4;
419     }
420
421     return position * 8 / 10;
422   }
423   else {
424     // In case of the Old RCU trailer format
425     // we have to read just the size of altro payload
426     // in units of 40-bit words
427     Int_t index = fRawReader->GetDataSize();
428     Int_t position = Get32bitWord(index);
429
430     fRCUId = -1;
431     fRCUTrailerSize = 0;
432     fRCUTrailerData = NULL;
433
434     // The size is specified in a number of 40bits
435     // Therefore we need to transform it to number of bytes
436     position *= 5;
437
438     if (!fIsShortDataHeader) {
439
440       // Check the consistency of the header and trailer
441       if (((fRawReader->GetDataSize() - 4) < position) ||
442           ((fRawReader->GetDataSize() - 4) >= (position + 4))) {
443         fRawReader->AddMajorErrorLog(kRCUTrailerSizeErr,Form("h=%d rcu=%d bytes",
444                                                              fRawReader->GetDataSize()-4,
445                                                              position));
446         //      PrintDebug();
447         AliWarning(Form("Inconsistent raw data size ! Expected %d bytes (from the header), found %d bytes (in the RCU trailer)!",
448                         fRawReader->GetDataSize()-4,
449                         position));
450         position = fRawReader->GetDataSize()-4;
451       }
452     }
453     else {
454       // Check the consistency of the header and trailer
455       // In this case the header is shorter by 4 bytes
456       if ((fRawReader->GetDataSize() < position) ||
457           (fRawReader->GetDataSize() >= (position + 4))) {
458         fRawReader->AddMajorErrorLog(kRCUTrailerSizeErr,Form("h=%d rcu=%d bytes",
459                                                              fRawReader->GetDataSize(),
460                                                              position));
461         //      PrintDebug();
462         AliWarning(Form("Inconsistent raw data size ! Expected %d bytes (from the header), found %d bytes (in the RCU trailer)!",
463                         fRawReader->GetDataSize(),
464                         position));
465         position = fRawReader->GetDataSize();
466       }
467
468       // 7 32-bit words Common Data Header
469       // therefore we have to shift back by 4 bytes
470       // the pointer to the raw data payload
471       fData -= 4;
472     }
473      
474     // Return the position in units of 10-bit words
475     return position*8/10;
476   }
477 }
478
479 //_____________________________________________________________________________
480 UInt_t AliAltroRawStream::Get32bitWord(Int_t &index)
481 {
482   // This method returns the 32 bit word at a given
483   // position inside the raw data payload.
484   // The 'index' points to the beginning of the next word.
485   // The method is supposed to be endian (platform)
486   // independent.
487   if (!fData) {
488     PrintDebug();
489     AliFatal("Raw data paylod buffer is not yet initialized !");
490   }
491
492   if (index < 4) {
493     fRawReader->AddFatalErrorLog(k32bitWordReadErr,Form("pos = %d",index));
494     //    PrintDebug();
495     AliWarning(Form("Invalid raw data payload position (%d) !",index));
496   }
497
498   UInt_t word = 0;
499   word  = fData[--index] << 24;
500   word |= fData[--index] << 16;
501   word |= fData[--index] << 8;
502   word |= fData[--index];
503
504   return word;
505 }
506
507 //_____________________________________________________________________________
508 Bool_t AliAltroRawStream::GetRCUTrailerData(UChar_t*& data) const
509 {
510   // Return a pointer to the RCU trailer
511   // data. Should be called always after
512   // the RCU trailer was already processed
513   // in the GetPosition() method
514   if (!fRCUTrailerSize || !fRCUTrailerData) {
515     AliError("No valid RCU trailer data is found !");
516     data = NULL;
517     return kFALSE;
518   }
519
520   data = fRCUTrailerData;
521
522   return kTRUE;
523 }
524
525 //_____________________________________________________________________________
526 void AliAltroRawStream::PrintDebug() const
527 {
528   // The method prints all the available
529   // debug information.
530   // Its is used in case of decoding errors.
531
532   AliError("Start of debug printout\n--------------------");
533
534   Dump();
535   if (fRawReader) fRawReader->Dump();
536
537   AliError("End of debug printout\n--------------------");
538 }
539
540 //_____________________________________________________________________________
541 Int_t AliAltroRawStream::GetBranch() const
542 {
543   // The method provides the RCU branch index (0 or 1)
544   // for the current hardware address.
545   // In case the hardware address has not been yet
546   // initialized, the method returns -1
547   if (fHWAddress == -1) return -1;
548
549   return ((fHWAddress >> 11) & 0x1);
550 }
551
552 //_____________________________________________________________________________
553 Int_t AliAltroRawStream::GetFEC() const
554 {
555   // The method provides the front-end card index
556   // for the current hardware address.
557   // In case the hardware address has not been yet
558   // initialized, the method returns -1
559   if (fHWAddress == -1) return -1;
560
561   return ((fHWAddress >> 7) & 0xF);
562 }
563
564 //_____________________________________________________________________________
565 Int_t AliAltroRawStream::GetAltro() const
566 {
567   // The method provides the altro chip index
568   // for the current hardware address.
569   // In case the hardware address has not been yet
570   // initialized, the method returns -1
571   if (fHWAddress == -1) return -1;
572
573   return ((fHWAddress >> 4) & 0x7);
574 }
575
576 //_____________________________________________________________________________
577 Int_t AliAltroRawStream::GetChannel() const
578 {
579   // The method provides the channel index
580   // for the current hardware address.
581   // In case the hardware address has not been yet
582   // initialized, the method returns -1
583   if (fHWAddress == -1) return -1;
584
585   return (fHWAddress & 0xF);
586 }
587
588 //_____________________________________________________________________________
589 void AliAltroRawStream::AddMappingErrorLog(const char *message)
590 {
591   // Signal a mapping error
592   // The method can be used by the TPC,PHOS,EMCAL,FMD raw stream
593   // classes in order to log an error related to bad altro mapping
594
595   if (fRawReader) fRawReader->AddMinorErrorLog(kBadAltroMapping,message);
596 }