]> git.uio.no Git - u/mrichter/AliRoot.git/blob - RAW/AliAltroRawStream.cxx
Bugfix. Now NextBunch method should correctly in case of more than one bunches in...
[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
280   temp = GetNextWord();
281   fHWAddress |= temp;
282
283   fPosition -= (4 - (fCount % 4)) % 4;  // skip fill words
284
285   return kTRUE;
286 }
287
288 //_____________________________________________________________________________
289 Bool_t AliAltroRawStream::ReadDummyTrailer()
290 {
291   //Read a trailer of 40 bits in the backward reading mode
292   //In case of no mapping is provided, read a dummy trailer
293   UShort_t temp;
294   while ((temp = GetNextWord()) == 0x2AA);
295
296   fSegmentation[0] = temp;
297   fSegmentation[1] = GetNextWord();
298   fSegmentation[2] = GetNextWord();
299   fCount = GetNextWord();
300   if (fCount == 0) return kFALSE;
301   fHWAddress = -1;
302
303   fPosition -= (4 - (fCount % 4)) % 4;  // skip fill words
304
305   return kTRUE;
306 }
307
308 //_____________________________________________________________________________
309 void AliAltroRawStream::ReadBunch()
310 {
311   // Read altro payload in 
312   // backward direction
313   if (fPosition <= 0) {
314     fRawReader->AddMinorErrorLog(kBunchLengthReadErr,"");
315     //    PrintDebug();
316     AliWarning("Could not read bunch length !");
317   }
318
319   fBunchLength = GetNextWord() - 2;
320   fTimeBunch = fBunchLength;
321   fCount--;
322
323   if (fPosition <= 0) {
324     fRawReader->AddMinorErrorLog(kTimeBinReadErr,"");
325     //    PrintDebug();
326     AliWarning("Could not read time bin !");
327   }
328
329   fTime = GetNextWord();
330   fCount--;
331
332   return;
333 }
334
335 //_____________________________________________________________________________
336 void AliAltroRawStream::ReadAmplitude()
337 {
338   // Read next time bin amplitude
339   if (fPosition <= 0) {
340     fRawReader->AddMinorErrorLog(kAmplitudeReadErr,"");
341     //    PrintDebug();
342     AliWarning("Could not read sample amplitude !");
343   }
344
345   fSignal = GetNextWord();
346   fCount--;
347   fBunchLength--;
348
349   return;
350 }
351
352 //_____________________________________________________________________________
353 Int_t AliAltroRawStream::GetPosition()
354 {
355   // Sets the position in the
356   // input stream
357   // Read the RCU trailer
358   // This includes the trailer size,
359   // RCU identifier and raw data payload.
360   // The RCU trailer format is described
361   // in details in the RCU manual.
362
363   if (!fIsOldRCUFormat) {
364     // First read 32-bit word with the
365     // trailer size (22 bits) and RCU ID (the rest)
366     Int_t index = fRawReader->GetDataSize();
367     UInt_t word = Get32bitWord(index);
368     fRCUId = (Int_t)(word >> 22);
369     Int_t trailerSize = (word & 0x3FFFFF);
370
371     // Now read the beginning of the trailer
372     // where the payload size is written
373     if (trailerSize < 2) {
374       fRawReader->AddMajorErrorLog(kRCUTrailerErr,Form("tr=%d bytes",
375                                                        trailerSize*4));
376       AliWarning(Form("Invalid trailer size found (%d bytes) !",
377                       trailerSize*4));
378     }
379     fRCUTrailerSize = (trailerSize-2)*4;
380     index -= fRCUTrailerSize;
381     if (index < 4) {
382       fRawReader->AddMajorErrorLog(kRCUTrailerErr,Form("tr=%d raw=%d bytes",
383                                                        trailerSize*4,
384                                                        fRawReader->GetDataSize()));
385       AliWarning(Form("Invalid trailer size found (%d bytes) ! The size is bigger than the raw data size (%d bytes)!",
386                       trailerSize*4,
387                       fRawReader->GetDataSize()));
388     }
389     fRCUTrailerData = fData + index;
390     Int_t position = Get32bitWord(index);
391     // The size is specified in a number of 40bits
392     // Therefore we need to transform it to number of bytes
393     position *= 5;
394
395     // Check the consistency of the header and trailer
396     if (((fRawReader->GetDataSize() - trailerSize*4) < position) ||
397         ((fRawReader->GetDataSize() - trailerSize*4) >= (position + 4))) {
398       fRawReader->AddMajorErrorLog(kRCUTrailerSizeErr,Form("h=%d tr=%d rcu=%d bytes",
399                                                            fRawReader->GetDataSize(),
400                                                            trailerSize*4,
401                                                            position));
402       AliWarning(Form("Inconsistent raw data size ! Raw data size - %d bytes (from the header), RCU trailer - %d bytes, raw data paylod - %d bytes !",
403                     fRawReader->GetDataSize(),
404                     trailerSize*4,
405                     position));
406       position = fRawReader->GetDataSize() - trailerSize*4;
407     }
408
409     return position * 8 / 10;
410   }
411   else {
412     // In case of the Old RCU trailer format
413     // we have to read just the size of altro payload
414     // in units of 40-bit words
415     Int_t index = fRawReader->GetDataSize();
416     Int_t position = Get32bitWord(index);
417
418     fRCUId = -1;
419     fRCUTrailerSize = 0;
420     fRCUTrailerData = NULL;
421
422     // The size is specified in a number of 40bits
423     // Therefore we need to transform it to number of bytes
424     position *= 5;
425
426     if (!fIsShortDataHeader) {
427
428       // Check the consistency of the header and trailer
429       if (((fRawReader->GetDataSize() - 4) < position) ||
430           ((fRawReader->GetDataSize() - 4) >= (position + 4))) {
431         fRawReader->AddMajorErrorLog(kRCUTrailerSizeErr,Form("h=%d rcu=%d bytes",
432                                                              fRawReader->GetDataSize()-4,
433                                                              position));
434         //      PrintDebug();
435         AliWarning(Form("Inconsistent raw data size ! Expected %d bytes (from the header), found %d bytes (in the RCU trailer)!",
436                         fRawReader->GetDataSize()-4,
437                         position));
438         position = fRawReader->GetDataSize()-4;
439       }
440     }
441     else {
442       // Check the consistency of the header and trailer
443       // In this case the header is shorter by 4 bytes
444       if ((fRawReader->GetDataSize() < position) ||
445           (fRawReader->GetDataSize() >= (position + 4))) {
446         fRawReader->AddMajorErrorLog(kRCUTrailerSizeErr,Form("h=%d rcu=%d bytes",
447                                                              fRawReader->GetDataSize(),
448                                                              position));
449         //      PrintDebug();
450         AliWarning(Form("Inconsistent raw data size ! Expected %d bytes (from the header), found %d bytes (in the RCU trailer)!",
451                         fRawReader->GetDataSize(),
452                         position));
453         position = fRawReader->GetDataSize();
454       }
455
456       // 7 32-bit words Common Data Header
457       // therefore we have to shift back by 4 bytes
458       // the pointer to the raw data payload
459       fData -= 4;
460     }
461      
462     // Return the position in units of 10-bit words
463     return position*8/10;
464   }
465 }
466
467 //_____________________________________________________________________________
468 UInt_t AliAltroRawStream::Get32bitWord(Int_t &index)
469 {
470   // This method returns the 32 bit word at a given
471   // position inside the raw data payload.
472   // The 'index' points to the beginning of the next word.
473   // The method is supposed to be endian (platform)
474   // independent.
475   if (!fData) {
476     PrintDebug();
477     AliFatal("Raw data paylod buffer is not yet initialized !");
478   }
479
480   if (index < 4) {
481     fRawReader->AddFatalErrorLog(k32bitWordReadErr,Form("pos = %d",index));
482     //    PrintDebug();
483     AliWarning(Form("Invalid raw data payload position (%d) !",index));
484   }
485
486   UInt_t word = 0;
487   word  = fData[--index] << 24;
488   word |= fData[--index] << 16;
489   word |= fData[--index] << 8;
490   word |= fData[--index];
491
492   return word;
493 }
494
495 //_____________________________________________________________________________
496 Bool_t AliAltroRawStream::GetRCUTrailerData(UChar_t*& data) const
497 {
498   // Return a pointer to the RCU trailer
499   // data. Should be called always after
500   // the RCU trailer was already processed
501   // in the GetPosition() method
502   if (!fRCUTrailerSize || !fRCUTrailerData) {
503     AliError("No valid RCU trailer data is found !");
504     data = NULL;
505     return kFALSE;
506   }
507
508   data = fRCUTrailerData;
509
510   return kTRUE;
511 }
512
513 //_____________________________________________________________________________
514 void AliAltroRawStream::PrintDebug() const
515 {
516   // The method prints all the available
517   // debug information.
518   // Its is used in case of decoding errors.
519
520   AliError("Start of debug printout\n--------------------");
521
522   Dump();
523   if (fRawReader) fRawReader->Dump();
524
525   AliError("End of debug printout\n--------------------");
526 }
527
528 //_____________________________________________________________________________
529 Int_t AliAltroRawStream::GetBranch() const
530 {
531   // The method provides the RCU branch index (0 or 1)
532   // for the current hardware address.
533   // In case the hardware address has not been yet
534   // initialized, the method returns -1
535   if (fHWAddress == -1) return -1;
536
537   return ((fHWAddress >> 11) & 0x1);
538 }
539
540 //_____________________________________________________________________________
541 Int_t AliAltroRawStream::GetFEC() const
542 {
543   // The method provides the front-end card index
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 >> 7) & 0xF);
550 }
551
552 //_____________________________________________________________________________
553 Int_t AliAltroRawStream::GetAltro() const
554 {
555   // The method provides the altro chip 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 >> 4) & 0x7);
562 }
563
564 //_____________________________________________________________________________
565 Int_t AliAltroRawStream::GetChannel() const
566 {
567   // The method provides the channel 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 & 0xF);
574 }
575
576 //_____________________________________________________________________________
577 void AliAltroRawStream::AddMappingErrorLog(const char *message)
578 {
579   // Signal a mapping error
580   // The method can be used by the TPC,PHOS,EMCAL,FMD raw stream
581   // classes in order to log an error related to bad altro mapping
582
583   if (fRawReader) fRawReader->AddMinorErrorLog(kBadAltroMapping,message);
584 }